core_validation.cpp revision 43ec3f090ca979777b306abe7c25662b9429e06d
14f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes/* Copyright (c) 2015-2017 The Khronos Group Inc. 24f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes * Copyright (c) 2015-2017 Valve Corporation 34f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes * Copyright (c) 2015-2017 LunarG, Inc. 44f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes * Copyright (C) 2015-2017 Google Inc. 55b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * 643b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * Licensed under the Apache License, Version 2.0 (the "License"); 743b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * you may not use this file except in compliance with the License. 843b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * You may obtain a copy of the License at 95b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * 1043b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * http://www.apache.org/licenses/LICENSE-2.0 115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * 1243b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * Unless required by applicable law or agreed to in writing, software 1343b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * distributed under the License is distributed on an "AS IS" BASIS, 1443b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1543b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * See the License for the specific language governing permissions and 1643b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * limitations under the License. 175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * 185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Cody Northrop <cnorthrop@google.com> 195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Michael Lentine <mlentine@google.com> 205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Tobin Ehlis <tobine@google.com> 215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Chia-I Wu <olv@google.com> 225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Chris Forbes <chrisf@ijw.co.nz> 235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Mark Lobodzinski <mark@lunarg.com> 245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis * Author: Ian Elliott <ianelliott@google.com> 2560cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Dave Houlton <daveh@lunarg.com> 2660cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Dustin Graves <dustin@lunarg.com> 2760cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Jeremy Hayes <jeremy@lunarg.com> 2860cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Jon Ashburn <jon@lunarg.com> 2960cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Karl Schultz <karl@lunarg.com> 3060cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Mark Young <marky@lunarg.com> 3160cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Mike Schuchardt <mikes@lunarg.com> 3260cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Mike Weiblen <mikew@lunarg.com> 3360cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Tony Barbour <tony@LunarG.com> 345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis */ 355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Allow use of STL min and max functions in Windows 375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#define NOMINMAX 385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3994c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <algorithm> 4094c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <assert.h> 4194c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <iostream> 4294c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <list> 4394c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <map> 44c8bee427d7a8ed0ccec899fbf47134d582dcafbdGabríel Arthúr Pétursson#include <memory> 45b9e992386a44404152747d66817a733aa127e281Jeremy Hayes#include <mutex> 4694c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <set> 4768d157d34807071526e5d78b3b3b68c5a4c6185fMark Lobodzinski#include <sstream> 485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include <stdio.h> 495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include <stdlib.h> 505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include <string.h> 5194c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <string> 525770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus#include <inttypes.h> 535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_loader_platform.h" 555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_dispatch_table_helper.h" 5668d157d34807071526e5d78b3b3b68c5a4c6185fMark Lobodzinski#include "vk_enum_string_helper.h" 575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if defined(__GNUC__) 585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#pragma GCC diagnostic ignored "-Wwrite-strings" 595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif 605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if defined(__GNUC__) 615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#pragma GCC diagnostic warning "-Wwrite-strings" 625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif 635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "core_validation.h" 64c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski#include "buffer_validation.h" 65d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes#include "shader_validation.h" 665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_table.h" 675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_data.h" 685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_extension_utils.h" 695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_utils.h" 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 825770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus// TODO: remove on NDK update (r15 will probably have proper STL impl) 835770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus#ifdef __ANDROID__ 845770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausnamespace std { 855770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 865770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraustemplate <typename T> 875770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausstd::string to_string(T var) { 885770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus std::ostringstream ss; 895770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus ss << var; 905770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus return ss.str(); 915770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus} 925770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus} 935770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus#endif 945770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 95d147a5463f8581604ca542aa1a44a27e512e0f60Mike Stroyan// This intentionally includes a cpp file 96d147a5463f8581604ca542aa1a44a27e512e0f60Mike Stroyan#include "vk_safe_struct.cpp" 97d147a5463f8581604ca542aa1a44a27e512e0f60Mike Stroyan 98d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wunamespace core_validation { 99d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 1005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisusing std::unordered_map; 1015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisusing std::unordered_set; 1020c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::unique_ptr; 1030c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::vector; 1040c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::string; 1050c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::stringstream; 1060c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::max; 1075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// WSI Image Objects bypass usual Image Object creation methods. A special Memory 1095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Object value will be used to identify them internally. 1105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic const VkDeviceMemory MEMTRACKER_SWAP_CHAIN_IMAGE_KEY = (VkDeviceMemory)(-1); 111888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// 2nd special memory handle used to flag object as unbound from memory 112888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisstatic const VkDeviceMemory MEMORY_UNBOUND = VkDeviceMemory(~((uint64_t)(0)) - 1); 113b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis 1142e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill// A special value of (0xFFFFFFFF, 0xFFFFFFFF) indicates that the surface size will be determined 1152e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill// by the extent of a swapchain targeting the surface. 1162e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madillstatic const uint32_t kSurfaceSizeFromSwapchain = 0xFFFFFFFFu; 1172e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill 118f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstruct instance_layer_data { 119d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes VkInstance instance = VK_NULL_HANDLE; 120d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes debug_report_data *report_data = nullptr; 1215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<VkDebugReportCallbackEXT> logging_callback; 1229172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes VkLayerInstanceDispatchTable dispatch_table; 1239172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes 124219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes CALL_STATE vkEnumeratePhysicalDevicesState = UNCALLED; 125219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes uint32_t physical_devices_count = 0; 126b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young CALL_STATE vkEnumeratePhysicalDeviceGroupsState = UNCALLED; 127b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young uint32_t physical_device_groups_count = 0; 128219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes CHECK_DISABLED disabled = {}; 129219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes 130f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes unordered_map<VkPhysicalDevice, PHYSICAL_DEVICE_STATE> physical_device_map; 131747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes unordered_map<VkSurfaceKHR, SURFACE_STATE> surface_map; 132747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 1330cf009a4e2a5c22e4645f343c7a998f188a22015Chris Forbes InstanceExtensions extensions; 134f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes}; 135f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes 136f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstruct layer_data { 137f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes debug_report_data *report_data = nullptr; 1384a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkLayerDispatchTable dispatch_table; 13994c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis 140a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinski DeviceExtensions extensions = {}; 141cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski unordered_set<VkQueue> queues; // All queues under given device 1425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Layer specific data 143d31a44af6da568692a73201825459689c9431867Tobin Ehlis unordered_map<VkSampler, unique_ptr<SAMPLER_STATE>> samplerMap; 14479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis unordered_map<VkImageView, unique_ptr<IMAGE_VIEW_STATE>> imageViewMap; 1451facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis unordered_map<VkImage, unique_ptr<IMAGE_STATE>> imageMap; 14639267c0c27b8f032f05a6747eb02d4508247fdc1Tobin Ehlis unordered_map<VkBufferView, unique_ptr<BUFFER_VIEW_STATE>> bufferViewMap; 1475cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis unordered_map<VkBuffer, unique_ptr<BUFFER_STATE>> bufferMap; 1484c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis unordered_map<VkPipeline, PIPELINE_STATE *> pipelineMap; 1498d6a38de0389036581ada119e548180c614fe0efChris Forbes unordered_map<VkCommandPool, COMMAND_POOL_NODE> commandPoolMap; 150a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_STATE *> descriptorPoolMap; 151397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> setMap; 152c8bee427d7a8ed0ccec899fbf47134d582dcafbdGabríel Arthúr Pétursson unordered_map<VkDescriptorSetLayout, std::unique_ptr<cvdescriptorset::DescriptorSetLayout>> descriptorSetLayoutMap; 1535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkPipelineLayout, PIPELINE_LAYOUT_NODE> pipelineLayoutMap; 15457fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis unordered_map<VkDeviceMemory, unique_ptr<DEVICE_MEM_INFO>> memObjMap; 1555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkFence, FENCE_NODE> fenceMap; 15636c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis unordered_map<VkQueue, QUEUE_STATE> queueMap; 1574710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis unordered_map<VkEvent, EVENT_STATE> eventMap; 1585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<QueryObject, bool> queryToStateMap; 1595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkQueryPool, QUERY_POOL_NODE> queryPoolMap; 1605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkSemaphore, SEMAPHORE_NODE> semaphoreMap; 16172d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis unordered_map<VkCommandBuffer, GLOBAL_CB_NODE *> commandBufferMap; 162c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis unordered_map<VkFramebuffer, unique_ptr<FRAMEBUFFER_STATE>> frameBufferMap; 1635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkImage, vector<ImageSubresourcePair>> imageSubresourceMap; 1645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> imageLayoutMap; 165127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis unordered_map<VkRenderPass, unique_ptr<RENDER_PASS_STATE>> renderPassMap; 166918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes unordered_map<VkShaderModule, unique_ptr<shader_module>> shaderModuleMap; 1676246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski unordered_map<VkDescriptorUpdateTemplateKHR, unique_ptr<TEMPLATE_STATE>> desc_template_map; 16816a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes unordered_map<VkSwapchainKHR, std::unique_ptr<SWAPCHAIN_NODE>> swapchainMap; 16907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 170d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes VkDevice device = VK_NULL_HANDLE; 171ec85232c4d8d9ddf7d2ae57cb8203c5ab52c1106Mark Lobodzinski VkPhysicalDevice physical_device = VK_NULL_HANDLE; 1725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 173cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski instance_layer_data *instance_data = nullptr; // from device to enclosing instance 17407a464bd7fec9583f346b8c4b8d43c88d2e9ffa4Chris Forbes 175f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes VkPhysicalDeviceFeatures enabled_features = {}; 1765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Device specific data 177d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes PHYS_DEV_PROPERTIES_NODE phys_dev_properties = {}; 178d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes VkPhysicalDeviceMemoryProperties phys_dev_mem_props = {}; 179e47dbc3f3340fa177d877a67b2adb76a570027e5Mark Lobodzinski VkPhysicalDeviceProperties phys_dev_props = {}; 1805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 1815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 182b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis// TODO : Do we need to guard access to layer_data_map w/ lock? 183b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlisstatic unordered_map<void *, layer_data *> layer_data_map; 184f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic unordered_map<void *, instance_layer_data *> instance_layer_data_map; 185b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis 186b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Youngstatic uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION; 187b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 188e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wustatic const VkLayerProperties global_layer = { 189f1ea418f193d10a8455cdf47e0eeeeb1f4d8b5bfJon Ashburn "VK_LAYER_LUNARG_core_validation", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer", 190e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wu}; 1915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 192cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <class TCreateInfo> 193cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskivoid ValidateLayerOrdering(const TCreateInfo &createInfo) { 1945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool foundLayer = false; 1955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < createInfo.enabledLayerCount; ++i) { 196e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wu if (!strcmp(createInfo.ppEnabledLayerNames[i], global_layer.layerName)) { 1975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis foundLayer = true; 1985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This has to be logged to console as we don't have a callback at this point. 2005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!foundLayer && !strcmp(createInfo.ppEnabledLayerNames[0], "VK_LAYER_GOOGLE_unique_objects")) { 201bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski LOGCONSOLE("Cannot activate layer VK_LAYER_GOOGLE_unique_objects prior to activating %s.", global_layer.layerName); 2025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 2055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO : This can be much smarter, using separate locks for separate global data 207b9e992386a44404152747d66817a733aa127e281Jeremy Hayesstatic std::mutex global_lock; 208593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 20979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis// Return IMAGE_VIEW_STATE ptr for specified imageView or else NULL 2109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisIMAGE_VIEW_STATE *GetImageViewState(const layer_data *dev_data, VkImageView image_view) { 2112c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis auto iv_it = dev_data->imageViewMap.find(image_view); 2122c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis if (iv_it == dev_data->imageViewMap.end()) { 2132c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis return nullptr; 2142c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis } 2152c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis return iv_it->second.get(); 2162c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis} 2179a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis// Return sampler node ptr for specified sampler or else NULL 2189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSAMPLER_STATE *GetSamplerState(const layer_data *dev_data, VkSampler sampler) { 2192c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis auto sampler_it = dev_data->samplerMap.find(sampler); 2202c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis if (sampler_it == dev_data->samplerMap.end()) { 2219a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis return nullptr; 2229a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis } 2239a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis return sampler_it->second.get(); 2249a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis} 2255cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// Return image state ptr for specified image or else NULL 2269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisIMAGE_STATE *GetImageState(const layer_data *dev_data, VkImage image) { 2276d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis auto img_it = dev_data->imageMap.find(image); 2286d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (img_it == dev_data->imageMap.end()) { 2296d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis return nullptr; 2306d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis } 2316d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis return img_it->second.get(); 2326d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis} 2335cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// Return buffer state ptr for specified buffer or else NULL 2349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisBUFFER_STATE *GetBufferState(const layer_data *dev_data, VkBuffer buffer) { 2352c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis auto buff_it = dev_data->bufferMap.find(buffer); 2362c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis if (buff_it == dev_data->bufferMap.end()) { 2378718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis return nullptr; 2388718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis } 2398718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis return buff_it->second.get(); 2408718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis} 241b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis// Return swapchain node for specified swapchain or else NULL 2429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSWAPCHAIN_NODE *GetSwapchainNode(const layer_data *dev_data, VkSwapchainKHR swapchain) { 24316a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes auto swp_it = dev_data->swapchainMap.find(swapchain); 24416a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes if (swp_it == dev_data->swapchainMap.end()) { 245b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis return nullptr; 246b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis } 2473f687bf405355f3eec6bd1bc0e8d04daba37a0f9Tobin Ehlis return swp_it->second.get(); 248b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis} 2492f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis// Return buffer node ptr for specified buffer or else NULL 2509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisBUFFER_VIEW_STATE *GetBufferViewState(const layer_data *dev_data, VkBufferView buffer_view) { 25151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto bv_it = dev_data->bufferViewMap.find(buffer_view); 25251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (bv_it == dev_data->bufferViewMap.end()) { 2532f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis return nullptr; 2542f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis } 2552f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis return bv_it->second.get(); 2562f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis} 2578718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis 2589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisFENCE_NODE *GetFenceNode(layer_data *dev_data, VkFence fence) { 25966fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes auto it = dev_data->fenceMap.find(fence); 26066fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes if (it == dev_data->fenceMap.end()) { 26166fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes return nullptr; 26266fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes } 26366fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes return &it->second; 26466fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes} 26566fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes 2669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisEVENT_STATE *GetEventNode(layer_data *dev_data, VkEvent event) { 2679556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis auto it = dev_data->eventMap.find(event); 2689556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis if (it == dev_data->eventMap.end()) { 2699556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis return nullptr; 2709556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis } 2719556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis return &it->second; 2729556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis} 2739556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis 2749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisQUERY_POOL_NODE *GetQueryPoolNode(layer_data *dev_data, VkQueryPool query_pool) { 275ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis auto it = dev_data->queryPoolMap.find(query_pool); 276ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis if (it == dev_data->queryPoolMap.end()) { 277ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis return nullptr; 278ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis } 279ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis return &it->second; 280ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis} 281ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis 2829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisQUEUE_STATE *GetQueueState(layer_data *dev_data, VkQueue queue) { 28366fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes auto it = dev_data->queueMap.find(queue); 28466fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes if (it == dev_data->queueMap.end()) { 28566fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes return nullptr; 28666fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes } 28766fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes return &it->second; 28866fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes} 28966fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes 2909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSEMAPHORE_NODE *GetSemaphoreNode(layer_data *dev_data, VkSemaphore semaphore) { 2915e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes auto it = dev_data->semaphoreMap.find(semaphore); 2925e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes if (it == dev_data->semaphoreMap.end()) { 2935e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes return nullptr; 2945e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes } 2955e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes return &it->second; 2965e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes} 2975e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes 2989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisCOMMAND_POOL_NODE *GetCommandPoolNode(layer_data *dev_data, VkCommandPool pool) { 2998d6a38de0389036581ada119e548180c614fe0efChris Forbes auto it = dev_data->commandPoolMap.find(pool); 3008d6a38de0389036581ada119e548180c614fe0efChris Forbes if (it == dev_data->commandPoolMap.end()) { 3018d6a38de0389036581ada119e548180c614fe0efChris Forbes return nullptr; 3028d6a38de0389036581ada119e548180c614fe0efChris Forbes } 3038d6a38de0389036581ada119e548180c614fe0efChris Forbes return &it->second; 3048d6a38de0389036581ada119e548180c614fe0efChris Forbes} 3053bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes 3069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisPHYSICAL_DEVICE_STATE *GetPhysicalDeviceState(instance_layer_data *instance_data, VkPhysicalDevice phys) { 307f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes auto it = instance_data->physical_device_map.find(phys); 308f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes if (it == instance_data->physical_device_map.end()) { 3093bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes return nullptr; 3103bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes } 3113bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes return &it->second; 3123bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes} 3133bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes 3149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSURFACE_STATE *GetSurfaceState(instance_layer_data *instance_data, VkSurfaceKHR surface) { 315747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes auto it = instance_data->surface_map.find(surface); 316747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (it == instance_data->surface_map.end()) { 317747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return nullptr; 318747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 319747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return &it->second; 320747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 321747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 322d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris ForbesDeviceExtensions const *GetEnabledExtensions(layer_data const *dev_data) { 323d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes return &dev_data->extensions; 324d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes} 325d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes 326f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// Return ptr to memory binding for given handle of specified type 3277a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic BINDABLE *GetObjectMemBinding(layer_data *dev_data, uint64_t handle, VulkanObjectType type) { 3285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (type) { 3297a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski case kVulkanObjectTypeImage: 3309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return GetImageState(dev_data, VkImage(handle)); 3317a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski case kVulkanObjectTypeBuffer: 3329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return GetBufferState(dev_data, VkBuffer(handle)); 333cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 334cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 33694c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis return nullptr; 3375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis// prototype 3399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisGLOBAL_CB_NODE *GetCBNode(layer_data const *, const VkCommandBuffer); 34072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis 3415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return ptr to info in map container containing mem, or NULL if not found 3425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Calls to this function should be wrapped in mutex 3439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisDEVICE_MEM_INFO *GetMemObjInfo(const layer_data *dev_data, const VkDeviceMemory mem) { 34457fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis auto mem_it = dev_data->memObjMap.find(mem); 34557fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_it == dev_data->memObjMap.end()) { 3465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 3475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 34857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis return mem_it->second.get(); 3495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 3505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 35151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void add_mem_obj_info(layer_data *dev_data, void *object, const VkDeviceMemory mem, 3525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkMemoryAllocateInfo *pAllocateInfo) { 3535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(object != NULL); 3545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 35551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->memObjMap[mem] = unique_ptr<DEVICE_MEM_INFO>(new DEVICE_MEM_INFO(object, mem, pAllocateInfo)); 3565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 357dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis 358cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given bound_object_handle, bound to given mem allocation, verify that the range for the bound object is valid 3597a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic bool ValidateMemoryIsValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t bound_object_handle, VulkanObjectType type, 3607a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski const char *functionName) { 3619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 362f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis if (mem_info) { 363f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis if (!mem_info->bound_ranges[bound_object_handle].valid) { 364f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 3659b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM", 366dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis "%s: Cannot read invalid region of memory allocation 0x%" PRIx64 " for bound %s object 0x%" PRIx64 367dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis ", please fill the memory before using.", 3689b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus functionName, HandleToUint64(mem), object_string[type], bound_object_handle); 369f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis } 370f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis } 371f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis return false; 372f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 3731facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// For given image_state 3741facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// If mem is special swapchain key, then verify that image_state valid member is true 375f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// Else verify that the image's bound memory range is valid 37660568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinskibool ValidateImageMemoryIsValid(layer_data *dev_data, IMAGE_STATE *image_state, const char *functionName) { 377e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_state->binding.mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 3781facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (!image_state->valid) { 379f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 3809b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(image_state->binding.mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM", 381414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "%s: Cannot read invalid swapchain image 0x%" PRIx64 ", please fill the memory before using.", 3829b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus functionName, HandleToUint64(image_state->image)); 3835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 3859b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus return ValidateMemoryIsValid(dev_data, image_state->binding.mem, HandleToUint64(image_state->image), kVulkanObjectTypeImage, 3869b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus functionName); 3875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 3895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 3905cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// For given buffer_state, verify that the range it's bound to is valid 391c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskibool ValidateBufferMemoryIsValid(layer_data *dev_data, BUFFER_STATE *buffer_state, const char *functionName) { 3929b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus return ValidateMemoryIsValid(dev_data, buffer_state->binding.mem, HandleToUint64(buffer_state->buffer), kVulkanObjectTypeBuffer, 3939b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus functionName); 394f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 395f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For the given memory allocation, set the range bound by the given handle object to the valid param value 396f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic void SetMemoryValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, bool valid) { 3979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 398f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis if (mem_info) { 399f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis mem_info->bound_ranges[handle].valid = valid; 400f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis } 401f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 402f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given image node 4031facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// If mem is special swapchain key, then set entire image_state to valid param value 404f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// Else set the image's bound memory range to valid param value 405623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinskivoid SetImageMemoryValid(layer_data *dev_data, IMAGE_STATE *image_state, bool valid) { 406e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_state->binding.mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 4071facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->valid = valid; 4085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 4099b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus SetMemoryValid(dev_data, image_state->binding.mem, HandleToUint64(image_state->image), valid); 4105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 412f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given buffer node set the buffer's bound memory range to valid param value 413c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskivoid SetBufferMemoryValid(layer_data *dev_data, BUFFER_STATE *buffer_state, bool valid) { 4149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus SetMemoryValid(dev_data, buffer_state->binding.mem, HandleToUint64(buffer_state->buffer), valid); 415f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 416ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 41756f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given sampler and command buffer node 418d31a44af6da568692a73201825459689c9431867Tobin Ehlisvoid AddCommandBufferBindingSampler(GLOBAL_CB_NODE *cb_node, SAMPLER_STATE *sampler_state) { 419d31a44af6da568692a73201825459689c9431867Tobin Ehlis sampler_state->cb_bindings.insert(cb_node); 4209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus cb_node->object_bindings.insert({HandleToUint64(sampler_state->sampler), kVulkanObjectTypeSampler}); 42156f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis} 42256f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis 42356f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given image node and command buffer node 4241facd2c91911508b9fb61f54a56269841299f663Tobin Ehlisvoid AddCommandBufferBindingImage(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *image_state) { 425ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Skip validation if this image was created through WSI 426e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_state->binding.mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 427ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // First update CB binding in MemObj mini CB list 428d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis for (auto mem_binding : image_state->GetBoundMemory()) { 4299a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem_binding); 430d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis if (pMemInfo) { 431d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis pMemInfo->cb_bindings.insert(cb_node); 432d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis // Now update CBInfo's Mem reference list 433d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis cb_node->memObjs.insert(mem_binding); 434d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis } 435ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } 436f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis // Now update cb binding for image 4379b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus cb_node->object_bindings.insert({HandleToUint64(image_state->image), kVulkanObjectTypeImage}); 4381facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->cb_bindings.insert(cb_node); 439ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } 440ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis} 441ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 44203ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis// Create binding link between given image view node and its image with command buffer node 44303ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlisvoid AddCommandBufferBindingImageView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_VIEW_STATE *view_state) { 44403ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis // First add bindings for imageView 44503ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis view_state->cb_bindings.insert(cb_node); 4469b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus cb_node->object_bindings.insert({HandleToUint64(view_state->image_view), kVulkanObjectTypeImageView}); 4479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, view_state->create_info.image); 44803ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis // Add bindings for image within imageView 4491facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state) { 4501facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis AddCommandBufferBindingImage(dev_data, cb_node, image_state); 45103ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis } 45203ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis} 45303ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis 454ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis// Create binding link between given buffer node and command buffer node 4555cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlisvoid AddCommandBufferBindingBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) { 456ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // First update CB binding in MemObj mini CB list 4575cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis for (auto mem_binding : buffer_state->GetBoundMemory()) { 4589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem_binding); 459d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis if (pMemInfo) { 460d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis pMemInfo->cb_bindings.insert(cb_node); 461d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis // Now update CBInfo's Mem reference list 462d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis cb_node->memObjs.insert(mem_binding); 463d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis } 464ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } 465ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Now update cb binding for buffer 4669b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus cb_node->object_bindings.insert({HandleToUint64(buffer_state->buffer), kVulkanObjectTypeBuffer}); 4675cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->cb_bindings.insert(cb_node); 468ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis} 469ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 47077b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis// Create binding link between given buffer view node and its buffer with command buffer node 47177b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlisvoid AddCommandBufferBindingBufferView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_VIEW_STATE *view_state) { 47277b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis // First add bindings for bufferView 47377b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis view_state->cb_bindings.insert(cb_node); 4749b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus cb_node->object_bindings.insert({HandleToUint64(view_state->buffer_view), kVulkanObjectTypeBufferView}); 4759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, view_state->create_info.buffer); 47677b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis // Add bindings for buffer within bufferView 4775cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 4785cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, buffer_state); 47977b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis } 48077b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis} 48177b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis 482400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis// For every mem obj bound to particular CB, free bindings related to that CB 483d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlisstatic void clear_cmd_buf_and_mem_references(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 484d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node) { 485d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node->memObjs.size() > 0) { 486d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto mem : cb_node->memObjs) { 4879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pInfo = GetMemObjInfo(dev_data, mem); 4885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pInfo) { 489d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis pInfo->cb_bindings.erase(cb_node); 4905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 492d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis cb_node->memObjs.clear(); 4935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 494d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis cb_node->validate_functions.clear(); 4955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 4975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 498f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// Clear a single object binding from given memory object, or report error if binding is missing 4997a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic bool ClearMemoryObjectBinding(layer_data *dev_data, uint64_t handle, VulkanObjectType type, VkDeviceMemory mem) { 5009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 501f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // This obj is bound to a memory object. Remove the reference to this object in that memory object's list 502d4cd34fd49caa759cf01cafa5fa271401b17c3b9Jeremy Hayes if (mem_info) { 503d4cd34fd49caa759cf01cafa5fa271401b17c3b9Jeremy Hayes mem_info->obj_bindings.erase({handle, type}); 504f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis } 505f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis return false; 506f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis} 507f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis 508f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// ClearMemoryObjectBindings clears the binding of objects to memory 509f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// For the given object it pulls the memory bindings and makes sure that the bindings 510f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// no longer refer to the object being cleared. This occurs when objects are destroyed. 5117a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskibool ClearMemoryObjectBindings(layer_data *dev_data, uint64_t handle, VulkanObjectType type) { 512f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis bool skip = false; 513f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 514f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (mem_binding) { 515f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (!mem_binding->sparse) { 516f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis skip = ClearMemoryObjectBinding(dev_data, handle, type, mem_binding->binding.mem); 517cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Sparse, clear all bindings 518bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &sparse_mem_binding : mem_binding->sparse_bindings) { 519f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis skip |= ClearMemoryObjectBinding(dev_data, handle, type, sparse_mem_binding.mem); 5205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 523f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis return skip; 5245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 5255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 526888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// For given mem object, verify that it is not null or UNBOUND, if it is, report error. Return skip value. 527888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisbool VerifyBoundMemoryIsValid(const layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, const char *api_name, 52835ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis const char *type_name, UNIQUE_VALIDATION_ERROR_CODE error_code) { 529888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis bool result = false; 530888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (VK_NULL_HANDLE == mem) { 531888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle, 532cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, error_code, "MEM", "%s: Vk%s object 0x%" PRIxLEAST64 533cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " used with no memory bound. Memory should be bound by calling " 534cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkBind%sMemory(). %s", 53535ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis api_name, type_name, handle, type_name, validation_error_map[error_code]); 536888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis } else if (MEMORY_UNBOUND == mem) { 537888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle, 538cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, error_code, "MEM", "%s: Vk%s object 0x%" PRIxLEAST64 539cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " used with no memory bound and previously bound memory was freed. " 540cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Memory must not be freed prior to this operation. %s", 54135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis api_name, type_name, handle, validation_error_map[error_code]); 542888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis } 543888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis return result; 544888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis} 545888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis 546b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was ever bound to this image 54735ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlisbool ValidateMemoryIsBoundToImage(const layer_data *dev_data, const IMAGE_STATE *image_state, const char *api_name, 54835ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 549b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski bool result = false; 5501facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (0 == (static_cast<uint32_t>(image_state->createInfo.flags) & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) { 5519b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus result = VerifyBoundMemoryIsValid(dev_data, image_state->binding.mem, HandleToUint64(image_state->image), api_name, "Image", 5529b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus error_code); 553b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski } 554b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski return result; 555b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski} 556b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 557b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was bound to this buffer 55835ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlisbool ValidateMemoryIsBoundToBuffer(const layer_data *dev_data, const BUFFER_STATE *buffer_state, const char *api_name, 55935ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 560b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski bool result = false; 5615cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (0 == (static_cast<uint32_t>(buffer_state->createInfo.flags) & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)) { 5629b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus result = VerifyBoundMemoryIsValid(dev_data, buffer_state->binding.mem, HandleToUint64(buffer_state->buffer), api_name, 5639b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Buffer", error_code); 564b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski } 565b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski return result; 566b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski} 567b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 5683a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// SetMemBinding is used to establish immutable, non-sparse binding between a single image/buffer object and memory object. 5693a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Corresponding valid usage checks are in ValidateSetMemBinding(). 5707a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic void SetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VulkanObjectType type, const char *apiName) { 571c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (mem != VK_NULL_HANDLE) { 572c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 573c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton assert(mem_binding); 574c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 575c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (mem_info) { 576c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton mem_info->obj_bindings.insert({handle, type}); 577c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // For image objects, make sure default memory state is correctly set 578c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // TODO : What's the best/correct way to handle this? 5797a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski if (kVulkanObjectTypeImage == type) { 580c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton auto const image_state = GetImageState(dev_data, VkImage(handle)); 581c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (image_state) { 582c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton VkImageCreateInfo ici = image_state->createInfo; 583c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (ici.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { 584c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // TODO:: More memory state transition stuff. 585c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 586c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 587c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 588c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton mem_binding->binding.mem = mem; 589c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 590c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 591c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton} 5923a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton 5933a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Valid usage checks for a call to SetMemBinding(). 5943a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// For NULL mem case, output warning 5953a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Make sure given object is in global object map 5963a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// IF a previous binding existed, output validation error 5973a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Otherwise, add reference from objectInfo to memoryInfo 5983a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Add reference off of objInfo 5993a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// TODO: We may need to refactor or pass in multiple valid usage statements to handle multiple valid usage conditions. 6007a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic bool ValidateSetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VulkanObjectType type, 601c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton const char *apiName) { 6023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 603f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // It's an error to bind an object to NULL memory 604d3876b4ff7c293a14f73fe3622513d1fa91bf2d0Jeremy Hayes if (mem != VK_NULL_HANDLE) { 605f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 606888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis assert(mem_binding); 60710ffe2d353eaff714ed92a2835af77d8b5042d31Cort if (mem_binding->sparse) { 608315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_1740082a; 60910ffe2d353eaff714ed92a2835af77d8b5042d31Cort const char *handle_type = "IMAGE"; 61074300755ed9ec780d6073af71e47f201217008d6Cort Stratton if (strcmp(apiName, "vkBindBufferMemory()") == 0) { 611315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis error_code = VALIDATION_ERROR_1700080c; 61210ffe2d353eaff714ed92a2835af77d8b5042d31Cort handle_type = "BUFFER"; 61310ffe2d353eaff714ed92a2835af77d8b5042d31Cort } else { 61474300755ed9ec780d6073af71e47f201217008d6Cort Stratton assert(strcmp(apiName, "vkBindImageMemory()") == 0); 61510ffe2d353eaff714ed92a2835af77d8b5042d31Cort } 6163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 6179b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem), __LINE__, error_code, "MEM", 6183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 6193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") which was created with sparse memory flags (VK_%s_CREATE_SPARSE_*_BIT). %s", 6209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus apiName, HandleToUint64(mem), handle, handle_type, validation_error_map[error_code]); 62110ffe2d353eaff714ed92a2835af77d8b5042d31Cort } 6229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 623888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (mem_info) { 6249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *prev_binding = GetMemObjInfo(dev_data, mem_binding->binding.mem); 625888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (prev_binding) { 626315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_17400828; 62774300755ed9ec780d6073af71e47f201217008d6Cort Stratton if (strcmp(apiName, "vkBindBufferMemory()") == 0) { 628315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis error_code = VALIDATION_ERROR_1700080a; 62998c2a17e1a549df84f4239f619bc0955f632cb43Cort } else { 63074300755ed9ec780d6073af71e47f201217008d6Cort Stratton assert(strcmp(apiName, "vkBindImageMemory()") == 0); 63198c2a17e1a549df84f4239f619bc0955f632cb43Cort } 6323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 6339b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem), __LINE__, error_code, "MEM", 6343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 6353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") which has already been bound to mem object 0x%" PRIxLEAST64 ". %s", 6369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus apiName, HandleToUint64(mem), handle, HandleToUint64(prev_binding->mem), 6373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[error_code]); 638f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis } else if (mem_binding->binding.mem == MEMORY_UNBOUND) { 6393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 6409b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem), __LINE__, MEMTRACK_REBIND_OBJECT, "MEM", 6413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 6423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") which was previous bound to memory that has since been freed. Memory bindings are immutable in " 6433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Vulkan so this attempt to bind to new memory is not allowed.", 6449b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus apiName, HandleToUint64(mem), handle); 6455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 6495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 6505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For NULL mem case, clear any previous binding Else... 6525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Make sure given object is in its object map 6535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// IF a previous binding existed, update binding 6545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Add reference from objectInfo to memoryInfo 6555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Add reference off of object's binding info 6560a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes// Return VK_TRUE if addition is successful, VK_FALSE otherwise 657ece0e981ee4a5ad2572d146a89fc64d699d79f36Chris Forbesstatic bool SetSparseMemBinding(layer_data *dev_data, MEM_BINDING binding, uint64_t handle, VulkanObjectType type) { 6583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = VK_FALSE; 6595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Handle NULL case separately, just clear previous binding & decrement reference 660f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (binding.mem == VK_NULL_HANDLE) { 661f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // TODO : This should cause the range of the resource to be unbound according to spec 6625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 663f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 664f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis assert(mem_binding); 665f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis assert(mem_binding->sparse); 6669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, binding.mem); 667f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (mem_info) { 668f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis mem_info->obj_bindings.insert({handle, type}); 6692e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis // Need to set mem binding for this object 670f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis mem_binding->sparse_bindings.insert(binding); 6715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 674caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis} 675caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis 6765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Check object status for selected flag state 67751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool validate_status(layer_data *dev_data, GLOBAL_CB_NODE *pNode, CBStatusFlags status_mask, VkFlags msg_flags, 6784f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes const char *fail_msg, UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 6793d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (!(pNode->status & status_mask)) { 6804f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes char const *const message = validation_error_map[msg_code]; 68151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis return log_msg(dev_data->report_data, msg_flags, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6829b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pNode->commandBuffer), __LINE__, msg_code, "DS", "command buffer object 0x%p: %s. %s.", 6839b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus pNode->commandBuffer, fail_msg, message); 6845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 685e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 6865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 6875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Retrieve pipeline node ptr for given pipeline object 68951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_STATE *getPipelineState(layer_data const *dev_data, VkPipeline pipeline) { 69051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->pipelineMap.find(pipeline); 69151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->pipelineMap.end()) { 692ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes return nullptr; 6935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 694ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes return it->second; 6955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 6965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisRENDER_PASS_STATE *GetRenderPassState(layer_data const *dev_data, VkRenderPass renderpass) { 69851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->renderPassMap.find(renderpass); 69951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->renderPassMap.end()) { 70016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return nullptr; 70116387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes } 702fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes return it->second.get(); 70316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes} 70416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes 7059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisFRAMEBUFFER_STATE *GetFramebufferState(const layer_data *dev_data, VkFramebuffer framebuffer) { 70651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->frameBufferMap.find(framebuffer); 70751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->frameBufferMap.end()) { 708f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes return nullptr; 709f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes } 71004861caca7eb93a5241b164e8480bb93c826902cTobin Ehlis return it->second.get(); 711f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes} 712f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes 7139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehliscvdescriptorset::DescriptorSetLayout const *GetDescriptorSetLayout(layer_data const *dev_data, VkDescriptorSetLayout dsLayout) { 71451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->descriptorSetLayoutMap.find(dsLayout); 71551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->descriptorSetLayoutMap.end()) { 71611f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes return nullptr; 71711f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes } 718c8bee427d7a8ed0ccec899fbf47134d582dcafbdGabríel Arthúr Pétursson return it->second.get(); 71911f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes} 72011f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes 72151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_LAYOUT_NODE const *getPipelineLayout(layer_data const *dev_data, VkPipelineLayout pipeLayout) { 72251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->pipelineLayoutMap.find(pipeLayout); 72351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->pipelineLayoutMap.end()) { 7244a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes return nullptr; 7254a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes } 7264a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes return &it->second; 7274a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes} 7284a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes 729d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbesshader_module const *GetShaderModuleState(layer_data const *dev_data, VkShaderModule module) { 730d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes auto it = dev_data->shaderModuleMap.find(module); 731d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes if (it == dev_data->shaderModuleMap.end()) { 732d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes return nullptr; 733d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes } 734d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes return it->second.get(); 735d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes} 736d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes 737e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if for a given PSO, the given state enum is dynamic, else return false 7384c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool isDynamic(const PIPELINE_STATE *pPipeline, const VkDynamicState state) { 7395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) { 7405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pPipeline->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) { 741cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (state == pPipeline->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) return true; 7425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 744e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 7455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 7465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate state stored as flags at time of draw call 7484f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayesstatic bool validate_draw_state_flags(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const PIPELINE_STATE *pPipe, bool indexed, 7494f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 7509c4006684a13db43f0dbc8d0015a9ef34872ca09Chris Forbes bool result = false; 751ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (pPipe->graphicsPipelineCI.pInputAssemblyState && 752ca546210846c65808717f8875deae39bd227c240Tobin Ehlis ((pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) || 753ca546210846c65808717f8875deae39bd227c240Tobin Ehlis (pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP))) { 7543d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_LINE_WIDTH_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7554f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic line width state not set for this command buffer", msg_code); 7563d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 75745824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pRasterizationState && 75845824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pRasterizationState->depthBiasEnable == VK_TRUE)) { 7593d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BIAS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7604f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic depth bias state not set for this command buffer", msg_code); 7613d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 7623d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipe->blendConstantsEnabled) { 7633d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_BLEND_CONSTANTS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7644f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic blend constants state not set for this command buffer", msg_code); 7653d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 76645824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pDepthStencilState && 76745824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE)) { 7683d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BOUNDS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7694f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic depth bounds state not set for this command buffer", msg_code); 7703d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 77145824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pDepthStencilState && 77245824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pDepthStencilState->stencilTestEnable == VK_TRUE)) { 7733d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_READ_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7744f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil read mask state not set for this command buffer", msg_code); 7753d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7764f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil write mask state not set for this command buffer", msg_code); 7773d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_REFERENCE_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7784f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil reference state not set for this command buffer", msg_code); 7793d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 7801c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (indexed) { 7813d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_INDEX_BUFFER_BOUND, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7824f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Index buffer object not bound to this command buffer when Indexed Draw attempted", msg_code); 7833d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 7844f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes 7855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 7865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 7875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify attachment reference compatibility according to spec 7895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// If one array is larger, treat missing elements of shorter array as VK_ATTACHMENT_UNUSED & other array much match this 7905ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski// If both AttachmentReference arrays have requested index, check their corresponding AttachmentDescriptions 7915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// to make sure that format and samples counts match. 7925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// If not, they are not compatible. 7935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic bool attachment_references_compatible(const uint32_t index, const VkAttachmentReference *pPrimary, 7945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const uint32_t primaryCount, const VkAttachmentDescription *pPrimaryAttachments, 7955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkAttachmentReference *pSecondary, const uint32_t secondaryCount, 7965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkAttachmentDescription *pSecondaryAttachments) { 797e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis // Check potential NULL cases first to avoid nullptr issues later 798e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis if (pPrimary == nullptr) { 799e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis if (pSecondary == nullptr) { 800e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return true; 801e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } 802e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return false; 803e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } else if (pSecondary == nullptr) { 804e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return false; 805e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } 806cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (index >= primaryCount) { // Check secondary as if primary is VK_ATTACHMENT_UNUSED 807cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (VK_ATTACHMENT_UNUSED == pSecondary[index].attachment) return true; 808cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (index >= secondaryCount) { // Check primary as if secondary is VK_ATTACHMENT_UNUSED 809cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (VK_ATTACHMENT_UNUSED == pPrimary[index].attachment) return true; 810cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Format and sample count must match 8115ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) && (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) { 8125ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski return true; 8135ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski } else if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) || (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) { 8145ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski return false; 8155ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski } 8165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((pPrimaryAttachments[pPrimary[index].attachment].format == 8175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSecondaryAttachments[pSecondary[index].attachment].format) && 8185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pPrimaryAttachments[pPrimary[index].attachment].samples == 8195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSecondaryAttachments[pSecondary[index].attachment].samples)) 8205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return true; 8215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Format and sample counts didn't match 8235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 8245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 825a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// TODO : Scrub verify_renderpass_compatibility() and validateRenderPassCompatibility() and unify them and/or share code 826266231a5421564c314f6b5d5bd3fed26fd389484Chris Forbes// For given primary RenderPass object and secondary RenderPassCreateInfo, verify that they're compatible 82751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verify_renderpass_compatibility(const layer_data *dev_data, const VkRenderPassCreateInfo *primaryRPCI, 8288da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis const VkRenderPassCreateInfo *secondaryRPCI, string &errorMsg) { 8295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryRPCI->subpassCount != secondaryRPCI->subpassCount) { 830c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 8315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "RenderPass for primary cmdBuffer has " << primaryRPCI->subpassCount 8325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis << " subpasses but renderPass for secondary cmdBuffer has " << secondaryRPCI->subpassCount << " subpasses."; 8335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 8345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 8355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t spIndex = 0; 8375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (spIndex = 0; spIndex < primaryRPCI->subpassCount; ++spIndex) { 8385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // For each subpass, verify that corresponding color, input, resolve & depth/stencil attachment references are compatible 8395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primaryColorCount = primaryRPCI->pSubpasses[spIndex].colorAttachmentCount; 8405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t secondaryColorCount = secondaryRPCI->pSubpasses[spIndex].colorAttachmentCount; 8415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t colorMax = std::max(primaryColorCount, secondaryColorCount); 8425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t cIdx = 0; cIdx < colorMax; ++cIdx) { 8435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pColorAttachments, primaryColorCount, 8445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pColorAttachments, 8455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 846c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 8475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "color attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible."; 8485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 8495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 8505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pResolveAttachments, 8515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryColorCount, primaryRPCI->pAttachments, 8525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryRPCI->pSubpasses[spIndex].pResolveAttachments, 8535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 854c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 8555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "resolve attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible."; 8565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 8575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 8585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 860fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 861bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (!attachment_references_compatible(0, primaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 1, 862bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 863fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 1, secondaryRPCI->pAttachments)) { 864c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 865fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes errorStr << "depth/stencil attachments of subpass index " << spIndex << " are not compatible."; 866fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes errorMsg = errorStr.str(); 867fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes return false; 868fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes } 869fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 8705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primaryInputCount = primaryRPCI->pSubpasses[spIndex].inputAttachmentCount; 8715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t secondaryInputCount = secondaryRPCI->pSubpasses[spIndex].inputAttachmentCount; 8725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t inputMax = std::max(primaryInputCount, secondaryInputCount); 8735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < inputMax; ++i) { 8741e49a9dd0518c3cd335dd040218aa9c25d7cb600Tobin Ehlis if (!attachment_references_compatible(i, primaryRPCI->pSubpasses[spIndex].pInputAttachments, primaryInputCount, 8755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pInputAttachments, 8761e49a9dd0518c3cd335dd040218aa9c25d7cb600Tobin Ehlis secondaryInputCount, secondaryRPCI->pAttachments)) { 877c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 8785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "input attachments at index " << i << " of subpass index " << spIndex << " are not compatible."; 8795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 8805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 8815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return true; 8855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 8865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Set node ptr for specified set or else NULL 8889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehliscvdescriptorset::DescriptorSet *GetSetNode(const layer_data *dev_data, VkDescriptorSet set) { 88951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto set_it = dev_data->setMap.find(set); 89051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (set_it == dev_data->setMap.end()) { 8915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 8925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 893104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis return set_it->second; 8945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 8955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 896eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// For given pipeline, return number of MSAA samples, or one if MSAA disabled 8974c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic VkSampleCountFlagBits getNumSamples(PIPELINE_STATE const *pipe) { 898ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes if (pipe->graphicsPipelineCI.pMultisampleState != NULL && 899ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO == pipe->graphicsPipelineCI.pMultisampleState->sType) { 900eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young return pipe->graphicsPipelineCI.pMultisampleState->rasterizationSamples; 901eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 902eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young return VK_SAMPLE_COUNT_1_BIT; 903eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young} 904eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 905bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void list_bits(std::ostream &s, uint32_t bits) { 906b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes for (int i = 0; i < 32 && bits; i++) { 907b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (bits & (1 << i)) { 908b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes s << i; 909b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes bits &= ~(1 << i); 910b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (bits) { 911b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes s << ","; 912b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 913b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 914b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 915b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes} 916b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 917eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// Validate draw-time state related to the PSO 91851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidatePipelineDrawtimeState(layer_data const *dev_data, LAST_BOUND_STATE const &state, const GLOBAL_CB_NODE *pCB, 9194c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE const *pPipeline) { 9203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 92129d196e071b2dc1db47702085469396f2b956820Chris Forbes 922d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen // Verify vertex binding 92329d196e071b2dc1db47702085469396f2b956820Chris Forbes if (pPipeline->vertexBindingDescriptions.size() > 0) { 92429d196e071b2dc1db47702085469396f2b956820Chris Forbes for (size_t i = 0; i < pPipeline->vertexBindingDescriptions.size(); i++) { 925312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis auto vertex_binding = pPipeline->vertexBindingDescriptions[i].binding; 926312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis if ((pCB->currentDrawData.buffers.size() < (vertex_binding + 1)) || 927312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis (pCB->currentDrawData.buffers[vertex_binding] == VK_NULL_HANDLE)) { 9283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 929df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9309b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", 931cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "The Pipeline State Object (0x%" PRIxLEAST64 932cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") expects that this Command Buffer's vertex binding Index %u " 933cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct " 934cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "at index " PRINTF_SIZE_T_SPECIFIER " of pVertexBindingDescriptions has a binding value of %u.", 9359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(state.pipeline_state->pipeline), vertex_binding, i, vertex_binding); 93629d196e071b2dc1db47702085469396f2b956820Chris Forbes } 93729d196e071b2dc1db47702085469396f2b956820Chris Forbes } 93829d196e071b2dc1db47702085469396f2b956820Chris Forbes } else { 93958b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (!pCB->currentDrawData.buffers.empty() && !pCB->vertex_buffer_used) { 9403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 9419b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(pCB->commandBuffer), __LINE__, 9429b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", 9433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Vertex buffers are bound to command buffer (0x%p" 9443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") but no vertex buffers are attached to this Pipeline State Object (0x%" PRIxLEAST64 ").", 9459b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus pCB->commandBuffer, HandleToUint64(state.pipeline_state->pipeline)); 94629d196e071b2dc1db47702085469396f2b956820Chris Forbes } 94729d196e071b2dc1db47702085469396f2b956820Chris Forbes } 94829d196e071b2dc1db47702085469396f2b956820Chris Forbes // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count. 94929d196e071b2dc1db47702085469396f2b956820Chris Forbes // Skip check if rasterization is disabled or there is no viewport. 95029d196e071b2dc1db47702085469396f2b956820Chris Forbes if ((!pPipeline->graphicsPipelineCI.pRasterizationState || 95129d196e071b2dc1db47702085469396f2b956820Chris Forbes (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) && 95229d196e071b2dc1db47702085469396f2b956820Chris Forbes pPipeline->graphicsPipelineCI.pViewportState) { 95329d196e071b2dc1db47702085469396f2b956820Chris Forbes bool dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT); 95429d196e071b2dc1db47702085469396f2b956820Chris Forbes bool dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR); 955b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 95629d196e071b2dc1db47702085469396f2b956820Chris Forbes if (dynViewport) { 957b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto requiredViewportsMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->viewportCount) - 1; 958b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto missingViewportMask = ~pCB->viewportMask & requiredViewportsMask; 959b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (missingViewportMask) { 960b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes std::stringstream ss; 961b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes ss << "Dynamic viewport(s) "; 962b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes list_bits(ss, missingViewportMask); 963d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetViewport()."; 9643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 9653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "%s", ss.str().c_str()); 96629d196e071b2dc1db47702085469396f2b956820Chris Forbes } 96729d196e071b2dc1db47702085469396f2b956820Chris Forbes } 968b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 96929d196e071b2dc1db47702085469396f2b956820Chris Forbes if (dynScissor) { 970b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto requiredScissorMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->scissorCount) - 1; 971b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto missingScissorMask = ~pCB->scissorMask & requiredScissorMask; 972b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (missingScissorMask) { 973b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes std::stringstream ss; 974b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes ss << "Dynamic scissor(s) "; 975b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes list_bits(ss, missingScissorMask); 976d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetScissor()."; 9773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 9783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "%s", ss.str().c_str()); 97929d196e071b2dc1db47702085469396f2b956820Chris Forbes } 98029d196e071b2dc1db47702085469396f2b956820Chris Forbes } 98129d196e071b2dc1db47702085469396f2b956820Chris Forbes } 98229d196e071b2dc1db47702085469396f2b956820Chris Forbes 98329d196e071b2dc1db47702085469396f2b956820Chris Forbes // Verify that any MSAA request in PSO matches sample# in bound FB 98429d196e071b2dc1db47702085469396f2b956820Chris Forbes // Skip the check if rasterization is disabled. 98529d196e071b2dc1db47702085469396f2b956820Chris Forbes if (!pPipeline->graphicsPipelineCI.pRasterizationState || 98629d196e071b2dc1db47702085469396f2b956820Chris Forbes (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) { 98729d196e071b2dc1db47702085469396f2b956820Chris Forbes VkSampleCountFlagBits pso_num_samples = getNumSamples(pPipeline); 98829d196e071b2dc1db47702085469396f2b956820Chris Forbes if (pCB->activeRenderPass) { 989fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const render_pass_info = pCB->activeRenderPass->createInfo.ptr(); 99029d196e071b2dc1db47702085469396f2b956820Chris Forbes const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pCB->activeSubpass]; 99129d196e071b2dc1db47702085469396f2b956820Chris Forbes uint32_t i; 99276957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes unsigned subpass_num_samples = 0; 9930a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes 99429d196e071b2dc1db47702085469396f2b956820Chris Forbes for (i = 0; i < subpass_desc->colorAttachmentCount; i++) { 99576957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes auto attachment = subpass_desc->pColorAttachments[i].attachment; 99676957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes if (attachment != VK_ATTACHMENT_UNUSED) 99776957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples; 99829d196e071b2dc1db47702085469396f2b956820Chris Forbes } 9990a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes 100076957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes if (subpass_desc->pDepthStencilAttachment && 100176957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 100276957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes auto attachment = subpass_desc->pDepthStencilAttachment->attachment; 100376957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples; 100429d196e071b2dc1db47702085469396f2b956820Chris Forbes } 1005eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 10060dc3fd4e57b8531638781daa01a2fb5d1048a6fbJamie Madill if (subpass_num_samples && static_cast<unsigned>(pso_num_samples) != subpass_num_samples) { 10073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 10089b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS", 10099b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Num samples mismatch! At draw-time in Pipeline (0x%" PRIxLEAST64 10109b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus ") with %u samples while current RenderPass (0x%" PRIxLEAST64 ") w/ %u samples!", 10119b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->pipeline), pso_num_samples, 10129b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->activeRenderPass->renderPass), subpass_num_samples); 1013eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 101429d196e071b2dc1db47702085469396f2b956820Chris Forbes } else { 10153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 10169b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS", 10173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "No active render pass found at draw-time in Pipeline (0x%" PRIxLEAST64 ")!", 10189b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->pipeline)); 1019eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 1020eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 1021528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis // Verify that PSO creation renderPass is compatible with active renderPass 1022528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis if (pCB->activeRenderPass) { 1023528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis std::string err_string; 1024a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if ((pCB->activeRenderPass->renderPass != pPipeline->graphicsPipelineCI.renderPass) && 102551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(), pPipeline->render_pass_ci.ptr(), 1026528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis err_string)) { 1027528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis // renderPass that PSO was created with must be compatible with active renderPass that PSO is being used with 10283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 10299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 10309b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "At Draw time the active render pass (0x%" PRIxLEAST64 10319b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus ") is incompatible w/ gfx pipeline " 10329b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "(0x%" PRIxLEAST64 ") that was created w/ render pass (0x%" PRIxLEAST64 ") due to: %s", 10339b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->activeRenderPass->renderPass), HandleToUint64(pPipeline->pipeline), 10349b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->graphicsPipelineCI.renderPass), err_string.c_str()); 1035528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis } 1036c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes 1037c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes if (pPipeline->graphicsPipelineCI.subpass != pCB->activeSubpass) { 10383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 10399b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 10409b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Pipeline was built for subpass %u but used in subpass %u", pPipeline->graphicsPipelineCI.subpass, 10413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCB->activeSubpass); 1042c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes } 1043528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis } 104429d196e071b2dc1db47702085469396f2b956820Chris Forbes // TODO : Add more checks here 104529d196e071b2dc1db47702085469396f2b956820Chris Forbes 10463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 1047eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young} 1048eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 1049d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes// For given cvdescriptorset::DescriptorSet, verify that its Set is compatible w/ the setLayout corresponding to 1050d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes// pipelineLayout[layoutIndex] 1051d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbesstatic bool verify_set_layout_compatibility(const cvdescriptorset::DescriptorSet *descriptor_set, 1052d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes PIPELINE_LAYOUT_NODE const *pipeline_layout, const uint32_t layoutIndex, 1053d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes string &errorMsg) { 1054d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes auto num_sets = pipeline_layout->set_layouts.size(); 1055d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes if (layoutIndex >= num_sets) { 1056d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes stringstream errorStr; 1057d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes errorStr << "VkPipelineLayout (" << pipeline_layout->layout << ") only contains " << num_sets 1058d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes << " setLayouts corresponding to sets 0-" << num_sets - 1 << ", but you're attempting to bind set to index " 1059d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes << layoutIndex; 1060d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes errorMsg = errorStr.str(); 1061d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes return false; 1062d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes } 1063d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes auto layout_node = pipeline_layout->set_layouts[layoutIndex]; 1064d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes return descriptor_set->IsCompatible(layout_node, &errorMsg); 1065d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes} 1066d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes 10675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate overall state at the time of a draw call 106851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const bool indexed, 10694f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes const VkPipelineBindPoint bind_point, const char *function, 10704f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 1071e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = false; 10721c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto const &state = cb_node->lastBound[bind_point]; 10734c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipe = state.pipeline_state; 107422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis if (nullptr == pPipe) { 107522fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis result |= log_msg( 1076df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 10779b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_PIPELINE, "DS", 107822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis "At Draw/Dispatch time no valid VkPipeline is bound! This is illegal. Please bind one with vkCmdBindPipeline()."); 107922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Early return as any further checks below will be busted w/o a pipeline 1080cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (result) return true; 108122fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 10823d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis // First check flag states 10831c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) 108451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result = validate_draw_state_flags(dev_data, cb_node, pPipe, indexed, msg_code); 10857a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis 10865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Now complete other state checks 108769b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis if (VK_NULL_HANDLE != state.pipeline_layout.layout) { 108822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis string errorString; 108969b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis auto pipeline_layout = pPipe->pipeline_layout; 1090169c4506062f06d6676eb4da3c9e0437d1d9d659Chris Forbes 10911c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (const auto &set_binding_pair : pPipe->active_slots) { 10921c130ea631a82716dc7334de17767536525f2292Tobin Ehlis uint32_t setIndex = set_binding_pair.first; 109322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // If valid set is not bound throw an error 109422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis if ((state.boundDescriptorSets.size() <= setIndex) || (!state.boundDescriptorSets[setIndex])) { 10959b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus result |= 10969b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 10979b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS", 10989b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "VkPipeline 0x%" PRIxLEAST64 " uses set #%u but that set is not bound.", 10999b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipe->pipeline), setIndex); 110012b7fc342b53fbdd399aae4a85959e37685936acChris Forbes } else if (!verify_set_layout_compatibility(state.boundDescriptorSets[setIndex], &pipeline_layout, setIndex, 110169b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis errorString)) { 110269b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis // Set is bound but not compatible w/ overlapping pipeline_layout from PSO 110371511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis VkDescriptorSet setHandle = state.boundDescriptorSets[setIndex]->GetSet(); 110422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis result |= 110551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 11069b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(setHandle), __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS", 1107414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "VkDescriptorSet (0x%" PRIxLEAST64 1108414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") bound as set #%u is not compatible with overlapping VkPipelineLayout 0x%" PRIxLEAST64 " due to: %s", 11099b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(setHandle), setIndex, HandleToUint64(pipeline_layout.layout), errorString.c_str()); 1110cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Valid set is bound and layout compatible, validate that it's updated 111122fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Pull the set node 11121c130ea631a82716dc7334de17767536525f2292Tobin Ehlis cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex]; 11137433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis // Validate the draw-time state for this descriptor set 11147433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis std::string err_str; 11150db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis if (!descriptor_set->ValidateDrawState(set_binding_pair.second, state.dynamicOffsets[setIndex], cb_node, function, 11160db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis &err_str)) { 11171c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto set = descriptor_set->GetSet(); 11180db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis result |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 11199b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, HandleToUint64(set), __LINE__, 11209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 11210db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis "Descriptor set 0x%" PRIxLEAST64 " encountered the following validation error at %s time: %s", 11229b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(set), function, err_str.c_str()); 11237433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis } 11245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 112522fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 112622fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 1127eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 1128eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young // Check general pipeline state that needs to be validated at drawtime 112951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) result |= ValidatePipelineDrawtimeState(dev_data, state, cb_node, pPipe); 1130eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 11315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 11325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 11335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 113451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void UpdateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const VkPipelineBindPoint bind_point) { 11351c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto const &state = cb_state->lastBound[bind_point]; 1136ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis PIPELINE_STATE *pPipe = state.pipeline_state; 1137ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis if (VK_NULL_HANDLE != state.pipeline_layout.layout) { 11381c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (const auto &set_binding_pair : pPipe->active_slots) { 11391c130ea631a82716dc7334de17767536525f2292Tobin Ehlis uint32_t setIndex = set_binding_pair.first; 1140ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis // Pull the set node 11411c130ea631a82716dc7334de17767536525f2292Tobin Ehlis cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex]; 1142ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis // Bind this set and its active descriptor resources to the command buffer 11431c130ea631a82716dc7334de17767536525f2292Tobin Ehlis descriptor_set->BindCommandBuffer(cb_state, set_binding_pair.second); 11447433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis // For given active slots record updated images & buffers 11451c130ea631a82716dc7334de17767536525f2292Tobin Ehlis descriptor_set->GetStorageUpdates(set_binding_pair.second, &cb_state->updateBuffers, &cb_state->updateImages); 1146ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis } 1147ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis } 114858b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (pPipe->vertexBindingDescriptions.size() > 0) { 114958b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis cb_state->vertex_buffer_used = true; 115058b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis } 1151ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis} 1152ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis 1153a27508babf63d50aea75883a3702979193c23683Mark Young// Validate HW line width capabilities prior to setting requested line width. 115406727c7f56d1080aff506a9ae1ae9d8c174b3e9dMark Lobodzinskistatic bool verifyLineWidth(layer_data *dev_data, DRAW_STATE_ERROR dsError, VulkanObjectType object_type, const uint64_t &target, 115506727c7f56d1080aff506a9ae1ae9d8c174b3e9dMark Lobodzinski float lineWidth) { 11563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 1157a27508babf63d50aea75883a3702979193c23683Mark Young 1158a27508babf63d50aea75883a3702979193c23683Mark Young // First check to see if the physical device supports wide lines. 115951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if ((VK_FALSE == dev_data->enabled_features.wideLines) && (1.0f != lineWidth)) { 11603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[object_type], target, __LINE__, 11613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski dsError, "DS", 11623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Attempt to set lineWidth to %f but physical device wideLines feature " 11633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "not supported/enabled so lineWidth must be 1.0f!", 11643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski lineWidth); 1165a27508babf63d50aea75883a3702979193c23683Mark Young } else { 1166a27508babf63d50aea75883a3702979193c23683Mark Young // Otherwise, make sure the width falls in the valid range. 116751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if ((dev_data->phys_dev_properties.properties.limits.lineWidthRange[0] > lineWidth) || 116851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis (dev_data->phys_dev_properties.properties.limits.lineWidthRange[1] < lineWidth)) { 11693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[object_type], target, 11703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, dsError, "DS", 11713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Attempt to set lineWidth to %f but physical device limits line width " 11723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "to between [%f, %f]!", 11733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski lineWidth, dev_data->phys_dev_properties.properties.limits.lineWidthRange[0], 11743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski dev_data->phys_dev_properties.properties.limits.lineWidthRange[1]); 1175a27508babf63d50aea75883a3702979193c23683Mark Young } 1176a27508babf63d50aea75883a3702979193c23683Mark Young } 1177a27508babf63d50aea75883a3702979193c23683Mark Young 11783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 1179a27508babf63d50aea75883a3702979193c23683Mark Young} 1180a27508babf63d50aea75883a3702979193c23683Mark Young 11815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify that create state for a pipeline is valid 118251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verifyPipelineCreateState(layer_data *dev_data, std::vector<PIPELINE_STATE *> pPipelines, int pipelineIndex) { 11833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 11845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11854c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipeline = pPipelines[pipelineIndex]; 11865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If create derivative bit is set, check that we've specified a base 11885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // pipeline correctly, and that the base pipeline was created to allow 11895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // derivatives. 11905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT) { 11914c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pBasePipeline = nullptr; 11925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!((pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) ^ 11935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pPipeline->graphicsPipelineCI.basePipelineIndex != -1))) { 1194315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis // This check is a superset of VALIDATION_ERROR_096005a8 and VALIDATION_ERROR_096005aa 11953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 11969b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 11979b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Invalid Pipeline CreateInfo: exactly one of base pipeline index and handle must be specified"); 11985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pPipeline->graphicsPipelineCI.basePipelineIndex != -1) { 11995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.basePipelineIndex >= pipelineIndex) { 12003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 1201df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1202315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_208005a0, "DS", 1203f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo: base pipeline must occur earlier in array than derivative pipeline. %s", 1204315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_208005a0]); 12055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 12065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pBasePipeline = pPipelines[pPipeline->graphicsPipelineCI.basePipelineIndex]; 12075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) { 120951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis pBasePipeline = getPipelineState(dev_data, pPipeline->graphicsPipelineCI.basePipelineHandle); 12105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pBasePipeline && !(pBasePipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT)) { 12133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 12149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 12159b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Invalid Pipeline CreateInfo: base pipeline does not allow derivatives."); 12165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.pColorBlendState != NULL) { 1220fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis const safe_VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState; 12219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto const render_pass_info = GetRenderPassState(dev_data, pPipeline->graphicsPipelineCI.renderPass)->createInfo.ptr(); 1222fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pPipeline->graphicsPipelineCI.subpass]; 1223fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis if (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount) { 12243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 122551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1226315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005d4, "DS", 1227fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis "vkCreateGraphicsPipelines(): Render pass (0x%" PRIxLEAST64 1228fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis ") subpass %u has colorAttachmentCount of %u which doesn't match the pColorBlendState->attachmentCount of %u. %s", 12299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->graphicsPipelineCI.renderPass), pPipeline->graphicsPipelineCI.subpass, 1230fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis subpass_desc->colorAttachmentCount, color_blend_state->attachmentCount, 1231315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_096005d4]); 1232fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis } 123351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (!dev_data->enabled_features.independentBlend) { 12343d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipeline->attachments.size() > 1) { 123526c548826ff0f83d12c769b51e7d6f76d1265c0eChris Forbes VkPipelineColorBlendAttachmentState *pAttachments = &pPipeline->attachments[0]; 1236c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski for (size_t i = 1; i < pPipeline->attachments.size(); i++) { 123706811df0256552cd7da9d7297672af377463fc4aMark Mueller // Quoting the spec: "If [the independent blend] feature is not enabled, the VkPipelineColorBlendAttachmentState 123806811df0256552cd7da9d7297672af377463fc4aMark Mueller // settings for all color attachments must be identical." VkPipelineColorBlendAttachmentState contains 123906811df0256552cd7da9d7297672af377463fc4aMark Mueller // only attachment state, so memcmp is best suited for the comparison 124006811df0256552cd7da9d7297672af377463fc4aMark Mueller if (memcmp(static_cast<const void *>(pAttachments), static_cast<const void *>(&pAttachments[i]), 124106811df0256552cd7da9d7297672af377463fc4aMark Mueller sizeof(pAttachments[0]))) { 12423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 1243df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1244315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_0f4004ba, "DS", 1245df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Invalid Pipeline CreateInfo: If independent blend feature not " 1246df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "enabled, all elements of pAttachments must be identical. %s", 1247315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0f4004ba]); 124806811df0256552cd7da9d7297672af377463fc4aMark Mueller break; 1249c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski } 12505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 125351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (!dev_data->enabled_features.logicOp && (pPipeline->graphicsPipelineCI.pColorBlendState->logicOpEnable != VK_FALSE)) { 12543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 1255df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1256315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_0f4004bc, "DS", 1257f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo: If logic operations feature not enabled, logicOpEnable must be VK_FALSE. %s", 1258315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0f4004bc]); 12595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1262a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis // Ensure the subpass index is valid. If not, then validate_and_capture_pipeline_shader_state 12635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // produces nonsense errors that confuse users. Other layers should already 12645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // emit errors for renderpass being invalid. 12659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto renderPass = GetRenderPassState(dev_data, pPipeline->graphicsPipelineCI.renderPass); 1266fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes if (renderPass && pPipeline->graphicsPipelineCI.subpass >= renderPass->createInfo.subpassCount) { 12673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1268315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005ee, "DS", 12693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: Subpass index %u " 12703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "is out of range for this renderpass (0..%u). %s", 12713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pPipeline->graphicsPipelineCI.subpass, renderPass->createInfo.subpassCount - 1, 1272315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_096005ee]); 12735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 127559ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis if (validate_and_capture_pipeline_shader_state(dev_data, pPipeline)) { 12763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = true; 12775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 127852156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes // Each shader's stage must be unique 127952156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes if (pPipeline->duplicate_shaders) { 128052156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes for (uint32_t stage = VK_SHADER_STAGE_VERTEX_BIT; stage & VK_SHADER_STAGE_ALL_GRAPHICS; stage <<= 1) { 128152156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes if (pPipeline->duplicate_shaders & stage) { 12829b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 12839b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 12849b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Invalid Pipeline CreateInfo State: Multiple shaders provided for stage %s", 12859b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus string_VkShaderStageFlagBits(VkShaderStageFlagBits(stage))); 128652156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 128752156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 128852156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 12895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // VS is required 12905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pPipeline->active_shaders & VK_SHADER_STAGE_VERTEX_BIT)) { 1291315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1292315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005ae, "DS", 1293315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "Invalid Pipeline CreateInfo State: Vertex Shader required. %s", 1294315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_096005ae]); 12955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Either both or neither TC/TE shaders should be defined 12973067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton bool has_control = (pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0; 12983067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton bool has_eval = (pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0; 12993067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton if (has_control && !has_eval) { 13003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1301315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005b2, "DS", 13023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s", 1303315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_096005b2]); 1304f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt } 13053067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton if (!has_control && has_eval) { 13063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1307315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005b4, "DS", 13083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s", 1309315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_096005b4]); 13105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Compute shaders should be specified independent of Gfx shaders 1312f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if (pPipeline->active_shaders & VK_SHADER_STAGE_COMPUTE_BIT) { 13133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1314315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005b0, "DS", 13153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: Do not specify Compute Shader for Gfx Pipeline. %s", 1316315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_096005b0]); 13175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology is only valid for tessellation pipelines. 13195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Mismatching primitive topology and tessellation fails graphics pipeline creation. 13203067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton if (has_control && has_eval && 1321ca546210846c65808717f8875deae39bd227c240Tobin Ehlis (!pPipeline->graphicsPipelineCI.pInputAssemblyState || 1322ca546210846c65808717f8875deae39bd227c240Tobin Ehlis pPipeline->graphicsPipelineCI.pInputAssemblyState->topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)) { 13233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1324315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005c0, "DS", 13253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: " 13263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST must be set as IA " 13273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "topology for tessellation pipelines. %s", 1328315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_096005c0]); 13295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1330ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (pPipeline->graphicsPipelineCI.pInputAssemblyState && 1331ca546210846c65808717f8875deae39bd227c240Tobin Ehlis pPipeline->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) { 13323067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton if (!has_control || !has_eval) { 13333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1334315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005c2, "DS", 13353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: " 13363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " 13373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "topology is only valid for tessellation pipelines. %s", 1338315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_096005c2]); 13395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1341f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt 13426b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If a rasterization state is provided... 1343a27508babf63d50aea75883a3702979193c23683Mark Young if (pPipeline->graphicsPipelineCI.pRasterizationState) { 13446b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // Make sure that the line width conforms to the HW. 1345a27508babf63d50aea75883a3702979193c23683Mark Young if (!isDynamic(pPipeline, VK_DYNAMIC_STATE_LINE_WIDTH)) { 13469b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= 13479b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus verifyLineWidth(dev_data, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, kVulkanObjectTypePipeline, 13489b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->pipeline), pPipeline->graphicsPipelineCI.pRasterizationState->lineWidth); 1349a27508babf63d50aea75883a3702979193c23683Mark Young } 13505dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes 135158c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski if ((pPipeline->graphicsPipelineCI.pRasterizationState->depthClampEnable == VK_TRUE) && 135258c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski (!dev_data->enabled_features.depthClamp)) { 13533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1354315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_1020061c, "DS", 13553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateGraphicsPipelines(): the depthClamp device feature is disabled: the depthClampEnable " 13563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "member of the VkPipelineRasterizationStateCreateInfo structure must be set to VK_FALSE. %s", 1357315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1020061c]); 135858c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski } 135958c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski 1360434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski if (!isDynamic(pPipeline, VK_DYNAMIC_STATE_DEPTH_BIAS) && 1361434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski (pPipeline->graphicsPipelineCI.pRasterizationState->depthBiasClamp != 0.0) && 1362434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski (!dev_data->enabled_features.depthBiasClamp)) { 13633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 13649b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS", 13653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateGraphicsPipelines(): the depthBiasClamp device feature is disabled: the depthBiasClamp " 13663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "member of the VkPipelineRasterizationStateCreateInfo structure must be set to 0.0 unless the " 13673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_DYNAMIC_STATE_DEPTH_BIAS dynamic state is enabled"); 1368434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski } 1369434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski 13706b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If rasterization is enabled... 13716b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE) { 13726b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen auto subpass_desc = renderPass ? &renderPass->createInfo.pSubpasses[pPipeline->graphicsPipelineCI.subpass] : nullptr; 13736b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen 1374148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski if ((pPipeline->graphicsPipelineCI.pMultisampleState->alphaToOneEnable == VK_TRUE) && 1375148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski (!dev_data->enabled_features.alphaToOne)) { 13763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1377315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_10000622, "DS", 13783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateGraphicsPipelines(): the alphaToOne device feature is disabled: the alphaToOneEnable " 13793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "member of the VkPipelineMultisampleStateCreateInfo structure must be set to VK_FALSE. %s", 1380315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_10000622]); 1381148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski } 1382148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski 13836b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If subpass uses a depth/stencil attachment, pDepthStencilState must be a pointer to a valid structure 13846b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (subpass_desc && subpass_desc->pDepthStencilAttachment && 13856b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 13866b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (!pPipeline->graphicsPipelineCI.pDepthStencilState) { 13873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1388315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005e0, "DS", 13893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: pDepthStencilState is NULL when rasterization is " 13903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "enabled and subpass uses a depth/stencil attachment. %s", 1391315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_096005e0]); 13929580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski 13939580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski } else if ((pPipeline->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE) && 13949580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski (!dev_data->enabled_features.depthBounds)) { 13953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 1396df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 13979b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS", 13989580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski "vkCreateGraphicsPipelines(): the depthBounds device feature is disabled: the depthBoundsTestEnable " 13999580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski "member of the VkPipelineDepthStencilStateCreateInfo structure must be set to VK_FALSE."); 14006b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen } 14015dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes } 1402326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen 1403326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen // If subpass uses color attachments, pColorBlendState must be valid pointer 1404326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (subpass_desc) { 1405326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen uint32_t color_attachment_count = 0; 1406326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen for (uint32_t i = 0; i < subpass_desc->colorAttachmentCount; ++i) { 1407326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (subpass_desc->pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) { 1408326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen ++color_attachment_count; 1409326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 1410326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 1411326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (color_attachment_count > 0 && pPipeline->graphicsPipelineCI.pColorBlendState == nullptr) { 14123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 1413315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005e2, "DS", 14143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: pColorBlendState is NULL when rasterization is " 14153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "enabled and subpass uses color attachments. %s", 1416315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_096005e2]); 1417326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 1418326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 14195dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes } 14205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14216b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen 14223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 14235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 14245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free the Pipeline nodes 142651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deletePipelines(layer_data *dev_data) { 142751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (dev_data->pipelineMap.size() <= 0) return; 142851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis for (auto &pipe_map_pair : dev_data->pipelineMap) { 1429ca546210846c65808717f8875deae39bd227c240Tobin Ehlis delete pipe_map_pair.second; 14305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 143151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->pipelineMap.clear(); 14325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 14335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Block of code at start here specifically for managing/tracking DSs 14355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Pool node ptr for specified pool or else NULL 14379a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisDESCRIPTOR_POOL_STATE *GetDescriptorPoolState(const layer_data *dev_data, const VkDescriptorPool pool) { 1438bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis auto pool_it = dev_data->descriptorPoolMap.find(pool); 1439bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis if (pool_it == dev_data->descriptorPoolMap.end()) { 14405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 14415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1442bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis return pool_it->second; 14435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 14445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate that given set is valid and that it's not being used by an in-flight CmdBuffer 14465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// func_str is the name of the calling function 1447e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return false if no errors occur 1448e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if validation error occurs and callback returns true (to skip upcoming API call down the chain) 14490dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlisstatic bool validateIdleDescriptorSet(const layer_data *dev_data, VkDescriptorSet set, std::string func_str) { 1450cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.idle_descriptor_set) return false; 14513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 14520dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis auto set_node = dev_data->setMap.find(set); 14530dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis if (set_node == dev_data->setMap.end()) { 14543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 14559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", 14563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", func_str.c_str(), 14579b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(set)); 14585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 14591c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis // TODO : This covers various error cases so should pass error enum into this function and use passed in enum here 14605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (set_node->second->in_use.load()) { 14613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 1462315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(set), __LINE__, VALIDATION_ERROR_2860026a, "DS", 14633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that is in use by a command buffer. %s", 1464315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis func_str.c_str(), HandleToUint64(set), validation_error_map[VALIDATION_ERROR_2860026a]); 14655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 14685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 1469f80bf38f4fb3f177b3e1be11b7b1c5edcdbf7d9bChris Forbes 1470e6651096ed8f07840447783c66827cc16d659a49Tobin Ehlis// Remove set from setMap and delete the set 14719dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlisstatic void freeDescriptorSet(layer_data *dev_data, cvdescriptorset::DescriptorSet *descriptor_set) { 14729dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis dev_data->setMap.erase(descriptor_set->GetSet()); 14739dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis delete descriptor_set; 14749dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis} 14755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free all DS Pools including their Sets & related sub-structs 14765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// NOTE : Calls to this function should be wrapped in mutex 147751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deletePools(layer_data *dev_data) { 1478ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson for (auto ii = dev_data->descriptorPoolMap.begin(); ii != dev_data->descriptorPoolMap.end();) { 1479c5f47f0a54e14c47d402aeabc6498d981ecda9ccTobin Ehlis // Remove this pools' sets from setMap and delete them 1480ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson for (auto ds : ii->second->sets) { 148151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis freeDescriptorSet(dev_data, ds); 14825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1483ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson ii->second->sets.clear(); 1484ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson delete ii->second; 1485ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson ii = dev_data->descriptorPoolMap.erase(ii); 14865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 14885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 148951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void clearDescriptorPool(layer_data *dev_data, const VkDevice device, const VkDescriptorPool pool, 14905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkDescriptorPoolResetFlags flags) { 14919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pPool = GetDescriptorPoolState(dev_data, pool); 1492de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // TODO: validate flags 1493de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // For every set off of this pool, clear it, remove from setMap, and free cvdescriptorset::DescriptorSet 1494de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis for (auto ds : pPool->sets) { 149551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis freeDescriptorSet(dev_data, ds); 1496de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis } 1497de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->sets.clear(); 1498de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // Reset available count for each type and available sets for this pool 1499de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis for (uint32_t i = 0; i < pPool->availableDescriptorTypeCount.size(); ++i) { 1500de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->availableDescriptorTypeCount[i] = pPool->maxDescriptorTypeCount[i]; 15015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1502de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->availableSets = pPool->maxSets; 15035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 15045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For given CB object, fetch associated CB Node from map 15069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisGLOBAL_CB_NODE *GetCBNode(layer_data const *dev_data, const VkCommandBuffer cb) { 150751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->commandBufferMap.find(cb); 150851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->commandBufferMap.end()) { 15095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 15105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15115121a8dcacb23766ba4455b4eea429f0a3d62099Chris Forbes return it->second; 15125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 15135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 151429f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis// If a renderpass is active, verify that the given command type is appropriate for current subpass state 151529f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlisbool ValidateCmdSubpassState(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd_type) { 1516cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pCB->activeRenderPass) return false; 15173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 1518d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS && 1519d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis (cmd_type != CMD_EXECUTECOMMANDS && cmd_type != CMD_NEXTSUBPASS && cmd_type != CMD_ENDRENDERPASS)) { 15203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 15219b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 15223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Commands cannot be called in a subpass using secondary command buffers."); 15235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_INLINE && cmd_type == CMD_EXECUTECOMMANDS) { 15243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 15259b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 15263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdExecuteCommands() cannot be called in a subpass using inline commands."); 15275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 15295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 15305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1531baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardtbool ValidateCmdQueueFlags(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const char *caller_name, VkQueueFlags required_flags, 1532baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt UNIQUE_VALIDATION_ERROR_CODE error_code) { 1533baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt auto pool = GetCommandPoolNode(dev_data, cb_node->createInfo.commandPool); 1534baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt if (pool) { 1535baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VkQueueFlags queue_flags = dev_data->phys_dev_properties.queue_family_properties[pool->queueFamilyIndex].queueFlags; 1536baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt if (!(required_flags & queue_flags)) { 1537baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt string required_flags_string; 1538baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt for (auto flag : {VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT, VK_QUEUE_COMPUTE_BIT}) { 1539baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt if (flag & required_flags) { 1540baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt if (required_flags_string.size()) { 1541baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt required_flags_string += " or "; 1542baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 1543baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt required_flags_string += string_VkQueueFlagBits(flag); 1544baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 1545baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 1546baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 15479b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, error_code, "DS", 1548baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt "Cannot call %s on a command buffer allocated from a pool without %s capabilities. %s.", caller_name, 1549baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt required_flags_string.c_str(), validation_error_map[error_code]); 1550baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 1551baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 15525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 15535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 15545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1555d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbesstatic char const * GetCauseStr(VK_OBJECT obj) { 1556d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes if (obj.type == kVulkanObjectTypeDescriptorSet) 1557d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes return "destroyed or updated"; 1558d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes if (obj.type == kVulkanObjectTypeCommandBuffer) 1559d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes return "destroyed or rerecorded"; 1560d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes return "destroyed"; 1561d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes} 1562d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes 1563ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinskistatic bool ReportInvalidCommandBuffer(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const char *call_source) { 1564ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski bool skip = false; 1565ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (auto obj : cb_state->broken_bindings) { 15667a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski const char *type_str = object_string[obj.type]; 1567d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes const char *cause_str = GetCauseStr(obj); 1568ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 15699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 1570ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "You are adding %s to command buffer 0x%p that is invalid because bound %s 0x%" PRIxLEAST64 " was %s.", 1571ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski call_source, cb_state->commandBuffer, type_str, obj.handle, cause_str); 1572ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 1573ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski return skip; 1574ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski} 1575ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 1576623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Validate the given command being added to the specified cmd buffer, flagging errors if CB is not in the recording state or if 1577623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// there's an issue with the Cmd ordering 1578946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinskibool ValidateCmd(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd, const char *caller_name) { 157933f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes switch (cb_state->state) { 158033f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes case CB_RECORDING: 158133f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes return ValidateCmdSubpassState(dev_data, cb_state, cmd); 158233f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes 158333f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes case CB_INVALID: 158433f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes return ReportInvalidCommandBuffer(dev_data, cb_state, caller_name); 158533f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes 158633f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes default: 158733f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 15889b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_NO_BEGIN_COMMAND_BUFFER, "DS", 158933f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes "You must call vkBeginCommandBuffer() before this call to %s", caller_name); 15905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 159229f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis 15931ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlisvoid UpdateCmdBufferLastCmd(GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd) { 159429f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis if (cb_state->state == CB_RECORDING) { 159529f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis cb_state->last_cmd = cmd; 159629f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis } 159729f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis} 15987e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For given object struct return a ptr of BASE_NODE type for its wrapping struct 15997e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin EhlisBASE_NODE *GetStateStructPtrFromObject(layer_data *dev_data, VK_OBJECT object_struct) { 16007e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis BASE_NODE *base_ptr = nullptr; 16017e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis switch (object_struct.type) { 1602ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeDescriptorSet: { 16039a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetSetNode(dev_data, reinterpret_cast<VkDescriptorSet &>(object_struct.handle)); 1604cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1605cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1606ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeSampler: { 16079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetSamplerState(dev_data, reinterpret_cast<VkSampler &>(object_struct.handle)); 1608cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1609cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1610ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeQueryPool: { 16119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetQueryPoolNode(dev_data, reinterpret_cast<VkQueryPool &>(object_struct.handle)); 1612cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1613cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1614ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypePipeline: { 1615cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski base_ptr = getPipelineState(dev_data, reinterpret_cast<VkPipeline &>(object_struct.handle)); 1616cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1617cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1618ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeBuffer: { 16199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(object_struct.handle)); 1620cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1621cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1622ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeBufferView: { 16239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetBufferViewState(dev_data, reinterpret_cast<VkBufferView &>(object_struct.handle)); 1624cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1625cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1626ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeImage: { 16279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetImageState(dev_data, reinterpret_cast<VkImage &>(object_struct.handle)); 1628cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1629cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1630ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeImageView: { 16319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetImageViewState(dev_data, reinterpret_cast<VkImageView &>(object_struct.handle)); 1632cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1633cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1634ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeEvent: { 16359a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetEventNode(dev_data, reinterpret_cast<VkEvent &>(object_struct.handle)); 1636cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1637cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1638ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeDescriptorPool: { 16399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetDescriptorPoolState(dev_data, reinterpret_cast<VkDescriptorPool &>(object_struct.handle)); 1640cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1641cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1642ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeCommandPool: { 16439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetCommandPoolNode(dev_data, reinterpret_cast<VkCommandPool &>(object_struct.handle)); 1644cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1645cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1646ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeFramebuffer: { 16479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetFramebufferState(dev_data, reinterpret_cast<VkFramebuffer &>(object_struct.handle)); 1648cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1649cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1650ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeRenderPass: { 16519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetRenderPassState(dev_data, reinterpret_cast<VkRenderPass &>(object_struct.handle)); 1652cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1653cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1654ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeDeviceMemory: { 16559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetMemObjInfo(dev_data, reinterpret_cast<VkDeviceMemory &>(object_struct.handle)); 1656cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1657cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1658cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1659cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO : Any other objects to be handled here? 1660cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(0); 1661cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1662bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis } 16637e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis return base_ptr; 16647e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis} 16657e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis 16667e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Tie the VK_OBJECT to the cmd buffer which includes: 16677e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Add object_binding to cmd buffer 16687e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Add cb_binding to object 16697e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void addCommandBufferBinding(std::unordered_set<GLOBAL_CB_NODE *> *cb_bindings, VK_OBJECT obj, GLOBAL_CB_NODE *cb_node) { 16707e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis cb_bindings->insert(cb_node); 16717e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis cb_node->object_bindings.insert(obj); 16727e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis} 16737e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For a given object, if cb_node is in that objects cb_bindings, remove cb_node 16747e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void removeCommandBufferBinding(layer_data *dev_data, VK_OBJECT const *object, GLOBAL_CB_NODE *cb_node) { 16757e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis BASE_NODE *base_obj = GetStateStructPtrFromObject(dev_data, *object); 1676cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (base_obj) base_obj->cb_bindings.erase(cb_node); 1677bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis} 16785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Reset the command buffer state 16795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Maintain the createInfo and set state to CB_NEW, but clear all other state 1680400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlisstatic void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { 1681400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis GLOBAL_CB_NODE *pCB = dev_data->commandBufferMap[cb]; 16825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 1683b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine pCB->in_use.store(0); 1684347d4d3139a1e743ed85bd375c20fd35bbe68d74Chris Forbes pCB->last_cmd = CMD_NONE; 16855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Reset CB state (note that createInfo is not cleared) 16865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->commandBuffer = cb; 16875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->beginInfo, 0, sizeof(VkCommandBufferBeginInfo)); 16885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo)); 1689b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes pCB->hasDrawCmd = false; 16905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->state = CB_NEW; 16915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->submitCount = 0; 16925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status = 0; 1693b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes pCB->viewportMask = 0; 1694b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes pCB->scissorMask = 0; 169593c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 169672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { 169772d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis pCB->lastBound[i].reset(); 169872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 169993c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 17005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->activeRenderPassBeginInfo, 0, sizeof(pCB->activeRenderPassBeginInfo)); 1701ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes pCB->activeRenderPass = nullptr; 17025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeSubpassContents = VK_SUBPASS_CONTENTS_INLINE; 17035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeSubpass = 0; 1704e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis pCB->broken_bindings.clear(); 17055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->waitedEvents.clear(); 17065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.clear(); 1707c7e6bc41aa9c6e5a677b138b9459b252cd3bedf2Mark Lobodzinski pCB->writeEventsBeforeWait.clear(); 17085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->waitedEventsBeforeQueryReset.clear(); 17095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->queryToStateMap.clear(); 17105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeQueries.clear(); 17115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->startedQueries.clear(); 17125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->imageLayoutMap.clear(); 17135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->eventToStageMap.clear(); 17145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->drawData.clear(); 17155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers.clear(); 171658b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis pCB->vertex_buffer_used = false; 17175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->primaryCommandBuffer = VK_NULL_HANDLE; 17181a3660584634742a3297915c94768d73f360e794Chris Forbes // If secondary, invalidate any primary command buffer that may call us. 17191a3660584634742a3297915c94768d73f360e794Chris Forbes if (pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) { 17201a3660584634742a3297915c94768d73f360e794Chris Forbes invalidateCommandBuffers(dev_data, 17211a3660584634742a3297915c94768d73f360e794Chris Forbes pCB->linkedCommandBuffers, 17221a3660584634742a3297915c94768d73f360e794Chris Forbes {HandleToUint64(cb), kVulkanObjectTypeCommandBuffer}); 17231a3660584634742a3297915c94768d73f360e794Chris Forbes } 17241a3660584634742a3297915c94768d73f360e794Chris Forbes 17251a3660584634742a3297915c94768d73f360e794Chris Forbes // Remove reverse command buffer links. 17261a3660584634742a3297915c94768d73f360e794Chris Forbes for (auto pSubCB : pCB->linkedCommandBuffers) { 17271a3660584634742a3297915c94768d73f360e794Chris Forbes pSubCB->linkedCommandBuffers.erase(pCB); 17281a3660584634742a3297915c94768d73f360e794Chris Forbes } 17291a3660584634742a3297915c94768d73f360e794Chris Forbes pCB->linkedCommandBuffers.clear(); 17307a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->updateImages.clear(); 17317a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->updateBuffers.clear(); 1732400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis clear_cmd_buf_and_mem_references(dev_data, pCB); 1733b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventUpdates.clear(); 1734d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine pCB->queryUpdates.clear(); 173593c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 1736bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis // Remove object bindings 1737bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis for (auto obj : pCB->object_bindings) { 1738bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis removeCommandBufferBinding(dev_data, &obj, pCB); 1739bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis } 1740a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis pCB->object_bindings.clear(); 174193c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski // Remove this cmdBuffer's reference from each FrameBuffer's CB ref list 174293c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski for (auto framebuffer : pCB->framebuffers) { 17439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb_state = GetFramebufferState(dev_data, framebuffer); 1744cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fb_state) fb_state->cb_bindings.erase(pCB); 174593c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski } 174693c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski pCB->framebuffers.clear(); 17477003b38da5cc27a063af3c45080f3a35438283eeTobin Ehlis pCB->activeFramebuffer = VK_NULL_HANDLE; 17485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 17505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Set PSO-related status bits for CB, including dynamic state set via PSO 17524c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic void set_cb_pso_status(GLOBAL_CB_NODE *pCB, const PIPELINE_STATE *pPipe) { 17535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Account for any dynamic state not set via this PSO 1754ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (!pPipe->graphicsPipelineCI.pDynamicState || 1755cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski !pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount) { // All state is static 17564052946ae557337ff95f3725e879131b1c63f865Tobin Ehlis pCB->status |= CBSTATUS_ALL_STATE_SET; 17575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 17585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // First consider all state on 17595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Then unset any state that's noted as dynamic in PSO 17605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Finally OR that into CB statemask 17614052946ae557337ff95f3725e879131b1c63f865Tobin Ehlis CBStatusFlags psoDynStateMask = CBSTATUS_ALL_STATE_SET; 1762ca546210846c65808717f8875deae39bd227c240Tobin Ehlis for (uint32_t i = 0; i < pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) { 1763ca546210846c65808717f8875deae39bd227c240Tobin Ehlis switch (pPipe->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) { 1764cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_LINE_WIDTH: 1765cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_LINE_WIDTH_SET; 1766cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1767cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_DEPTH_BIAS: 1768cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_DEPTH_BIAS_SET; 1769cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1770cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_BLEND_CONSTANTS: 1771cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_BLEND_CONSTANTS_SET; 1772cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1773cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_DEPTH_BOUNDS: 1774cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_DEPTH_BOUNDS_SET; 1775cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1776cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: 1777cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_READ_MASK_SET; 1778cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1779cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: 1780cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_WRITE_MASK_SET; 1781cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1782cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_REFERENCE: 1783cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_REFERENCE_SET; 1784cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1785cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1786cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO : Flag error here 1787cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 17885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= psoDynStateMask; 17915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 17935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1794623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Flags validation error if the associated call is made inside a render pass. The apiName routine should ONLY be called outside a 1795623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// render pass. 179651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisbool insideRenderPass(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 1797e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool inside = false; 17985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass) { 179951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis inside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 18009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->commandBuffer), __LINE__, msgCode, "DS", 1801ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen "%s: It is invalid to issue this call inside an active render pass (0x%" PRIxLEAST64 "). %s", apiName, 18029b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->activeRenderPass->renderPass), validation_error_map[msgCode]); 18035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return inside; 18055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 18065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Flags validation error if the associated call is made outside a render pass. The apiName 18085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// routine should ONLY be called inside a render pass. 180951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisbool outsideRenderPass(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 1810e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool outside = false; 18115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) && (!pCB->activeRenderPass)) || 18125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) && (!pCB->activeRenderPass) && 18135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))) { 181451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis outside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 18159b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->commandBuffer), __LINE__, msgCode, "DS", 1816ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen "%s: This call must be issued inside an active render pass. %s", apiName, validation_error_map[msgCode]); 18175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return outside; 18195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 18205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1821f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic void init_core_validation(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) { 1822b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_core_validation"); 18235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 18245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18257a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis// For the given ValidationCheck enum, set all relevant instance disabled flags to true 18267a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlisvoid SetDisabledFlags(instance_layer_data *instance_data, VkValidationFlagsEXT *val_flags_struct) { 18277a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) { 18287a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis switch (val_flags_struct->pDisabledValidationChecks[i]) { 182959ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis case VK_VALIDATION_CHECK_SHADERS_EXT: 183059ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis instance_data->disabled.shader_validation = true; 183159ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis break; 18327a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis case VK_VALIDATION_CHECK_ALL_EXT: 18337a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis // Set all disabled flags to true 18347a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis instance_data->disabled.SetAll(true); 18357a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis break; 18367a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis default: 18377a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis break; 18387a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 18397a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 18407a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis} 18417a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis 1842bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, 1843bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkInstance *pInstance) { 18445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 18455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(chain_info->u.pLayerInfo); 18475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 18485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance"); 1849cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED; 18505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Advance the link info for the next element on the chain 18525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 18535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); 1855cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (result != VK_SUCCESS) return result; 18565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 185756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), instance_layer_data_map); 185856a5ba3e60a723781945959ffc10e2e215350de5Chia-I Wu instance_data->instance = *pInstance; 18599172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fpGetInstanceProcAddr); 18609172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->report_data = debug_report_create_instance( 18619172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes &instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames); 18620cf009a4e2a5c22e4645f343c7a998f188a22015Chris Forbes instance_data->extensions.InitFromInstanceCreateInfo(pCreateInfo); 1863b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis init_core_validation(instance_data, pAllocator); 1864825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski 18655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ValidateLayerOrdering(*pCreateInfo); 18667a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis // Parse any pNext chains 18677a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis if (pCreateInfo->pNext) { 18687a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis GENERIC_HEADER *struct_header = (GENERIC_HEADER *)pCreateInfo->pNext; 18697a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis while (struct_header) { 18707a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis // Check for VkValidationFlagsExt 18717a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis if (VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT == struct_header->sType) { 18727a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis SetDisabledFlags(instance_data, (VkValidationFlagsEXT *)struct_header); 18737a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 18747a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis struct_header = (GENERIC_HEADER *)struct_header->pNext; 18757a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 18767a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 18775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 18795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 18805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 188125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Hook DestroyInstance to remove tableInstanceMap entry 188289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) { 18835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODOSC : Shouldn't need any customization here 18845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dispatch_key key = get_dispatch_key(instance); 18855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TBD: Need any locking this early, in case this function is called at the 18865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // same time by more than one thread? 188756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(key, instance_layer_data_map); 18889172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DestroyInstance(instance, pAllocator); 18895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1890b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 18915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Clean up logging callback, if any 18929172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes while (instance_data->logging_callback.size() > 0) { 18939172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes VkDebugReportCallbackEXT callback = instance_data->logging_callback.back(); 18949172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator); 18959172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->logging_callback.pop_back(); 18965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18989172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_debug_report_destroy_instance(instance_data->report_data); 1899d27b109eaf4da0a5514dc2ae2f3dd6a76976ba0dGabríel Arthúr Pétursson FreeLayerDataPtr(key, instance_layer_data_map); 19005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 19015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 19025770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausstatic bool ValidatePhysicalDeviceQueueFamily(instance_layer_data *instance_data, const PHYSICAL_DEVICE_STATE *pd_state, 19035770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus uint32_t requested_queue_family, int32_t err_code, const char *cmd_name, 19045770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus const char *queue_family_var_name, const char *vu_note = nullptr) { 19053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 19065770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 19075770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus if (!vu_note) vu_note = validation_error_map[err_code]; 19085770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 19095770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus const char *conditional_ext_cmd = 1910d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski instance_data->extensions.vk_khr_get_physical_device_properties_2 ? "or vkGetPhysicalDeviceQueueFamilyProperties2KHR" : ""; 19115770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 19125770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus std::string count_note = (UNCALLED == pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) 19135770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus ? "the pQueueFamilyPropertyCount was never obtained" 19145770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus : "i.e. is not less than " + std::to_string(pd_state->queue_family_count); 19155770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 19165770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus if (requested_queue_family >= pd_state->queue_family_count) { 19173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 19189b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pd_state->phys_device), __LINE__, err_code, "DL", 19199b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "%s: %s (= %" PRIu32 19209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus ") is not less than any previously obtained pQueueFamilyPropertyCount from " 19215770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus "vkGetPhysicalDeviceQueueFamilyProperties%s (%s). %s", 19225770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus cmd_name, queue_family_var_name, requested_queue_family, conditional_ext_cmd, count_note.c_str(), vu_note); 19235770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus } 19245770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus return skip; 19255770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus} 19265770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 19275770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus// Verify VkDeviceQueueCreateInfos 19285770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausstatic bool ValidateDeviceQueueCreateInfos(instance_layer_data *instance_data, const PHYSICAL_DEVICE_STATE *pd_state, 19295770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus uint32_t info_count, const VkDeviceQueueCreateInfo *infos) { 19305770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus bool skip = false; 19315770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 19325770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus for (uint32_t i = 0; i < info_count; ++i) { 19335770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus const auto requested_queue_family = infos[i].queueFamilyIndex; 19345770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 19355770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus // Verify that requested queue family is known to be valid at this point in time 19365770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus std::string queue_family_var_name = "pCreateInfo->pQueueCreateInfos[" + std::to_string(i) + "].queueFamilyIndex"; 1937315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, requested_queue_family, VALIDATION_ERROR_06c002fa, 19385770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus "vkCreateDevice", queue_family_var_name.c_str()); 19395770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 19405770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus // Verify that requested queue count of queue family is known to be valid at this point in time 19415770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus if (requested_queue_family < pd_state->queue_family_count) { 19425770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus const auto requested_queue_count = infos[i].queueCount; 19435770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus const auto queue_family_props_count = pd_state->queue_family_properties.size(); 19445770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus const bool queue_family_has_props = requested_queue_family < queue_family_props_count; 1945d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski const char *conditional_ext_cmd = instance_data->extensions.vk_khr_get_physical_device_properties_2 19465770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus ? "or vkGetPhysicalDeviceQueueFamilyProperties2KHR" 19475770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus : ""; 19485770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus std::string count_note = 19495770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus !queue_family_has_props 19505770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus ? "the pQueueFamilyProperties[" + std::to_string(requested_queue_family) + "] was never obtained" 19515770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus : "i.e. is not less than or equal to " + 19525770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus std::to_string(pd_state->queue_family_properties[requested_queue_family].queueCount); 19535770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 19545770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus if (!queue_family_has_props || 19555770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus requested_queue_count > pd_state->queue_family_properties[requested_queue_family].queueCount) { 19563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 19579b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, HandleToUint64(pd_state->phys_device), __LINE__, 1958315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_06c002fc, "DL", 19599b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "vkCreateDevice: pCreateInfo->pQueueCreateInfos[%" PRIu32 "].queueCount (=%" PRIu32 19609b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus ") is not " 19615770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus "less than or equal to available queue count for this " 19629b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "pCreateInfo->pQueueCreateInfos[%" PRIu32 "].queueFamilyIndex} (=%" PRIu32 19639b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus ") obtained previously " 19645770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus "from vkGetPhysicalDeviceQueueFamilyProperties%s (%s). %s", 19655770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus i, requested_queue_count, i, requested_queue_family, conditional_ext_cmd, count_note.c_str(), 1966315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_06c002fc]); 1967838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 1968838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 1969838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 19705770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 19713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 1972838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski} 1973838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski 1974f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski// Verify that features have been queried and that they are available 19755770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausstatic bool ValidateRequestedFeatures(instance_layer_data *instance_data, const PHYSICAL_DEVICE_STATE *pd_state, 1976bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkPhysicalDeviceFeatures *requested_features) { 19773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 1978f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 19795770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus const VkBool32 *actual = reinterpret_cast<const VkBool32 *>(&pd_state->features); 1980825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski const VkBool32 *requested = reinterpret_cast<const VkBool32 *>(requested_features); 1981f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO : This is a nice, compact way to loop through struct, but a bad way to report issues 1982f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // Need to provide the struct member name with the issue. To do that seems like we'll 1983f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // have to loop through each struct member which should be done w/ codegen to keep in synch. 1984f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski uint32_t errors = 0; 1985f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski uint32_t total_bools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32); 1986f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski for (uint32_t i = 0; i < total_bools; i++) { 1987f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski if (requested[i] > actual[i]) { 1988f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO: Add index to struct member name helper to be able to include a feature name 19895770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 19905770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL", 19913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "While calling vkCreateDevice(), requesting feature #%u in VkPhysicalDeviceFeatures struct, " 19923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "which is not available on this device.", 19933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski i); 1994f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski errors++; 1995f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 1996f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 19975770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus if (errors && (UNCALLED == pd_state->vkGetPhysicalDeviceFeaturesState)) { 1998f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // If user didn't request features, notify them that they should 1999f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO: Verify this against the spec. I believe this is an invalid use of the API and should return an error 20005770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 20015770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL", 20023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "You requested features that are unavailable on this device. You should first query feature " 20033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "availability by calling vkGetPhysicalDeviceFeatures()."); 2004f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 20053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 2006f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski} 2007f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 200889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo, 200989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) { 20103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 20115770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(gpu), instance_layer_data_map); 2012f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 20135770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus std::unique_lock<std::mutex> lock(global_lock); 2014f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus auto pd_state = GetPhysicalDeviceState(instance_data, gpu); 2015f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 2016f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus // TODO: object_tracker should perhaps do this instead 2017f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus // and it does not seem to currently work anyway -- the loader just crashes before this point 2018f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus if (!GetPhysicalDeviceState(instance_data, gpu)) { 2019f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 2020f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 0, __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 2021f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus "Invalid call to vkCreateDevice() w/o first calling vkEnumeratePhysicalDevices()."); 2022f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus } 2023f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 2024f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // Check that any requested features are available 2025f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski if (pCreateInfo->pEnabledFeatures) { 20265770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus skip |= ValidateRequestedFeatures(instance_data, pd_state, pCreateInfo->pEnabledFeatures); 2027f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 20285770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus skip |= 20295770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus ValidateDeviceQueueCreateInfos(instance_data, pd_state, pCreateInfo->queueCreateInfoCount, pCreateInfo->pQueueCreateInfos); 2030f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 20315770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 20321d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller 20335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 20345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(chain_info->u.pLayerInfo); 20365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 20375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; 203856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_data->instance, "vkCreateDevice"); 20395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (fpCreateDevice == NULL) { 20405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_INITIALIZATION_FAILED; 20415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Advance the link info for the next element on the chain 20445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 20455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20465770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus lock.unlock(); 20475770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 20485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice); 20495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result != VK_SUCCESS) { 20505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 20515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20535770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus lock.lock(); 205456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map); 20555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 205656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->instance_data = instance_data; 20575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Setup device dispatch table 205856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_init_device_dispatch_table(*pDevice, &device_data->dispatch_table, fpGetDeviceProcAddr); 205956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->device = *pDevice; 2060ec85232c4d8d9ddf7d2ae57cb8203c5ab52c1106Mark Lobodzinski // Save PhysicalDevice handle 206156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->physical_device = gpu; 20625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 206356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice); 2064a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinski device_data->extensions.InitFromDeviceCreateInfo(&instance_data->extensions, pCreateInfo); 2065d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski 20665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Get physical device limits for this device 206756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &(device_data->phys_dev_properties.properties)); 20685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t count; 206956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(gpu, &count, nullptr); 207056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->phys_dev_properties.queue_family_properties.resize(count); 207156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties( 207256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis gpu, &count, &device_data->phys_dev_properties.queue_family_properties[0]); 20735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: device limits should make sure these are compatible 20745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCreateInfo->pEnabledFeatures) { 207556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->enabled_features = *pCreateInfo->pEnabledFeatures; 20765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 207756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis memset(&device_data->enabled_features, 0, sizeof(VkPhysicalDeviceFeatures)); 20785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2079e47dbc3f3340fa177d877a67b2adb76a570027e5Mark Lobodzinski // Store physical device properties and physical device mem limits into device layer_data structs 208056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceMemoryProperties(gpu, &device_data->phys_dev_mem_props); 208156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &device_data->phys_dev_props); 2082b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 20835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ValidateLayerOrdering(*pCreateInfo); 20855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 20875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// prototype 209089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) { 20915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODOSC : Shouldn't need any customization here 20925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dispatch_key key = get_dispatch_key(device); 209356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(key, layer_data_map); 20945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Free all the memory 2095b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 20965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis deletePipelines(dev_data); 2097fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes dev_data->renderPassMap.clear(); 20989b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes for (auto ii = dev_data->commandBufferMap.begin(); ii != dev_data->commandBufferMap.end(); ++ii) { 20999b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes delete (*ii).second; 21009b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes } 21019b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes dev_data->commandBufferMap.clear(); 2102f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis // This will also delete all sets in the pool & remove them from setMap 21035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis deletePools(dev_data); 2104f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis // All sets should be removed 2105f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis assert(dev_data->setMap.empty()); 2106fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis dev_data->descriptorSetLayoutMap.clear(); 21075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageViewMap.clear(); 21085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageMap.clear(); 21095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap.clear(); 21105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap.clear(); 21115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->bufferViewMap.clear(); 21125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->bufferMap.clear(); 21131344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis // Queues persist until device is destroyed 21141344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis dev_data->queueMap.clear(); 21155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Report any memory leaks 21165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis layer_debug_report_destroy_device(device); 2117b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 21185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 21195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if DISPATCH_MAP_DEBUG 2120414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller fprintf(stderr, "Device: 0x%p, key: 0x%p\n", device, key); 21215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif 2122d27b109eaf4da0a5514dc2ae2f3dd6a76976ba0dGabríel Arthúr Pétursson 2123d27b109eaf4da0a5514dc2ae2f3dd6a76976ba0dGabríel Arthúr Pétursson dev_data->dispatch_table.DestroyDevice(device, pAllocator); 2124d27b109eaf4da0a5514dc2ae2f3dd6a76976ba0dGabríel Arthúr Pétursson FreeLayerDataPtr(key, layer_data_map); 21255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 21265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 21275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}}; 21285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2129208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis// For given stage mask, if Geometry shader stage is on w/o GS being enabled, report geo_error_id 2130208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis// and if Tessellation Control or Evaluation shader stages are on w/o TS being enabled, report tess_error_id 2131208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlisstatic bool ValidateStageMaskGsTsEnables(layer_data *dev_data, VkPipelineStageFlags stageMask, const char *caller, 2132208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE geo_error_id, UNIQUE_VALIDATION_ERROR_CODE tess_error_id) { 2133208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis bool skip = false; 2134208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis if (!dev_data->enabled_features.geometryShader && (stageMask & VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT)) { 2135208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 2136cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski geo_error_id, "DL", 2137cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call includes a stageMask with VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT bit set when " 2138cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "device does not have geometryShader feature enabled. %s", 2139208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis caller, validation_error_map[geo_error_id]); 2140208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 2141208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis if (!dev_data->enabled_features.tessellationShader && 2142208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis (stageMask & (VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT))) { 2143208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 2144cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski tess_error_id, "DL", 2145cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call includes a stageMask with VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT " 2146cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "and/or VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT bit(s) set when device " 2147cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "does not have tessellationShader feature enabled. %s", 2148208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis caller, validation_error_map[tess_error_id]); 2149208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 2150208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis return skip; 2151208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis} 2152208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis 2153ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes// Loop through bound objects and increment their in_use counts. 2154ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayesstatic void IncrementBoundObjects(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) { 2155a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis for (auto obj : cb_node->object_bindings) { 2156a317e7593a0fe227635fc8241908471acb36c952Chris Forbes auto base_obj = GetStateStructPtrFromObject(dev_data, obj); 2157ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes if (base_obj) { 215851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour base_obj->in_use.fetch_add(1); 2159162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis } 2160a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis } 2161a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis} 21625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Track which resources are in-flight by atomically incrementing their "in_use" count 216351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void incrementResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 216451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cb_node->submitCount++; 21659a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis cb_node->in_use.fetch_add(1); 2166a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 2167a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // First Increment for all "generic" objects bound to cmd buffer, followed by special-case objects below 2168ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes IncrementBoundObjects(dev_data, cb_node); 2169a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // TODO : We should be able to remove the NULL look-up checks from the code below as long as 2170a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state 2171a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // should then be flagged prior to calling this function 21729a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto drawDataElement : cb_node->drawData) { 21735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto buffer : drawDataElement.buffers) { 21749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 217551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (buffer_state) { 21765cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->in_use.fetch_add(1); 21775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 21785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 21795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 21809a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto event : cb_node->writeEventsBeforeWait) { 21819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 2182cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (event_state) event_state->write_in_use++; 2183c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 21845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 21855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2186b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Note: This function assumes that the global lock is held by the calling thread. 2187b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// For the given queue, verify the queue state up to the given seq number. 2188b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Currently the only check is to make sure that if there are events to be waited on prior to 2189b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// a QueryReset, make sure that all such events have been signalled. 2190d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbesstatic bool VerifyQueueStateToSeq(layer_data *dev_data, QUEUE_STATE *initial_queue, uint64_t initial_seq) { 2191b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis bool skip = false; 2192d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 2193d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes // sequence number we want to validate up to, per queue 2194d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes std::unordered_map<QUEUE_STATE *, uint64_t> target_seqs { { initial_queue, initial_seq } }; 2195d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes // sequence number we've completed validation for, per queue 2196d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes std::unordered_map<QUEUE_STATE *, uint64_t> done_seqs; 2197d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes std::vector<QUEUE_STATE *> worklist { initial_queue }; 2198d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 2199d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes while (worklist.size()) { 2200d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto queue = worklist.back(); 2201d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes worklist.pop_back(); 2202d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 2203d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto target_seq = target_seqs[queue]; 2204d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto seq = std::max(done_seqs[queue], queue->seq); 2205d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto sub_it = queue->submissions.begin() + int(seq - queue->seq); // seq >= queue->seq 2206d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 2207d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes for (; seq < target_seq; ++sub_it, ++seq) { 2208d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes for (auto &wait : sub_it->waitSemaphores) { 2209d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto other_queue = GetQueueState(dev_data, wait.queue); 2210d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 2211d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes if (other_queue == queue) 2212d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes continue; // semaphores /always/ point backwards, so no point here. 2213d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 2214d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto other_target_seq = std::max(target_seqs[other_queue], wait.seq); 2215d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto other_done_seq = std::max(done_seqs[other_queue], other_queue->seq); 2216d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 2217d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes // if this wait is for another queue, and covers new sequence 2218d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes // numbers beyond what we've already validated, mark the new 2219d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes // target seq and (possibly-re)add the queue to the worklist. 2220d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes if (other_done_seq < other_target_seq) { 2221d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes target_seqs[other_queue] = other_target_seq; 2222d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes worklist.push_back(other_queue); 2223d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes } 2224d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes } 2225d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 2226d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes for (auto cb : sub_it->cbs) { 2227d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto cb_node = GetCBNode(dev_data, cb); 2228d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes if (cb_node) { 2229d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes for (auto queryEventsPair : cb_node->waitedEventsBeforeQueryReset) { 2230d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes for (auto event : queryEventsPair.second) { 2231d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes if (dev_data->eventMap[event].needsSignaled) { 2232d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 2233d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 0, DRAWSTATE_INVALID_QUERY, "DS", 2234d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes "Cannot get query results on queryPool 0x%" PRIx64 2235d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes " with index %d which was guarded by unsignaled event 0x%" PRIx64 ".", 22369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(queryEventsPair.first.pool), queryEventsPair.first.index, 22379b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(event)); 2238d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes } 2239b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 2240b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 2241b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 2242b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 2243b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 2244d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 2245d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes // finally mark the point we've now validated this queue to. 2246d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes done_seqs[queue] = seq; 224792b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis } 2248d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 2249b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis return skip; 2250b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis} 2251b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis 2252b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// When the given fence is retired, verify outstanding queue operations through the point of the fence 2253b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic bool VerifyQueueStateToFence(layer_data *dev_data, VkFence fence) { 22549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fence_state = GetFenceNode(dev_data, fence); 2255b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis if (VK_NULL_HANDLE != fence_state->signaler.first) { 22569a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return VerifyQueueStateToSeq(dev_data, GetQueueState(dev_data, fence_state->signaler.first), fence_state->signaler.second); 2257b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 2258b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis return false; 2259b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 22607d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes 2261a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis// Decrement in-use count for objects bound to command buffer 22622f8cbf3b166e175174877a59929902e005953d6dTobin Ehlisstatic void DecrementBoundResources(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) { 226300e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis BASE_NODE *base_obj = nullptr; 2264a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis for (auto obj : cb_node->object_bindings) { 22657e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis base_obj = GetStateStructPtrFromObject(dev_data, obj); 226600e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis if (base_obj) { 226700e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis base_obj->in_use.fetch_sub(1); 226800e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis } 2269a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis } 2270a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis} 2271da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes 227236c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void RetireWorkOnQueue(layer_data *dev_data, QUEUE_STATE *pQueue, uint64_t seq) { 22739867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::unordered_map<VkQueue, uint64_t> otherQueueSeqs; 22749867daedbf52debc77d6568162ee21e071699b80Chris Forbes 22759867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Roll this queue forward, one submission at a time. 22769867daedbf52debc77d6568162ee21e071699b80Chris Forbes while (pQueue->seq < seq) { 2277bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &submission = pQueue->submissions.front(); 22789867daedbf52debc77d6568162ee21e071699b80Chris Forbes 2279bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &wait : submission.waitSemaphores) { 22809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, wait.semaphore); 2281c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (pSemaphore) { 2282c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski pSemaphore->in_use.fetch_sub(1); 2283c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 2284bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &lastSeq = otherQueueSeqs[wait.queue]; 22859867daedbf52debc77d6568162ee21e071699b80Chris Forbes lastSeq = std::max(lastSeq, wait.seq); 2286da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 2287cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes 2288bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &semaphore : submission.signalSemaphores) { 22899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 2290c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (pSemaphore) { 2291c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski pSemaphore->in_use.fetch_sub(1); 2292c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 22939867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 2294cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes 22959867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto cb : submission.cbs) { 22969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, cb); 2297c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (!cb_node) { 2298c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski continue; 2299c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 2300a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // First perform decrement on general case bound objects 23019a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis DecrementBoundResources(dev_data, cb_node); 23029a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto drawDataElement : cb_node->drawData) { 23039867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto buffer : drawDataElement.buffers) { 23049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 23055cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 23065cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->in_use.fetch_sub(1); 23079867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 23089867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 2309da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 23109a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto event : cb_node->writeEventsBeforeWait) { 23119867daedbf52debc77d6568162ee21e071699b80Chris Forbes auto eventNode = dev_data->eventMap.find(event); 23129867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (eventNode != dev_data->eventMap.end()) { 23139867daedbf52debc77d6568162ee21e071699b80Chris Forbes eventNode->second.write_in_use--; 23149867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 23159867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 23169a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto queryStatePair : cb_node->queryToStateMap) { 23179867daedbf52debc77d6568162ee21e071699b80Chris Forbes dev_data->queryToStateMap[queryStatePair.first] = queryStatePair.second; 23189867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 23199a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto eventStagePair : cb_node->eventToStageMap) { 23209867daedbf52debc77d6568162ee21e071699b80Chris Forbes dev_data->eventMap[eventStagePair.first].stageMask = eventStagePair.second; 2321da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 23220a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine 2323a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes cb_node->in_use.fetch_sub(1); 23240a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 23259867daedbf52debc77d6568162ee21e071699b80Chris Forbes 23269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, submission.fence); 23279867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence) { 23289867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->state = FENCE_RETIRED; 23290a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 23309867daedbf52debc77d6568162ee21e071699b80Chris Forbes 23319867daedbf52debc77d6568162ee21e071699b80Chris Forbes pQueue->submissions.pop_front(); 23329867daedbf52debc77d6568162ee21e071699b80Chris Forbes pQueue->seq++; 2333b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 23349867daedbf52debc77d6568162ee21e071699b80Chris Forbes 23359867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Roll other queues forward to the highest seq we saw a wait for 23369867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto qs : otherQueueSeqs) { 23379a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis RetireWorkOnQueue(dev_data, GetQueueState(dev_data, qs.first), qs.second); 2338d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 23399867daedbf52debc77d6568162ee21e071699b80Chris Forbes} 2340651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 2341651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// Submit a fence to a queue, delimiting previous fences and previous untracked 2342651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// work by it. 234336c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void SubmitFence(QUEUE_STATE *pQueue, FENCE_NODE *pFence, uint64_t submitCount) { 2344cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes pFence->state = FENCE_INFLIGHT; 23459867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->signaler.first = pQueue->queue; 23469867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->signaler.second = pQueue->seq + pQueue->submissions.size() + submitCount; 2347b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 2348b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine 234951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateCommandBufferSimultaneousUse(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) { 23503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 2351a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes if ((pCB->in_use.load() || current_submit_count > 1) && 23525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 23533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 2354315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_31a0008e, "DS", 23553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Command Buffer 0x%p is already in use and is not marked for simultaneous use. %s", pCB->commandBuffer, 2356315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_31a0008e]); 23575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 23595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 23605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2361946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinskistatic bool validateCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const char *call_source, 23620de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski int current_submit_count, UNIQUE_VALIDATION_ERROR_CODE vu_id) { 2363c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis bool skip = false; 2364cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.command_buffer_state) return skip; 23650a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis // Validate ONE_TIME_SUBMIT_BIT CB is not being submitted more than once 2366946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if ((cb_state->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) && 2367946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (cb_state->submitCount + current_submit_count > 1)) { 2368c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 2369c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis __LINE__, DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS", 2370226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Commandbuffer 0x%p was begun w/ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT " 2371c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis "set, but has been submitted 0x%" PRIxLEAST64 " times.", 2372946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->commandBuffer, cb_state->submitCount + current_submit_count); 23730a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis } 237494307efee520ad91d5da2ff8f40609b31f05b2efChris Forbes 23755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate that cmd buffers have been updated 2376946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (CB_RECORDED != cb_state->state) { 2377946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (CB_INVALID == cb_state->state) { 2378946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ReportInvalidCommandBuffer(dev_data, cb_state, call_source); 23790de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski } else if (CB_NEW == cb_state->state) { 23800de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 23810de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski (uint64_t)(cb_state->commandBuffer), __LINE__, vu_id, "DS", 23820de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski "Command buffer 0x%p used in the call to %s is unrecorded and contains no commands. %s", 23830de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski cb_state->commandBuffer, call_source, validation_error_map[vu_id]); 2384cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Flag error for using CB w/o vkEndCommandBuffer() called 2385c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 23869b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_NO_END_COMMAND_BUFFER, "DS", 2387946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "You must call vkEndCommandBuffer() on command buffer 0x%p before this call to %s!", 2388946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->commandBuffer, call_source); 23895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2391c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis return skip; 23925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 23935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 239451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 23953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 239651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 239751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // TODO : We should be able to remove the NULL look-up checks from the code below as long as 239851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state 239951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // should then be flagged prior to calling this function 240051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto drawDataElement : cb_node->drawData) { 240151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto buffer : drawDataElement.buffers) { 240251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto buffer_state = GetBufferState(dev_data, buffer); 240351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (!buffer_state) { 24043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 24059b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(buffer), __LINE__, DRAWSTATE_INVALID_BUFFER, "DS", 24069b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Cannot submit cmd buffer using deleted buffer 0x%" PRIx64 ".", HandleToUint64(buffer)); 240751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 240851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 240951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 24103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 241151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 241251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 2413f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski// Check that the queue family index of 'queue' matches one of the entries in pQueueFamilyIndices 2414f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinskibool ValidImageBufferQueue(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const VK_OBJECT *object, VkQueue queue, uint32_t count, 2415f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski const uint32_t *indices) { 2416f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski bool found = false; 2417f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski bool skip = false; 2418f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski auto queue_state = GetQueueState(dev_data, queue); 2419f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (queue_state) { 2420f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski for (uint32_t i = 0; i < count; i++) { 2421f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (indices[i] == queue_state->queueFamilyIndex) { 2422f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski found = true; 2423f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski break; 2424f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 2425f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 2426f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski 2427f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (!found) { 24289b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip = log_msg( 24299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[object->type], object->handle, __LINE__, 24309b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus DRAWSTATE_INVALID_QUEUE_FAMILY, "DS", "vkQueueSubmit: Command buffer 0x%" PRIxLEAST64 " contains %s 0x%" PRIxLEAST64 24319b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus " which was not created allowing concurrent access to this queue family %d.", 24329b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), object_string[object->type], object->handle, queue_state->queueFamilyIndex); 2433f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 2434f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 2435f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski return skip; 2436f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski} 2437f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski 24387bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Validate that queueFamilyIndices of primary command buffers match this queue 24397bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Secondary command buffers were previously validated in vkCmdExecuteCommands(). 24407bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinskistatic bool validateQueueFamilyIndices(layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkQueue queue) { 24413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 24429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool); 24439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto queue_state = GetQueueState(dev_data, queue); 24447bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 2445f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (pPool && queue_state) { 2446f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (pPool->queueFamilyIndex != queue_state->queueFamilyIndex) { 24473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2448315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_31a00094, "DS", 24493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkQueueSubmit: Primary command buffer 0x%p created in queue family %d is being submitted on queue " 24503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "0x%p from queue family %d. %s", 24513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCB->commandBuffer, pPool->queueFamilyIndex, queue, queue_state->queueFamilyIndex, 2452315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_31a00094]); 2453f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 2454f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski 2455f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski // Ensure that any bound images or buffers created with SHARING_MODE_CONCURRENT have access to the current queue family 2456f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski for (auto object : pCB->object_bindings) { 24577a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski if (object.type == kVulkanObjectTypeImage) { 2458f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski auto image_state = GetImageState(dev_data, reinterpret_cast<VkImage &>(object.handle)); 2459f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (image_state && image_state->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { 24603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidImageBufferQueue(dev_data, pCB, &object, queue, image_state->createInfo.queueFamilyIndexCount, 24613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski image_state->createInfo.pQueueFamilyIndices); 2462f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 24637a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski } else if (object.type == kVulkanObjectTypeBuffer) { 2464f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski auto buffer_state = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(object.handle)); 2465f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (buffer_state && buffer_state->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { 24663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidImageBufferQueue(dev_data, pCB, &object, queue, buffer_state->createInfo.queueFamilyIndexCount, 24673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski buffer_state->createInfo.pQueueFamilyIndices); 2468f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 2469f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 2470f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 24717bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski } 24727bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 24733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 24747bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski} 24757bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 247651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) { 24775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Track in-use for resources off of primary and any secondary CBs 24783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 2479a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 2480a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes // If USAGE_SIMULTANEOUS_USE_BIT not set then CB cannot already be executing 2481a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes // on device 24823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateCommandBufferSimultaneousUse(dev_data, pCB, current_submit_count); 2483a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 24843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateResources(dev_data, pCB); 2485a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 24861a3660584634742a3297915c94768d73f360e794Chris Forbes for (auto pSubCB : pCB->linkedCommandBuffers) { 248711decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes skip |= validateResources(dev_data, pSubCB); 24881a3660584634742a3297915c94768d73f360e794Chris Forbes // TODO: replace with invalidateCommandBuffers() at recording. 248911decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes if ((pSubCB->primaryCommandBuffer != pCB->commandBuffer) && 249011decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes !(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 2491315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 2492315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_31a00092, "DS", 2493315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "Commandbuffer 0x%p was submitted with secondary buffer 0x%p but that buffer has subsequently been bound to " 2494f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "primary cmd buffer 0x%p and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. %s", 2495315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis pCB->commandBuffer, pSubCB->commandBuffer, pSubCB->primaryCommandBuffer, 2496315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_31a00092]); 24975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 24985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2499a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 2500315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= validateCommandBufferState(dev_data, pCB, "vkQueueSubmit()", current_submit_count, VALIDATION_ERROR_31a00090); 2501a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 25023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 25035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 25045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2505bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool ValidateFenceForSubmit(layer_data *dev_data, FENCE_NODE *pFence) { 25063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 250781c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 2508651d92815dfff917308137bb67aacccc4f60df86Chris Forbes if (pFence) { 2509cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes if (pFence->state == FENCE_INFLIGHT) { 2510315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis // TODO: opportunities for VALIDATION_ERROR_31a00080, VALIDATION_ERROR_316008b4, VALIDATION_ERROR_16400a0e 25113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 25129b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pFence->fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", 25139b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Fence 0x%" PRIx64 " is already in use by another submission.", HandleToUint64(pFence->fence)); 2514a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis } 251581c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 2516cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes else if (pFence->state == FENCE_RETIRED) { 2517315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis // TODO: opportunities for VALIDATION_ERROR_31a0007e, VALIDATION_ERROR_316008b2, VALIDATION_ERROR_16400a0e 25183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 25199b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pFence->fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 25203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted", 25219b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pFence->fence)); 2522a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis } 25235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 252481c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 25253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 252681c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes} 252781c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 252851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void PostCallRecordQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, 252951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkFence fence) { 25309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pQueue = GetQueueState(dev_data, queue); 25319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 2532d7d60cccc862fee2d0b3ad410c5fdcc40ddc83aeChris Forbes 2533651d92815dfff917308137bb67aacccc4f60df86Chris Forbes // Mark the fence in-use. 2534651d92815dfff917308137bb67aacccc4f60df86Chris Forbes if (pFence) { 25359867daedbf52debc77d6568162ee21e071699b80Chris Forbes SubmitFence(pQueue, pFence, std::max(1u, submitCount)); 2536651d92815dfff917308137bb67aacccc4f60df86Chris Forbes } 2537651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 253851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // Now process each individual submit 25395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 254051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour std::vector<VkCommandBuffer> cbs; 25415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubmitInfo *submit = &pSubmits[submit_idx]; 25429867daedbf52debc77d6568162ee21e071699b80Chris Forbes vector<SEMAPHORE_WAIT> semaphore_waits; 25439867daedbf52debc77d6568162ee21e071699b80Chris Forbes vector<VkSemaphore> semaphore_signals; 25445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) { 254551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkSemaphore semaphore = submit->pWaitSemaphores[i]; 254651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 254751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore) { 254851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore->signaler.first != VK_NULL_HANDLE) { 254951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second}); 255051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->in_use.fetch_add(1); 255151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 255251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.first = VK_NULL_HANDLE; 255351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaled = false; 255451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 255551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 255651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) { 255751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkSemaphore semaphore = submit->pSignalSemaphores[i]; 255851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 255951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore) { 256051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.first = queue; 256151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1; 256251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaled = true; 256351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->in_use.fetch_add(1); 256451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour semaphore_signals.push_back(semaphore); 256551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 256651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 256751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->commandBufferCount; i++) { 256851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]); 256951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (cb_node) { 257051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cbs.push_back(submit->pCommandBuffers[i]); 25711a3660584634742a3297915c94768d73f360e794Chris Forbes for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) { 257211decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes cbs.push_back(secondaryCmdBuffer->commandBuffer); 257351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 257451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour UpdateCmdBufImageLayouts(dev_data, cb_node); 257551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour incrementResources(dev_data, cb_node); 25761a3660584634742a3297915c94768d73f360e794Chris Forbes for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) { 257711decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes incrementResources(dev_data, secondaryCmdBuffer); 257851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 257951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 258051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 258151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pQueue->submissions.emplace_back(cbs, semaphore_waits, semaphore_signals, 258251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour submit_idx == submitCount - 1 ? fence : VK_NULL_HANDLE); 258351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 258451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 258551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pFence && !submitCount) { 258651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // If no submissions, but just dropping a fence on the end of the queue, 258751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // record an empty submission with just the fence, so we can determine 258851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // its completion. 258951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(), std::vector<VkSemaphore>(), 259051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour fence); 259151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 259251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 259351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 259451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool PreCallValidateQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, 259551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkFence fence) { 259651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pFence = GetFenceNode(dev_data, fence); 25973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = ValidateFenceForSubmit(dev_data, pFence); 25983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 259951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return true; 260051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 260151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 260251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_set<VkSemaphore> signaled_semaphores; 260351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_set<VkSemaphore> unsignaled_semaphores; 260451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour vector<VkCommandBuffer> current_cmds; 260551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> localImageLayoutMap = dev_data->imageLayoutMap; 260651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // Now verify each individual submit 260751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 260851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour const VkSubmitInfo *submit = &pSubmits[submit_idx]; 260951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) { 2610315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, submit->pWaitDstStageMask[i], "vkQueueSubmit()", 2611315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_13c00098, VALIDATION_ERROR_13c0009a); 261201a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = submit->pWaitSemaphores[i]; 26139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 261401a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 261551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (unsignaled_semaphores.count(semaphore) || 2616440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour (!(signaled_semaphores.count(semaphore)) && !(pSemaphore->signaled))) { 26173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 26189b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 26193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue, 26209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(semaphore)); 262151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } else { 262251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour signaled_semaphores.erase(semaphore); 262351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unsignaled_semaphores.insert(semaphore); 26241344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 26255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 26265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 26275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) { 262801a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = submit->pSignalSemaphores[i]; 26299a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 263001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 2631440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour if (signaled_semaphores.count(semaphore) || (!(unsignaled_semaphores.count(semaphore)) && pSemaphore->signaled)) { 26323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 26339b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 26343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Queue 0x%p is signaling semaphore 0x%" PRIx64 26353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " that has already been signaled but not waited on by queue 0x%" PRIx64 ".", 26369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus queue, HandleToUint64(semaphore), HandleToUint64(pSemaphore->signaler.first)); 26371344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } else { 263851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unsignaled_semaphores.erase(semaphore); 263951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour signaled_semaphores.insert(semaphore); 26401344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 26410a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 26425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 26435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->commandBufferCount; i++) { 26449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]); 2645d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node) { 26463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdBufImageLayouts(dev_data, cb_node, localImageLayoutMap); 264751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour current_cmds.push_back(submit->pCommandBuffers[i]); 26483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validatePrimaryCommandBufferState( 264951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour dev_data, cb_node, (int)std::count(current_cmds.begin(), current_cmds.end(), submit->pCommandBuffers[i])); 26503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateQueueFamilyIndices(dev_data, cb_node, queue); 265151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 2652ea371fa7c8c57edb4d1436e4570cf54f3fc0463fTobin Ehlis // Potential early exit here as bad object state may crash in delayed function calls 26533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 265451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return true; 265551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 265651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 26571344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis // Call submit-time functions to validate/update state 2658d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->validate_functions) { 26593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= function(); 26601344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 2661d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->eventUpdates) { 26623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= function(queue); 26631344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 2664d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->queryUpdates) { 26653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= function(queue); 2666d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 26671344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 26685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 26699867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 26703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 267151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 26729867daedbf52debc77d6568162ee21e071699b80Chris Forbes 267351920949f887ce8d3666c73c28ff19a5d8325a37Tony BarbourVKAPI_ATTR VkResult VKAPI_CALL QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) { 267451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 267551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour std::unique_lock<std::mutex> lock(global_lock); 267651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 267751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour bool skip = PreCallValidateQueueSubmit(dev_data, queue, submitCount, pSubmits, fence); 2678b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 26795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2680440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 268151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 268251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkResult result = dev_data->dispatch_table.QueueSubmit(queue, submitCount, pSubmits, fence); 268351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 268451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour lock.lock(); 268551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour PostCallRecordQueueSubmit(dev_data, queue, submitCount, pSubmits, fence); 268651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour lock.unlock(); 26875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 26885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 26895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2690f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic bool PreCallValidateAllocateMemory(layer_data *dev_data) { 2691f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz bool skip = false; 2692f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (dev_data->memObjMap.size() >= dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount) { 2693f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 2694315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_16c004f8, "MEM", 2695f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz "Number of currently valid memory objects is not less than the maximum allowed (%u). %s", 2696f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount, 2697315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_16c004f8]); 2698f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz } 2699f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz return skip; 2700f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz} 2701f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz 2702f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic void PostCallRecordAllocateMemory(layer_data *dev_data, const VkMemoryAllocateInfo *pAllocateInfo, VkDeviceMemory *pMemory) { 2703f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz add_mem_obj_info(dev_data, dev_data->device, *pMemory, pAllocateInfo); 2704f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz return; 2705f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz} 2706f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz 270789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo, 270889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) { 2709f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 271056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 2711f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz std::unique_lock<std::mutex> lock(global_lock); 2712f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz bool skip = PreCallValidateAllocateMemory(dev_data); 2713f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (!skip) { 2714f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz lock.unlock(); 2715f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz result = dev_data->dispatch_table.AllocateMemory(device, pAllocateInfo, pAllocator, pMemory); 2716f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz lock.lock(); 2717f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (VK_SUCCESS == result) { 2718f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz PostCallRecordAllocateMemory(dev_data, pAllocateInfo, pMemory); 2719f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz } 2720e12739a56d02ca2fb5f0273862668e7475a21a6cMark Lobodzinski } 27215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 27225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 27235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2724177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis// For given obj node, if it is use, flag a validation error and return callback result, else return false 2725177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisbool ValidateObjectNotInUse(const layer_data *dev_data, BASE_NODE *obj_node, VK_OBJECT obj_struct, 2726177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 2727cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.object_in_use) return false; 2728177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = false; 2729177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (obj_node->in_use.load()) { 27307a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski skip |= 273102a510945ff39f3d9e486e456aca5bfa6ea0c43aMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[obj_struct.type], obj_struct.handle, 27327a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski __LINE__, error_code, "DS", "Cannot delete %s 0x%" PRIx64 " that is currently in use by a command buffer. %s", 27337a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski object_string[obj_struct.type], obj_struct.handle, validation_error_map[error_code]); 2734177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 2735177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis return skip; 2736177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 27375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2738177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic bool PreCallValidateFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO **mem_info, VK_OBJECT *obj_struct) { 27399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *mem_info = GetMemObjInfo(dev_data, mem); 27409b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(mem), kVulkanObjectTypeDeviceMemory}; 2741cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.free_memory) return false; 2742177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = false; 2743177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (*mem_info) { 2744315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *mem_info, *obj_struct, VALIDATION_ERROR_2880054a); 2745177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 2746177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis return skip; 2747177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 27485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2749177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic void PostCallRecordFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO *mem_info, VK_OBJECT obj_struct) { 2750177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis // Clear mem binding for any bound objects 275147705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis for (auto obj : mem_info->obj_bindings) { 275202a510945ff39f3d9e486e456aca5bfa6ea0c43aMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, get_debug_report_enum[obj.type], obj.handle, __LINE__, 27537a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski MEMTRACK_FREED_MEM_REF, "MEM", "VK Object 0x%" PRIxLEAST64 " still has a reference to mem obj 0x%" PRIxLEAST64, 27549b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus obj.handle, HandleToUint64(mem_info->mem)); 275547705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis switch (obj.type) { 27567a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski case kVulkanObjectTypeImage: { 27579a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, reinterpret_cast<VkImage &>(obj.handle)); 2758cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(image_state); // Any destroyed images should already be removed from bindings 2759cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski image_state->binding.mem = MEMORY_UNBOUND; 2760cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2761cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 27627a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski case kVulkanObjectTypeBuffer: { 27639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(obj.handle)); 2764cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(buffer_state); // Any destroyed buffers should already be removed from bindings 2765cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski buffer_state->binding.mem = MEMORY_UNBOUND; 2766cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2767cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 2768cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 2769cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Should only have buffer or image objects bound to memory 2770cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(0); 2771177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 2772177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 2773177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis // Any bound cmd buffers are now invalid 277439c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, mem_info->cb_bindings, obj_struct); 2775177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis dev_data->memObjMap.erase(mem); 2776177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 2777177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis 2778177063aac84fac6f4e650c2629a08b48be643f96Tobin EhlisVKAPI_ATTR void VKAPI_CALL FreeMemory(VkDevice device, VkDeviceMemory mem, const VkAllocationCallbacks *pAllocator) { 277956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 2780177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis DEVICE_MEM_INFO *mem_info = nullptr; 2781177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis VK_OBJECT obj_struct; 2782b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 2783177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = PreCallValidateFreeMemory(dev_data, mem, &mem_info, &obj_struct); 2784177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (!skip) { 2785177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis lock.unlock(); 2786177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis dev_data->dispatch_table.FreeMemory(device, mem, pAllocator); 2787177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis lock.lock(); 2788405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (mem != VK_NULL_HANDLE) { 2789405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordFreeMemory(dev_data, mem, mem_info, obj_struct); 2790405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 279174243a735fe102b370237ddf80d3e6f7ec5246dbMark Mueller } 27925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 27935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2794f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// Validate that given Map memory range is valid. This means that the memory should not already be mapped, 2795f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// and that the size of the map range should be: 2796f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// 1. Not zero 2797f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// 2. Within the size of the memory allocation 279851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidateMapMemRange(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) { 27993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 28005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 28015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == 0) { 28023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 28039b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem), __LINE__, MEMTRACK_INVALID_MAP, "MEM", 28043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VkMapMemory: Attempting to map memory range of size zero"); 28055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 280751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto mem_element = dev_data->memObjMap.find(mem); 280851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (mem_element != dev_data->memObjMap.end()) { 280957fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis auto mem_info = mem_element->second.get(); 28105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // It is an application error to call VkMapMemory on an object that is already mapped 2811de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (mem_info->mem_range.size != 0) { 28129b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip = 28139b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 28149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem), __LINE__, MEMTRACK_INVALID_MAP, "MEM", 28159b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "VkMapMemory: Attempting to map memory on an already-mapped object 0x%" PRIxLEAST64, HandleToUint64(mem)); 28165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 28185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate that offset + size is within object's allocationSize 28195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == VK_WHOLE_SIZE) { 2820de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (offset >= mem_info->alloc_info.allocationSize) { 28213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 28229b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem), __LINE__, MEMTRACK_INVALID_MAP, "MEM", 28233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 28243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " with size of VK_WHOLE_SIZE oversteps total array size 0x%" PRIx64, 28253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski offset, mem_info->alloc_info.allocationSize, mem_info->alloc_info.allocationSize); 28265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 2828de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if ((offset + size) > mem_info->alloc_info.allocationSize) { 28293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 2830315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(mem), __LINE__, VALIDATION_ERROR_31200552, "MEM", 28313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " oversteps total array size 0x%" PRIx64 ". %s", 28323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski offset, size + offset, mem_info->alloc_info.allocationSize, 2833315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_31200552]); 28345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 28385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 28395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 284051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void storeMemRanges(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) { 28419a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 284257fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 2843de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.offset = offset; 2844de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.size = size; 28455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 28475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 284851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool deleteMemRanges(layer_data *dev_data, VkDeviceMemory mem) { 28493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 28509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 285157fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 2852de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (!mem_info->mem_range.size) { 28535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Valid Usage: memory must currently be mapped 28543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 2855315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(mem), __LINE__, VALIDATION_ERROR_33600562, "MEM", 28569b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Unmapping Memory without memory being mapped: mem obj 0x%" PRIxLEAST64 ". %s", HandleToUint64(mem), 2857315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_33600562]); 28585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2859de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.size = 0; 28605f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info->shadow_copy) { 28615f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski free(mem_info->shadow_copy_base); 28625f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy_base = 0; 28635f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 0; 28645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 28675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 28685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 28695f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski// Guard value for pad data 28705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic char NoncoherentMemoryFillValue = 0xb; 28715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 28725f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinskistatic void initializeAndTrackMemory(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, 28735f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski void **ppData) { 28749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 287557fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 2876de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->p_driver_data = *ppData; 2877de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis uint32_t index = mem_info->alloc_info.memoryTypeIndex; 2878b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis if (dev_data->phys_dev_mem_props.memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) { 28795f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 0; 28805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 28815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == VK_WHOLE_SIZE) { 28825f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski size = mem_info->alloc_info.allocationSize - offset; 28835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28845f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_pad_size = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment; 288516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton assert(SafeModulo(mem_info->shadow_pad_size, 28865f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment) == 0); 28875f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // Ensure start of mapped region reflects hardware alignment constraints 28885f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski uint64_t map_alignment = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment; 28895f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 28905f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // From spec: (ppData - offset) must be aligned to at least limits::minMemoryMapAlignment. 28915f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski uint64_t start_offset = offset % map_alignment; 28925f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // Data passed to driver will be wrapped by a guardband of data to detect over- or under-writes. 2893bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski mem_info->shadow_copy_base = 2894bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski malloc(static_cast<size_t>(2 * mem_info->shadow_pad_size + size + map_alignment + start_offset)); 28955f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 28965f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 28975f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski reinterpret_cast<char *>((reinterpret_cast<uintptr_t>(mem_info->shadow_copy_base) + map_alignment) & 2898bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski ~(map_alignment - 1)) + 2899bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski start_offset; 290016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton assert(SafeModulo(reinterpret_cast<uintptr_t>(mem_info->shadow_copy) + mem_info->shadow_pad_size - start_offset, 29015f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski map_alignment) == 0); 29025f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 29036e17c244b21ce43ac57404a00a0d844039eed363Mark Lobodzinski memset(mem_info->shadow_copy, NoncoherentMemoryFillValue, static_cast<size_t>(2 * mem_info->shadow_pad_size + size)); 29045f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski *ppData = static_cast<char *>(mem_info->shadow_copy) + mem_info->shadow_pad_size; 29055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 29085f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 2909a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis// Verify that state for fence being waited on is appropriate. That is, 29109867daedbf52debc77d6568162ee21e071699b80Chris Forbes// a fence being waited on should not already be signaled and 2911a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis// it should have been submitted on a queue or during acquire next image 291249f6132af865afd5b7f413c91125971ac97c135aChris Forbesstatic inline bool verifyWaitFenceState(layer_data *dev_data, VkFence fence, const char *apiCall) { 29133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 29149b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes 29159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 29169b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes if (pFence) { 2917cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes if (pFence->state == FENCE_UNSIGNALED) { 29183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 29199b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 29203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s called for fence 0x%" PRIxLEAST64 29213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " which has not been submitted on a Queue or during " 29223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "acquire next image.", 29239b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus apiCall, HandleToUint64(fence)); 29245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 29275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 2928a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 2929b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void RetireFence(layer_data *dev_data, VkFence fence) { 29309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 2931b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes if (pFence->signaler.first != VK_NULL_HANDLE) { 293225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Fence signaller is a queue -- use this as proof that prior operations on that queue have completed. 29339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis RetireWorkOnQueue(dev_data, GetQueueState(dev_data, pFence->signaler.first), pFence->signaler.second); 2934bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 293525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Fence signaller is the WSI. We're not tracking what the WSI op actually /was/ in CV yet, but we need to mark 293625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // the fence as retired. 2937d4513979120463171eb479cdded9336eb9944da1Chris Forbes pFence->state = FENCE_RETIRED; 2938d4513979120463171eb479cdded9336eb9944da1Chris Forbes } 2939b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes} 2940b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes 2941accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlisstatic bool PreCallValidateWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences) { 2942cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.wait_for_fences) return false; 2943accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis bool skip = false; 2944accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis for (uint32_t i = 0; i < fence_count; i++) { 2945accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis skip |= verifyWaitFenceState(dev_data, fences[i], "vkWaitForFences"); 2946b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis skip |= VerifyQueueStateToFence(dev_data, fences[i]); 2947accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 2948accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis return skip; 2949accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis} 2950accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis 2951b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences, VkBool32 wait_all) { 2952b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis // When we know that all fences are complete we can clean/remove their CBs 2953accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis if ((VK_TRUE == wait_all) || (1 == fence_count)) { 2954accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis for (uint32_t i = 0; i < fence_count; i++) { 2955b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis RetireFence(dev_data, fences[i]); 2956accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 2957accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 2958accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis // NOTE : Alternate case not handled here is when some fences have completed. In 2959accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis // this case for app to guarantee which fences completed it will have to call 2960b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis // vkGetFenceStatus() at which point we'll clean/remove their CBs if complete. 2961accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis} 2962accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis 2963bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, 2964bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint64_t timeout) { 296556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 29665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Verify fence status of submitted fences 2967b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 2968accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis bool skip = PreCallValidateWaitForFences(dev_data, fenceCount, pFences); 2969b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 2970cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 2971a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 29724a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.WaitForFences(device, fenceCount, pFences, waitAll, timeout); 2973414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller 29745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 2975b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 2976b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis PostCallRecordWaitForFences(dev_data, fenceCount, pFences, waitAll); 2977b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 29785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 29805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 29815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2982f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlisstatic bool PreCallValidateGetFenceStatus(layer_data *dev_data, VkFence fence) { 2983cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.get_fence_state) return false; 2984f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis return verifyWaitFenceState(dev_data, fence, "vkGetFenceStatus"); 2985f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis} 2986f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis 2987b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordGetFenceStatus(layer_data *dev_data, VkFence fence) { RetireFence(dev_data, fence); } 2988f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis 298989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL GetFenceStatus(VkDevice device, VkFence fence) { 299056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 2991b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 2992f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis bool skip = PreCallValidateGetFenceStatus(dev_data, fence); 2993b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 2994cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 2995a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 29964a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetFenceStatus(device, fence); 29975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 2998f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis lock.lock(); 2999b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis PostCallRecordGetFenceStatus(dev_data, fence); 3000f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis lock.unlock(); 30015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 30035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 30045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30053b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlisstatic void PostCallRecordGetDeviceQueue(layer_data *dev_data, uint32_t q_family_index, VkQueue queue) { 30063b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis // Add queue to tracking set only if it is new 30073b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis auto result = dev_data->queues.emplace(queue); 30083b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis if (result.second == true) { 300936c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis QUEUE_STATE *queue_state = &dev_data->queueMap[queue]; 30103b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->queue = queue; 30113b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->queueFamilyIndex = q_family_index; 30123b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->seq = 0; 30133b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis } 30143b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis} 30153b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis 3016bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) { 301756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 30184a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue); 3019b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 3020b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski 30213b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis PostCallRecordGetDeviceQueue(dev_data, queueFamilyIndex, *pQueue); 30225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 30235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 302436c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic bool PreCallValidateQueueWaitIdle(layer_data *dev_data, VkQueue queue, QUEUE_STATE **queue_state) { 30259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *queue_state = GetQueueState(dev_data, queue); 3026cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.queue_wait_idle) return false; 3027e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis return VerifyQueueStateToSeq(dev_data, *queue_state, (*queue_state)->seq + (*queue_state)->submissions.size()); 30284273a1c157585a645dca4c960086032793899d05Tobin Ehlis} 30294273a1c157585a645dca4c960086032793899d05Tobin Ehlis 303036c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void PostCallRecordQueueWaitIdle(layer_data *dev_data, QUEUE_STATE *queue_state) { 3031e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis RetireWorkOnQueue(dev_data, queue_state, queue_state->seq + queue_state->submissions.size()); 30324273a1c157585a645dca4c960086032793899d05Tobin Ehlis} 30334273a1c157585a645dca4c960086032793899d05Tobin Ehlis 303489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueueWaitIdle(VkQueue queue) { 303556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 303636c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis QUEUE_STATE *queue_state = nullptr; 30379867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 30384273a1c157585a645dca4c960086032793899d05Tobin Ehlis bool skip = PreCallValidateQueueWaitIdle(dev_data, queue, &queue_state); 30399867daedbf52debc77d6568162ee21e071699b80Chris Forbes lock.unlock(); 3040cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 30414a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.QueueWaitIdle(queue); 30424273a1c157585a645dca4c960086032793899d05Tobin Ehlis if (VK_SUCCESS == result) { 3043e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis lock.lock(); 3044e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis PostCallRecordQueueWaitIdle(dev_data, queue_state); 3045e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis lock.unlock(); 30464273a1c157585a645dca4c960086032793899d05Tobin Ehlis } 30475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 30485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 30495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30508767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic bool PreCallValidateDeviceWaitIdle(layer_data *dev_data) { 3051cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.device_wait_idle) return false; 30528767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis bool skip = false; 30538767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis for (auto &queue : dev_data->queueMap) { 30548767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis skip |= VerifyQueueStateToSeq(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size()); 30558767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 30568767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis return skip; 30578767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis} 30588767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis 30598767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic void PostCallRecordDeviceWaitIdle(layer_data *dev_data) { 30608767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis for (auto &queue : dev_data->queueMap) { 30618767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis RetireWorkOnQueue(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size()); 30628767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 30638767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis} 30648767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis 306589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL DeviceWaitIdle(VkDevice device) { 306656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 3067b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 30688767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis bool skip = PreCallValidateDeviceWaitIdle(dev_data); 3069b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 3070cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 30714a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.DeviceWaitIdle(device); 30728767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis if (VK_SUCCESS == result) { 30738767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis lock.lock(); 30748767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis PostCallRecordDeviceWaitIdle(dev_data); 30758767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis lock.unlock(); 30768767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 30775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 30785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 30795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30801d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic bool PreCallValidateDestroyFence(layer_data *dev_data, VkFence fence, FENCE_NODE **fence_node, VK_OBJECT *obj_struct) { 30819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *fence_node = GetFenceNode(dev_data, fence); 30829b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(fence), kVulkanObjectTypeFence}; 3083cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_fence) return false; 30841d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis bool skip = false; 30851d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if (*fence_node) { 30861d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if ((*fence_node)->state == FENCE_INFLIGHT) { 30871d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 3088315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(fence), __LINE__, VALIDATION_ERROR_24e008c0, "DS", "Fence 0x%" PRIx64 " is in use. %s", 3089315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(fence), validation_error_map[VALIDATION_ERROR_24e008c0]); 30901d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 30911d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 30921d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis return skip; 30931d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis} 30941d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis 30951d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic void PostCallRecordDestroyFence(layer_data *dev_data, VkFence fence) { dev_data->fenceMap.erase(fence); } 30961d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis 309789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) { 309856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 30991d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis // Common data objects used pre & post call 31001d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis FENCE_NODE *fence_node = nullptr; 31011d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis VK_OBJECT obj_struct; 3102b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 31031d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis bool skip = PreCallValidateDestroyFence(dev_data, fence, &fence_node, &obj_struct); 31041344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 31051d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if (!skip) { 31061d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis lock.unlock(); 31074a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyFence(device, fence, pAllocator); 31081d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis lock.lock(); 31091d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis PostCallRecordDestroyFence(dev_data, fence); 31101d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 31115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 31125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3113c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic bool PreCallValidateDestroySemaphore(layer_data *dev_data, VkSemaphore semaphore, SEMAPHORE_NODE **sema_node, 3114c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis VK_OBJECT *obj_struct) { 31159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *sema_node = GetSemaphoreNode(dev_data, semaphore); 31169b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(semaphore), kVulkanObjectTypeSemaphore}; 3117cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_semaphore) return false; 3118c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis bool skip = false; 3119c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis if (*sema_node) { 3120315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *sema_node, *obj_struct, VALIDATION_ERROR_268008e2); 3121c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis } 3122c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis return skip; 3123c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis} 3124c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis 3125c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic void PostCallRecordDestroySemaphore(layer_data *dev_data, VkSemaphore sema) { dev_data->semaphoreMap.erase(sema); } 3126c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis 3127bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) { 312856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 3129c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis SEMAPHORE_NODE *sema_node; 3130c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis VK_OBJECT obj_struct; 3131e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 3132c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis bool skip = PreCallValidateDestroySemaphore(dev_data, semaphore, &sema_node, &obj_struct); 3133eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis if (!skip) { 3134eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis lock.unlock(); 31354a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroySemaphore(device, semaphore, pAllocator); 3136c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis lock.lock(); 3137c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis PostCallRecordDestroySemaphore(dev_data, semaphore); 313899d938c90c2f000ee73fb13513dacf84ffa5651fMark Mueller } 31395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 31405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 31414710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic bool PreCallValidateDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE **event_state, VK_OBJECT *obj_struct) { 31429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *event_state = GetEventNode(dev_data, event); 31439b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(event), kVulkanObjectTypeEvent}; 3144cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_event) return false; 3145d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis bool skip = false; 3146d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis if (*event_state) { 3147315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *event_state, *obj_struct, VALIDATION_ERROR_24c008f2); 3148d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis } 3149d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis return skip; 3150d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis} 3151d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis 31524710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic void PostCallRecordDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE *event_state, VK_OBJECT obj_struct) { 315339c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, event_state->cb_bindings, obj_struct); 3154d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis dev_data->eventMap.erase(event); 3155d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis} 3156d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis 315789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) { 315856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 31594710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis EVENT_STATE *event_state = nullptr; 3160d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis VK_OBJECT obj_struct; 3161b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 3162d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis bool skip = PreCallValidateDestroyEvent(dev_data, event, &event_state, &obj_struct); 3163f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 3164f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 31654a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyEvent(device, event, pAllocator); 3166d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis lock.lock(); 3167405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (event != VK_NULL_HANDLE) { 3168405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyEvent(dev_data, event, event_state, obj_struct); 3169405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 3170f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 31715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 31725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 317383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlisstatic bool PreCallValidateDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE **qp_state, 317483c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis VK_OBJECT *obj_struct) { 31759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *qp_state = GetQueryPoolNode(dev_data, query_pool); 31769b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(query_pool), kVulkanObjectTypeQueryPool}; 3177cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_query_pool) return false; 317883c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis bool skip = false; 317983c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis if (*qp_state) { 3180315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *qp_state, *obj_struct, VALIDATION_ERROR_26200632); 318183c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis } 318283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis return skip; 318383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis} 318483c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis 3185bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void PostCallRecordDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE *qp_state, 3186bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_OBJECT obj_struct) { 318783c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis invalidateCommandBuffers(dev_data, qp_state->cb_bindings, obj_struct); 318883c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis dev_data->queryPoolMap.erase(query_pool); 318983c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis} 319083c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis 3191bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks *pAllocator) { 319256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 319383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis QUERY_POOL_NODE *qp_state = nullptr; 319483c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis VK_OBJECT obj_struct; 3195ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 319683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis bool skip = PreCallValidateDestroyQueryPool(dev_data, queryPool, &qp_state, &obj_struct); 3197f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 3198f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 31994a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyQueryPool(device, queryPool, pAllocator); 320083c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis lock.lock(); 3201405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (queryPool != VK_NULL_HANDLE) { 3202405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyQueryPool(dev_data, queryPool, qp_state, obj_struct); 3203405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 3204f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 32055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 32069fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic bool PreCallValidateGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query, 32079fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis uint32_t query_count, VkQueryResultFlags flags, 32089fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) { 3209a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes // TODO: clean this up, it's insanely wasteful. 3210a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes for (auto cmd_buffer : dev_data->commandBufferMap) { 3211a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes if (cmd_buffer.second->in_use.load()) { 3212a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes for (auto query_state_pair : cmd_buffer.second->queryToStateMap) { 3213a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes (*queries_in_flight)[query_state_pair.first].push_back( 3214a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes cmd_buffer.first); 3215a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes } 32165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 32175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3218cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.get_query_pool_results) return false; 32199fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis bool skip = false; 32209fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (uint32_t i = 0; i < query_count; ++i) { 32219fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis QueryObject query = {query_pool, first_query + i}; 32229fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto qif_pair = queries_in_flight->find(query); 32239fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_state_pair = dev_data->queryToStateMap.find(query); 32249fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_state_pair != dev_data->queryToStateMap.end()) { 3225ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Available and in flight 32269fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 32279fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis query_state_pair->second) { 32289fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 32299a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 32309fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query); 32319fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_event_pair == cb->waitedEventsBeforeQueryReset.end()) { 32329fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 32339fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 32349fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is in flight.", 32359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(query_pool), first_query + i); 3236ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 3237ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 3238ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Unavailable and in flight 32399fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 32409fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis !query_state_pair->second) { 3241ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // TODO : Can there be the same query in use by multiple command buffers in flight? 3242ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski bool make_available = false; 32439fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 32449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 32459fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis make_available |= cb->queryToStateMap[query]; 3246ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 3247ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski if (!(((flags & VK_QUERY_RESULT_PARTIAL_BIT) || (flags & VK_QUERY_RESULT_WAIT_BIT)) && make_available)) { 32489fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 32499fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 32509fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.", 32519b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(query_pool), first_query + i); 32525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3253ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Unavailable 32549fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (query_state_pair != dev_data->queryToStateMap.end() && !query_state_pair->second) { 32559fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 32569fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 32579fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.", 32589b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(query_pool), first_query + i); 32599fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis // Uninitialized 32609fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (query_state_pair == dev_data->queryToStateMap.end()) { 32619fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 32629fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 32639fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 32649fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis " with index %d as data has not been collected for this index.", 32659b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(query_pool), first_query + i); 32665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 32675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 32685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 32699fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis return skip; 32709fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis} 32719fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis 32729fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic void PostCallRecordGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query, 32739fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis uint32_t query_count, 32749fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) { 32759fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (uint32_t i = 0; i < query_count; ++i) { 32769fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis QueryObject query = {query_pool, first_query + i}; 32779fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto qif_pair = queries_in_flight->find(query); 32789fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_state_pair = dev_data->queryToStateMap.find(query); 32799fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_state_pair != dev_data->queryToStateMap.end()) { 32809fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis // Available and in flight 32819fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 32829fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis query_state_pair->second) { 32839fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 32849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 32859fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query); 32869fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_event_pair != cb->waitedEventsBeforeQueryReset.end()) { 32879fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto event : query_event_pair->second) { 32889fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis dev_data->eventMap[event].needsSignaled = true; 32899fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 32909fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 32919fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 32929fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 32939fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 32949fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 32959fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis} 32969fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis 32979fdee42cd357379efb9aa27f90beb75d1f824955Tobin EhlisVKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, 32989fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis size_t dataSize, void *pData, VkDeviceSize stride, VkQueryResultFlags flags) { 329956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 33009fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> queries_in_flight; 33019fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 33029fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis bool skip = PreCallValidateGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, flags, &queries_in_flight); 3303b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 3304cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 33059fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VkResult result = 33069fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis dev_data->dispatch_table.GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags); 33079fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis lock.lock(); 33089fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis PostCallRecordGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, &queries_in_flight); 33099fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis lock.unlock(); 33109fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis return result; 33115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3313825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if given ranges intersect, else false 3314825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Prereq : For both ranges, range->end - range->start > 0. This case should have already resulted 3315825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// in an error so not checking that here 3316825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// pad_ranges bool indicates a linear and non-linear comparison which requires padding 33173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski// In the case where padding is required, if an alias is encountered then a validation error is reported and skip 33183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski// may be set by the callback function so caller should merge in skip value if padding case is possible. 33192ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton// This check can be skipped by passing skip_checks=true, for call sites outside the validation path. 33203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinskistatic bool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, MEMORY_RANGE const *range2, bool *skip, 33212ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton bool skip_checks) { 33223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski *skip = false; 3323825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r1_start = range1->start; 3324825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r1_end = range1->end; 3325825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r2_start = range2->start; 3326825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r2_end = range2->end; 3327825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis VkDeviceSize pad_align = 1; 3328825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis if (range1->linear != range2->linear) { 3329825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis pad_align = dev_data->phys_dev_properties.properties.limits.bufferImageGranularity; 3330825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 3331cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if ((r1_end & ~(pad_align - 1)) < (r2_start & ~(pad_align - 1))) return false; 3332cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if ((r1_start & ~(pad_align - 1)) > (r2_end & ~(pad_align - 1))) return false; 333347aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 33342ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton if (!skip_checks && (range1->linear != range2->linear)) { 333553ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis // In linear vs. non-linear case, warn of aliasing 3336825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r1_linear_str = range1->linear ? "Linear" : "Non-linear"; 3337825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r1_type_str = range1->image ? "image" : "buffer"; 3338825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r2_linear_str = range2->linear ? "linear" : "non-linear"; 3339825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r2_type_str = range2->image ? "image" : "buffer"; 3340825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto obj_type = range1->image ? VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT : VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT; 33413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski *skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, obj_type, range1->handle, 0, 33423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski MEMTRACK_INVALID_ALIASING, "MEM", "%s %s 0x%" PRIx64 " is aliased with %s %s 0x%" PRIx64 33433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " which may indicate a bug. For further info refer to the " 33443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Buffer-Image Granularity section of the Vulkan specification. " 33453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "(https://www.khronos.org/registry/vulkan/specs/1.0-extensions/" 33463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "xhtml/vkspec.html#resources-bufferimagegranularity)", 33473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski r1_linear_str, r1_type_str, range1->handle, r2_linear_str, r2_type_str, range2->handle); 334847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 3349825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Ranges intersect 3350825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis return true; 335147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 3352623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis// Simplified rangesIntersect that calls above function to check range1 for intersection with offset & end addresses 3353c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinskibool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, VkDeviceSize offset, VkDeviceSize end) { 3354825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Create a local MEMORY_RANGE struct to wrap offset/size 3355825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis MEMORY_RANGE range_wrap; 3356825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Synch linear with range1 to avoid padding and potential validation error case 3357825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range_wrap.linear = range1->linear; 3358825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range_wrap.start = offset; 3359cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis range_wrap.end = end; 3360825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis bool tmp_bool; 33612ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton return rangesIntersect(dev_data, range1, &range_wrap, &tmp_bool, true); 3362825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 3363cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given mem_info, set all ranges valid that intersect [offset-end] range 3364cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// TODO : For ranges where there is no alias, we may want to create new buffer ranges that are valid 3365cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlisstatic void SetMemRangesValid(layer_data const *dev_data, DEVICE_MEM_INFO *mem_info, VkDeviceSize offset, VkDeviceSize end) { 3366cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis bool tmp_bool = false; 3367f6e16b28b808a342cb92768001afa2cfeee08a11Tobin Ehlis MEMORY_RANGE map_range = {}; 3368cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.linear = true; 3369cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.start = offset; 3370cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.end = end; 3371cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis for (auto &handle_range_pair : mem_info->bound_ranges) { 33722ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton if (rangesIntersect(dev_data, &handle_range_pair.second, &map_range, &tmp_bool, false)) { 3373cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : WARN here if tmp_bool true? 3374cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis handle_range_pair.second.valid = true; 3375cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis } 3376cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis } 3377cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis} 33780ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 33790ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertMemoryRange(layer_data const *dev_data, uint64_t handle, DEVICE_MEM_INFO *mem_info, 33800ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkDeviceSize memoryOffset, VkMemoryRequirements memRequirements, bool is_image, 33810ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton bool is_linear, const char *api_name) { 33820ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton bool skip = false; 33830ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 33840ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton MEMORY_RANGE range; 33850ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.image = is_image; 33860ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.handle = handle; 33870ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.linear = is_linear; 33880ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.valid = mem_info->global_valid; 33890ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.memory = mem_info->mem; 33900ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.start = memoryOffset; 33910ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.size = memRequirements.size; 33920ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.end = memoryOffset + memRequirements.size - 1; 33930ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.aliases.clear(); 33940ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 33950ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Check for aliasing problems. 33960ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton for (auto &obj_range_pair : mem_info->bound_ranges) { 33970ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton auto check_range = &obj_range_pair.second; 33980ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton bool intersection_error = false; 33992ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton if (rangesIntersect(dev_data, &range, check_range, &intersection_error, false)) { 34000ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton skip |= intersection_error; 34010ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.aliases.insert(check_range); 34020ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 34030ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 34040ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 34050ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton if (memoryOffset >= mem_info->alloc_info.allocationSize) { 3406315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code = is_image ? VALIDATION_ERROR_1740082c : VALIDATION_ERROR_1700080e; 34070ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 34089b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem_info->mem), __LINE__, error_code, "MEM", 34090ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 34100ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton "), memoryOffset=0x%" PRIxLEAST64 " must be less than the memory allocation size 0x%" PRIxLEAST64 ". %s", 34119b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus api_name, HandleToUint64(mem_info->mem), handle, memoryOffset, mem_info->alloc_info.allocationSize, 34129b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus validation_error_map[error_code]); 34130ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 34140ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 34150ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton return skip; 34160ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton} 34170ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 3418825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Object with given handle is being bound to memory w/ given mem_info struct. 3419825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Track the newly bound memory range with given memoryOffset 3420825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Also scan any previous ranges, track aliased ranges with new range, and flag an error if a linear 3421825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// and non-linear range incorrectly overlap. 3422825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if an error is flagged and the user callback returns "true", otherwise false 3423825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_image indicates an image object, otherwise handle is for a buffer 3424825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_linear indicates a buffer or linear image 34250ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertMemoryRange(layer_data const *dev_data, uint64_t handle, DEVICE_MEM_INFO *mem_info, VkDeviceSize memoryOffset, 34260ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkMemoryRequirements memRequirements, bool is_image, bool is_linear) { 34275360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis MEMORY_RANGE range; 3428825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 3429825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.image = is_image; 343047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.handle = handle; 3431825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.linear = is_linear; 3432f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis range.valid = mem_info->global_valid; 3433825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.memory = mem_info->mem; 343447aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.start = memoryOffset; 3435825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.size = memRequirements.size; 343647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.end = memoryOffset + memRequirements.size - 1; 34375360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis range.aliases.clear(); 34385360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis // Update Memory aliasing 343975f4c8cec0996021a4258b9bf920a9e0fea4eac1Tobin 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 34405360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis // inserted into map before loop to get the final ptr, then we may enter loop when not needed & we check range against itself 34415360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis std::unordered_set<MEMORY_RANGE *> tmp_alias_ranges; 3442825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis for (auto &obj_range_pair : mem_info->bound_ranges) { 3443825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto check_range = &obj_range_pair.second; 34445360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis bool intersection_error = false; 34452ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton if (rangesIntersect(dev_data, &range, check_range, &intersection_error, true)) { 3446825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.aliases.insert(check_range); 34475360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis tmp_alias_ranges.insert(check_range); 3448825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 3449825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 34505360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis mem_info->bound_ranges[handle] = std::move(range); 34515360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis for (auto tmp_range : tmp_alias_ranges) { 34525360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis tmp_range->aliases.insert(&mem_info->bound_ranges[handle]); 34535360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis } 3454825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis if (is_image) 3455825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_images.insert(handle); 3456825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis else 3457825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_buffers.insert(handle); 345847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 345947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 34600ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertImageMemoryRange(layer_data const *dev_data, VkImage image, DEVICE_MEM_INFO *mem_info, 34610ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkDeviceSize mem_offset, VkMemoryRequirements mem_reqs, bool is_linear, 34620ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton const char *api_name) { 34639b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus return ValidateInsertMemoryRange(dev_data, HandleToUint64(image), mem_info, mem_offset, mem_reqs, true, is_linear, api_name); 34640ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton} 34650ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertImageMemoryRange(layer_data const *dev_data, VkImage image, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset, 34660ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkMemoryRequirements mem_reqs, bool is_linear) { 34679b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus InsertMemoryRange(dev_data, HandleToUint64(image), mem_info, mem_offset, mem_reqs, true, is_linear); 3468825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 3469825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 34700ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertBufferMemoryRange(layer_data const *dev_data, VkBuffer buffer, DEVICE_MEM_INFO *mem_info, 34710ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkDeviceSize mem_offset, VkMemoryRequirements mem_reqs, const char *api_name) { 34729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus return ValidateInsertMemoryRange(dev_data, HandleToUint64(buffer), mem_info, mem_offset, mem_reqs, false, true, api_name); 34730ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton} 34740ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertBufferMemoryRange(layer_data const *dev_data, VkBuffer buffer, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset, 34750ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkMemoryRequirements mem_reqs) { 34769b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus InsertMemoryRange(dev_data, HandleToUint64(buffer), mem_info, mem_offset, mem_reqs, false, true); 3477825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 3478825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 3479825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Remove MEMORY_RANGE struct for give handle from bound_ranges of mem_info 3480825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_image indicates if handle is for image or buffer 3481825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// This function will also remove the handle-to-index mapping from the appropriate 3482825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// map and clean up any aliases for range being removed. 3483825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlisstatic void RemoveMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info, bool is_image) { 3484825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto erase_range = &mem_info->bound_ranges[handle]; 3485825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis for (auto alias_range : erase_range->aliases) { 3486825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis alias_range->aliases.erase(erase_range); 348747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 34885360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis erase_range->aliases.clear(); 3489825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_ranges.erase(handle); 34901cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis if (is_image) { 3491825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_images.erase(handle); 34921cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis } else { 3493825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_buffers.erase(handle); 34941cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis } 349547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 349647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 3497842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid RemoveBufferMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, false); } 3498825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 34998c59133586421be878d393799b30044497f77727Mark Lobodzinskivoid RemoveImageMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, true); } 3500825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 3501bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) { 350256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 3503e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 3504e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis VK_OBJECT obj_struct; 3505b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 3506e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis bool skip = PreCallValidateDestroyBuffer(dev_data, buffer, &buffer_state, &obj_struct); 3507e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis if (!skip) { 3508b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 35094a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyBuffer(device, buffer, pAllocator); 3510e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis lock.lock(); 3511405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (buffer != VK_NULL_HANDLE) { 3512405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyBuffer(dev_data, buffer, buffer_state, obj_struct); 3513405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 351447aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 35155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 35165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3517bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator) { 351856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 3519f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis // Common data objects used pre & post call 35208e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis BUFFER_VIEW_STATE *buffer_view_state = nullptr; 35218e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis VK_OBJECT obj_struct; 3522a123662876eebfa844faa65ae3f071d3d77618ebTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 35238e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis // Validate state before calling down chain, update common data if we'll be calling down chain 35248e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis bool skip = PreCallValidateDestroyBufferView(dev_data, bufferView, &buffer_view_state, &obj_struct); 352538e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis if (!skip) { 352638e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis lock.unlock(); 35274a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyBufferView(device, bufferView, pAllocator); 35288e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis lock.lock(); 3529405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (bufferView != VK_NULL_HANDLE) { 3530405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyBufferView(dev_data, bufferView, buffer_view_state, obj_struct); 3531405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 35325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 35335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 35345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 35352a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) { 353656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 35371facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis IMAGE_STATE *image_state = nullptr; 35382a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis VK_OBJECT obj_struct; 35392a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 35402a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis bool skip = PreCallValidateDestroyImage(dev_data, image, &image_state, &obj_struct); 35412a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis if (!skip) { 3542f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis lock.unlock(); 35434a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyImage(device, image, pAllocator); 35442a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis lock.lock(); 3545405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (image != VK_NULL_HANDLE) { 3546405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyImage(dev_data, image, image_state, obj_struct); 3547405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 35485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 35495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 35505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 35514261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinskistatic bool ValidateMemoryTypes(const layer_data *dev_data, const DEVICE_MEM_INFO *mem_info, const uint32_t memory_type_bits, 3552f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen const char *funcName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 35533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 3554de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (((1 << mem_info->alloc_info.memoryTypeIndex) & memory_type_bits) == 0) { 35553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 35569b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem_info->mem), __LINE__, msgCode, "MT", 35573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s(): MemoryRequirements->memoryTypeBits (0x%X) for this object type are not compatible with the memory " 35583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "type (0x%X) of this memory object 0x%" PRIx64 ". %s", 35599b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus funcName, memory_type_bits, mem_info->alloc_info.memoryTypeIndex, HandleToUint64(mem_info->mem), 35609b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus validation_error_map[msgCode]); 35614261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski } 35623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 35634261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski} 35644261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski 3565160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic bool PreCallValidateBindBufferMemory(layer_data *dev_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VkDeviceMemory mem, 3566160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton VkDeviceSize memoryOffset) { 35679207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton bool skip = false; 35685cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 3569160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 35709207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // Track objects tied to memory 35719b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus uint64_t buffer_handle = HandleToUint64(buffer); 35727a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski skip = ValidateSetMemBinding(dev_data, mem, buffer_handle, kVulkanObjectTypeBuffer, "vkBindBufferMemory()"); 35732eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis if (!buffer_state->memory_requirements_checked) { 35742eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis // There's not an explicit requirement in the spec to call vkGetBufferMemoryRequirements() prior to calling 35759207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // BindBufferMemory, but it's implied in that memory being bound must conform with VkMemoryRequirements from 35769207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // vkGetBufferMemoryRequirements() 35779207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 35789207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_handle, __LINE__, DRAWSTATE_INVALID_BUFFER, "DS", 35799207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton "vkBindBufferMemory(): Binding memory to buffer 0x%" PRIxLEAST64 35809207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton " but vkGetBufferMemoryRequirements() has not been called on that buffer.", 35819207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_handle); 35822eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis // Make the call for them so we can verify the state 35832eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis lock.unlock(); 35849207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton dev_data->dispatch_table.GetBufferMemoryRequirements(dev_data->device, buffer, &buffer_state->requirements); 35852eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis lock.lock(); 35862eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis } 358747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 35880ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Validate bound memory range information 35899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 359057fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 35910ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton skip |= ValidateInsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements, 35920ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton "vkBindBufferMemory()"); 35939207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= ValidateMemoryTypes(dev_data, mem_info, buffer_state->requirements.memoryTypeBits, "vkBindBufferMemory()", 3594315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_17000816); 359547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 359647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 35972c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves // Validate memory requirements alignment 359816769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(memoryOffset, buffer_state->requirements.alignment) != 0) { 3599f60e41965223825191505eebc96491bb52e494a2Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 3600315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis buffer_handle, __LINE__, VALIDATION_ERROR_17000818, "DS", 36019207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton "vkBindBufferMemory(): memoryOffset is 0x%" PRIxLEAST64 36029207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton " but must be an integer multiple of the " 36039207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64 36049207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton ", returned from a call to vkGetBufferMemoryRequirements with buffer. %s", 3605315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis memoryOffset, buffer_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_17000818]); 36062c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 3607ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 3608160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton // Validate memory requirements size 3609160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton if (buffer_state->requirements.size > (mem_info->alloc_info.allocationSize - memoryOffset)) { 3610160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 3611315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis buffer_handle, __LINE__, VALIDATION_ERROR_1700081a, "DS", 3612160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "vkBindBufferMemory(): memory size minus memoryOffset is 0x%" PRIxLEAST64 3613160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton " but must be at least as large as " 3614160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "VkMemoryRequirements::size value 0x%" PRIxLEAST64 3615160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton ", returned from a call to vkGetBufferMemoryRequirements with buffer. %s", 3616160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton mem_info->alloc_info.allocationSize - memoryOffset, buffer_state->requirements.size, 3617315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1700081a]); 3618160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton } 3619160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton 36202c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves // Validate device limits alignments 3621ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller static const VkBufferUsageFlagBits usage_list[3] = { 3622ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller static_cast<VkBufferUsageFlagBits>(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), 3623bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT}; 3624bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski static const char *memory_type[3] = {"texel", "uniform", "storage"}; 3625bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski static const char *offset_name[3] = {"minTexelBufferOffsetAlignment", "minUniformBufferOffsetAlignment", 3626bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "minStorageBufferOffsetAlignment"}; 3627cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 36289207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // TODO: vk_validation_stats.py cannot abide braces immediately preceding or following a validation error enum 3629cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // clang-format off 3630315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis static const UNIQUE_VALIDATION_ERROR_CODE msgCode[3] = { VALIDATION_ERROR_17000810, VALIDATION_ERROR_17000812, 3631315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_17000814 }; 3632cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // clang-format on 3633ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 3634ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller // Keep this one fresh! 3635ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller const VkDeviceSize offset_requirement[3] = { 3636ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller dev_data->phys_dev_properties.properties.limits.minTexelBufferOffsetAlignment, 3637ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment, 3638bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment}; 36398718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis VkBufferUsageFlags usage = dev_data->bufferMap[buffer].get()->createInfo.usage; 3640ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 3641ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller for (int i = 0; i < 3; i++) { 3642ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller if (usage & usage_list[i]) { 364316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(memoryOffset, offset_requirement[i]) != 0) { 36449207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= log_msg( 3645f60e41965223825191505eebc96491bb52e494a2Cort Stratton dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, buffer_handle, 3646cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, msgCode[i], "DS", "vkBindBufferMemory(): %s memoryOffset is 0x%" PRIxLEAST64 3647cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " but must be a multiple of " 3648cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "device limit %s 0x%" PRIxLEAST64 ". %s", 3649cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski memory_type[i], memoryOffset, offset_name[i], offset_requirement[i], validation_error_map[msgCode[i]]); 3650ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller } 36512c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 36522c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 36535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 36549207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton return skip; 36559207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton} 36569207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton 3657160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic void PostCallRecordBindBufferMemory(layer_data *dev_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VkDeviceMemory mem, 3658160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton VkDeviceSize memoryOffset) { 36599207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton if (buffer_state) { 3660160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 36610ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Track bound memory range information 36620ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton auto mem_info = GetMemObjInfo(dev_data, mem); 36630ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton if (mem_info) { 36640ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton InsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements); 36650ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 36660ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 3667c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // Track objects tied to memory 36689b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus uint64_t buffer_handle = HandleToUint64(buffer); 36697a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski SetMemBinding(dev_data, mem, buffer_handle, kVulkanObjectTypeBuffer, "vkBindBufferMemory()"); 3670c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton 36719207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_state->binding.mem = mem; 36729207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_state->binding.offset = memoryOffset; 36739207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_state->binding.size = buffer_state->requirements.size; 36749207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton } 36759207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton} 36769207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton 36779207132ef623d47fcbdfeb9ebc796eade35a2f4cCort StrattonVKAPI_ATTR VkResult VKAPI_CALL BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 36789207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 36799207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 3680160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton auto buffer_state = GetBufferState(dev_data, buffer); 3681160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton bool skip = PreCallValidateBindBufferMemory(dev_data, buffer, buffer_state, mem, memoryOffset); 36829207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton if (!skip) { 36834a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.BindBufferMemory(device, buffer, mem, memoryOffset); 36849207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton if (result == VK_SUCCESS) { 3685160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton PostCallRecordBindBufferMemory(dev_data, buffer, buffer_state, mem, memoryOffset); 36869207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton } 36875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 36885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 36895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 36905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3691bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, 3692bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkMemoryRequirements *pMemoryRequirements) { 369356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 369415caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis dev_data->dispatch_table.GetBufferMemoryRequirements(device, buffer, pMemoryRequirements); 36959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 369615caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis if (buffer_state) { 369715caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis buffer_state->requirements = *pMemoryRequirements; 36982eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis buffer_state->memory_requirements_checked = true; 369915caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis } 37005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3702bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) { 370356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 370415caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis dev_data->dispatch_table.GetImageMemoryRequirements(device, image, pMemoryRequirements); 37059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 370615caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis if (image_state) { 370715caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis image_state->requirements = *pMemoryRequirements; 37082eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis image_state->memory_requirements_checked = true; 370915caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis } 37105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 3711593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 3712bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) { 371356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 3714f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis // Common data objects used pre & post call 3715f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis IMAGE_VIEW_STATE *image_view_state = nullptr; 3716f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis VK_OBJECT obj_struct; 3717a123662876eebfa844faa65ae3f071d3d77618ebTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 3718f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis bool skip = PreCallValidateDestroyImageView(dev_data, imageView, &image_view_state, &obj_struct); 3719d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis if (!skip) { 3720d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis lock.unlock(); 37214a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyImageView(device, imageView, pAllocator); 3722f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis lock.lock(); 3723405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (imageView != VK_NULL_HANDLE) { 3724405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyImageView(dev_data, imageView, image_view_state, obj_struct); 3725405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 3726d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis } 37275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3729bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyShaderModule(VkDevice device, VkShaderModule shaderModule, 3730bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 373156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 3732918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 3733b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 373451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->shaderModuleMap.erase(shaderModule); 3735b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 3736918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 373751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->dispatch_table.DestroyShaderModule(device, shaderModule, pAllocator); 37385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37404c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool PreCallValidateDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE **pipeline_state, 37418bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT *obj_struct) { 374294165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *pipeline_state = getPipelineState(dev_data, pipeline); 37439b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(pipeline), kVulkanObjectTypePipeline}; 3744cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_pipeline) return false; 37458bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis bool skip = false; 37468bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis if (*pipeline_state) { 3747315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *pipeline_state, *obj_struct, VALIDATION_ERROR_25c005fa); 37488bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis } 37498bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis return skip; 37508bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis} 37518bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis 37524c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic void PostCallRecordDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE *pipeline_state, 37538bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT obj_struct) { 37548bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis // Any bound cmd buffers are now invalid 375539c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, pipeline_state->cb_bindings, obj_struct); 37560a136bc9fe42c042857c90a421d0426bd0c029efGabríel Arthúr Pétursson delete getPipelineState(dev_data, pipeline); 37578bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis dev_data->pipelineMap.erase(pipeline); 37588bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis} 37598bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis 3760bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) { 376156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 37624c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pipeline_state = nullptr; 37638bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT obj_struct; 3764e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 37658bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis bool skip = PreCallValidateDestroyPipeline(dev_data, pipeline, &pipeline_state, &obj_struct); 3766f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 3767f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 37684a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipeline(device, pipeline, pAllocator); 37698bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis lock.lock(); 3770405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (pipeline != VK_NULL_HANDLE) { 3771405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyPipeline(dev_data, pipeline, pipeline_state, obj_struct); 3772405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 3773f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 37745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3776bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, 3777bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 377856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 3779e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 37806792ea7cc0ce5fa64b7bd6c946460608cbda91c7Tobin Ehlis dev_data->pipelineLayoutMap.erase(pipelineLayout); 3781e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis lock.unlock(); 3782e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 37834a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipelineLayout(device, pipelineLayout, pAllocator); 37845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3786d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic bool PreCallValidateDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE **sampler_state, 3787806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT *obj_struct) { 37889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *sampler_state = GetSamplerState(dev_data, sampler); 37899b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(sampler), kVulkanObjectTypeSampler}; 3790cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_sampler) return false; 3791806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis bool skip = false; 3792806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis if (*sampler_state) { 3793315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *sampler_state, *obj_struct, VALIDATION_ERROR_26600874); 3794806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis } 3795806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis return skip; 3796806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis} 3797806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis 3798d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic void PostCallRecordDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE *sampler_state, 3799806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT obj_struct) { 3800806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis // Any bound cmd buffers are now invalid 3801cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (sampler_state) invalidateCommandBuffers(dev_data, sampler_state->cb_bindings, obj_struct); 3802806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis dev_data->samplerMap.erase(sampler); 3803806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis} 3804806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis 3805bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) { 380656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 3807d31a44af6da568692a73201825459689c9431867Tobin Ehlis SAMPLER_STATE *sampler_state = nullptr; 3808806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT obj_struct; 380956f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 3810806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis bool skip = PreCallValidateDestroySampler(dev_data, sampler, &sampler_state, &obj_struct); 3811f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 3812f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 38134a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroySampler(device, sampler, pAllocator); 3814806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis lock.lock(); 3815405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (sampler != VK_NULL_HANDLE) { 3816405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroySampler(dev_data, sampler, sampler_state, obj_struct); 3817405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 3818f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 38195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 38205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 382179c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlisstatic void PostCallRecordDestroyDescriptorSetLayout(layer_data *dev_data, VkDescriptorSetLayout ds_layout) { 382279c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis dev_data->descriptorSetLayoutMap.erase(ds_layout); 382379c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis} 382479c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis 3825bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, 3826bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 382756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 382879c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis dev_data->dispatch_table.DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator); 382979c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 383079c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis PostCallRecordDestroyDescriptorSetLayout(dev_data, descriptorSetLayout); 38315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 38325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3833c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic bool PreCallValidateDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool pool, 3834a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE **desc_pool_state, VK_OBJECT *obj_struct) { 38359a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *desc_pool_state = GetDescriptorPoolState(dev_data, pool); 38369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(pool), kVulkanObjectTypeDescriptorPool}; 3837cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_descriptor_pool) return false; 3838c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis bool skip = false; 3839c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis if (*desc_pool_state) { 3840315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *desc_pool_state, *obj_struct, VALIDATION_ERROR_2440025e); 3841c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 3842c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis return skip; 3843c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis} 3844c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis 3845c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic void PostCallRecordDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool descriptorPool, 3846a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *desc_pool_state, VK_OBJECT obj_struct) { 3847c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis // Any bound cmd buffers are now invalid 384839c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, desc_pool_state->cb_bindings, obj_struct); 3849c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis // Free sets that were in this pool 3850c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis for (auto ds : desc_pool_state->sets) { 3851c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis freeDescriptorSet(dev_data, ds); 3852c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 3853c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis dev_data->descriptorPoolMap.erase(descriptorPool); 3854ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson delete desc_pool_state; 3855c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis} 3856c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis 3857bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, 3858bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 385956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 3860a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *desc_pool_state = nullptr; 3861c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis VK_OBJECT obj_struct; 3862c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 3863c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis bool skip = PreCallValidateDestroyDescriptorPool(dev_data, descriptorPool, &desc_pool_state, &obj_struct); 3864c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis if (!skip) { 3865c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis lock.unlock(); 3866c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis dev_data->dispatch_table.DestroyDescriptorPool(device, descriptorPool, pAllocator); 3867c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis lock.lock(); 3868405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptorPool != VK_NULL_HANDLE) { 3869405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyDescriptorPool(dev_data, descriptorPool, desc_pool_state, obj_struct); 3870405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 3871c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 38725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 38733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski// Verify cmdBuffer in given cb_node is not in global in-flight set, and return skip result 3874bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// If this is a secondary command buffer, then make sure its primary is also in-flight 3875bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// If primary is not in-flight, then remove secondary from global in-flight set 3876bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// This function is only valid at a point when cmdBuffer is being reset or freed 3877cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBufferInFlight(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const char *action, 3878cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 38793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 3880a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes if (cb_node->in_use.load()) { 3881a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3882a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes HandleToUint64(cb_node->commandBuffer), __LINE__, error_code, "DS", 3883a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes "Attempt to %s command buffer (0x%p) which is in use. %s", action, cb_node->commandBuffer, 3884a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes validation_error_map[error_code]); 3885bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 38863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 3887bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis} 3888a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes 3889bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// Iterate over all cmdBuffers in given commandPool and verify that each is not in use 3890cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBuffersInFlight(layer_data *dev_data, COMMAND_POOL_NODE *pPool, const char *action, 3891cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 38923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 3893a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmd_buffer : pPool->commandBuffers) { 3894a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes skip |= checkCommandBufferInFlight(dev_data, GetCBNode(dev_data, cmd_buffer), action, error_code); 3895bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 38963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 3897bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis} 38985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3899bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL FreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, 3900bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCommandBuffer *pCommandBuffers) { 390156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 39023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 3903b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 3904c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 39055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < commandBufferCount; i++) { 39069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, pCommandBuffers[i]); 39075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Delete CB information structure, and remove from commandBufferMap 39089f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 3909315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= checkCommandBufferInFlight(dev_data, cb_node, "free", VALIDATION_ERROR_2840005e); 3910c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes } 3911c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes } 3912c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 39133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return; 3914c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 39159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, commandPool); 3916c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes for (uint32_t i = 0; i < commandBufferCount; i++) { 39179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, pCommandBuffers[i]); 3918c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes // Delete CB information structure, and remove from commandBufferMap 39199f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 39205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // reset prior to delete for data clean-up 3921a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes // TODO: fix this, it's insane. 39229f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis resetCB(dev_data, cb_node->commandBuffer); 39239f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis dev_data->commandBufferMap.erase(cb_node->commandBuffer); 39249f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis delete cb_node; 39255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 39265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Remove commandBuffer reference from commandPoolMap 3928c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes pPool->commandBuffers.remove(pCommandBuffers[i]); 39295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3930b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 3931e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 39324a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers); 39335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 39345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 393589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, 3936bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) { 393756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 39385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39394a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool); 39405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 3942b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 39435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandPoolMap[*pCommandPool].createFlags = pCreateInfo->flags; 39445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandPoolMap[*pCommandPool].queueFamilyIndex = pCreateInfo->queueFamilyIndex; 39455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 39465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 39475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 39485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 394989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo, 395089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) { 395156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 39520c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis bool skip = false; 39530c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (pCreateInfo && pCreateInfo->queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS) { 39540c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (!dev_data->enabled_features.pipelineStatisticsQuery) { 39550c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 3956315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_11c0062e, "DS", 39570c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis "Query pool with type VK_QUERY_TYPE_PIPELINE_STATISTICS created on a device " 39580c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis "with VkDeviceCreateInfo.pEnabledFeatures.pipelineStatisticsQuery == VK_FALSE. %s", 3959315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_11c0062e]); 39600c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 39610c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 39620c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis 39630c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 39640c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (!skip) { 39650c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis result = dev_data->dispatch_table.CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool); 39660c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 39675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 3968b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 3969eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis QUERY_POOL_NODE *qp_node = &dev_data->queryPoolMap[*pQueryPool]; 3970eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis qp_node->createInfo = *pCreateInfo; 39715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 39725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 39735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 39745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39755f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlisstatic bool PreCallValidateDestroyCommandPool(layer_data *dev_data, VkCommandPool pool, COMMAND_POOL_NODE **cp_state) { 39769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *cp_state = GetCommandPoolNode(dev_data, pool); 3977cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_command_pool) return false; 39785f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis bool skip = false; 39795f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis if (*cp_state) { 39805f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis // Verify that command buffers in pool are complete (not in-flight) 3981315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= checkCommandBuffersInFlight(dev_data, *cp_state, "destroy command pool with", VALIDATION_ERROR_24000052); 39825f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis } 39835f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis return skip; 39845f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis} 39855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39865f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlisstatic void PostCallRecordDestroyCommandPool(layer_data *dev_data, VkCommandPool pool, COMMAND_POOL_NODE *cp_state) { 39879f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis // Must remove cmdpool from cmdpoolmap, after removing all cmdbuffers in its list from the commandBufferMap 39885f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis for (auto cb : cp_state->commandBuffers) { 39899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, cb); 39907b34d10b918c1f69e7252174965c6a7a7c35ae05Chris Forbes clear_cmd_buf_and_mem_references(dev_data, cb_node); 3991d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis // Remove references to this cb_node prior to delete 3992d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis // TODO : Need better solution here, resetCB? 39937165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski for (auto obj : cb_node->object_bindings) { 39947165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski removeCommandBufferBinding(dev_data, &obj, cb_node); 39957165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski } 3996d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis for (auto framebuffer : cb_node->framebuffers) { 39979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb_state = GetFramebufferState(dev_data, framebuffer); 3998cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fb_state) fb_state->cb_bindings.erase(cb_node); 3999d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis } 4000cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski dev_data->commandBufferMap.erase(cb); // Remove this command buffer 4001cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski delete cb_node; // delete CB info structure 4002a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes } 40035f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis dev_data->commandPoolMap.erase(pool); 40045f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis} 4005e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 40065f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis// Destroy commandPool along with all of the commandBuffers allocated from that pool 40075f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) { 400856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 40095f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis COMMAND_POOL_NODE *cp_state = nullptr; 40105f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 40115f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis bool skip = PreCallValidateDestroyCommandPool(dev_data, commandPool, &cp_state); 40125f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis if (!skip) { 40135f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis lock.unlock(); 40145f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis dev_data->dispatch_table.DestroyCommandPool(device, commandPool, pAllocator); 40155f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis lock.lock(); 4016405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (commandPool != VK_NULL_HANDLE) { 4017405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyCommandPool(dev_data, commandPool, cp_state); 4018405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 40195f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis } 40205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 40215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4022bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) { 402356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 40243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 4025400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis 40261ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 40279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, commandPool); 4028315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= checkCommandBuffersInFlight(dev_data, pPool, "reset command pool with", VALIDATION_ERROR_32800050); 40291ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.unlock(); 4030a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes 40313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 40325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 40334a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetCommandPool(device, commandPool, flags); 40345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 40355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Reset all of the CBs allocated from this pool 40365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 40371ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.lock(); 4038a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmdBuffer : pPool->commandBuffers) { 4039a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes resetCB(dev_data, cmdBuffer); 40405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 40411ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.unlock(); 40425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 40435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 40445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 40455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 404689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) { 404756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 40483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 4049b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 40505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < fenceCount; ++i) { 40519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, pFences[i]); 4052090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (pFence && pFence->state == FENCE_INFLIGHT) { 4053315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 4054315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 4055315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pFences[i]), __LINE__, VALIDATION_ERROR_32e008c6, "DS", "Fence 0x%" PRIx64 " is in use. %s", 4056315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pFences[i]), validation_error_map[VALIDATION_ERROR_32e008c6]); 40575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 40585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4059b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4060090da73358f71ba026e2474a822fecf55267d166Chris Forbes 40613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 4062090da73358f71ba026e2474a822fecf55267d166Chris Forbes 40634a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetFences(device, fenceCount, pFences); 4064090da73358f71ba026e2474a822fecf55267d166Chris Forbes 4065090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (result == VK_SUCCESS) { 4066090da73358f71ba026e2474a822fecf55267d166Chris Forbes lock.lock(); 4067090da73358f71ba026e2474a822fecf55267d166Chris Forbes for (uint32_t i = 0; i < fenceCount; ++i) { 40689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, pFences[i]); 4069090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (pFence) { 4070090da73358f71ba026e2474a822fecf55267d166Chris Forbes pFence->state = FENCE_UNSIGNALED; 4071090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 4072090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 4073090da73358f71ba026e2474a822fecf55267d166Chris Forbes lock.unlock(); 4074090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 4075090da73358f71ba026e2474a822fecf55267d166Chris Forbes 40765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 40775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 40785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4079e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis// For given cb_nodes, invalidate them and track object causing invalidation 40800a4087f99558069e9f6a437ff2dbb5a9c1c22ccaTobin Ehlisvoid invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj) { 4081e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis for (auto cb_node : cb_nodes) { 408239c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis if (cb_node->state == CB_RECORDING) { 408339c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 40849b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 4085226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Invalidating a command buffer that's currently being recorded: 0x%p.", cb_node->commandBuffer); 408639c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis } 4087e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis cb_node->state = CB_INVALID; 4088e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis cb_node->broken_bindings.push_back(obj); 4089db365f522319df6446b50584277a3bbfee1c1052Chris Forbes 4090db365f522319df6446b50584277a3bbfee1c1052Chris Forbes // if secondary, then propagate the invalidation to the primaries that will call us. 4091db365f522319df6446b50584277a3bbfee1c1052Chris Forbes if (cb_node->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) { 4092db365f522319df6446b50584277a3bbfee1c1052Chris Forbes invalidateCommandBuffers(dev_data, cb_node->linkedCommandBuffers, obj); 4093db365f522319df6446b50584277a3bbfee1c1052Chris Forbes } 4094e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis } 4095e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis} 4096e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis 4097c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool PreCallValidateDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, 4098c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis FRAMEBUFFER_STATE **framebuffer_state, VK_OBJECT *obj_struct) { 40999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *framebuffer_state = GetFramebufferState(dev_data, framebuffer); 41009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(framebuffer), kVulkanObjectTypeFramebuffer}; 4101cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_framebuffer) return false; 4102728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis bool skip = false; 4103728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis if (*framebuffer_state) { 4104315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *framebuffer_state, *obj_struct, VALIDATION_ERROR_250006f8); 4105728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis } 4106728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis return skip; 4107728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis} 4108728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis 4109c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void PostCallRecordDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, FRAMEBUFFER_STATE *framebuffer_state, 4110728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis VK_OBJECT obj_struct) { 411139c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, framebuffer_state->cb_bindings, obj_struct); 4112728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis dev_data->frameBufferMap.erase(framebuffer); 4113728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis} 4114728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis 4115bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) { 411656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4117c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis FRAMEBUFFER_STATE *framebuffer_state = nullptr; 4118728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis VK_OBJECT obj_struct; 4119b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4120728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis bool skip = PreCallValidateDestroyFramebuffer(dev_data, framebuffer, &framebuffer_state, &obj_struct); 4121728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis if (!skip) { 4122728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis lock.unlock(); 4123728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis dev_data->dispatch_table.DestroyFramebuffer(device, framebuffer, pAllocator); 4124728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis lock.lock(); 4125405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (framebuffer != VK_NULL_HANDLE) { 4126405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyFramebuffer(dev_data, framebuffer, framebuffer_state, obj_struct); 4127405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 41285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 41305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 41310ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic bool PreCallValidateDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE **rp_state, 41320ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT *obj_struct) { 41339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *rp_state = GetRenderPassState(dev_data, render_pass); 41349b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus *obj_struct = {HandleToUint64(render_pass), kVulkanObjectTypeRenderPass}; 4135cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_renderpass) return false; 41360ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis bool skip = false; 41370ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis if (*rp_state) { 4138315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *rp_state, *obj_struct, VALIDATION_ERROR_264006d2); 41390ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis } 41400ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis return skip; 41410ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis} 41420ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis 41430ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic void PostCallRecordDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE *rp_state, 41440ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT obj_struct) { 414539c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, rp_state->cb_bindings, obj_struct); 41460ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis dev_data->renderPassMap.erase(render_pass); 41470ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis} 41480ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis 4149bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) { 415056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 41510ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis RENDER_PASS_STATE *rp_state = nullptr; 41520ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT obj_struct; 4153e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 41540ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis bool skip = PreCallValidateDestroyRenderPass(dev_data, renderPass, &rp_state, &obj_struct); 4155a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis if (!skip) { 4156a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis lock.unlock(); 41574a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyRenderPass(device, renderPass, pAllocator); 41580ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis lock.lock(); 4159405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (renderPass != VK_NULL_HANDLE) { 4160405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyRenderPass(dev_data, renderPass, rp_state, obj_struct); 4161405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 4162a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis } 41635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 41645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 416589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, 416689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) { 416756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 41683683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 41693683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski bool skip = PreCallValidateCreateBuffer(dev_data, pCreateInfo); 41703683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.unlock(); 41713683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 41723683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 41734a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateBuffer(device, pCreateInfo, pAllocator, pBuffer); 41745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 41755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 41763683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.lock(); 41773683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski PostCallRecordCreateBuffer(dev_data, pCreateInfo, pBuffer); 41783683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.unlock(); 41795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 41815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 41825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 418389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo, 418489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkBufferView *pView) { 418556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 41868c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young std::unique_lock<std::mutex> lock(global_lock); 41873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = PreCallValidateCreateBufferView(dev_data, pCreateInfo); 41888c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 41893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 41904a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateBufferView(device, pCreateInfo, pAllocator, pView); 41915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 41928c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.lock(); 41933683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski PostCallRecordCreateBufferView(dev_data, pCreateInfo, pView); 41948c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 41955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 41975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 41985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 41998dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski// Access helper functions for external modules 4200d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst VkFormatProperties *GetFormatProperties(core_validation::layer_data *device_data, VkFormat format) { 4201d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkFormatProperties *format_properties = new VkFormatProperties; 4202d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_layer_data *instance_data = 4203d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 4204d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(device_data->physical_device, format, format_properties); 4205d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski return format_properties; 42068dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 42078dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 4208d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst VkImageFormatProperties *GetImageFormatProperties(core_validation::layer_data *device_data, VkFormat format, 4209d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageType image_type, VkImageTiling tiling, VkImageUsageFlags usage, 4210d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageCreateFlags flags) { 4211d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageFormatProperties *image_format_properties = new VkImageFormatProperties; 4212d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_layer_data *instance_data = 4213d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 4214d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceImageFormatProperties(device_data->physical_device, format, image_type, tiling, 4215d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski usage, flags, image_format_properties); 4216d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski return image_format_properties; 42178dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 42188dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 42197a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlisconst debug_report_data *GetReportData(const core_validation::layer_data *device_data) { return device_data->report_data; } 42208dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 42218dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinskiconst VkPhysicalDeviceProperties *GetPhysicalDeviceProperties(core_validation::layer_data *device_data) { 42228dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski return &device_data->phys_dev_props; 42238dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 42248dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 42258c59133586421be878d393799b30044497f77727Mark Lobodzinskiconst CHECK_DISABLED *GetDisables(core_validation::layer_data *device_data) { return &device_data->instance_data->disabled; } 42268c59133586421be878d393799b30044497f77727Mark Lobodzinski 42278c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::unique_ptr<IMAGE_STATE>> *GetImageMap(core_validation::layer_data *device_data) { 42288c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageMap; 42298c59133586421be878d393799b30044497f77727Mark Lobodzinski} 42308c59133586421be878d393799b30044497f77727Mark Lobodzinski 42318c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::vector<ImageSubresourcePair>> *GetImageSubresourceMap(core_validation::layer_data *device_data) { 42328c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageSubresourceMap; 42338c59133586421be878d393799b30044497f77727Mark Lobodzinski} 42348c59133586421be878d393799b30044497f77727Mark Lobodzinski 42358c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> *GetImageLayoutMap(layer_data *device_data) { 42368c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageLayoutMap; 42378c59133586421be878d393799b30044497f77727Mark Lobodzinski} 42388c59133586421be878d393799b30044497f77727Mark Lobodzinski 42390db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlisstd::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> const *GetImageLayoutMap(layer_data const *device_data) { 42400db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis return &device_data->imageLayoutMap; 42410db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis} 42420db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis 42433683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBuffer, std::unique_ptr<BUFFER_STATE>> *GetBufferMap(layer_data *device_data) { 42443683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski return &device_data->bufferMap; 42453683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 42463683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 42473683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBufferView, std::unique_ptr<BUFFER_VIEW_STATE>> *GetBufferViewMap(layer_data *device_data) { 42483683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski return &device_data->bufferViewMap; 42493683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 42503683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 42511c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskistd::unordered_map<VkImageView, std::unique_ptr<IMAGE_VIEW_STATE>> *GetImageViewMap(layer_data *device_data) { 42521c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski return &device_data->imageViewMap; 42531c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski} 42541c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski 4255d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst PHYS_DEV_PROPERTIES_NODE *GetPhysDevProperties(const layer_data *device_data) { 42566a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return &device_data->phys_dev_properties; 42576a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 42586a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 42595f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinskiconst VkPhysicalDeviceFeatures *GetEnabledFeatures(const layer_data *device_data) { 42605f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski return &device_data->enabled_features; 42615f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski} 42625f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski 4263a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinskiconst DeviceExtensions *GetDeviceExtensions(const layer_data *device_data) { return &device_data->extensions; } 42640e2296e24065d02615ee87561bbb80af414a1ddfMike Schuchardt 426589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, 426689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkImage *pImage) { 42678dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 426856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 42698dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski bool skip = PreCallValidateCreateImage(dev_data, pCreateInfo, pAllocator, pImage); 42708dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski if (!skip) { 42718dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski result = dev_data->dispatch_table.CreateImage(device, pCreateInfo, pAllocator, pImage); 42728dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 42735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 4274b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 4275920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski PostCallRecordCreateImage(dev_data, pCreateInfo, pImage); 42765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 42775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 42785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 42795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 42808c07a094dc9cc4afb6b62181f341c12b9e969041Mark YoungVKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo, 42818c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young const VkAllocationCallbacks *pAllocator, VkImageView *pView) { 428256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 42838c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young std::unique_lock<std::mutex> lock(global_lock); 4284e3effabf8e97cae8e006477806ceaca62e4f2ce7Tobin Ehlis bool skip = PreCallValidateCreateImageView(dev_data, pCreateInfo); 42858c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 4286cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 42874a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateImageView(device, pCreateInfo, pAllocator, pView); 42885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 42898c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.lock(); 429079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis PostCallRecordCreateImageView(dev_data, pCreateInfo, *pView); 42918c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 42925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4293bb6624cb996175d8945190886a200e720b3871efChris Forbes 42945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 42955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 42965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4297bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, 4298bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkFence *pFence) { 429956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 43004a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateFence(device, pCreateInfo, pAllocator, pFence); 43015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 4302b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 4303a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis auto &fence_node = dev_data->fenceMap[*pFence]; 43048988ad37ea5a054ff2ae3cbe4b767ae6c13cf48bChris Forbes fence_node.fence = *pFence; 4305a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis fence_node.createInfo = *pCreateInfo; 4306cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes fence_node.state = (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) ? FENCE_RETIRED : FENCE_UNSIGNALED; 43075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 43085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 43095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 43105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 43115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO handle pipeline caches 431289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo, 431389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkPipelineCache *pPipelineCache) { 431456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 43154a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache); 43165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 43175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 43185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4319bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, 4320bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 432156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 43224a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipelineCache(device, pipelineCache, pAllocator); 43235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 43245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4325bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize, 4326bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski void *pData) { 432756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 43284a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetPipelineCacheData(device, pipelineCache, pDataSize, pData); 43295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 43305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 43315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4332bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, 4333bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkPipelineCache *pSrcCaches) { 433456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 43354a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches); 43365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 43375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 43385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 43393d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis// utility function to set collective state for pipeline 43404c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisvoid set_pipeline_state(PIPELINE_STATE *pPipe) { 43413d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis // If any attachment used by this pipeline has blendEnable, set top-level blendEnable 43423d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipe->graphicsPipelineCI.pColorBlendState) { 43433d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis for (size_t i = 0; i < pPipe->attachments.size(); ++i) { 43443d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (VK_TRUE == pPipe->attachments[i].blendEnable) { 43453d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (((pPipe->attachments[i].dstAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 43463d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].dstAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 43473d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].dstColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 43483d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].dstColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 43493d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].srcAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 43503d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].srcAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 43513d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].srcColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 43523d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].srcColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA))) { 43533d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis pPipe->blendConstantsEnabled = true; 43543d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 43553d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 43563d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 43573d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 43583d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis} 43593d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis 4360daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinskibool validate_dual_src_blend_feature(layer_data *device_data, PIPELINE_STATE *pipe_state) { 4361daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski bool skip = false; 4362daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski if (pipe_state->graphicsPipelineCI.pColorBlendState) { 4363daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski for (size_t i = 0; i < pipe_state->attachments.size(); ++i) { 4364daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski if (!device_data->enabled_features.dualSrcBlend) { 4365daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski if ((pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_COLOR) || 4366daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR) || 4367daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_ALPHA) || 4368daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA) || 4369daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_COLOR) || 4370daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR) || 4371daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_ALPHA) || 4372daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA)) { 4373daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski skip |= 4374daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 43759b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pipe_state->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS", 4376daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski "CmdBindPipeline: vkPipeline (0x%" PRIxLEAST64 ") attachment[" PRINTF_SIZE_T_SPECIFIER 4377daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski "] has a dual-source blend factor but this device feature is not enabled.", 43789b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pipe_state->pipeline), i); 4379daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski } 4380daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski } 4381daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski } 4382daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski } 4383daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski return skip; 4384daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski} 4385daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski 438648b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinskistatic bool PreCallCreateGraphicsPipelines(layer_data *device_data, uint32_t count, 438748b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski const VkGraphicsPipelineCreateInfo *create_infos, vector<PIPELINE_STATE *> &pipe_state) { 438848b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski bool skip = false; 4389bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_layer_data *instance_data = 439056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 439148b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski 439248b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski for (uint32_t i = 0; i < count; i++) { 439348b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski skip |= verifyPipelineCreateState(device_data, pipe_state, i); 439478b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski if (create_infos[i].pVertexInputState != NULL) { 439578b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski for (uint32_t j = 0; j < create_infos[i].pVertexInputState->vertexAttributeDescriptionCount; j++) { 439678b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski VkFormat format = create_infos[i].pVertexInputState->pVertexAttributeDescriptions[j].format; 439778b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski // Internal call to get format info. Still goes through layers, could potentially go directly to ICD. 439878b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski VkFormatProperties properties; 439978b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(device_data->physical_device, format, &properties); 440078b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski if ((properties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0) { 440178b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski skip |= log_msg( 440278b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 4403315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_14a004de, "IMAGE", 440478b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski "vkCreateGraphicsPipelines: pCreateInfo[%d].pVertexInputState->vertexAttributeDescriptions[%d].format " 440578b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski "(%s) is not a supported vertex buffer format. %s", 4406315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, j, string_VkFormat(format), validation_error_map[VALIDATION_ERROR_14a004de]); 440778b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 440878b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 440978b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 441048b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski } 441148b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski return skip; 441248b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski} 441348b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski 4414bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, 4415bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkGraphicsPipelineCreateInfo *pCreateInfos, 4416bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) { 44175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO What to do with pipelineCache? 44185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // The order of operations here is a little convoluted but gets the job done 44194c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis // 1. Pipeline create state is first shadowed into PIPELINE_STATE struct 44205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // 2. Create state is then validated (which uses flags setup during shadowing) 44215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // 3. If everything looks good, we'll then create the pipeline and add NODE to pipelineMap 442242486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski bool skip = false; 44235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic 442442486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski vector<PIPELINE_STATE *> pipe_state(count); 442556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 44265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 44275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t i = 0; 4428b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 44295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 44305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 443142486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i] = new PIPELINE_STATE; 443242486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i]->initGraphicsPipeline(&pCreateInfos[i]); 44339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis pipe_state[i]->render_pass_ci.initialize(GetRenderPassState(dev_data, pCreateInfos[i].renderPass)->createInfo.ptr()); 443442486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout); 44355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 443642486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski skip |= PreCallCreateGraphicsPipelines(dev_data, count, pCreateInfos, pipe_state); 44375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4438c70226063be6148056ceeccf835175a1fd59f24fChris Forbes if (skip) { 4439c70226063be6148056ceeccf835175a1fd59f24fChris Forbes for (i = 0; i < count; i++) { 4440c70226063be6148056ceeccf835175a1fd59f24fChris Forbes delete pipe_state[i]; 44411ab616b32d4e5b7d62d4a8c41b0c03ea335ab845Chris Forbes pPipelines[i] = VK_NULL_HANDLE; 4442c70226063be6148056ceeccf835175a1fd59f24fChris Forbes } 44437a456d188475c23b566334be45dc0489b2789653Chris Forbes return VK_ERROR_VALIDATION_FAILED_EXT; 44447a456d188475c23b566334be45dc0489b2789653Chris Forbes } 44457a456d188475c23b566334be45dc0489b2789653Chris Forbes 44467a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.unlock(); 4447bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 4448bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->dispatch_table.CreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines); 44497a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.lock(); 44507a456d188475c23b566334be45dc0489b2789653Chris Forbes for (i = 0; i < count; i++) { 445161943a7503bc8594338f3364ef42f1d863486c04Chris Forbes if (pPipelines[i] == VK_NULL_HANDLE) { 445261943a7503bc8594338f3364ef42f1d863486c04Chris Forbes delete pipe_state[i]; 4453bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 445461943a7503bc8594338f3364ef42f1d863486c04Chris Forbes pipe_state[i]->pipeline = pPipelines[i]; 445561943a7503bc8594338f3364ef42f1d863486c04Chris Forbes dev_data->pipelineMap[pipe_state[i]->pipeline] = pipe_state[i]; 445661943a7503bc8594338f3364ef42f1d863486c04Chris Forbes } 44575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4458c70226063be6148056ceeccf835175a1fd59f24fChris Forbes 44595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 44605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 44615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4462bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, 4463bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkComputePipelineCreateInfo *pCreateInfos, 4464bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) { 44650108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes bool skip = false; 44665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 44675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic 44684c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis vector<PIPELINE_STATE *> pPipeState(count); 446956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 44705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 44715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t i = 0; 4472b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 44735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 44745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Verify compute stage bits 44755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 44765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Create and initialize internal tracking data structure 44774c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis pPipeState[i] = new PIPELINE_STATE; 44784c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis pPipeState[i]->initComputePipeline(&pCreateInfos[i]); 4479c2a5a36d03bbe52f5854a5884346e4a84115e259Tobin Ehlis pPipeState[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout); 44805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 44815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Add Compute Pipeline Verification 4482e446ad08318228362ef35d73e7a0636075cb3636Chris Forbes skip |= validate_compute_pipeline(dev_data, pPipeState[i]); 44830108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes // skip |= verifyPipelineCreateState(dev_data, pPipeState[i]); 44845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 44855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 44867a456d188475c23b566334be45dc0489b2789653Chris Forbes if (skip) { 44875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 44885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Clean up any locally allocated data structures 44894c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis delete pPipeState[i]; 4490fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes pPipelines[i] = VK_NULL_HANDLE; 44915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 44925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 44935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 44947a456d188475c23b566334be45dc0489b2789653Chris Forbes 44957a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.unlock(); 4496bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 4497bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->dispatch_table.CreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines); 44987a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.lock(); 44997a456d188475c23b566334be45dc0489b2789653Chris Forbes for (i = 0; i < count; i++) { 4500fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes if (pPipelines[i] == VK_NULL_HANDLE) { 4501fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes delete pPipeState[i]; 4502bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 4503fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes pPipeState[i]->pipeline = pPipelines[i]; 4504fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes dev_data->pipelineMap[pPipeState[i]->pipeline] = pPipeState[i]; 4505fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes } 45067a456d188475c23b566334be45dc0489b2789653Chris Forbes } 45077a456d188475c23b566334be45dc0489b2789653Chris Forbes 45085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 45095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 45105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 451189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo, 451289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) { 451356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 45144a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateSampler(device, pCreateInfo, pAllocator, pSampler); 45155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 4516b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 4517d31a44af6da568692a73201825459689c9431867Tobin Ehlis dev_data->samplerMap[*pSampler] = unique_ptr<SAMPLER_STATE>(new SAMPLER_STATE(pSampler, pCreateInfo)); 45185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 45205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 45215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 45220c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic bool PreCallValidateCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info) { 4523cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.create_descriptor_set_layout) return false; 45240c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis return cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(dev_data->report_data, create_info); 45250c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis} 45260c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis 45270c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic void PostCallRecordCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info, 45280c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis VkDescriptorSetLayout set_layout) { 4529c8bee427d7a8ed0ccec899fbf47134d582dcafbdGabríel Arthúr Pétursson dev_data->descriptorSetLayoutMap[set_layout] = std::unique_ptr<cvdescriptorset::DescriptorSetLayout>( 4530c8bee427d7a8ed0ccec899fbf47134d582dcafbdGabríel Arthúr Pétursson new cvdescriptorset::DescriptorSetLayout(create_info, set_layout)); 45310c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis} 45320c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis 4533bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 4534bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 4535bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorSetLayout *pSetLayout) { 453656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 45370c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 45380c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 45390c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis bool skip = PreCallValidateCreateDescriptorSetLayout(dev_data, pCreateInfo); 45400c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis if (!skip) { 45410c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis lock.unlock(); 45420c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis result = dev_data->dispatch_table.CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout); 45430c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis if (VK_SUCCESS == result) { 45440c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis lock.lock(); 45450c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis PostCallRecordCreateDescriptorSetLayout(dev_data, pCreateInfo, *pSetLayout); 45460c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis } 45475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 45495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 45505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 45519e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Used by CreatePipelineLayout and CmdPushConstants. 45529e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Note that the index argument is optional and only used by CreatePipelineLayout. 45539e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultzstatic bool validatePushConstantRange(const layer_data *dev_data, const uint32_t offset, const uint32_t size, 45549e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz const char *caller_name, uint32_t index = 0) { 4555cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.push_constant_range) return false; 45569e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz uint32_t const maxPushConstantsSize = dev_data->phys_dev_properties.properties.limits.maxPushConstantsSize; 45573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 45589e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Check that offset + size don't exceed the max. 45599e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Prevent arithetic overflow here by avoiding addition and testing in this order. 45609e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((offset >= maxPushConstantsSize) || (size > maxPushConstantsSize - offset)) { 45619e24d8153ab63bc3ac08b5a1517c203930b5de91Karl 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. 45629e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 4563e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis if (offset >= maxPushConstantsSize) { 45643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 4565315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_11a0024c, "DS", 45663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with offset %u that " 45673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 4568315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_11a0024c]); 4569e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis } 4570e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis if (size > maxPushConstantsSize - offset) { 4571315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 4572315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_11a00254, "DS", 4573315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "%s call has push constants index %u with offset %u and size %u that " 4574315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "exceeds this device's maxPushConstantSize of %u. %s", 4575315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis caller_name, index, offset, size, maxPushConstantsSize, 4576315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_11a00254]); 4577e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis } 45789e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 45794527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (offset >= maxPushConstantsSize) { 45803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 4581315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_1bc002e4, "DS", 45823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with offset %u that " 45833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 4584315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_1bc002e4]); 45854527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 45864527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size > maxPushConstantsSize - offset) { 4587315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 4588315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_1bc002e6, "DS", 4589315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "%s call has push constants index %u with offset %u and size %u that " 4590315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "exceeds this device's maxPushConstantSize of %u. %s", 4591315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis caller_name, index, offset, size, maxPushConstantsSize, 4592315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1bc002e6]); 45934527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 45949e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 45953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 45963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 45979e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 45989e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 45999e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // size needs to be non-zero and a multiple of 4. 46009e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((size == 0) || ((size & 0x3) != 0)) { 46019e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 4602891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis if (size == 0) { 46033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 4604315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_11a00250, "DS", 46053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with " 46063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "size %u. Size must be greater than zero. %s", 4607315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis caller_name, index, size, validation_error_map[VALIDATION_ERROR_11a00250]); 4608891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis } 4609891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis if (size & 0x3) { 46103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 4611315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_11a00252, "DS", 46123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with " 46133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "size %u. Size must be a multiple of 4. %s", 4614315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis caller_name, index, size, validation_error_map[VALIDATION_ERROR_11a00252]); 4615891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis } 46169e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 46174527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size == 0) { 46183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 4619315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_1bc2c21b, "DS", 46203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with " 46213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "size %u. Size must be greater than zero. %s", 4622315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis caller_name, index, size, validation_error_map[VALIDATION_ERROR_1bc2c21b]); 46234527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 46244527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size & 0x3) { 46253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 4626315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_1bc002e2, "DS", 46273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with " 46283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "size %u. Size must be a multiple of 4. %s", 4629315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis caller_name, index, size, validation_error_map[VALIDATION_ERROR_1bc002e2]); 46304527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 46319e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 46323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 46333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 46349e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 46359e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 46369e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // offset needs to be a multiple of 4. 46379e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((offset & 0x3) != 0) { 46389e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 46393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 4640315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_11a0024e, "DS", 46413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with " 46423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "offset %u. Offset must be a multiple of 4. %s", 4643315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis caller_name, index, offset, validation_error_map[VALIDATION_ERROR_11a0024e]); 46449e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 46453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 4646315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_1bc002e0, "DS", 46473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants with " 46483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "offset %u. Offset must be a multiple of 4. %s", 4649315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis caller_name, offset, validation_error_map[VALIDATION_ERROR_1bc002e0]); 46509e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 46513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 46523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 46539e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 46545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 46553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 46565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 46575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4658bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo, 465989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout) { 46603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 466156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4662bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // TODO : Add checks for VALIDATION_ERRORS 865-870 46639e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Push Constant Range checks 466407a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz uint32_t i, j; 46655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 46663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validatePushConstantRange(dev_data, pCreateInfo->pPushConstantRanges[i].offset, 46673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCreateInfo->pPushConstantRanges[i].size, "vkCreatePipelineLayout()", i); 46689e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == pCreateInfo->pPushConstantRanges[i].stageFlags) { 46693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 4670315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_11a2dc03, "DS", "vkCreatePipelineLayout() call has no stageFlags set. %s", 4671315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_11a2dc03]); 46729e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 46739e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 46743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 467507a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz 4676bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl 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. 467707a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 467807a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz for (j = i + 1; j < pCreateInfo->pushConstantRangeCount; ++j) { 4679bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz if (0 != (pCreateInfo->pPushConstantRanges[i].stageFlags & pCreateInfo->pPushConstantRanges[j].stageFlags)) { 46803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 4681315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_0fe00248, "DS", 46823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreatePipelineLayout() Duplicate stage flags found in ranges %d and %d. %s", i, j, 4683315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0fe00248]); 46849e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 46855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 46865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4687f73b2046273413ea1338dd714d67c39f8e0fa09eChris Forbes 46884a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout); 46895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 4690b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 46915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PIPELINE_LAYOUT_NODE &plNode = dev_data->pipelineLayoutMap[*pPipelineLayout]; 469269b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis plNode.layout = *pPipelineLayout; 4693416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.set_layouts.resize(pCreateInfo->setLayoutCount); 46945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->setLayoutCount; ++i) { 46959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis plNode.set_layouts[i] = GetDescriptorSetLayout(dev_data, pCreateInfo->pSetLayouts[i]); 46965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4697416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.push_constant_ranges.resize(pCreateInfo->pushConstantRangeCount); 46985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 4699416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.push_constant_ranges[i] = pCreateInfo->pPushConstantRanges[i]; 47005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 47035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4705bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, 4706bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool) { 470756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 47084a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool); 47095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 4710a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *pNewNode = new DESCRIPTOR_POOL_STATE(*pDescriptorPool, pCreateInfo); 47115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (NULL == pNewNode) { 47125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 47139b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(*pDescriptorPool), __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS", 4714a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis "Out of memory while attempting to allocate DESCRIPTOR_POOL_STATE in vkCreateDescriptorPool()")) 47155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 47165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 4717b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 47185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->descriptorPoolMap[*pDescriptorPool] = pNewNode; 47195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 47215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Need to do anything if pool create fails? 47225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 47245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4726bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, 4727bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorPoolResetFlags flags) { 4728315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis // TODO : Add checks for VALIDATION_ERROR_32a00272 472956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 47304a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetDescriptorPool(device, descriptorPool, flags); 47315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 4732b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 47335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis clearDescriptorPool(dev_data, device, descriptorPool, flags); 47345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 47365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47372c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes// Ensure the pool contains enough descriptors and descriptor sets to satisfy 4738789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// an allocation request. Fills common_data with the total number of descriptors of each type required, 4739789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// as well as DescriptorSetLayout ptrs used for later update. 47407f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlisstatic bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, 47417f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis cvdescriptorset::AllocateDescriptorSetsData *common_data) { 47427a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis // Always update common data 47437a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis cvdescriptorset::UpdateAllocateDescriptorSetsData(dev_data, pAllocateInfo, common_data); 4744cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.allocate_descriptor_sets) return false; 47457e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis // All state checks for AllocateDescriptorSets is done in single function 47467a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis return cvdescriptorset::ValidateAllocateDescriptorSets(dev_data, pAllocateInfo, common_data); 47477e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis} 47487e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis// Allocation state was good and call down chain was made so update state based on allocating descriptor sets 47497e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlisstatic void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, 47507f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis VkDescriptorSet *pDescriptorSets, 47517f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis const cvdescriptorset::AllocateDescriptorSetsData *common_data) { 47527e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis // All the updates are contained in a single cvdescriptorset function 47532c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, 4754b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis &dev_data->setMap, dev_data); 47552c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes} 47562c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes 4757bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, 4758bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorSet *pDescriptorSets) { 475956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4760b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 47617f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis cvdescriptorset::AllocateDescriptorSetsData common_data(pAllocateInfo->descriptorSetCount); 47623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = PreCallValidateAllocateDescriptorSets(dev_data, pAllocateInfo, &common_data); 4763b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4764d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes 47653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 4766d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes 47674a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets); 47686511ce241f7f210211e0c0e882f3c14889071f4dChris Forbes 47695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 4770b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 47717f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis PostCallRecordAllocateDescriptorSets(dev_data, pAllocateInfo, pDescriptorSets, &common_data); 4772b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 47735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 47755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 4776cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Verify state before freeing DescriptorSets 4777cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic bool PreCallValidateFreeDescriptorSets(const layer_data *dev_data, VkDescriptorPool pool, uint32_t count, 4778cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis const VkDescriptorSet *descriptor_sets) { 4779cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.free_descriptor_sets) return false; 47803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 4781cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // First make sure sets being destroyed are not currently in-use 4782405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour for (uint32_t i = 0; i < count; ++i) { 4783405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptor_sets[i] != VK_NULL_HANDLE) { 47843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateIdleDescriptorSet(dev_data, descriptor_sets[i], "vkFreeDescriptorSets"); 4785405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 4786405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 4787cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis 47889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool); 4789a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis if (pool_state && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pool_state->createInfo.flags)) { 4790cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // Can't Free from a NON_FREE pool 47913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 4792315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pool), __LINE__, VALIDATION_ERROR_28600270, "DS", 47933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "It is invalid to call vkFreeDescriptorSets() with a pool created without setting " 47943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT. %s", 4795315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_28600270]); 4796cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis } 47973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 4798cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis} 4799cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Sets have been removed from the pool so update underlying state 4800cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic void PostCallRecordFreeDescriptorSets(layer_data *dev_data, VkDescriptorPool pool, uint32_t count, 4801cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis const VkDescriptorSet *descriptor_sets) { 48029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool); 4803cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // Update available descriptor sets in pool 4804cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis pool_state->availableSets += count; 4805cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis 4806cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // For each freed descriptor add its resources back into the pool as available and remove from pool and setMap 4807cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis for (uint32_t i = 0; i < count; ++i) { 4808405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptor_sets[i] != VK_NULL_HANDLE) { 4809405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour auto descriptor_set = dev_data->setMap[descriptor_sets[i]]; 4810405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour uint32_t type_index = 0, descriptor_count = 0; 4811405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour for (uint32_t j = 0; j < descriptor_set->GetBindingCount(); ++j) { 4812405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour type_index = static_cast<uint32_t>(descriptor_set->GetTypeFromIndex(j)); 4813405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour descriptor_count = descriptor_set->GetDescriptorCountFromIndex(j); 4814405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour pool_state->availableDescriptorTypeCount[type_index] += descriptor_count; 4815405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 4816405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour freeDescriptorSet(dev_data, descriptor_set); 4817405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour pool_state->sets.erase(descriptor_set); 4818405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 4819cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis } 4820cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis} 48215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4822bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, 4823bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDescriptorSet *pDescriptorSets) { 482456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 48255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Make sure that no sets being destroyed are in-flight 4826b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 48273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = PreCallValidateFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets); 4828b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4829e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 48303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 48314a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets); 48325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 4833b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 4834cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis PostCallRecordFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets); 4835b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 48365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 48385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 48396b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// TODO : This is a Proof-of-concept for core validation architecture 48406b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// Really we'll want to break out these functions to separate files but 48416b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// keeping it all together here to prove out design 48426b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PreCallValidate* handles validating all of the state prior to calling down chain to UpdateDescriptorSets() 48436b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic bool PreCallValidateUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, 48446b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 48456b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkCopyDescriptorSet *pDescriptorCopies) { 4846cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.update_descriptor_sets) return false; 48476b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // First thing to do is perform map look-ups. 48486b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // NOTE : UpdateDescriptorSets is somewhat unique in that it's operating on a number of DescriptorSets 48496b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // so we can't just do a single map look-up up-front, but do them individually in functions below 48506b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis 48516b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Now make call(s) that validate state, but don't perform state updates in this function 48526b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Note, here DescriptorSets is unique in that we don't yet have an instance. Using a helper function in the 48536b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // namespace which will parse params and make calls into specific class instances 4854104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis return cvdescriptorset::ValidateUpdateDescriptorSets(dev_data->report_data, dev_data, descriptorWriteCount, pDescriptorWrites, 4855104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis descriptorCopyCount, pDescriptorCopies); 48566b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis} 48576b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSets() 48586b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic void PostCallRecordUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, 48596b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 48606b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkCopyDescriptorSet *pDescriptorCopies) { 4861104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis cvdescriptorset::PerformUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 48626b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis pDescriptorCopies); 48636b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis} 48645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4865bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, 4866bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 4867bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCopyDescriptorSet *pDescriptorCopies) { 48686b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Only map look-up at top level is for device-level layer_data 486956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4870b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 48713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = PreCallValidateUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 48723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pDescriptorCopies); 4873b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 48743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 48754a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 48764a0754042cf090e131e9e769d8a3633c228625beChris Forbes pDescriptorCopies); 48776b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis lock.lock(); 48786b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Since UpdateDescriptorSets() is void, nothing to check prior to updating state 48796b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis PostCallRecordUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 48806b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis pDescriptorCopies); 48815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 48835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4884bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pCreateInfo, 4885bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkCommandBuffer *pCommandBuffer) { 488656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 48874a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AllocateCommandBuffers(device, pCreateInfo, pCommandBuffer); 48885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 4889b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 48909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, pCreateInfo->commandPool); 4891cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes 4892cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (pPool) { 489372d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis for (uint32_t i = 0; i < pCreateInfo->commandBufferCount; i++) { 48945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Add command buffer to its commandPool map 4895cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes pPool->commandBuffers.push_back(pCommandBuffer[i]); 48965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis GLOBAL_CB_NODE *pCB = new GLOBAL_CB_NODE; 48975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Add command buffer to map 48985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandBufferMap[pCommandBuffer[i]] = pCB; 48995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, pCommandBuffer[i]); 49005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->createInfo = *pCreateInfo; 49015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->device = device; 49025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4904b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 49055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 49075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4909883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis// Add bindings between the given cmd buffer & framebuffer and the framebuffer's children 4910c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void AddFramebufferBinding(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, FRAMEBUFFER_STATE *fb_state) { 49119b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus addCommandBufferBinding(&fb_state->cb_bindings, {HandleToUint64(fb_state->framebuffer), kVulkanObjectTypeFramebuffer}, 49120245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis cb_state); 4913883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis for (auto attachment : fb_state->attachments) { 4914883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis auto view_state = attachment.view_state; 4915883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis if (view_state) { 491603ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis AddCommandBufferBindingImageView(dev_data, cb_state, view_state); 4917883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 49189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, fb_state->createInfo.renderPass); 4919883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis if (rp_state) { 49209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus addCommandBufferBinding(&rp_state->cb_bindings, {HandleToUint64(rp_state->renderPass), kVulkanObjectTypeRenderPass}, 49219b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus cb_state); 4922883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 4923883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 4924883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis} 4925883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis 4926bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) { 49273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 492856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 4929b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 49305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate command buffer level 49319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer); 4932f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node) { 49335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This implicitly resets the Cmd Buffer so make sure any fence is done and then clear memory references 4934a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes if (cb_node->in_use.load()) { 49353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 4936315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_16e00062, "MEM", 493759ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis "Calling vkBeginCommandBuffer() on active command buffer %p before it has completed. " 49383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "You must check command buffer fence before this call. %s", 4939315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis commandBuffer, validation_error_map[VALIDATION_ERROR_16e00062]); 49405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4941f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis clear_cmd_buf_and_mem_references(dev_data, cb_node); 4942f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 49435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Secondary Command Buffer 49445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkCommandBufferInheritanceInfo *pInfo = pBeginInfo->pInheritanceInfo; 49455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pInfo) { 49463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 49475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 4948315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_16e00066, "DS", 4949bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must have inheritance info. %s", commandBuffer, 4950315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_16e00066]); 49515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 49525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) { 49532c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis assert(pInfo->renderPass); 49542c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis string errorString = ""; 49559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto framebuffer = GetFramebufferState(dev_data, pInfo->framebuffer); 49562c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis if (framebuffer) { 49572c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis if ((framebuffer->createInfo.renderPass != pInfo->renderPass) && 49582c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis !verify_renderpass_compatibility(dev_data, framebuffer->renderPassCreateInfo.ptr(), 49599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GetRenderPassState(dev_data, pInfo->renderPass)->createInfo.ptr(), 49602c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis errorString)) { 49612c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // renderPass that framebuffer was created with must be compatible with local renderPass 49623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 49639b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer), __LINE__, 4964315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_0280006e, "DS", 49653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkBeginCommandBuffer(): Secondary Command " 49663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Buffer (0x%p) renderPass (0x%" PRIxLEAST64 49673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") is incompatible w/ framebuffer " 49683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "(0x%" PRIxLEAST64 ") w/ render pass (0x%" PRIxLEAST64 ") due to: %s. %s", 49699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus commandBuffer, HandleToUint64(pInfo->renderPass), HandleToUint64(pInfo->framebuffer), 49709b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(framebuffer->createInfo.renderPass), errorString.c_str(), 4971315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0280006e]); 49725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49732c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // Connect this framebuffer and its children to this cmdBuffer 49742c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis AddFramebufferBinding(dev_data, cb_node, framebuffer); 49755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49774527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if ((pInfo->occlusionQueryEnable == VK_FALSE || dev_data->enabled_features.occlusionQueryPrecise == VK_FALSE) && 49785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pInfo->queryFlags & VK_QUERY_CONTROL_PRECISE_BIT)) { 49793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 49809b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer), __LINE__, 4981315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_16e00068, "DS", 49823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must not have " 49833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_QUERY_CONTROL_PRECISE_BIT if occulusionQuery is disabled or the device does not " 49843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "support precise occlusion queries. %s", 4985315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis commandBuffer, validation_error_map[VALIDATION_ERROR_16e00068]); 49865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pInfo && pInfo->renderPass != VK_NULL_HANDLE) { 49899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto renderPass = GetRenderPassState(dev_data, pInfo->renderPass); 499016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes if (renderPass) { 4991fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes if (pInfo->subpass >= renderPass->createInfo.subpassCount) { 49923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 49939b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer), __LINE__, 4994315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_0280006c, "DS", 49953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) must have a subpass index (%d) " 49963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "that is less than the number of subpasses (%d). %s", 49973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski commandBuffer, pInfo->subpass, renderPass->createInfo.subpassCount, 4998315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0280006c]); 49995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 50005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 50015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 50025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5003f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (CB_RECORDING == cb_node->state) { 50043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5005315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_16e00062, "DS", 50063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkBeginCommandBuffer(): Cannot call Begin on command buffer (0x%p" 50073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") in the RECORDING state. Must first call vkEndCommandBuffer(). %s", 5008315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis commandBuffer, validation_error_map[VALIDATION_ERROR_16e00062]); 5009347d4d3139a1e743ed85bd375c20fd35bbe68d74Chris Forbes } else if (CB_RECORDED == cb_node->state || (CB_INVALID == cb_node->state && CMD_END == cb_node->last_cmd)) { 5010f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis VkCommandPool cmdPool = cb_node->createInfo.commandPool; 50119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, cmdPool); 5012cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) { 50133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 50145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5015315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_16e00064, "DS", 5016226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Call to vkBeginCommandBuffer() on command buffer (0x%p" 5017414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") attempts to implicitly reset cmdBuffer created from command pool (0x%" PRIxLEAST64 50184527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s", 5019315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis commandBuffer, HandleToUint64(cmdPool), validation_error_map[VALIDATION_ERROR_16e00064]); 50205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 50215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, commandBuffer); 50225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 50235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Set updated state here in case implicit reset occurs above 5024f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->state = CB_RECORDING; 5025f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->beginInfo = *pBeginInfo; 5026f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node->beginInfo.pInheritanceInfo) { 5027f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->inheritanceInfo = *(cb_node->beginInfo.pInheritanceInfo); 5028f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->beginInfo.pInheritanceInfo = &cb_node->inheritanceInfo; 5029888e1d268098177fde4a2263e3d7b7cc415f1debMark Young // If we are a secondary command-buffer and inheriting. Update the items we should inherit. 5030f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) && 5031f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis (cb_node->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 50329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis cb_node->activeRenderPass = GetRenderPassState(dev_data, cb_node->beginInfo.pInheritanceInfo->renderPass); 5033f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpass = cb_node->beginInfo.pInheritanceInfo->subpass; 5034350841afb70bf8dcfc3c6ec6b66f0aaa639553a3Tobin Ehlis cb_node->activeFramebuffer = cb_node->beginInfo.pInheritanceInfo->framebuffer; 5035f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->framebuffers.insert(cb_node->beginInfo.pInheritanceInfo->framebuffer); 5036888e1d268098177fde4a2263e3d7b7cc415f1debMark Young } 50375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 50385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5039b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 50403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 50415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 50425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 50434a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.BeginCommandBuffer(commandBuffer, pBeginInfo); 5044400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis 50455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 50465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 50475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 504889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL EndCommandBuffer(VkCommandBuffer commandBuffer) { 50493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 505056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5051b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 50529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 50535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 50544527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if ((VK_COMMAND_BUFFER_LEVEL_PRIMARY == pCB->createInfo.level) || 50554527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 5056fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop // This needs spec clarification to update valid usage, see comments in PR: 5057fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop // https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/pull/516#discussion_r63013756 5058315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(dev_data, pCB, "vkEndCommandBuffer()", VALIDATION_ERROR_27400078); 5059fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop } 50603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_END, "vkEndCommandBuffer()"); 50611ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_END); 50625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto query : pCB->activeQueries) { 50633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5064315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_2740007a, "DS", 50653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Ending command buffer with in progress query: queryPool 0x%" PRIx64 ", index %d. %s", 5066315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(query.pool), query.index, validation_error_map[VALIDATION_ERROR_2740007a]); 50675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 50685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 50693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 5070b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 50710d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes auto result = dev_data->dispatch_table.EndCommandBuffer(commandBuffer); 5072b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 50735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 50745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->state = CB_RECORDED; 50755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 50760d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes return result; 50775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 50780d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes return VK_ERROR_VALIDATION_FAILED_EXT; 50795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 50805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 50815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5082bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) { 50833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 508456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5085b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 50869a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 50875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkCommandPool cmdPool = pCB->createInfo.commandPool; 50889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, cmdPool); 5089cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) { 50903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5091315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_3260005c, "DS", 50923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Attempt to reset command buffer (0x%p) created from command pool (0x%" PRIxLEAST64 50933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s", 5094315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis commandBuffer, HandleToUint64(cmdPool), validation_error_map[VALIDATION_ERROR_3260005c]); 50955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5096315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= checkCommandBufferInFlight(dev_data, pCB, "reset", VALIDATION_ERROR_3260005a); 5097b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 50983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 50994a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetCommandBuffer(commandBuffer, flags); 51005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 5101b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 51025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, commandBuffer); 5103b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 51045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 51065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 510793c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 5108bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, 5109bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipeline pipeline) { 5110e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis bool skip = false; 511156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5112b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 51139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 5114e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (cb_state) { 5115baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdBindPipeline()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 5116315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_18002415); 511729f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip |= ValidateCmd(dev_data, cb_state, CMD_BINDPIPELINE, "vkCmdBindPipeline()"); 51181ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_state, CMD_BINDPIPELINE); 5119e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if ((VK_PIPELINE_BIND_POINT_COMPUTE == pipelineBindPoint) && (cb_state->activeRenderPass)) { 5120e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis skip |= 51215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 51229b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pipeline), __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS", 5123414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "Incorrectly binding compute pipeline (0x%" PRIxLEAST64 ") during active RenderPass (0x%" PRIxLEAST64 ")", 51249b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pipeline), HandleToUint64(cb_state->activeRenderPass->renderPass)); 51255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5126315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis // TODO: VALIDATION_ERROR_18000612 VALIDATION_ERROR_18000616 51275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5128e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis PIPELINE_STATE *pipe_state = getPipelineState(dev_data, pipeline); 5129e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (pipe_state) { 5130e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis cb_state->lastBound[pipelineBindPoint].pipeline_state = pipe_state; 5131e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis set_cb_pso_status(cb_state, pipe_state); 5132e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis set_pipeline_state(pipe_state); 5133daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski skip |= validate_dual_src_blend_feature(dev_data, pipe_state); 51345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 5135e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 5136315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pipeline), __LINE__, VALIDATION_ERROR_18027e01, "DS", 51379b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Attempt to bind Pipeline 0x%" PRIxLEAST64 " that doesn't exist! %s", HandleToUint64(pipeline), 5138315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_18027e01]); 5139e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis } 51409b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus addCommandBufferBinding(&pipe_state->cb_bindings, {HandleToUint64(pipeline), kVulkanObjectTypePipeline}, cb_state); 5141e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) { 5142e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis // Add binding for child renderpass 51439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, pipe_state->graphicsPipelineCI.renderPass); 5144e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (rp_state) { 51459b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus addCommandBufferBinding(&rp_state->cb_bindings, {HandleToUint64(rp_state->renderPass), kVulkanObjectTypeRenderPass}, 51469b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus cb_state); 5147e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis } 51485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5150b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5151cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline); 51525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 51535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5154bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, 5155bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkViewport *pViewports) { 51563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 515756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5158b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 51599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 51605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 5161315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetViewport()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1e002415); 51623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETVIEWPORTSTATE, "vkCmdSetViewport()"); 51631ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETVIEWPORTSTATE); 5164bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->viewportMask |= ((1u << viewportCount) - 1u) << firstViewport; 51655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5166b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 51673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports); 51685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 51695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5170bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, 5171bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkRect2D *pScissors) { 51723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 517356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5174b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 51759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 51765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 5177315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetScissor()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1d802415); 51783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETSCISSORSTATE, "vkCmdSetScissor()"); 51791ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSCISSORSTATE); 5180bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->scissorMask |= ((1u << scissorCount) - 1u) << firstScissor; 51815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5182b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 51833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors); 51845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 51855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 518689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) { 51873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 518856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5189b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 51909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 51915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 5192315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetLineWidth()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1d602415); 51933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETLINEWIDTHSTATE, "vkCmdSetLineWidth()"); 51941ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETLINEWIDTHSTATE); 51955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_LINE_WIDTH_SET; 5196a27508babf63d50aea75883a3702979193c23683Mark Young 51974c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipeTrav = pCB->lastBound[VK_PIPELINE_BIND_POINT_GRAPHICS].pipeline_state; 5198a27508babf63d50aea75883a3702979193c23683Mark Young if (pPipeTrav != NULL && !isDynamic(pPipeTrav, VK_DYNAMIC_STATE_LINE_WIDTH)) { 51993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5200315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1d600626, "DS", 52013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdSetLineWidth called but pipeline was created without VK_DYNAMIC_STATE_LINE_WIDTH " 52023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "flag. This is undefined behavior and could be ignored. %s", 5203315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1d600626]); 5204a27508babf63d50aea75883a3702979193c23683Mark Young } else { 52059b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= verifyLineWidth(dev_data, DRAWSTATE_INVALID_SET, kVulkanObjectTypeCommandBuffer, HandleToUint64(commandBuffer), 52069b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus lineWidth); 5207a27508babf63d50aea75883a3702979193c23683Mark Young } 52085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5209b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 52103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetLineWidth(commandBuffer, lineWidth); 52115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 52125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5213bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, 5214bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski float depthBiasSlopeFactor) { 52153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 521656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5217b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 52189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 52195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 5220315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetDepthBias()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1cc02415); 52213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBIASSTATE, "vkCmdSetDepthBias()"); 5222434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski if ((depthBiasClamp != 0.0) && (!dev_data->enabled_features.depthBiasClamp)) { 52233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5224315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1cc0062c, "DS", 52253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdSetDepthBias(): the depthBiasClamp device feature is disabled: the depthBiasClamp " 52263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "parameter must be set to 0.0. %s", 5227315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1cc0062c]); 5228434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski } 52293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 5230434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski UpdateCmdBufferLastCmd(pCB, CMD_SETDEPTHBIASSTATE); 5231434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski pCB->status |= CBSTATUS_DEPTH_BIAS_SET; 5232434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski } 52335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5234b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 52353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) 52364a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor); 52375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 52385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 523989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) { 52403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 524156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5242b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 52439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 52445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 5245315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetBlendConstants()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1ca02415); 52463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETBLENDSTATE, "vkCmdSetBlendConstants()"); 52471ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETBLENDSTATE); 52483d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis pCB->status |= CBSTATUS_BLEND_CONSTANTS_SET; 52495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5250b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 52513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetBlendConstants(commandBuffer, blendConstants); 52525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 52535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5254bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) { 52553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 525656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5257b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 52589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 52595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 5260315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetDepthBounds()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1ce02415); 52613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBOUNDSSTATE, "vkCmdSetDepthBounds()"); 52621ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETDEPTHBOUNDSSTATE); 52635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_DEPTH_BOUNDS_SET; 52645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5265b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 52663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds); 52675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 52685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5269bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, 5270bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t compareMask) { 52713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 527256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5273b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 52749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 52755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 5276315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 5277315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilCompareMask()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1da02415); 52783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREADMASKSTATE, "vkCmdSetStencilCompareMask()"); 52791ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILREADMASKSTATE); 52805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_READ_MASK_SET; 52815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5282b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 52833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask); 52845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 52855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5286bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) { 52873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 528856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5289b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 52909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 52915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 5292315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 5293315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilWriteMask()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1de02415); 52943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILWRITEMASKSTATE, "vkCmdSetStencilWriteMask()"); 52951ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILWRITEMASKSTATE); 52965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_WRITE_MASK_SET; 52975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5298b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 52993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask); 53005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 53015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5302bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) { 53033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 530456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5305b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 53069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 53075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 5308315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 5309315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilReference()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1dc02415); 53103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREFERENCESTATE, "vkCmdSetStencilReference()"); 53111ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILREFERENCESTATE); 53125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_REFERENCE_SET; 53135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5314b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 53153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetStencilReference(commandBuffer, faceMask, reference); 53165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 53175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5318bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, 5319bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, 5320bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount, 5321bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const uint32_t *pDynamicOffsets) { 5322946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 532356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5324b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5325946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 5326946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 5327baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdBindDescriptorSets()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 5328315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_17c02415); 5329946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_BINDDESCRIPTORSETS, "vkCmdBindDescriptorSets()"); 5330ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Track total count of dynamic descriptor types to make sure we have an offset for each one 5331946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski uint32_t total_dynamic_descriptors = 0; 5332946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski string error_string = ""; 5333946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski uint32_t last_set_index = firstSet + setCount - 1; 5334946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (last_set_index >= cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.size()) { 5335946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.resize(last_set_index + 1); 5336946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].dynamicOffsets.resize(last_set_index + 1); 5337946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski } 5338946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski auto old_final_bound_set = cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[last_set_index]; 5339ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski auto pipeline_layout = getPipelineLayout(dev_data, layout); 5340ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t set_idx = 0; set_idx < setCount; set_idx++) { 5341ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cvdescriptorset::DescriptorSet *descriptor_set = GetSetNode(dev_data, pDescriptorSets[set_idx]); 5342ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (descriptor_set) { 5343946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].pipeline_layout = *pipeline_layout; 5344946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[set_idx + firstSet] = descriptor_set; 5345946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 53469b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, HandleToUint64(pDescriptorSets[set_idx]), __LINE__, 5347946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski DRAWSTATE_NONE, "DS", "Descriptor Set 0x%" PRIxLEAST64 " bound on pipeline %s", 53489b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pDescriptorSets[set_idx]), string_VkPipelineBindPoint(pipelineBindPoint)); 5349ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (!descriptor_set->IsUpdated() && (descriptor_set->GetTotalDescriptorCount() != 0)) { 5350946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 53519b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, HandleToUint64(pDescriptorSets[set_idx]), 53529b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 5353946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "Descriptor Set 0x%" PRIxLEAST64 5354946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " bound but it was never updated. You may want to either update it or not bind it.", 53559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pDescriptorSets[set_idx])); 5356ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 5357ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Verify that set being bound is compatible with overlapping setLayout of pipelineLayout 535812b7fc342b53fbdd399aae4a85959e37685936acChris Forbes if (!verify_set_layout_compatibility(descriptor_set, pipeline_layout, set_idx + firstSet, error_string)) { 5359946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 53609b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, HandleToUint64(pDescriptorSets[set_idx]), 5361315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_17c002cc, "DS", 5362946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "descriptorSet #%u being bound is not compatible with overlapping descriptorSetLayout " 5363946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "at index %u of pipelineLayout 0x%" PRIxLEAST64 " due to: %s. %s", 53649b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus set_idx, set_idx + firstSet, HandleToUint64(layout), error_string.c_str(), 5365315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_17c002cc]); 53665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5367ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 5368946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski auto set_dynamic_descriptor_count = descriptor_set->GetDynamicDescriptorCount(); 5369ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 5370946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + set_idx].clear(); 5371ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 5372946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (set_dynamic_descriptor_count) { 5373ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // First make sure we won't overstep bounds of pDynamicOffsets array 5374946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if ((total_dynamic_descriptors + set_dynamic_descriptor_count) > dynamicOffsetCount) { 53759b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg( 53769b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 53779b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pDescriptorSets[set_idx]), __LINE__, DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS", 53789b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "descriptorSet #%u (0x%" PRIxLEAST64 53799b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus ") requires %u dynamicOffsets, but only %u dynamicOffsets are left in pDynamicOffsets " 53809b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "array. There must be one dynamic offset for each dynamic descriptor being bound.", 53819b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus set_idx, HandleToUint64(pDescriptorSets[set_idx]), descriptor_set->GetDynamicDescriptorCount(), 53829b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus (dynamicOffsetCount - total_dynamic_descriptors)); 5383ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else { // Validate and store dynamic offsets with the set 5384ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Validate Dynamic Offset Minimums 5385946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski uint32_t cur_dyn_offset = total_dynamic_descriptors; 5386ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t d = 0; d < descriptor_set->GetTotalDescriptorCount(); d++) { 5387ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) { 538816769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo( 5389ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski pDynamicOffsets[cur_dyn_offset], 5390ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment) != 0) { 5391315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 5392315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 5393315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, 5394315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_17c002d4, "DS", 5395315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of " 5396315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "device limit minUniformBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s", 5397315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis cur_dyn_offset, pDynamicOffsets[cur_dyn_offset], 5398315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment, 5399315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_17c002d4]); 5400ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 5401ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset++; 5402ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) { 540316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo( 5404ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski pDynamicOffsets[cur_dyn_offset], 5405ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment) != 0) { 5406315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 5407315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 5408315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, 5409315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_17c002d4, "DS", 5410315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of " 5411315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "device limit minStorageBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s", 5412315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis cur_dyn_offset, pDynamicOffsets[cur_dyn_offset], 5413315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment, 5414315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_17c002d4]); 5415ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 5416ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset++; 5417ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 541872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 5419ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 5420946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + set_idx] = 5421946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::vector<uint32_t>(pDynamicOffsets + total_dynamic_descriptors, 5422946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski pDynamicOffsets + total_dynamic_descriptors + set_dynamic_descriptor_count); 5423ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Keep running total of dynamic descriptor count to verify at the end 5424946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski total_dynamic_descriptors += set_dynamic_descriptor_count; 542572d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 542672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 5427ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else { 54289b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= 54299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 54309b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pDescriptorSets[set_idx]), __LINE__, DRAWSTATE_INVALID_SET, "DS", 54319b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Attempt to bind descriptor set 0x%" PRIxLEAST64 " that doesn't exist!", 54329b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pDescriptorSets[set_idx])); 5433ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 5434946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_BINDDESCRIPTORSETS); 5435ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // For any previously bound sets, need to set them to "invalid" if they were disturbed by this update 5436ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (firstSet > 0) { // Check set #s below the first bound set 5437ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t i = 0; i < firstSet; ++i) { 5438946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i] && 543912b7fc342b53fbdd399aae4a85959e37685936acChris Forbes !verify_set_layout_compatibility(cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i], 5440946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski pipeline_layout, i, error_string)) { 5441946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 5442ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 5443ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 54449b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i]), __LINE__, DRAWSTATE_NONE, 54459b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "DS", "DescriptorSet 0x%" PRIxLEAST64 54469b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus " previously bound as set #%u was disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")", 54479b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i]), i, 54489b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(layout)); 5449946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i] = VK_NULL_HANDLE; 54505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 54515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 54525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5453ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Check if newly last bound set invalidates any remaining bound sets 5454946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if ((cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.size() - 1) > (last_set_index)) { 5455946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (old_final_bound_set && 545612b7fc342b53fbdd399aae4a85959e37685936acChris Forbes !verify_set_layout_compatibility(old_final_bound_set, pipeline_layout, last_set_index, error_string)) { 5457946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski auto old_set = old_final_bound_set->GetSet(); 5458946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 54599b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, HandleToUint64(old_set), __LINE__, 5460946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski DRAWSTATE_NONE, "DS", "DescriptorSet 0x%" PRIxLEAST64 5461946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " previously bound as set #%u is incompatible with set 0x%" PRIxLEAST64 5462946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " newly bound as set #%u so set #%u and any subsequent sets were " 5463946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")", 54649b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(old_set), last_set_index, 54659b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[last_set_index]), 54669b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus last_set_index, last_set_index + 1, HandleToUint64(layout)); 5467946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.resize(last_set_index + 1); 5468ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 5469787f29d93dee194c015789cf61c079504c980572Tobin Ehlis } 5470ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 5471ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound 5472946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (total_dynamic_descriptors != dynamicOffsetCount) { 5473315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 5474315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5475315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_17c002ce, "DS", 5476315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "Attempting to bind %u descriptorSets with %u dynamic descriptors, but dynamicOffsetCount " 5477315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "is %u. It should exactly match the number of dynamic descriptors. %s", 5478315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis setCount, total_dynamic_descriptors, dynamicOffsetCount, validation_error_map[VALIDATION_ERROR_17c002ce]); 54795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 54805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5481b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5482946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) 54834a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, setCount, 54844a0754042cf090e131e9e769d8a3633c228625beChris Forbes pDescriptorSets, dynamicOffsetCount, pDynamicOffsets); 54855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 54865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5487bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, 5488bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkIndexType indexType) { 5489946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 549056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5491593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis // TODO : Somewhere need to verify that IBs have correct usage state flagged 5492b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5493b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 54949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 54959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 54965cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && buffer_state) { 5497315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 5498315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBindIndexBuffer()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_17e02415); 5499946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_BINDINDEXBUFFER, "vkCmdBindIndexBuffer()"); 5500315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindIndexBuffer()", VALIDATION_ERROR_17e00364); 5501ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski std::function<bool()> function = [=]() { 5502ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindIndexBuffer()"); 5503ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski }; 5504ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cb_node->validate_functions.push_back(function); 5505ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_node, CMD_BINDINDEXBUFFER); 5506ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VkDeviceSize offset_align = 0; 5507ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski switch (indexType) { 5508ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski case VK_INDEX_TYPE_UINT16: 5509ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski offset_align = 2; 5510ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski break; 5511ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski case VK_INDEX_TYPE_UINT32: 5512ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski offset_align = 4; 5513ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski break; 5514ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski default: 5515ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // ParamChecker should catch bad enum, we'll also throw alignment error below if offset_align stays 0 5516ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski break; 55175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5518ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (!offset_align || (offset % offset_align)) { 5519df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 55209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(commandBuffer), __LINE__, DRAWSTATE_VTX_INDEX_ALIGNMENT_ERROR, "DS", 5521946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "vkCmdBindIndexBuffer() offset (0x%" PRIxLEAST64 ") does not fall on alignment (%s) boundary.", offset, 5522946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski string_VkIndexType(indexType)); 5523ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 5524ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cb_node->status |= CBSTATUS_INDEX_BUFFER_BOUND; 5525ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 5526ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 55275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5528b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5529946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType); 55305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 55315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 55325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisvoid updateResourceTracking(GLOBAL_CB_NODE *pCB, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *pBuffers) { 55335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t end = firstBinding + bindingCount; 55345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->currentDrawData.buffers.size() < end) { 55355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers.resize(end); 55365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 55375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < bindingCount; ++i) { 55385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers[i + firstBinding] = pBuffers[i]; 55395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 55405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 55415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5542e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic inline void updateResourceTrackingOnDraw(GLOBAL_CB_NODE *pCB) { pCB->drawData.push_back(pCB->currentDrawData); } 55435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5544bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, 5545bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkBuffer *pBuffers, const VkDeviceSize *pOffsets) { 5546946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 554756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5548593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis // TODO : Somewhere need to verify that VBs have correct usage state flagged 5549b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5550b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 55519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 55529f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 5553315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 5554315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBindVertexBuffers()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_18202415); 5555baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmd(dev_data, cb_node, CMD_BINDVERTEXBUFFER, "vkCmdBindVertexBuffers()"); 5556ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t i = 0; i < bindingCount; ++i) { 5557ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski auto buffer_state = GetBufferState(dev_data, pBuffers[i]); 5558ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski assert(buffer_state); 5559315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindVertexBuffers()", VALIDATION_ERROR_182004e8); 5560ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski std::function<bool()> function = [=]() { 5561ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindVertexBuffers()"); 5562ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski }; 5563ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cb_node->validate_functions.push_back(function); 55645fe7f75f980a78c0179ff93438d8786e6cb44b20Tony Barbour if (pOffsets[i] >= buffer_state->createInfo.size) { 55655fe7f75f980a78c0179ff93438d8786e6cb44b20Tony Barbour skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 5566315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(buffer_state->buffer), __LINE__, VALIDATION_ERROR_182004e4, "DS", 55675fe7f75f980a78c0179ff93438d8786e6cb44b20Tony Barbour "vkCmdBindVertexBuffers() offset (0x%" PRIxLEAST64 ") is beyond the end of the buffer. %s", 5568315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis pOffsets[i], validation_error_map[VALIDATION_ERROR_182004e4]); 55695fe7f75f980a78c0179ff93438d8786e6cb44b20Tony Barbour } 55705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5571ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_node, CMD_BINDVERTEXBUFFER); 5572ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski updateResourceTracking(cb_node, firstBinding, bindingCount, pBuffers); 55735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 55747828015969ab31ee01d597f0288cbb124b637fcdMark Lobodzinski assert(0); 55755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5576b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5577946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets); 55785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 55795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 558025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Expects global_lock to be held by caller 55815569d6457ac22e7d245f3cdee045e71ffbc8b06eTobin Ehlisstatic void MarkStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { 55827a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis for (auto imageView : pCB->updateImages) { 55839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, imageView); 5584cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!view_state) continue; 5585249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 55869a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, view_state->create_info.image); 55871facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis assert(image_state); 5588e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 55891facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis SetImageMemoryValid(dev_data, image_state, true); 5590e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 55917a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis }; 55927a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->validate_functions.push_back(function); 55937a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis } 55947a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis for (auto buffer : pCB->updateBuffers) { 55959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 55965cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis assert(buffer_state); 5597e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 55985cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, buffer_state, true); 5599e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 56007a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis }; 56017a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->validate_functions.push_back(function); 56025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 56035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5605ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle validation for all CmdDraw* type functions 5606ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool ValidateCmdDrawType(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point, 5607baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt CMD_TYPE cmd_type, GLOBAL_CB_NODE **cb_state, const char *caller, VkQueueFlags queue_flags, 5608baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt UNIQUE_VALIDATION_ERROR_CODE queue_flag_code, UNIQUE_VALIDATION_ERROR_CODE msg_code, 5609baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt UNIQUE_VALIDATION_ERROR_CODE const dynamic_state_msg_code) { 561058b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis bool skip = false; 56119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *cb_state = GetCBNode(dev_data, cmd_buffer); 561258b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (*cb_state) { 5613baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, *cb_state, caller, queue_flags, queue_flag_code); 5614ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis skip |= ValidateCmd(dev_data, *cb_state, cmd_type, caller); 56154f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes skip |= ValidateDrawState(dev_data, *cb_state, indexed, bind_point, caller, dynamic_state_msg_code); 561625d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis skip |= (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) ? outsideRenderPass(dev_data, *cb_state, caller, msg_code) 561725d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis : insideRenderPass(dev_data, *cb_state, caller, msg_code); 561858b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis } 561958b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis return skip; 562058b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis} 562158b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis 562225d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis// Generic function to handle state update for all CmdDraw* and CmdDispatch* type functions 5623ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void UpdateStateCmdDrawDispatchType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 5624ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis CMD_TYPE cmd_type) { 5625ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateDrawState(dev_data, cb_state, bind_point); 56262f921d33544c162dcb726fc3c7b915e89c02ff24Tobin Ehlis MarkStoreImagesAndBuffersAsWritten(dev_data, cb_state); 56271ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_state, cmd_type); 562825d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 562925d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 5630ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle state update for all CmdDraw* type functions 5631ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void UpdateStateCmdDrawType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 5632b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes CMD_TYPE cmd_type) { 5633ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, cmd_type); 5634c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis updateResourceTrackingOnDraw(cb_state); 5635b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes cb_state->hasDrawCmd = true; 5636ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 5637ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 5638ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDraw(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point, 5639ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis GLOBAL_CB_NODE **cb_state, const char *caller) { 5640baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAW, cb_state, caller, VK_QUEUE_GRAPHICS_BIT, 5641315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1a202415, VALIDATION_ERROR_1a200017, VALIDATION_ERROR_1a200376); 5642ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 5643ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 5644ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDraw(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 5645b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAW); 5646c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis} 5647c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis 564889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, 564989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu uint32_t firstVertex, uint32_t firstInstance) { 565056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 565158b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 5652b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5653ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = PreCallValidateCmdDraw(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, "vkCmdDraw()"); 5654b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 565558b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (!skip) { 56564a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance); 5657c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis lock.lock(); 5658ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDraw(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS); 5659c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis lock.unlock(); 5660c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis } 56615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5663ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexed(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, 5664ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) { 5665baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXED, cb_state, caller, VK_QUEUE_GRAPHICS_BIT, 5666315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1a402415, VALIDATION_ERROR_1a400017, VALIDATION_ERROR_1a40039c); 5667ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 5668ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 5669ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexed(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 5670b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDEXED); 5671ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 5672ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 5673bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, 5674bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) { 567556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5676ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 5677b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5678ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis bool skip = PreCallValidateCmdDrawIndexed(dev_data, commandBuffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, 5679ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis "vkCmdDrawIndexed()"); 5680b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5681ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis if (!skip) { 56824a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); 5683ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis lock.lock(); 5684ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndexed(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS); 5685ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis lock.unlock(); 5686ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis } 56875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5689ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 5690ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, BUFFER_STATE **buffer_state, 5691ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis const char *caller) { 5692315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis bool skip = 5693315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDIRECT, cb_state, caller, VK_QUEUE_GRAPHICS_BIT, 5694315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1aa02415, VALIDATION_ERROR_1aa00017, VALIDATION_ERROR_1aa003cc); 56959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 5696315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_1aa003b4); 569713c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the 569813c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // VkDrawIndirectCommand structures accessed by this command must be 0, which will require access to the contents of 'buffer'. 5699d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis return skip; 5700d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis} 5701d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis 5702ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 5703ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 5704b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDIRECT); 5705d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 5706d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis} 5707d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis 5708bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, 5709bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t stride) { 571056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5711d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 5712d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 5713b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5714872a2f0ca3ffdeddfa7483e777191fa64b853892Tony Barbour bool skip = PreCallValidateCmdDrawIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, 5715ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &buffer_state, "vkCmdDrawIndirect()"); 5716b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5717d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis if (!skip) { 57184a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndirect(commandBuffer, buffer, offset, count, stride); 5719d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis lock.lock(); 5720ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state); 5721d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis lock.unlock(); 5722d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis } 57235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 57245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5725ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexedIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 5726ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, 5727ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE **buffer_state, const char *caller) { 5728315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis bool skip = 5729315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXEDINDIRECT, cb_state, caller, 5730315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1a602415, VALIDATION_ERROR_1a600017, VALIDATION_ERROR_1a600434); 57319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 5732315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_1a60041c); 573313c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the 573413c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // VkDrawIndexedIndirectCommand structures accessed by this command must be 0, which will require access to the contents of 573513c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // 'buffer'. 57360c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis return skip; 57370c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis} 57380c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis 5739ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexedIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 5740ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 5741b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDEXEDINDIRECT); 57420c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 57430c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis} 57440c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis 5745bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, 5746bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t count, uint32_t stride) { 574756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 57480c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 57490c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 5750b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 57510c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis bool skip = PreCallValidateCmdDrawIndexedIndirect(dev_data, commandBuffer, buffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, 5752ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &cb_state, &buffer_state, "vkCmdDrawIndexedIndirect()"); 5753b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 57540c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis if (!skip) { 57554a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride); 57560c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis lock.lock(); 5757ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndexedIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state); 57580c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis lock.unlock(); 57590c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis } 57605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 57615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5762ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatch(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, 5763ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) { 5764baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCH, cb_state, caller, VK_QUEUE_COMPUTE_BIT, 5765315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_19c02415, VALIDATION_ERROR_19c00017, VALIDATION_ERROR_UNDEFINED); 576625d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 576725d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 5768ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatch(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 5769ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, CMD_DISPATCH); 577025d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 577125d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 577289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) { 577356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 577425d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 5775b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5776ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = 5777ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PreCallValidateCmdDispatch(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, &cb_state, "vkCmdDispatch()"); 5778b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 577925d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis if (!skip) { 57804a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDispatch(commandBuffer, x, y, z); 578125d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis lock.lock(); 5782ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDispatch(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE); 578325d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis lock.unlock(); 578425d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis } 57855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 57865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5787ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatchIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 5788ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, 5789ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE **buffer_state, const char *caller) { 5790baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt bool skip = 5791baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCHINDIRECT, cb_state, caller, VK_QUEUE_COMPUTE_BIT, 5792315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1a002415, VALIDATION_ERROR_1a000017, VALIDATION_ERROR_UNDEFINED); 57939a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 5794315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_1a000322); 579579c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis return skip; 579679c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis} 579779c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis 5798ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatchIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 5799ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 5800ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, CMD_DISPATCHINDIRECT); 580179c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 580279c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis} 580379c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis 5804bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) { 580556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 580679c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 580779c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 5808b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 58097433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis bool skip = PreCallValidateCmdDispatchIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, 5810ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &cb_state, &buffer_state, "vkCmdDispatchIndirect()"); 5811b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 581279c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis if (!skip) { 58134a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDispatchIndirect(commandBuffer, buffer, offset); 581479c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis lock.lock(); 5815ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDispatchIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, buffer_state); 581679c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis lock.unlock(); 581779c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis } 58185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 582089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, 582189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu uint32_t regionCount, const VkBufferCopy *pRegions) { 5822c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5823b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5824ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 5825c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 5826c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto src_buffer_state = GetBufferState(device_data, srcBuffer); 5827c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto dst_buffer_state = GetBufferState(device_data, dstBuffer); 5828593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 5829c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski if (cb_node && src_buffer_state && dst_buffer_state) { 5830c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski bool skip = PreCallValidateCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state); 5831c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski if (!skip) { 5832c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski PreCallRecordCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state); 5833c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski lock.unlock(); 5834c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski device_data->dispatch_table.CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions); 5835c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski } 5836ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 5837c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski lock.unlock(); 5838ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 58395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 58405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5842bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 5843bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 5844bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageCopy *pRegions) { 58456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski bool skip = false; 58466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5847b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5848249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 58496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 58506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto src_image_state = GetImageState(device_data, srcImage); 58516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto dst_image_state = GetImageState(device_data, dstImage); 58521facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (cb_node && src_image_state && dst_image_state) { 58536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip = PreCallValidateCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, 58546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski srcImageLayout, dstImageLayout); 58556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (!skip) { 5856a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis PreCallRecordCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, srcImageLayout, 5857a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis dstImageLayout); 58586a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski lock.unlock(); 58596a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski device_data->dispatch_table.CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 58606a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski pRegions); 58615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5862249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis } else { 58636a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski lock.unlock(); 5864249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis assert(0); 58655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 58665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5868eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski// Validate that an image's sampleCount matches the requirement for a specific API call 586960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinskibool ValidateImageSampleCount(layer_data *dev_data, IMAGE_STATE *image_state, VkSampleCountFlagBits sample_count, 587060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski const char *location, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 5871eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski bool skip = false; 58721facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state->createInfo.samples != sample_count) { 58739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 58749b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(image_state->image), 0, msgCode, "DS", 58759b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "%s for image 0x%" PRIxLEAST64 " was created with a sample count of %s but must be %s. %s", location, 58769b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(image_state->image), string_VkSampleCountFlagBits(image_state->createInfo.samples), 58779b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus string_VkSampleCountFlagBits(sample_count), validation_error_map[msgCode]); 5878eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski } 5879eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski return skip; 5880eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski} 5881eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski 5882bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 5883bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 5884bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageBlit *pRegions, VkFilter filter) { 588556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5886b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5887593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 58889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 58899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto src_image_state = GetImageState(dev_data, srcImage); 58909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_image_state = GetImageState(dev_data, dstImage); 58910dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski 5892055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski bool skip = PreCallValidateCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, filter); 58930dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski 5894dca02371c9531e7a9a2a51decae1db4d297862c4Mark Lobodzinski if (!skip) { 5895eebd811afd800663f15fda8fc71bc203a03fe294Mark Lobodzinski PreCallRecordCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state); 5896eebd811afd800663f15fda8fc71bc203a03fe294Mark Lobodzinski lock.unlock(); 58974a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 58984a0754042cf090e131e9e769d8a3633c228625beChris Forbes pRegions, filter); 58990dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski } 59005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5902bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, 5903bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImageLayout dstImageLayout, uint32_t regionCount, 5904bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkBufferImageCopy *pRegions) { 5905940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5906b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5907940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski bool skip = false; 5908940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 5909940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto src_buffer_state = GetBufferState(device_data, srcBuffer); 5910940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto dst_image_state = GetImageState(device_data, dstImage); 5911940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (cb_node && src_buffer_state && dst_image_state) { 5912940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski skip = PreCallValidateCmdCopyBufferToImage(device_data, dstImageLayout, cb_node, src_buffer_state, dst_image_state, 591371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski regionCount, pRegions, "vkCmdCopyBufferToImage()"); 5914ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 5915d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 5916ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 5917e4d82c37d6c861b388dbc80297c18d6255858cb4Dave Houlton // TODO: report VU01244 here, or put in object tracker? 59185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5919940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (!skip) { 5920a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis PreCallRecordCmdCopyBufferToImage(device_data, cb_node, src_buffer_state, dst_image_state, regionCount, pRegions, 5921a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis dstImageLayout); 5922d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 5923940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski device_data->dispatch_table.CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions); 5924d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski } 59255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5927bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 5928bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions) { 5929940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski bool skip = false; 5930940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5931b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5932593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 5933940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 5934940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto src_image_state = GetImageState(device_data, srcImage); 5935940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto dst_buffer_state = GetBufferState(device_data, dstBuffer); 5936940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (cb_node && src_image_state && dst_buffer_state) { 5937940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski skip = PreCallValidateCmdCopyImageToBuffer(device_data, srcImageLayout, cb_node, src_image_state, dst_buffer_state, 593871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski regionCount, pRegions, "vkCmdCopyImageToBuffer()"); 5939ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 5940d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 5941ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 5942e4d82c37d6c861b388dbc80297c18d6255858cb4Dave Houlton // TODO: report VU01262 here, or put in object tracker? 59435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5944940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (!skip) { 5945a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis PreCallRecordCmdCopyImageToBuffer(device_data, cb_node, src_image_state, dst_buffer_state, regionCount, pRegions, 5946a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis srcImageLayout); 5947d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 5948940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski device_data->dispatch_table.CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions); 5949d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski } 59505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5952bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, 5953bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize dataSize, const uint32_t *pData) { 59543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 595556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5956b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5957593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 59589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 59599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_buff_state = GetBufferState(dev_data, dstBuffer); 59605cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && dst_buff_state) { 5961315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdUpdateBuffer()", VALIDATION_ERROR_1e400046); 5962ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Update bindings between buffer and cmd buffer 59635cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state); 5964ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Validate that DST buffer has correct usage flags set 5965315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, 5966315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1e400044, "vkCmdUpdateBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 5967e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 59685cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, dst_buff_state, true); 5969e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 59705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis }; 59719f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 5972593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 5973315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 5974315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdUpdateBuffer()", 5975315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_1e402415); 59763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_UPDATEBUFFER, "vkCmdUpdateBuffer()"); 59771ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_UPDATEBUFFER); 5978315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(dev_data, cb_node, "vkCmdUpdateBuffer()", VALIDATION_ERROR_1e400017); 5979ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 5980ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 59815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5982b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 59833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData); 59845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5986bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, 5987bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize size, uint32_t data) { 598823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 5989b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 599023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 599123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski auto buffer_state = GetBufferState(device_data, dstBuffer); 5992593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 599323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski if (cb_node && buffer_state) { 599423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski bool skip = PreCallValidateCmdFillBuffer(device_data, cb_node, buffer_state); 599523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski if (!skip) { 599623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski PreCallRecordCmdFillBuffer(device_data, cb_node, buffer_state); 599723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski lock.unlock(); 599823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski device_data->dispatch_table.CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data); 599923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski } 6000ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 600123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski lock.unlock(); 6002ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 60035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 60045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 60064028af23e688ab5730f48ab2244dd042e2eefaedMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount, 60074028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski const VkClearAttachment *pAttachments, uint32_t rectCount, 60084028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski const VkClearRect *pRects) { 60094028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski bool skip = false; 601056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 60114028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski { 60124028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 60134028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski skip = PreCallValidateCmdClearAttachments(dev_data, commandBuffer, attachmentCount, pAttachments, rectCount, pRects); 60144028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski } 6015cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects); 60165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 60180482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, 60190482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkClearColorValue *pColor, uint32_t rangeCount, 60200482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkImageSubresourceRange *pRanges) { 602156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6022b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 60230482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 60240482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski bool skip = PreCallValidateCmdClearColorImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges); 60250482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski if (!skip) { 60260482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges, CMD_CLEARCOLORIMAGE); 60270482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski lock.unlock(); 60280482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski dev_data->dispatch_table.CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges); 60290482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski } 60300482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski} 60310482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 60320482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, 60330482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount, 60340482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkImageSubresourceRange *pRanges) { 603556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 60360482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 60370482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 60380482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski bool skip = PreCallValidateCmdClearDepthStencilImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges); 60390482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski if (!skip) { 60400482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges, CMD_CLEARDEPTHSTENCILIMAGE); 60410482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski lock.unlock(); 60420482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski dev_data->dispatch_table.CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges); 60437f8aa8f5abceedbb599ef69af1dfbb38c0df2660Slawomir Cygan } 60445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6046bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 6047bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 6048bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageResolve *pRegions) { 604956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6050b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 6051593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 60529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 60539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto src_image_state = GetImageState(dev_data, srcImage); 60549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_image_state = GetImageState(dev_data, dstImage); 605509fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski 605625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski bool skip = PreCallValidateCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions); 605709fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski 605809fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski if (!skip) { 60596c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski PreCallRecordCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state); 60606c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski lock.unlock(); 60614a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 60624a0754042cf090e131e9e769d8a3633c228625beChris Forbes pRegions); 606309fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski } 60645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6066a8d1e377bdeaf61a3209cb997502da4356a185bbMike WeiblenVKAPI_ATTR void VKAPI_CALL GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource, 6067a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen VkSubresourceLayout *pLayout) { 6068a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 6069a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen 6070a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen bool skip = PreCallValidateGetImageSubresourceLayout(device_data, image, pSubresource); 6071a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen if (!skip) { 6072b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski device_data->dispatch_table.GetImageSubresourceLayout(device, image, pSubresource, pLayout); 6073b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski } 6074b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski} 6075b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski 6076b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentinebool setEventStageMask(VkQueue queue, VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 607756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 60789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 6079b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (pCB) { 6080b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventToStageMap[event] = stageMask; 6081b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 6082b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine auto queue_data = dev_data->queueMap.find(queue); 6083b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (queue_data != dev_data->queueMap.end()) { 6084b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine queue_data->second.eventToStageMap[event] = stageMask; 6085b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 6086b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine return false; 6087b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine} 6088b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine 6089bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 60903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 609156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6092b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 60939a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 60945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 60953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetEvent()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 6096315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1d402415); 60973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETEVENT, "vkCmdSetEvent()"); 60981ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETEVENT); 6099315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(dev_data, pCB, "vkCmdSetEvent()", VALIDATION_ERROR_1d400017); 6100315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdSetEvent()", VALIDATION_ERROR_1d4008fc, 6101315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1d4008fe); 61029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 61034710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 61049b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus addCommandBufferBinding(&event_state->cb_bindings, {HandleToUint64(event), kVulkanObjectTypeEvent}, pCB); 61054710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->cb_bindings.insert(pCB); 6106ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 61075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.push_back(event); 6108c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (!pCB->waitedEvents.count(event)) { 6109c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine pCB->writeEventsBeforeWait.push_back(event); 6110c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 6111f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes pCB->eventUpdates.emplace_back([=](VkQueue q){return setEventStageMask(q, commandBuffer, event, stageMask);}); 61125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6113b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 61143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetEvent(commandBuffer, event, stageMask); 61155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6117bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 61183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 611956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6120b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 61219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 61225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 61233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdResetEvent()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 6124315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1c402415); 61253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_RESETEVENT, "vkCmdResetEvent()"); 61261ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_RESETEVENT); 6127315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(dev_data, pCB, "vkCmdResetEvent()", VALIDATION_ERROR_1c400017); 6128315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdResetEvent()", VALIDATION_ERROR_1c400904, 6129315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1c400906); 61309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 61314710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 61329b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus addCommandBufferBinding(&event_state->cb_bindings, {HandleToUint64(event), kVulkanObjectTypeEvent}, pCB); 61334710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->cb_bindings.insert(pCB); 6134ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 61355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.push_back(event); 6136c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (!pCB->waitedEvents.count(event)) { 6137c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine pCB->writeEventsBeforeWait.push_back(event); 6138c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 6139315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis // TODO : Add check for VALIDATION_ERROR_32c008f8 6140f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes pCB->eventUpdates.emplace_back([=](VkQueue q){return setEventStageMask(q, commandBuffer, event, VkPipelineStageFlags(0));}); 61415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6142b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 61433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdResetEvent(commandBuffer, event, stageMask); 61445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6146e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, uint32_t memBarrierCount, 6147e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkMemoryBarrier *pMemBarriers, uint32_t bufferBarrierCount, 6148e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkBufferMemoryBarrier *pBufferMemBarriers, uint32_t imageMemBarrierCount, 6149e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkImageMemoryBarrier *pImageMemBarriers) { 6150a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis bool skip = false; 615156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(cmdBuffer), layer_data_map); 61529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, cmdBuffer); 61535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass && memBarrierCount) { 6154ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes if (!pCB->activeRenderPass->hasSelfDependency[pCB->activeSubpass]) { 6155df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 61569b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 6157cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Barriers cannot be set during subpass %d " 6158cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "with no self dependency specified.", 6159a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, pCB->activeSubpass); 61605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 61615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 61625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < imageMemBarrierCount; ++i) { 61635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto mem_barrier = &pImageMemBarriers[i]; 61648f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski auto image_data = GetImageState(dev_data, mem_barrier->image); 61658f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski if (image_data) { 61668f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski uint32_t src_q_f_index = mem_barrier->srcQueueFamilyIndex; 61678f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski uint32_t dst_q_f_index = mem_barrier->dstQueueFamilyIndex; 61688f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski if (image_data->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { 61698f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski // srcQueueFamilyIndex and dstQueueFamilyIndex must both 61708f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski // be VK_QUEUE_FAMILY_IGNORED 61718f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski if ((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) { 61728f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 61739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(cmdBuffer), __LINE__, 61749b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus DRAWSTATE_INVALID_QUEUE_INDEX, "DS", "%s: Image Barrier for image 0x%" PRIx64 61759b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus " was created with sharingMode of " 61769b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "VK_SHARING_MODE_CONCURRENT. Src and dst " 61779b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "queueFamilyIndices must be VK_QUEUE_FAMILY_IGNORED.", 61789b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus funcName, HandleToUint64(mem_barrier->image)); 61798f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski } 61808f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski } else { 61818f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski // Sharing mode is VK_SHARING_MODE_EXCLUSIVE. srcQueueFamilyIndex and 61828f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski // dstQueueFamilyIndex must either both be VK_QUEUE_FAMILY_IGNORED, 61838f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski // or both be a valid queue family 61848f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski if (((src_q_f_index == VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index == VK_QUEUE_FAMILY_IGNORED)) && 61858f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski (src_q_f_index != dst_q_f_index)) { 61868f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 61879b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(cmdBuffer), __LINE__, 61889b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus DRAWSTATE_INVALID_QUEUE_INDEX, "DS", "%s: Image 0x%" PRIx64 61899b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus " was created with sharingMode " 61909b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "of VK_SHARING_MODE_EXCLUSIVE. If one of src- or " 61919b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "dstQueueFamilyIndex is VK_QUEUE_FAMILY_IGNORED, both " 61929b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "must be.", 61939b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus funcName, HandleToUint64(mem_barrier->image)); 61948f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski } else if (((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) && (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) && 61958f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski ((src_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()) || 61968f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski (dst_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()))) { 61978f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 61989b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(cmdBuffer), __LINE__, 61998f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 62008f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski "%s: Image 0x%" PRIx64 62018f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski " was created with sharingMode " 62028f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski "of VK_SHARING_MODE_EXCLUSIVE, but srcQueueFamilyIndex %d" 62038f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski " or dstQueueFamilyIndex %d is greater than " PRINTF_SIZE_T_SPECIFIER 62048f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski "queueFamilies crated for this device.", 62059b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus funcName, HandleToUint64(mem_barrier->image), src_q_f_index, dst_q_f_index, 62068f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski dev_data->phys_dev_properties.queue_family_properties.size()); 62075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 62085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 62098f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski } 62105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62118f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski if (mem_barrier->oldLayout != mem_barrier->newLayout) { 62128f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski if (pCB->activeRenderPass) { 62139b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= 62149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6215315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(cmdBuffer), __LINE__, VALIDATION_ERROR_1b80093a, "DS", 62169b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "%s: As the Image Barrier for image 0x%" PRIx64 62179b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus " is being executed within a render pass instance, oldLayout must equal newLayout yet they are " 62189b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "%s and %s. %s", 62199b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus funcName, HandleToUint64(mem_barrier->image), string_VkImageLayout(mem_barrier->oldLayout), 6220315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis string_VkImageLayout(mem_barrier->newLayout), validation_error_map[VALIDATION_ERROR_1b80093a]); 6221d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour } 62228f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski skip |= ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->srcAccessMask, mem_barrier->oldLayout, "Source"); 62238f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski skip |= ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->dstAccessMask, mem_barrier->newLayout, "Dest"); 62248f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski } 62258f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski if (mem_barrier->newLayout == VK_IMAGE_LAYOUT_UNDEFINED || mem_barrier->newLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) { 62268f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 62279b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 6228df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Image Layout cannot be transitioned to UNDEFINED or " 6229df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "PREINITIALIZED.", 6230df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski funcName); 62318f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski } 62328f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski if (image_data) { 62338f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski auto aspect_mask = mem_barrier->subresourceRange.aspectMask; 62342044b110851e8f1b75d6d406a0c88612476c63dbChris Forbes skip |= ValidateImageAspectMask(dev_data, image_data->image, image_data->createInfo.format, aspect_mask, funcName); 623595b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski 623623c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus std::string param_name = "pImageMemoryBarriers[" + std::to_string(i) + "].subresourceRange"; 6237dab32891b91206a5bef7a3929b781e44fc1b7268Petr Kraus skip |= ValidateImageSubresourceRange(dev_data, image_data, false, mem_barrier->subresourceRange, funcName, 623823c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus param_name.c_str()); 62395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 62405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 62412044b110851e8f1b75d6d406a0c88612476c63dbChris Forbes 62425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < bufferBarrierCount; ++i) { 62435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto mem_barrier = &pBufferMemBarriers[i]; 62445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass) { 6245df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 62469b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 6247df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Buffer Barriers cannot be used during a render pass.", funcName); 62485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6249cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!mem_barrier) continue; 62505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate buffer barrier queue family indices 62525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((mem_barrier->srcQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED && 6253b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis mem_barrier->srcQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size()) || 62545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (mem_barrier->dstQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED && 6255b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis mem_barrier->dstQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size())) { 6256df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 62579b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cmdBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 6258cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Buffer Barrier 0x%" PRIx64 6259cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " has QueueFamilyIndex greater " 6260a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis "than the number of QueueFamilies (" PRINTF_SIZE_T_SPECIFIER ") for this device.", 62619b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus funcName, HandleToUint64(mem_barrier->buffer), 6262a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis dev_data->phys_dev_properties.queue_family_properties.size()); 62635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 62645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, mem_barrier->buffer); 62665cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 62675cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis auto buffer_size = buffer_state->requirements.size; 62685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem_barrier->offset >= buffer_size) { 62699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 62709b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(cmdBuffer), __LINE__, 62719b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus DRAWSTATE_INVALID_BARRIER, "DS", "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 62729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus " which is not less than total size 0x%" PRIx64 ".", 62739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus funcName, HandleToUint64(mem_barrier->buffer), HandleToUint64(mem_barrier->offset), 62749b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(buffer_size)); 6275df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski } else if (mem_barrier->size != VK_WHOLE_SIZE && (mem_barrier->offset + mem_barrier->size > buffer_size)) { 6276df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= 6277df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 62789b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 6279df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " and size 0x%" PRIx64 6280df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " whose sum is greater than total size 0x%" PRIx64 ".", 62819b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus funcName, HandleToUint64(mem_barrier->buffer), HandleToUint64(mem_barrier->offset), 62829b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem_barrier->size), HandleToUint64(buffer_size)); 62835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 62845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 62855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6286a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis return skip; 62875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6289bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskibool validateEventStageMask(VkQueue queue, GLOBAL_CB_NODE *pCB, uint32_t eventCount, size_t firstEventIndex, 6290bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipelineStageFlags sourceStageMask) { 62913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 6292b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine VkPipelineStageFlags stageMask = 0; 629356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 6294b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine for (uint32_t i = 0; i < eventCount; ++i) { 62952ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes auto event = pCB->events[firstEventIndex + i]; 6296b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine auto queue_data = dev_data->queueMap.find(queue); 6297cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (queue_data == dev_data->queueMap.end()) return false; 62982ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes auto event_data = queue_data->second.eventToStageMap.find(event); 6299b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (event_data != queue_data->second.eventToStageMap.end()) { 6300b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine stageMask |= event_data->second; 6301b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } else { 63029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto global_event_data = GetEventNode(dev_data, event); 63039556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis if (!global_event_data) { 63043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, 63059b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(event), __LINE__, DRAWSTATE_INVALID_EVENT, "DS", 63069b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Event 0x%" PRIx64 " cannot be waited on if it has never been set.", HandleToUint64(event)); 6307b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } else { 63089556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis stageMask |= global_event_data->stageMask; 6309b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 6310b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 6311b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 6312c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine // TODO: Need to validate that host_bit is only set if set event is called 6313c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine // but set event can be called at any time. 6314c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (sourceStageMask != stageMask && sourceStageMask != (stageMask | VK_PIPELINE_STAGE_HOST_BIT)) { 63153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6316315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_1e62d401, "DS", 63173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Submitting cmdbuffer with call to VkCmdWaitEvents " 63183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "using srcStageMask 0x%X which must be the bitwise " 63193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "OR of the stageMask parameters used in calls to " 63203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if " 63213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "used with vkSetEvent but instead is 0x%X. %s", 6322315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis sourceStageMask, stageMask, validation_error_map[VALIDATION_ERROR_1e62d401]); 6323b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 63243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 6325b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine} 6326b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine 632707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski// Note that we only check bits that HAVE required queueflags -- don't care entries are skipped 632807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic std::unordered_map<VkPipelineStageFlags, VkQueueFlags> supported_pipeline_stages_table = { 632907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT}, 633007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT}, 633107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_QUEUE_GRAPHICS_BIT}, 633207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 633307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 633407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 633507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 633607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 633707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT}, 633807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT}, 633907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_QUEUE_GRAPHICS_BIT}, 634007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_QUEUE_COMPUTE_BIT}, 634107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT}, 634207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_QUEUE_GRAPHICS_BIT}}; 634307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 634407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic const VkPipelineStageFlags stage_flag_bit_array[] = {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX, 634507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 634607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 634707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 634807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, 634907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, 635007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, 635107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 635207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 635307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 635407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 635507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 635607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TRANSFER_BIT, 635707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT}; 635807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 635907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskibool CheckStageMaskQueueCompatibility(layer_data *dev_data, VkCommandBuffer command_buffer, VkPipelineStageFlags stage_mask, 636007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkQueueFlags queue_flags, const char *function, const char *src_or_dest, 636107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski UNIQUE_VALIDATION_ERROR_CODE error_code) { 636207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski bool skip = false; 636307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // Lookup each bit in the stagemask and check for overlap between its table bits and queue_flags 636407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski for (const auto &item : stage_flag_bit_array) { 636507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if (stage_mask & item) { 636607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((supported_pipeline_stages_table[item] & queue_flags) == 0) { 636707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= 636807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 63699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(command_buffer), __LINE__, error_code, "DL", 637007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski "%s(): %s flag %s is not compatible with the queue family properties of this " 637107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski "command buffer. %s", 637207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, src_or_dest, string_VkPipelineStageFlagBits(static_cast<VkPipelineStageFlagBits>(item)), 637307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski validation_error_map[error_code]); 637407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 637507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 637607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 637707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski return skip; 637807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski} 637907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 638007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskibool ValidateStageMasksAgainstQueueCapabilities(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, 638107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkPipelineStageFlags source_stage_mask, VkPipelineStageFlags dest_stage_mask, 638207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski const char *function, UNIQUE_VALIDATION_ERROR_CODE error_code) { 638307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski bool skip = false; 638407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski uint32_t queue_family_index = dev_data->commandPoolMap[cb_state->createInfo.commandPool].queueFamilyIndex; 638556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(dev_data->physical_device), instance_layer_data_map); 63869a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, dev_data->physical_device); 638707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 638807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // Any pipeline stage included in srcStageMask or dstStageMask must be supported by the capabilities of the queue family 638907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // specified by the queueFamilyIndex member of the VkCommandPoolCreateInfo structure that was used to create the VkCommandPool 639007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // that commandBuffer was allocated from, as specified in the table of supported pipeline stages. 639107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 639207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if (queue_family_index < physical_device_state->queue_family_properties.size()) { 639307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkQueueFlags specified_queue_flags = physical_device_state->queue_family_properties[queue_family_index].queueFlags; 639407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 639507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((source_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) { 639607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, source_stage_mask, specified_queue_flags, 639707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, "srcStageMask", error_code); 639807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 639907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((dest_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) { 640007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, dest_stage_mask, specified_queue_flags, 640107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, "dstStageMask", error_code); 640207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 640307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 640407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski return skip; 640507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski} 640607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 6407d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents, 6408d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VkPipelineStageFlags sourceStageMask, VkPipelineStageFlags dstStageMask, 6409d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 6410d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 6411d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 6412d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski bool skip = false; 641356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6414b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 64159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 6416d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (cb_state) { 6417d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski skip |= ValidateStageMasksAgainstQueueCapabilities(dev_data, cb_state, sourceStageMask, dstStageMask, "vkCmdWaitEvents", 6418315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1e600918); 6419315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, sourceStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_1e60090e, 6420315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1e600912); 6421315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, dstStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_1e600910, 6422315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1e600914); 6423d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski auto first_event_index = cb_state->events.size(); 64245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < eventCount; ++i) { 64259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, pEvents[i]); 64264710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 64279b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus addCommandBufferBinding(&event_state->cb_bindings, {HandleToUint64(pEvents[i]), kVulkanObjectTypeEvent}, cb_state); 6428d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski event_state->cb_bindings.insert(cb_state); 6429ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 6430d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->waitedEvents.insert(pEvents[i]); 6431d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->events.push_back(pEvents[i]); 64325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6433f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes cb_state->eventUpdates.emplace_back([=](VkQueue q){ 6434f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes return validateEventStageMask(q, cb_state, eventCount, first_event_index, sourceStageMask); 6435f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes }); 6436baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdWaitEvents()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 6437315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1e602415); 6438ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_WAITEVENTS, "vkCmdWaitEvents()"); 6439ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_WAITEVENTS); 6440a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen skip |= 6441a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen ValidateBarriersToImages(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers, "vkCmdWaitEvents()"); 6442e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski if (!skip) { 6443e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski TransitionImageLayouts(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 6444e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski } 6445e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski 6446364a03b109f0b2b37be2e13d293fa93b8af5203aMike Weiblen skip |= ValidateBarriers("vkCmdWaitEvents()", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 6447d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 64485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6449b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6450d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (!skip) 64514a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdWaitEvents(commandBuffer, eventCount, pEvents, sourceStageMask, dstStageMask, 64524a0754042cf090e131e9e769d8a3633c228625beChris Forbes memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, 64534a0754042cf090e131e9e769d8a3633c228625beChris Forbes imageMemoryBarrierCount, pImageMemoryBarriers); 64545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 64555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 645603122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinskistatic bool PreCallValidateCmdPipelineBarrier(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkCommandBuffer commandBuffer, 645703122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, 645803122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 645903122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 646003122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 646103122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski bool skip = false; 646203122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateStageMasksAgainstQueueCapabilities(device_data, cb_state, srcStageMask, dstStageMask, "vkCmdPipelineBarrier", 6463315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1b80093e); 6464baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(device_data, cb_state, "vkCmdPipelineBarrier()", 6465315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_1b802415); 646603122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateCmd(device_data, cb_state, CMD_PIPELINEBARRIER, "vkCmdPipelineBarrier()"); 6467315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(device_data, srcStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_1b800920, 6468315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1b800924); 6469315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(device_data, dstStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_1b800922, 6470315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1b800926); 6471a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen skip |= ValidateBarriersToImages(device_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers, 6472a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen "vkCmdPipelineBarrier()"); 647303122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateBarriers("vkCmdPipelineBarrier()", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 647403122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 647503122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski return skip; 647603122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski} 647703122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski 64786f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinskistatic void PreCallRecordCmdPipelineBarrier(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkCommandBuffer commandBuffer, 64796f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 64806f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_PIPELINEBARRIER); 64816f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski TransitionImageLayouts(device_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 64826f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski} 64836f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski 6484d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, 6485d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, 6486d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 6487d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 6488d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 6489d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski bool skip = false; 64906f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6491b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 64926f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(device_data, commandBuffer); 6493d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (cb_state) { 64946f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski skip |= PreCallValidateCmdPipelineBarrier(device_data, cb_state, commandBuffer, srcStageMask, dstStageMask, 649503122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 649603122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 64976f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski if (!skip) { 64986f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski PreCallRecordCmdPipelineBarrier(device_data, cb_state, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 64996f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski } 65006f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski } else { 65016f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski assert(0); 65025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6503b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6504a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour if (!skip) { 6505a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour device_data->dispatch_table.CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, 6506a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, 6507a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour imageMemoryBarrierCount, pImageMemoryBarriers); 6508a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour } 65095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 65105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 651143ec3f090ca979777b306abe7c25662b9429e06dChris Forbesstatic bool setQueryState(VkQueue queue, VkCommandBuffer commandBuffer, QueryObject object, bool value) { 651256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 65139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 6514d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (pCB) { 6515d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine pCB->queryToStateMap[object] = value; 6516d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 6517d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto queue_data = dev_data->queueMap.find(queue); 6518d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (queue_data != dev_data->queueMap.end()) { 6519d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine queue_data->second.queryToStateMap[object] = value; 6520d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 6521d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine return false; 6522d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine} 6523d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine 6524bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkFlags flags) { 65253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 652656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6527b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 65289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 65295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 65303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdBeginQuery()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 6531315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_17802415); 65323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_BEGINQUERY, "vkCmdBeginQuery()"); 653343ec3f090ca979777b306abe7c25662b9429e06dChris Forbes } 653443ec3f090ca979777b306abe7c25662b9429e06dChris Forbes lock.unlock(); 653543ec3f090ca979777b306abe7c25662b9429e06dChris Forbes 653643ec3f090ca979777b306abe7c25662b9429e06dChris Forbes if (skip) return; 653743ec3f090ca979777b306abe7c25662b9429e06dChris Forbes 653843ec3f090ca979777b306abe7c25662b9429e06dChris Forbes dev_data->dispatch_table.CmdBeginQuery(commandBuffer, queryPool, slot, flags); 653943ec3f090ca979777b306abe7c25662b9429e06dChris Forbes 654043ec3f090ca979777b306abe7c25662b9429e06dChris Forbes lock.lock(); 654143ec3f090ca979777b306abe7c25662b9429e06dChris Forbes if (pCB) { 654243ec3f090ca979777b306abe7c25662b9429e06dChris Forbes QueryObject query = {queryPool, slot}; 654343ec3f090ca979777b306abe7c25662b9429e06dChris Forbes pCB->activeQueries.insert(query); 654443ec3f090ca979777b306abe7c25662b9429e06dChris Forbes pCB->startedQueries.insert(query); 65451ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_BEGINQUERY); 65469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 65479b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, pCB); 65485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 65505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 655189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) { 6552946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 655356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6554b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 6555946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 6556946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 65575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 6558946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!cb_state->activeQueries.count(query)) { 6559df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6560315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1ae00652, "DS", 65619b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Ending a query before it was started: queryPool 0x%" PRIx64 ", index %d. %s", 6562315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(queryPool), slot, validation_error_map[VALIDATION_ERROR_1ae00652]); 65635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 6564946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->activeQueries.erase(query); 65655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6566f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes cb_state->queryUpdates.emplace_back([=](VkQueue q){return setQueryState(q, commandBuffer, query, true);}); 6567baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "VkCmdEndQuery()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 6568315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1ae02415); 6569946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_ENDQUERY, "VkCmdEndQuery()"); 6570946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_ENDQUERY); 65719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 65729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_state); 65735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6574b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6575946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdEndQuery(commandBuffer, queryPool, slot); 65765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 65775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6578bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, 6579bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t queryCount) { 6580946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 658156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6582b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 6583946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 65843a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes skip |= insideRenderPass(dev_data, cb_state, "vkCmdResetQueryPool()", VALIDATION_ERROR_1c600017); 65853a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes skip |= ValidateCmd(dev_data, cb_state, CMD_RESETQUERYPOOL, "VkCmdResetQueryPool()"); 6586baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "VkCmdResetQueryPool()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 6587315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1c602415); 6588b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 65893a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes 65903a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes if (skip) return; 65913a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes 65923a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes dev_data->dispatch_table.CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount); 65933a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes 65943a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes lock.lock(); 65953a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes for (uint32_t i = 0; i < queryCount; i++) { 65963a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes QueryObject query = {queryPool, firstQuery + i}; 65973a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes cb_state->waitedEventsBeforeQueryReset[query] = cb_state->waitedEvents; 6598f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes cb_state->queryUpdates.emplace_back([=](VkQueue q){return setQueryState(q, commandBuffer, query, false);}); 65993a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes } 66003a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes UpdateCmdBufferLastCmd(cb_state, CMD_RESETQUERYPOOL); 66013a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 66023a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_state); 66035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 66045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 66057ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbesstatic bool IsQueryInvalid(layer_data *dev_data, QUEUE_STATE *queue_data, VkQueryPool queryPool, uint32_t queryIndex) { 66067ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes QueryObject query = {queryPool, queryIndex}; 66077ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes auto query_data = queue_data->queryToStateMap.find(query); 66087ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes if (query_data != queue_data->queryToStateMap.end()) { 66097ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes if (!query_data->second) return true; 66107ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes } else { 66117ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes auto it = dev_data->queryToStateMap.find(query); 66127ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes if (it == dev_data->queryToStateMap.end() || !it->second) 66137ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes return true; 66147ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes } 66157ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes 66167ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes return false; 66177ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes} 66187ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes 66197ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbesstatic bool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) { 66203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 662156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(pCB->commandBuffer), layer_data_map); 66227ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes auto queue_data = GetQueueState(dev_data, queue); 66237ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes if (!queue_data) return false; 6624d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine for (uint32_t i = 0; i < queryCount; i++) { 66257ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes if (IsQueryInvalid(dev_data, queue_data, queryPool, firstQuery + i)) { 66263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 66279b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 66283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d", 66299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(queryPool), firstQuery + i); 6630d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 6631d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 66323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 6633d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine} 6634d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine 6635bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, 6636bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, 6637bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize stride, VkQueryResultFlags flags) { 6638946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 663956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6640b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 6641ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 66429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 66439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_buff_state = GetBufferState(dev_data, dstBuffer); 66445cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && dst_buff_state) { 6645315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_19400674); 6646ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Update bindings between buffer and cmd buffer 66475cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state); 6648ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Validate that DST buffer has correct usage flags set 6649315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 6650315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_19400672, 6651315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "vkCmdCopyQueryPoolResults()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 6652e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 66535cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, dst_buff_state, true); 6654e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 66555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis }; 66569f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 6657f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes cb_node->queryUpdates.emplace_back([=](VkQueue q) { 6658f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes return validateQuery(q, cb_node, queryPool, firstQuery, queryCount); 6659f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes }); 6660baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdCopyQueryPoolResults()", 6661315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_19402415); 6662946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()"); 6663ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_node, CMD_COPYQUERYPOOLRESULTS); 6664315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(dev_data, cb_node, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_19400017); 66659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 66669b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_node); 6667ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 6668ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 66695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6670b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6671946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) 66724a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset, 66734a0754042cf090e131e9e769d8a3633c228625beChris Forbes stride, flags); 66745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 66755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6676bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, 6677bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t offset, uint32_t size, const void *pValues) { 6678946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 667956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6680b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 6681946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 6682946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 6683baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdPushConstants()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 6684315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1bc02415); 6685946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_PUSHCONSTANTS, "vkCmdPushConstants()"); 6686946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_PUSHCONSTANTS); 66875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6688946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= validatePushConstantRange(dev_data, offset, size, "vkCmdPushConstants()"); 66899e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == stageFlags) { 6690df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6691315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1bc2dc03, "DS", 6692315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "vkCmdPushConstants() call has no stageFlags set. %s", validation_error_map[VALIDATION_ERROR_1bc2dc03]); 66939e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 66949e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz 6695bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // Check if specified push constant range falls within a pipeline-defined range which has matching stageFlags. 6696bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // The spec doesn't seem to disallow having multiple push constant ranges with the 6697bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // same offset and size, but different stageFlags. So we can't just check the 6698bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // stageFlags in the first range with matching offset and size. 6699bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz if (!skip) { 6700bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz const auto &ranges = getPipelineLayout(dev_data, layout)->push_constant_ranges; 6701bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz bool found_matching_range = false; 6702bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz for (const auto &range : ranges) { 6703bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz if ((stageFlags == range.stageFlags) && (offset >= range.offset) && (offset + size <= range.offset + range.size)) { 6704bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz found_matching_range = true; 670515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis break; 6706a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz } 67079e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 6708bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz if (!found_matching_range) { 6709315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6710315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1bc002de, "DS", 6711315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "vkCmdPushConstants() stageFlags = 0x%" PRIx32 6712315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis " do not match the stageFlags in any of the ranges with" 6713315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis " offset = %d and size = %d in pipeline layout 0x%" PRIx64 ". %s", 6714315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis (uint32_t)stageFlags, offset, size, HandleToUint64(layout), 6715315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1bc002de]); 671615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis } 67175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6718b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6719946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues); 67205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 67215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6722bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, 6723bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkQueryPool queryPool, uint32_t slot) { 6724946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 672556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6726b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 6727946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 6728946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 67295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 6730f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes cb_state->queryUpdates.emplace_back([=](VkQueue q) {return setQueryState(q, commandBuffer, query, true);}); 6731baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdWriteTimestamp()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 6732315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1e802415); 6733946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()"); 6734946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_WRITETIMESTAMP); 67355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6736b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6737946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot); 67385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 67395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 67406600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinskistatic bool MatchUsage(layer_data *dev_data, uint32_t count, const VkAttachmentReference *attachments, 67419bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt const VkFramebufferCreateInfo *fbci, VkImageUsageFlagBits usage_flag, 67429bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt UNIQUE_VALIDATION_ERROR_CODE error_code) { 6743946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 67446600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 67456600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski for (uint32_t attach = 0; attach < count; attach++) { 67466600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (attachments[attach].attachment != VK_ATTACHMENT_UNUSED) { 67476600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Attachment counts are verified elsewhere, but prevent an invalid access 67486600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (attachments[attach].attachment < fbci->attachmentCount) { 67496600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski const VkImageView *image_view = &fbci->pAttachments[attachments[attach].attachment]; 67509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, *image_view); 675179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (view_state) { 67529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis const VkImageCreateInfo *ici = &GetImageState(dev_data, view_state->create_info.image)->createInfo; 67536600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (ici != nullptr) { 67546600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if ((ici->usage & usage_flag) == 0) { 6755df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 6756df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, error_code, "DS", 6757946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "vkCreateFramebuffer: Framebuffer Attachment (%d) conflicts with the image's " 6758946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "IMAGE_USAGE flags (%s). %s", 6759946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski attachments[attach].attachment, string_VkImageUsageFlagBits(usage_flag), 6760946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski validation_error_map[error_code]); 67616600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 67626600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 67636600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 67646600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 67656600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 67666600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 6767946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski return skip; 67686600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski} 67696600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 6770d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// Validate VkFramebufferCreateInfo which includes: 6771d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// 1. attachmentCount equals renderPass attachmentCount 67725ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 2. corresponding framebuffer and renderpass attachments have matching formats 67735ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 3. corresponding framebuffer and renderpass attachments have matching sample counts 67745ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 4. fb attachments only have a single mip level 67755ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 5. fb attachment dimensions are each at least as large as the fb 67765ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 6. fb attachments use idenity swizzle 67775ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 7. fb attachments used by renderPass for color/input/ds have correct usage bit set 67786fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis// 8. fb dimensions are within physical device limits 6779d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlisstatic bool ValidateFramebufferCreateInfo(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) { 67803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 67816600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 67829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, pCreateInfo->renderPass); 6783127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (rp_state) { 6784127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis const VkRenderPassCreateInfo *rpci = rp_state->createInfo.ptr(); 6785d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis if (rpci->attachmentCount != pCreateInfo->attachmentCount) { 67863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 6787d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 6788315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_094006d8, "DS", 6789d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis "vkCreateFramebuffer(): VkFramebufferCreateInfo attachmentCount of %u does not match attachmentCount of %u of " 67909bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "renderPass (0x%" PRIxLEAST64 ") being used to create Framebuffer. %s", 67919b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus pCreateInfo->attachmentCount, rpci->attachmentCount, HandleToUint64(pCreateInfo->renderPass), 6792315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_094006d8]); 67935ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } else { 679441ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis // attachmentCounts match, so make sure corresponding attachment details line up 67955ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis const VkImageView *image_views = pCreateInfo->pAttachments; 67965ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 67979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, image_views[i]); 679812d5600c2f9e32343016fd944432ba95df370797Tobin Ehlis auto &ivci = view_state->create_info; 679979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (ivci.format != rpci->pAttachments[i].format) { 68003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 68015ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 6802315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_094006e0, "DS", 68039bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has format of %s that does not match " 68049bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "the format of " 68059bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s", 680679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis i, string_VkFormat(ivci.format), string_VkFormat(rpci->pAttachments[i].format), 6807315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_094006e0]); 68085ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 68099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis const VkImageCreateInfo *ici = &GetImageState(dev_data, ivci.image)->createInfo; 68105ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis if (ici->samples != rpci->pAttachments[i].samples) { 68113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 681241ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 6813315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_094006e2, "DS", 68149bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has %s samples that do not match " 68159bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "the %s samples used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s", 681641ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis i, string_VkSampleCountFlagBits(ici->samples), string_VkSampleCountFlagBits(rpci->pAttachments[i].samples), 6817315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_094006e2]); 68185ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 68195ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis // Verify that view only has a single mip level 682079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (ivci.subresourceRange.levelCount != 1) { 68213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 6822315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis 0, __LINE__, VALIDATION_ERROR_094006e6, "DS", 68233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has mip levelCount of %u " 68243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "but only a single mip level (levelCount == 1) is allowed when creating a Framebuffer. %s", 6825315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, ivci.subresourceRange.levelCount, validation_error_map[VALIDATION_ERROR_094006e6]); 68265ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 682779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis const uint32_t mip_level = ivci.subresourceRange.baseMipLevel; 6828aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis uint32_t mip_width = max(1u, ici->extent.width >> mip_level); 6829aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis uint32_t mip_height = max(1u, ici->extent.height >> mip_level); 683079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if ((ivci.subresourceRange.layerCount < pCreateInfo->layers) || (mip_width < pCreateInfo->width) || 6831aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis (mip_height < pCreateInfo->height)) { 68322c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton skip |= log_msg( 68332c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 6834315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_094006e4, "DS", 68352c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u mip level %u has dimensions smaller " 68362c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton "than the corresponding framebuffer dimensions. Here are the respective dimensions for attachment #%u, " 68372c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton "framebuffer:\n" 68382c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton "width: %u, %u\n" 68392c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton "height: %u, %u\n" 68402c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton "layerCount: %u, %u\n%s", 68412c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton i, ivci.subresourceRange.baseMipLevel, i, mip_width, pCreateInfo->width, mip_height, pCreateInfo->height, 6842315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ivci.subresourceRange.layerCount, pCreateInfo->layers, validation_error_map[VALIDATION_ERROR_094006e4]); 68435ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 684479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (((ivci.components.r != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.r != VK_COMPONENT_SWIZZLE_R)) || 684579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.g != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.g != VK_COMPONENT_SWIZZLE_G)) || 684679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.b != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.b != VK_COMPONENT_SWIZZLE_B)) || 684779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.a != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.a != VK_COMPONENT_SWIZZLE_A))) { 68483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 68495b9ab1fb8720c30edfbe8dd974e2364425471ad5Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 6850315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_094006e8, "DS", 6851da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has non-identy swizzle. All framebuffer " 6852da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "attachments must have been created with the identity swizzle. Here are the actual swizzle values:\n" 6853da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "r swizzle = %s\n" 6854da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "g swizzle = %s\n" 6855da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "b swizzle = %s\n" 68569bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "a swizzle = %s\n" 68579bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 685879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis i, string_VkComponentSwizzle(ivci.components.r), string_VkComponentSwizzle(ivci.components.g), 68599bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt string_VkComponentSwizzle(ivci.components.b), string_VkComponentSwizzle(ivci.components.a), 6860315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_094006e8]); 68615ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 68625ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 6863d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis } 68645ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis // Verify correct attachment usage flags 68656600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski for (uint32_t subpass = 0; subpass < rpci->subpassCount; subpass++) { 68666600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify input attachments: 68673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 68689bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt MatchUsage(dev_data, rpci->pSubpasses[subpass].inputAttachmentCount, rpci->pSubpasses[subpass].pInputAttachments, 6869315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis pCreateInfo, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VALIDATION_ERROR_094006de); 68706600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify color attachments: 68713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 68729bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt MatchUsage(dev_data, rpci->pSubpasses[subpass].colorAttachmentCount, rpci->pSubpasses[subpass].pColorAttachments, 6873315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis pCreateInfo, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VALIDATION_ERROR_094006da); 68746600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify depth/stencil attachments: 68756600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (rpci->pSubpasses[subpass].pDepthStencilAttachment != nullptr) { 68763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= MatchUsage(dev_data, 1, rpci->pSubpasses[subpass].pDepthStencilAttachment, pCreateInfo, 6877315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VALIDATION_ERROR_094006dc); 68786600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 68796600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 68806600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 68816fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis // Verify FB dimensions are within physical device limits 68829bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->width > dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth) { 68833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 6884315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_094006ec, "DS", 68853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo width exceeds physical device limits. " 68863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Requested width: %u, device max: %u\n" 68873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s", 68883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCreateInfo->width, dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth, 6889315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_094006ec]); 68909bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt } 68919bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->height > dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight) { 68923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 6893315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_094006f0, "DS", 68943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo height exceeds physical device limits. " 68953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Requested height: %u, device max: %u\n" 68963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s", 68973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCreateInfo->height, dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight, 6898315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_094006f0]); 68999bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt } 69009bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->layers > dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers) { 69013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 6902315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_094006f4, "DS", 69033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo layers exceeds physical device limits. " 69043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Requested layers: %u, device max: %u\n" 69053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s", 69063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCreateInfo->layers, dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers, 6907315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_094006f4]); 69086fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis } 6909c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton // Verify FB dimensions are greater than zero 6910c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton if (pCreateInfo->width <= 0) { 6911c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 6912315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_094006ea, "DS", 6913c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo width must be greater than zero. %s", 6914315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_094006ea]); 6915c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton } 6916c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton if (pCreateInfo->height <= 0) { 6917c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 6918315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_094006ee, "DS", 6919c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo height must be greater than zero. %s", 6920315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_094006ee]); 6921c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton } 6922c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton if (pCreateInfo->layers <= 0) { 6923c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 6924315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_094006f2, "DS", 6925c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo layers must be greater than zero. %s", 6926315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_094006f2]); 6927c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton } 69283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 69296600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski} 69306600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 693164c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// Validate VkFramebufferCreateInfo state prior to calling down chain to create Framebuffer object 693264c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// Return true if an error is encountered and callback returns true to skip call down chain 693364c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// false indicates that call down chain should proceed 693464c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlisstatic bool PreCallValidateCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) { 693564c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis // TODO : Verify that renderPass FB is created with is compatible with FB 69363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 69373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateFramebufferCreateInfo(dev_data, pCreateInfo); 69383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 693964c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis} 694064c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 694154e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis// CreateFramebuffer state has been validated and call down chain completed so record new framebuffer object 694254e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlisstatic void PostCallRecordCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo, VkFramebuffer fb) { 694354e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis // Shadow create info and store in map 6944c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis std::unique_ptr<FRAMEBUFFER_STATE> fb_state( 6945c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis new FRAMEBUFFER_STATE(fb, pCreateInfo, dev_data->renderPassMap[pCreateInfo->renderPass]->createInfo.ptr())); 694676f04ca0e692f9f15d5ef7e0c658c24d11f34ebcTobin Ehlis 694754e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 694854e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis VkImageView view = pCreateInfo->pAttachments[i]; 69499a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, view); 695079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (!view_state) { 695154e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis continue; 695254e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis } 695354e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis MT_FB_ATTACHMENT_INFO fb_info; 6954883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis fb_info.view_state = view_state; 695579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis fb_info.image = view_state->create_info.image; 6956c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis fb_state->attachments.push_back(fb_info); 695754e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis } 6958c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis dev_data->frameBufferMap[fb] = std::move(fb_state); 695954e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis} 696054e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis 696189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo, 6962bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer) { 696356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 696464c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 69653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = PreCallValidateCreateFramebuffer(dev_data, pCreateInfo); 696664c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis lock.unlock(); 696764c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 69683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 696964c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 69704a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer); 69716600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 69725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 697364c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis lock.lock(); 697454e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis PostCallRecordCreateFramebuffer(dev_data, pCreateInfo, *pFramebuffer); 697554e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis lock.unlock(); 69765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 69785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 69795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 69804e11bb1277f55311686a42000520791e1db1dd7bbungemanstatic bool FindDependency(const uint32_t index, const uint32_t dependent, const std::vector<DAGNode> &subpass_to_node, 6981e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::unordered_set<uint32_t> &processed_nodes) { 69825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If we have already checked this node we have not found a dependency path so return false. 6983cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (processed_nodes.count(index)) return false; 69845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis processed_nodes.insert(index); 69855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[index]; 69865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Look for a dependency path. If one exists return true else recurse on the previous nodes. 69874e11bb1277f55311686a42000520791e1db1dd7bbungeman if (std::find(node.prev.begin(), node.prev.end(), dependent) == node.prev.end()) { 69885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto elem : node.prev) { 6989cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (FindDependency(elem, dependent, subpass_to_node, processed_nodes)) return true; 69905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 6992e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return true; 69935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6994e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 69955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 69965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 69974e11bb1277f55311686a42000520791e1db1dd7bbungemanstatic bool CheckDependencyExists(const layer_data *dev_data, const uint32_t subpass, 69983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski const std::vector<uint32_t> &dependent_subpasses, const std::vector<DAGNode> &subpass_to_node, 69993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool &skip) { 7000e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = true; 70015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through all subpasses that share the same attachment and make sure a dependency exists 70025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t k = 0; k < dependent_subpasses.size(); ++k) { 7003cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (static_cast<uint32_t>(subpass) == dependent_subpasses[k]) continue; 70045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[subpass]; 70055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Check for a specified dependency between the two nodes. If one exists we are done. 70065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto prev_elem = std::find(node.prev.begin(), node.prev.end(), dependent_subpasses[k]); 70075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto next_elem = std::find(node.next.begin(), node.next.end(), dependent_subpasses[k]); 70085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (prev_elem == node.prev.end() && next_elem == node.next.end()) { 70097655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen // If no dependency exits an implicit dependency still might. If not, throw an error. 70105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_set<uint32_t> processed_nodes; 70117655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen if (!(FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) || 7012bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes))) { 70133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 70143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 70153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "A dependency between subpasses %d and %d must exist but one is not specified.", subpass, 70163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski dependent_subpasses[k]); 7017e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves result = false; 70185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 70225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 70248860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CheckPreserved(const layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo, const int index, 70253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski const uint32_t attachment, const std::vector<DAGNode> &subpass_to_node, int depth, bool &skip) { 70265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[index]; 70275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If this node writes to the attachment return true as next nodes need to preserve the attachment. 70285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[index]; 70295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 7030cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == subpass.pColorAttachments[j].attachment) return true; 70315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7032a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 7033a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour if (attachment == subpass.pInputAttachments[j].attachment) return true; 7034a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour } 70355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 7036cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == subpass.pDepthStencilAttachment->attachment) return true; 70375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7038e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = false; 70395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through previous nodes and see if any of them write to the attachment. 70405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto elem : node.prev) { 70413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski result |= CheckPreserved(dev_data, pCreateInfo, elem, attachment, subpass_to_node, depth + 1, skip); 70425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment was written to by a previous node than this node needs to preserve it. 70445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result && depth > 0) { 7045e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool has_preserved = false; 70465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) { 70475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pPreserveAttachments[j] == attachment) { 7048e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves has_preserved = true; 70495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis break; 70505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7052e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves if (!has_preserved) { 70533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 70543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 70553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Attachment %d is used by a later subpass and must be preserved in subpass %d.", attachment, index); 70565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 70595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7061cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <class T> 7062cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskibool isRangeOverlapping(T offset1, T size1, T offset2, T size2) { 70635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return (((offset1 + size1) > offset2) && ((offset1 + size1) < (offset2 + size2))) || 70645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ((offset1 > offset2) && (offset1 < (offset2 + size2))); 70655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 70675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisbool isRegionOverlapping(VkImageSubresourceRange range1, VkImageSubresourceRange range2) { 70685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return (isRangeOverlapping(range1.baseMipLevel, range1.levelCount, range2.baseMipLevel, range2.levelCount) && 70695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis isRangeOverlapping(range1.baseArrayLayer, range1.layerCount, range2.baseArrayLayer, range2.layerCount)); 70705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7072c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool ValidateDependencies(const layer_data *dev_data, FRAMEBUFFER_STATE const *framebuffer, 7073127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis RENDER_PASS_STATE const *renderPass) { 70743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 7075fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const pFramebufferInfo = framebuffer->createInfo.ptr(); 7076fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const pCreateInfo = renderPass->createInfo.ptr(); 7077bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto const &subpass_to_node = renderPass->subpassToNode; 70785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> output_attachment_to_subpass(pCreateInfo->attachmentCount); 70795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> input_attachment_to_subpass(pCreateInfo->attachmentCount); 70805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> overlapping_attachments(pCreateInfo->attachmentCount); 70815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Find overlapping attachments 70825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 70835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = i + 1; j < pCreateInfo->attachmentCount; ++j) { 70845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkImageView viewi = pFramebufferInfo->pAttachments[i]; 70855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkImageView viewj = pFramebufferInfo->pAttachments[j]; 70865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (viewi == viewj) { 70875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 70885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 70895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 70905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state_i = GetImageViewState(dev_data, viewi); 70929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state_j = GetImageViewState(dev_data, viewj); 709379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (!view_state_i || !view_state_j) { 70945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 70955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 709679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis auto view_ci_i = view_state_i->create_info; 709779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis auto view_ci_j = view_state_j->create_info; 709879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (view_ci_i.image == view_ci_j.image && isRegionOverlapping(view_ci_i.subresourceRange, view_ci_j.subresourceRange)) { 70995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 71005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 71015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 71025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71039a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data_i = GetImageState(dev_data, view_ci_i.image); 71049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data_j = GetImageState(dev_data, view_ci_j.image); 71056d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (!image_data_i || !image_data_j) { 71065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 71075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7108e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_data_i->binding.mem == image_data_j->binding.mem && 7109e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis isRangeOverlapping(image_data_i->binding.offset, image_data_i->binding.size, image_data_j->binding.offset, 7110e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis image_data_j->binding.size)) { 71115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 71125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 71135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < overlapping_attachments.size(); ++i) { 71175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = i; 71185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto other_attachment : overlapping_attachments[i]) { 71195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pCreateInfo->pAttachments[attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) { 71209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, 7121315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(framebuffer->framebuffer), __LINE__, VALIDATION_ERROR_12200682, "DS", 71229b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Attachment %d aliases attachment %d but doesn't " 71239b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s", 7124315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis attachment, other_attachment, validation_error_map[VALIDATION_ERROR_12200682]); 71255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pCreateInfo->pAttachments[other_attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) { 71279b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, 7128315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(framebuffer->framebuffer), __LINE__, VALIDATION_ERROR_12200682, "DS", 71299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Attachment %d aliases attachment %d but doesn't " 71309b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s", 7131315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis other_attachment, attachment, validation_error_map[VALIDATION_ERROR_12200682]); 71325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Find for each attachment the subpasses that use them. 71361c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young unordered_set<uint32_t> attachmentIndices; 71375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 71385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 71391c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young attachmentIndices.clear(); 71405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 71415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pInputAttachments[j].attachment; 7142cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 71435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis input_attachment_to_subpass[attachment].push_back(i); 71445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 71455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis input_attachment_to_subpass[overlapping_attachment].push_back(i); 71465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 71495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pColorAttachments[j].attachment; 7150cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 71515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[attachment].push_back(i); 71525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 71535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[overlapping_attachment].push_back(i); 71545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71551c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young attachmentIndices.insert(attachment); 71565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 71585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 71595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[attachment].push_back(i); 71605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 71615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[overlapping_attachment].push_back(i); 71625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71631c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young 71641c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young if (attachmentIndices.count(attachment)) { 71653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 7166df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 7167df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 71688860b85a52096f9f9b28616bc37feed505497a54Chris Forbes "Cannot use same attachment (%u) as both color and depth output in same subpass (%u).", attachment, i); 71691c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young } 71705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If there is a dependency needed make sure one exists 71735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 71745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 71755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment is an input then all subpasses that output must have a dependency relationship 71765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 717793fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes uint32_t attachment = subpass.pInputAttachments[j].attachment; 7178cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 71793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip); 71805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment is an output then all subpasses that use the attachment must have a dependency relationship 71825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 718393fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes uint32_t attachment = subpass.pColorAttachments[j].attachment; 7184cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 71853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip); 71863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip); 71875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 71895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const uint32_t &attachment = subpass.pDepthStencilAttachment->attachment; 71903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip); 71913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip); 71925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through implicit dependencies, if this pass reads make sure the attachment is preserved for all passes after it was 71955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // written. 71965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 71975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 71985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 71993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski CheckPreserved(dev_data, pCreateInfo, i, subpass.pInputAttachments[j].attachment, subpass_to_node, 0, skip); 72005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 72035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 72045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 720532f68580aa01aab3e923cb52915a1d3dd4e993c5Chris Forbesstatic bool CreatePassDAG(const layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo, 7206e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::vector<DAGNode> &subpass_to_node, std::vector<bool> &has_self_dependency) { 72073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 72085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 72095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DAGNode &subpass_node = subpass_to_node[i]; 72105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis subpass_node.pass = i; 72115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) { 72135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDependency &dependency = pCreateInfo->pDependencies[i]; 721466a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes if (dependency.srcSubpass == VK_SUBPASS_EXTERNAL || dependency.dstSubpass == VK_SUBPASS_EXTERNAL) { 721566a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes if (dependency.srcSubpass == dependency.dstSubpass) { 72163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 7217df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 7218df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", "The src and dest subpasses cannot both be external."); 721966a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes } 722066a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes } else if (dependency.srcSubpass > dependency.dstSubpass) { 72213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 72223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 72233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Depedency graph must be specified such that an earlier pass cannot depend on a later pass."); 72245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (dependency.srcSubpass == dependency.dstSubpass) { 72255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis has_self_dependency[dependency.srcSubpass] = true; 72265c6aacf95832467d52b2fde1130b04bef559573aChris Forbes } else { 72275c6aacf95832467d52b2fde1130b04bef559573aChris Forbes subpass_to_node[dependency.dstSubpass].prev.push_back(dependency.srcSubpass); 72285c6aacf95832467d52b2fde1130b04bef559573aChris Forbes subpass_to_node[dependency.srcSubpass].next.push_back(dependency.dstSubpass); 72295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 72325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 7233918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 723489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo, 7235bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule) { 723656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 72377aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes bool spirv_valid; 7238b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes 72397aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes if (PreCallValidateCreateShaderModule(dev_data, pCreateInfo, &spirv_valid)) 72407aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes return VK_ERROR_VALIDATION_FAILED_EXT; 72415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 72424a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult res = dev_data->dispatch_table.CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule); 72435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 724459ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis if (res == VK_SUCCESS) { 7245b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 72467aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes unique_ptr<shader_module> new_shader_module(spirv_valid ? new shader_module(pCreateInfo) : new shader_module()); 72477aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes dev_data->shaderModuleMap[*pShaderModule] = std::move(new_shader_module); 72485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return res; 72505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 72515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 72524f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateAttachmentIndex(layer_data *dev_data, uint32_t attachment, uint32_t attachment_count, const char *type) { 72533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 72544f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (attachment >= attachment_count && attachment != VK_ATTACHMENT_UNUSED) { 72553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 7256315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_12200684, "DS", 72573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateRenderPass: %s attachment %d must be less than the total number of attachments %d. %s", type, 7258315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis attachment, attachment_count, validation_error_map[VALIDATION_ERROR_12200684]); 72594f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 72603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 72614f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski} 72624f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 7263bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool IsPowerOfTwo(unsigned x) { return x && !(x & (x - 1)); } 7264805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 72654f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateRenderpassAttachmentUsage(layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo) { 72663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 72674f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 72684f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 72694f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pipelineBindPoint != VK_PIPELINE_BIND_POINT_GRAPHICS) { 72703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 7271315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_14000698, "DS", 72723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateRenderPass: Pipeline bind point for subpass %d must be VK_PIPELINE_BIND_POINT_GRAPHICS. %s", i, 7273315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_14000698]); 72744f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 7275ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton 72764f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) { 72774f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pPreserveAttachments[j]; 72784f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) { 72793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 7280315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_140006aa, "DS", 72813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateRenderPass: Preserve attachment (%d) must not be VK_ATTACHMENT_UNUSED. %s", j, 7282315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_140006aa]); 72834f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } else { 72843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Preserve"); 7285ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton 7286ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton bool found = (subpass.pDepthStencilAttachment != NULL && subpass.pDepthStencilAttachment->attachment == attachment); 7287ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton for (uint32_t r = 0; !found && r < subpass.inputAttachmentCount; ++r) { 7288ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton found = (subpass.pInputAttachments[r].attachment == attachment); 7289ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton } 7290ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton for (uint32_t r = 0; !found && r < subpass.colorAttachmentCount; ++r) { 7291ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton found = (subpass.pColorAttachments[r].attachment == attachment) || 7292ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton (subpass.pResolveAttachments != NULL && subpass.pResolveAttachments[r].attachment == attachment); 7293ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton } 7294ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton if (found) { 7295ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton skip |= log_msg( 7296ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 7297315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_140006ac, "DS", 7298ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton "CreateRenderPass: subpass %u pPreserveAttachments[%u] (%u) must not be used elsewhere in the subpass. %s", 7299315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, j, attachment, validation_error_map[VALIDATION_ERROR_140006ac]); 7300ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton } 73014f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 73024f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 73036a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 7304bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto subpass_performs_resolve = 7305bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski subpass.pResolveAttachments && 7306bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski std::any_of(subpass.pResolveAttachments, subpass.pResolveAttachments + subpass.colorAttachmentCount, 7307bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski [](VkAttachmentReference ref) { return ref.attachment != VK_ATTACHMENT_UNUSED; }); 73086a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 7309805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes unsigned sample_count = 0; 7310805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 73114f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 73124f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment; 73134f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pResolveAttachments) { 73144f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment = subpass.pResolveAttachments[j].attachment; 73153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Resolve"); 73166a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 73173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip && attachment != VK_ATTACHMENT_UNUSED && 73186a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes pCreateInfo->pAttachments[attachment].samples != VK_SAMPLE_COUNT_1_BIT) { 73193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 7320315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis 0, __LINE__, VALIDATION_ERROR_140006a2, "DS", 73213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateRenderPass: Subpass %u requests multisample resolve into attachment %u, " 73223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "which must have VK_SAMPLE_COUNT_1_BIT but has %s. %s", 73233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski i, attachment, string_VkSampleCountFlagBits(pCreateInfo->pAttachments[attachment].samples), 7324315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_140006a2]); 73256a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes } 7326ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton 7327ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton if (!skip && subpass.pResolveAttachments[j].attachment != VK_ATTACHMENT_UNUSED && 7328ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton subpass.pColorAttachments[j].attachment == VK_ATTACHMENT_UNUSED) { 7329ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 7330315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis 0, __LINE__, VALIDATION_ERROR_1400069e, "DS", 7331ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton "CreateRenderPass: Subpass %u requests multisample resolve from attachment %u " 7332ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton "which has attachment=VK_ATTACHMENT_UNUSED. %s", 7333315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, attachment, validation_error_map[VALIDATION_ERROR_1400069e]); 7334ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton } 73354f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 73364f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment = subpass.pColorAttachments[j].attachment; 73373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Color"); 73386a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 73393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip && attachment != VK_ATTACHMENT_UNUSED) { 7340805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples; 7341805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 7342bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (subpass_performs_resolve && pCreateInfo->pAttachments[attachment].samples == VK_SAMPLE_COUNT_1_BIT) { 73433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 7344315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis 0, __LINE__, VALIDATION_ERROR_140006a0, "DS", 73453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateRenderPass: Subpass %u requests multisample resolve from attachment %u " 73463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "which has VK_SAMPLE_COUNT_1_BIT. %s", 7347315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, attachment, validation_error_map[VALIDATION_ERROR_140006a0]); 7348dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes } 7349ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton 7350ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton if (subpass_performs_resolve && subpass.pResolveAttachments[j].attachment != VK_ATTACHMENT_UNUSED) { 7351ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton const auto &color_desc = pCreateInfo->pAttachments[attachment]; 7352ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton const auto &resolve_desc = pCreateInfo->pAttachments[subpass.pResolveAttachments[j].attachment]; 7353ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton if (color_desc.format != resolve_desc.format) { 7354315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 7355315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 7356315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis 0, __LINE__, VALIDATION_ERROR_140006a4, "DS", 7357315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "CreateRenderPass: Subpass %u pColorAttachments[%u] resolves to an attachment with a " 7358315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "different format. " 7359315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "color format: %u, resolve format: %u. %s", 7360315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, j, color_desc.format, resolve_desc.format, validation_error_map[VALIDATION_ERROR_140006a4]); 7361ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton } 7362ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton } 73636a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes } 73644f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 7365dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes 73664f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 73674f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 73683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Depth stencil"); 7369805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 73703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip && attachment != VK_ATTACHMENT_UNUSED) { 7371805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples; 7372805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes } 73734f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 7374dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes 73754f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 73764f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pInputAttachments[j].attachment; 73773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Input"); 73784f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 7379805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 7380805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes if (sample_count && !IsPowerOfTwo(sample_count)) { 73813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 7382315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis __LINE__, VALIDATION_ERROR_0082b401, "DS", 73833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateRenderPass: Subpass %u attempts to render to " 73843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "attachments with inconsistent sample counts. %s", 7385315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis i, validation_error_map[VALIDATION_ERROR_0082b401]); 7386805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes } 73874f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 73883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 73894f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski} 73904f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 73915245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbesstatic void MarkAttachmentFirstUse(RENDER_PASS_STATE *render_pass, 73925245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes uint32_t index, 73935245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes bool is_read) { 73945245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes if (index == VK_ATTACHMENT_UNUSED) 73955245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes return; 73965245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes 73975245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes if (!render_pass->attachment_first_read.count(index)) 73985245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes render_pass->attachment_first_read[index] = is_read; 73995245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes} 74005245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes 740189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo, 74024f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) { 74033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 740456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 74054f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 74064f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 74074f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski // TODO: As part of wrapping up the mem_tracker/core_validation merge the following routine should be consolidated with 74084f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski // ValidateLayouts. 74093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateRenderpassAttachmentUsage(dev_data, pCreateInfo); 7410208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) { 74113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].srcStageMask, "vkCreateRenderPass()", 7412315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_13e006b8, VALIDATION_ERROR_13e006bc); 74133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].dstStageMask, "vkCreateRenderPass()", 7414315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_13e006ba, VALIDATION_ERROR_13e006be); 7415208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 74163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 74173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateLayouts(dev_data, device, pCreateInfo); 7418ab38df28c5ae1816c5fa33c0c7840c6950e83f0dChris Forbes } 7419ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes lock.unlock(); 74204f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 74213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 74224f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 74234f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 74244f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 74254a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass); 7426ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes 74275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 74284f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski lock.lock(); 74294f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 74304f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::vector<bool> has_self_dependency(pCreateInfo->subpassCount); 74314f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::vector<DAGNode> subpass_to_node(pCreateInfo->subpassCount); 743232f68580aa01aab3e923cb52915a1d3dd4e993c5Chris Forbes skip |= CreatePassDAG(dev_data, pCreateInfo, subpass_to_node, has_self_dependency); 74334f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 7434127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis auto render_pass = unique_ptr<RENDER_PASS_STATE>(new RENDER_PASS_STATE(pCreateInfo)); 743598cddf7090b5d5dcc382045867753ef703d1c3d3Chris Forbes render_pass->renderPass = *pRenderPass; 7436cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes render_pass->hasSelfDependency = has_self_dependency; 7437cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes render_pass->subpassToNode = subpass_to_node; 7438db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes 743987e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 744087e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 744187e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 74425245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes MarkAttachmentFirstUse(render_pass.get(), subpass.pColorAttachments[j].attachment, false); 74439cde292b1c19c643b7c13018d9834cccfe6ef7eaChris Forbes 74445245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes // resolve attachments are considered to be written 74455245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes if (subpass.pResolveAttachments) { 74465245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes MarkAttachmentFirstUse(render_pass.get(), subpass.pResolveAttachments[j].attachment, false); 74479cde292b1c19c643b7c13018d9834cccfe6ef7eaChris Forbes } 744887e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 74495245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes if (subpass.pDepthStencilAttachment) { 74505245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes MarkAttachmentFirstUse(render_pass.get(), subpass.pDepthStencilAttachment->attachment, false); 745187e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 7452a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 74535245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes MarkAttachmentFirstUse(render_pass.get(), subpass.pInputAttachments[j].attachment, true); 7454a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine } 745587e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 7456db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes 7457fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes dev_data->renderPassMap[*pRenderPass] = std::move(render_pass); 74585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 74595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 74605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74614f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 7462eb4c61477130f69f48fdf3ac31cb82104181cc73Chris Forbesstatic bool validatePrimaryCommandBuffer(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, char const *cmd_name, 74639bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt UNIQUE_VALIDATION_ERROR_CODE error_code) { 74643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 74655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 74663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 74679b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->commandBuffer), __LINE__, error_code, "DS", 74689b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Cannot execute command %s on a secondary command buffer. %s", cmd_name, validation_error_map[error_code]); 74695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 74703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 74715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 74738860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool VerifyRenderAreaBounds(const layer_data *dev_data, const VkRenderPassBeginInfo *pRenderPassBegin) { 74743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 7475c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis const safe_VkFramebufferCreateInfo *pFramebufferInfo = 74769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis &GetFramebufferState(dev_data, pRenderPassBegin->framebuffer)->createInfo; 7477885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine if (pRenderPassBegin->renderArea.offset.x < 0 || 7478885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine (pRenderPassBegin->renderArea.offset.x + pRenderPassBegin->renderArea.extent.width) > pFramebufferInfo->width || 7479885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.offset.y < 0 || 7480885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine (pRenderPassBegin->renderArea.offset.y + pRenderPassBegin->renderArea.extent.height) > pFramebufferInfo->height) { 74813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= static_cast<bool>(log_msg( 7482df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 7483885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine DRAWSTATE_INVALID_RENDER_AREA, "CORE", 7484885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "Cannot execute a render pass with renderArea not within the bound of the " 7485885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "framebuffer. RenderArea: x %d, y %d, width %d, height %d. Framebuffer: width %d, " 7486885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "height %d.", 7487885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.offset.x, pRenderPassBegin->renderArea.offset.y, pRenderPassBegin->renderArea.extent.width, 7488885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.extent.height, pFramebufferInfo->width, pFramebufferInfo->height)); 7489885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine } 74903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 7491885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine} 7492885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine 74931a65650f856376768d7b03ea2d080aaff87cacfdMark 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 74941a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// [load|store]Op flag must be checked 74951a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// TODO: The memory valid flag in DEVICE_MEM_INFO should probably be split to track the validity of stencil memory separately. 7496cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <typename T> 7497cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic bool FormatSpecificLoadAndStoreOpSettings(VkFormat format, T color_depth_op, T stencil_op, T op) { 7498a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski if (color_depth_op != op && stencil_op != op) { 7499a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski return false; 7500a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski } 750116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton bool check_color_depth_load_op = !FormatIsStencilOnly(format); 750216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton bool check_stencil_load_op = FormatIsDepthAndStencil(format) || !check_color_depth_load_op; 7503a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski 75040d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes return ((check_color_depth_load_op && (color_depth_op == op)) || 75050d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes (check_stencil_load_op && (stencil_op == op))); 75061a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski} 75071a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski 7508bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, 7509bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkSubpassContents contents) { 75103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 751156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7512b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 75139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer); 75149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto render_pass_state = pRenderPassBegin ? GetRenderPassState(dev_data, pRenderPassBegin->renderPass) : nullptr; 75159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto framebuffer = pRenderPassBegin ? GetFramebufferState(dev_data, pRenderPassBegin->framebuffer) : nullptr; 7516f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node) { 7517308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski if (render_pass_state) { 7518cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski uint32_t clear_op_size = 0; // Make sure pClearValues is at least as large as last LOAD_OP_CLEAR 7519f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeFramebuffer = pRenderPassBegin->framebuffer; 7520308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski for (uint32_t i = 0; i < render_pass_state->createInfo.attachmentCount; ++i) { 7521f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; 7522308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski auto pAttachment = &render_pass_state->createInfo.pAttachments[i]; 7523bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, pAttachment->stencilLoadOp, 75241a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski VK_ATTACHMENT_LOAD_OP_CLEAR)) { 752592bc0680357019834b7529148ab6d73353ce02c7Mark Lobodzinski clear_op_size = static_cast<uint32_t>(i) + 1; 752616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 75279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true); 752816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return false; 752916387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 7530f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 7531db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, 7532bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_DONT_CARE)) { 753316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 75349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false); 753516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return false; 753616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 7537f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 7538db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, 7539bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_LOAD)) { 754016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 75419a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image), 7542f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis "vkCmdBeginRenderPass()"); 754316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 7544f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 754516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes } 7546308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski if (render_pass_state->attachment_first_read[i]) { 754716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 75489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image), 7549f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis "vkCmdBeginRenderPass()"); 755016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 7551f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 75525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 75535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 75546de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis if (clear_op_size > pRenderPassBegin->clearValueCount) { 75553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 7556369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 7557315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(render_pass_state->renderPass), __LINE__, VALIDATION_ERROR_1200070c, "DS", 7558bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but there must " 7559bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "be at least %u entries in pClearValues array to account for the highest index attachment in renderPass " 7560cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "0x%" PRIx64 7561cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " that uses VK_ATTACHMENT_LOAD_OP_CLEAR is %u. Note that the pClearValues array " 7562bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "is indexed by attachment number so even if some pClearValues entries between 0 and %u correspond to " 7563bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "attachments that aren't cleared they will be ignored. %s", 75649b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus pRenderPassBegin->clearValueCount, clear_op_size, HandleToUint64(render_pass_state->renderPass), clear_op_size, 7565315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis clear_op_size - 1, validation_error_map[VALIDATION_ERROR_1200070c]); 7566369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan } 75673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin); 75683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= VerifyFramebufferAndRenderPassLayouts(dev_data, cb_node, pRenderPassBegin, 75693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski GetFramebufferState(dev_data, pRenderPassBegin->framebuffer)); 7570315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= insideRenderPass(dev_data, cb_node, "vkCmdBeginRenderPass()", VALIDATION_ERROR_17a00017); 75713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateDependencies(dev_data, framebuffer, render_pass_state); 7572315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= validatePrimaryCommandBuffer(dev_data, cb_node, "vkCmdBeginRenderPass()", VALIDATION_ERROR_17a00019); 7573315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBeginRenderPass()", VK_QUEUE_GRAPHICS_BIT, 7574315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_17a02415); 75753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_BEGINRENDERPASS, "vkCmdBeginRenderPass()"); 75761ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_BEGINRENDERPASS); 7577308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski cb_node->activeRenderPass = render_pass_state; 75785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This is a shallow copy as that is all that is needed for now 7579f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeRenderPassBeginInfo = *pRenderPassBegin; 7580f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpass = 0; 7581f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpassContents = contents; 7582f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->framebuffers.insert(pRenderPassBegin->framebuffer); 7583883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis // Connect this framebuffer and its children to this cmdBuffer 7584883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis AddFramebufferBinding(dev_data, cb_node, framebuffer); 75855f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis // transition attachments to the correct layouts for beginning of renderPass and first subpass 75865f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis TransitionBeginRenderPassLayouts(dev_data, cb_node, render_pass_state, framebuffer); 75875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 75885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7589b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 75903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 75914a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents); 75925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 75935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 75945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 759589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) { 75963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 759756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7598b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 75999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 76005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 7601315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdNextSubpass()", VALIDATION_ERROR_1b600019); 7602315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdNextSubpass()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1b602415); 76033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_NEXTSUBPASS, "vkCmdNextSubpass()"); 76041ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_NEXTSUBPASS); 7605315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= outsideRenderPass(dev_data, pCB, "vkCmdNextSubpass()", VALIDATION_ERROR_1b600017); 760680281691386b37385846f21b38e8c9d4b12cc74eChris Forbes 7607fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto subpassCount = pCB->activeRenderPass->createInfo.subpassCount; 760880281691386b37385846f21b38e8c9d4b12cc74eChris Forbes if (pCB->activeSubpass == subpassCount - 1) { 76093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7610315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1b60071a, "DS", 76113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdNextSubpass(): Attempted to advance beyond final subpass. %s", 7612315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1b60071a]); 761380281691386b37385846f21b38e8c9d4b12cc74eChris Forbes } 76145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7615b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 761696ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 76173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return; 761896ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 76194a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdNextSubpass(commandBuffer, contents); 762096ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 762196ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes if (pCB) { 7622bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski lock.lock(); 7623bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->activeSubpass++; 7624bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->activeSubpassContents = contents; 76255f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis TransitionSubpassLayouts(dev_data, pCB, pCB->activeRenderPass, pCB->activeSubpass, 76269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GetFramebufferState(dev_data, pCB->activeRenderPassBeginInfo.framebuffer)); 762796ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes } 76285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 763089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) { 76313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 763256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7633b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 76349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pCB = GetCBNode(dev_data, commandBuffer); 763555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski FRAMEBUFFER_STATE *framebuffer = NULL; 763658c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes if (pCB) { 7637127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis RENDER_PASS_STATE *rp_state = pCB->activeRenderPass; 76389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis framebuffer = GetFramebufferState(dev_data, pCB->activeFramebuffer); 7639127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (rp_state) { 7640127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (pCB->activeSubpass != rp_state->createInfo.subpassCount - 1) { 76413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 76429b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer), __LINE__, 7643315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1b00071c, "DS", "vkCmdEndRenderPass(): Called before reaching final subpass. %s", 7644315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1b00071c]); 764502a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes } 764602a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes 7647127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis for (size_t i = 0; i < rp_state->createInfo.attachmentCount; ++i) { 7648e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; 7649127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis auto pAttachment = &rp_state->createInfo.pAttachments[i]; 7650bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp, pAttachment->stencilStoreOp, 7651bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_ATTACHMENT_STORE_OP_STORE)) { 765258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes std::function<bool()> function = [=]() { 76539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true); 765458c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes return false; 765558c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes }; 765658c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->validate_functions.push_back(function); 7657db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp, 7658bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilStoreOp, VK_ATTACHMENT_STORE_OP_DONT_CARE)) { 765958c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes std::function<bool()> function = [=]() { 76609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false); 766158c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes return false; 766258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes }; 766358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->validate_functions.push_back(function); 76645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 76655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 76665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7667315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass()", VALIDATION_ERROR_1b000017); 7668315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass()", VALIDATION_ERROR_1b000019); 7669315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdEndRenderPass()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1b002415); 76703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()"); 76711ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_ENDRENDERPASS); 76720e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes } 76730e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes lock.unlock(); 76740e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 76753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return; 76760e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 76774a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdEndRenderPass(commandBuffer); 76780e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 76790e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes if (pCB) { 76800e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes lock.lock(); 768155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionFinalSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, framebuffer); 768258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeRenderPass = nullptr; 768358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeSubpass = 0; 768458c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeFramebuffer = VK_NULL_HANDLE; 76855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 76865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7688a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool logInvalidAttachmentMessage(layer_data *dev_data, VkCommandBuffer secondaryBuffer, uint32_t primaryAttach, 7689a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis uint32_t secondaryAttach, const char *msg) { 7690df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7691315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(secondaryBuffer), __LINE__, VALIDATION_ERROR_1b2000c4, "DS", 7692df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Secondary Cmd Buffer 0x%" PRIx64 7693df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " which has a render pass " 7694df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "that is not compatible with the Primary Cmd Buffer current render pass. " 7695df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Attachment %u is not compatible with %u: %s. %s", 76969b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(secondaryBuffer), primaryAttach, secondaryAttach, msg, 7697315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1b2000c4]); 76985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7700a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateAttachmentCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 7701a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, uint32_t primaryAttach, 7702a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkCommandBuffer secondaryBuffer, VkRenderPassCreateInfo const *secondaryPassCI, 7703e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves uint32_t secondaryAttach, bool is_multi) { 77043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 7705a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->attachmentCount <= primaryAttach) { 77065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryAttach = VK_ATTACHMENT_UNUSED; 77075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7708a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (secondaryPassCI->attachmentCount <= secondaryAttach) { 77095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryAttach = VK_ATTACHMENT_UNUSED; 77105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryAttach == VK_ATTACHMENT_UNUSED && secondaryAttach == VK_ATTACHMENT_UNUSED) { 77123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 77135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryAttach == VK_ATTACHMENT_UNUSED) { 77153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, 77163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "The first is unused while the second is not."); 77173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 77185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondaryAttach == VK_ATTACHMENT_UNUSED) { 77203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, 77213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "The second is unused while the first is not."); 77223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 77235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7724a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->pAttachments[primaryAttach].format != secondaryPassCI->pAttachments[secondaryAttach].format) { 77253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 7726a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different formats."); 77275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7728a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->pAttachments[primaryAttach].samples != secondaryPassCI->pAttachments[secondaryAttach].samples) { 77293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 7730a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different samples."); 77315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7732a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (is_multi && primaryPassCI->pAttachments[primaryAttach].flags != secondaryPassCI->pAttachments[secondaryAttach].flags) { 77333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 7734a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different flags."); 77355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 77375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7739a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateSubpassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 7740a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer, 7741a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *secondaryPassCI, const int subpass, bool is_multi) { 77423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 7743a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis const VkSubpassDescription &primary_desc = primaryPassCI->pSubpasses[subpass]; 7744a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis const VkSubpassDescription &secondary_desc = secondaryPassCI->pSubpasses[subpass]; 77455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t maxInputAttachmentCount = std::max(primary_desc.inputAttachmentCount, secondary_desc.inputAttachmentCount); 77465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < maxInputAttachmentCount; ++i) { 77475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_input_attach = VK_ATTACHMENT_UNUSED, secondary_input_attach = VK_ATTACHMENT_UNUSED; 77485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.inputAttachmentCount) { 77495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_input_attach = primary_desc.pInputAttachments[i].attachment; 77505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.inputAttachmentCount) { 77525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_input_attach = secondary_desc.pInputAttachments[i].attachment; 77535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_input_attach, secondaryBuffer, 77553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski secondaryPassCI, secondary_input_attach, is_multi); 77565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t maxColorAttachmentCount = std::max(primary_desc.colorAttachmentCount, secondary_desc.colorAttachmentCount); 77585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < maxColorAttachmentCount; ++i) { 77595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_color_attach = VK_ATTACHMENT_UNUSED, secondary_color_attach = VK_ATTACHMENT_UNUSED; 77605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.colorAttachmentCount) { 77615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_color_attach = primary_desc.pColorAttachments[i].attachment; 77625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.colorAttachmentCount) { 77645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_color_attach = secondary_desc.pColorAttachments[i].attachment; 77655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_color_attach, secondaryBuffer, 77673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski secondaryPassCI, secondary_color_attach, is_multi); 77685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_resolve_attach = VK_ATTACHMENT_UNUSED, secondary_resolve_attach = VK_ATTACHMENT_UNUSED; 77695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.colorAttachmentCount && primary_desc.pResolveAttachments) { 77705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_resolve_attach = primary_desc.pResolveAttachments[i].attachment; 77715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.colorAttachmentCount && secondary_desc.pResolveAttachments) { 77735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_resolve_attach = secondary_desc.pResolveAttachments[i].attachment; 77745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_resolve_attach, secondaryBuffer, 77763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski secondaryPassCI, secondary_resolve_attach, is_multi); 77775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_depthstencil_attach = VK_ATTACHMENT_UNUSED, secondary_depthstencil_attach = VK_ATTACHMENT_UNUSED; 77795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primary_desc.pDepthStencilAttachment) { 77805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_depthstencil_attach = primary_desc.pDepthStencilAttachment[0].attachment; 77815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondary_desc.pDepthStencilAttachment) { 77835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_depthstencil_attach = secondary_desc.pDepthStencilAttachment[0].attachment; 77845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_depthstencil_attach, secondaryBuffer, 77863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski secondaryPassCI, secondary_depthstencil_attach, is_multi); 77873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 77885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7790a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// Verify that given renderPass CreateInfo for primary and secondary command buffers are compatible. 7791a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// This function deals directly with the CreateInfo, there are overloaded versions below that can take the renderPass handle and 7792a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// will then feed into this function 7793a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 7794a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer, 7795a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *secondaryPassCI) { 77963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 7797a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis 7798a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->subpassCount != secondaryPassCI->subpassCount) { 77993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 78009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(primaryBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 78013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid secondary Cmd Buffer 0x%" PRIx64 78023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " that has a subpassCount of %u that is incompatible with the primary Cmd Buffer 0x%" PRIx64 78033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " that has a subpassCount of %u.", 78049b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(secondaryBuffer), secondaryPassCI->subpassCount, HandleToUint64(primaryBuffer), 78059b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus primaryPassCI->subpassCount); 7806a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } else { 7807a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis for (uint32_t i = 0; i < primaryPassCI->subpassCount; ++i) { 78083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateSubpassCompatibility(dev_data, primaryBuffer, primaryPassCI, secondaryBuffer, secondaryPassCI, i, 78093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski primaryPassCI->subpassCount > 1); 7810a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 78115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 78135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7815e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateFramebuffer(layer_data *dev_data, VkCommandBuffer primaryBuffer, const GLOBAL_CB_NODE *pCB, 7816e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves VkCommandBuffer secondaryBuffer, const GLOBAL_CB_NODE *pSubCB) { 78173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 78185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pSubCB->beginInfo.pInheritanceInfo) { 78193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 78205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7821c5b97dda856ff837638b3ebb7e231d5507c495a3Chris Forbes VkFramebuffer primary_fb = pCB->activeFramebuffer; 78225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkFramebuffer secondary_fb = pSubCB->beginInfo.pInheritanceInfo->framebuffer; 78235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondary_fb != VK_NULL_HANDLE) { 78245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primary_fb != secondary_fb) { 78253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7826315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(primaryBuffer), __LINE__, VALIDATION_ERROR_1b2000c6, "DS", 78273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid secondary command buffer 0x%" PRIx64 78283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " which has a framebuffer 0x%" PRIx64 78293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " that is not the same as the primary command buffer's current active framebuffer 0x%" PRIx64 ". %s", 78309b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(secondaryBuffer), HandleToUint64(secondary_fb), HandleToUint64(primary_fb), 7831315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1b2000c6]); 78325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb = GetFramebufferState(dev_data, secondary_fb); 7834e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes if (!fb) { 78353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 78369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(primaryBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 78373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 78383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "which has invalid framebuffer 0x%" PRIx64 ".", 78399b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus (void *)secondaryBuffer, HandleToUint64(secondary_fb)); 78403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 78415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_renderpass = GetRenderPassState(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass); 7843a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (cb_renderpass->renderPass != fb->createInfo.renderPass) { 78443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateRenderPassCompatibility(dev_data, secondaryBuffer, fb->renderPassCreateInfo.ptr(), secondaryBuffer, 78453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski cb_renderpass->createInfo.ptr()); 7846a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 78475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 78495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7851e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateSecondaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, GLOBAL_CB_NODE *pSubCB) { 78523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 78535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_set<int> activeTypes; 78545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto queryObject : pCB->activeQueries) { 78555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool); 78565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData != dev_data->queryPoolMap.end()) { 78575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData->second.createInfo.queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS && 78585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSubCB->beginInfo.pInheritanceInfo) { 78595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkQueryPipelineStatisticFlags cmdBufStatistics = pSubCB->beginInfo.pInheritanceInfo->pipelineStatistics; 78605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((cmdBufStatistics & queryPoolData->second.createInfo.pipelineStatistics) != cmdBufStatistics) { 78619b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg( 78629b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7863315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_1b2000d0, "DS", 78649b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 78659b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "which has invalid active query pool 0x%" PRIx64 78669b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus ". Pipeline statistics is being queried so the command " 78679b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "buffer must have all bits set on the queryPool. %s", 7868315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis pCB->commandBuffer, HandleToUint64(queryPoolData->first), validation_error_map[VALIDATION_ERROR_1b2000d0]); 78695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis activeTypes.insert(queryPoolData->second.createInfo.queryType); 78725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto queryObject : pSubCB->startedQueries) { 78755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool); 78765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData != dev_data->queryPoolMap.end() && activeTypes.count(queryPoolData->second.createInfo.queryType)) { 78779b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 78789b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 78799b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 78809b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "which has invalid active query pool 0x%" PRIx64 78819b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "of type %d but a query of that type has been started on " 78829b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "secondary Cmd Buffer 0x%p.", 78839b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus pCB->commandBuffer, HandleToUint64(queryPoolData->first), queryPoolData->second.createInfo.queryType, 78849b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus pSubCB->commandBuffer); 78855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78877bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 78889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto primary_pool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool); 78899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto secondary_pool = GetCommandPoolNode(dev_data, pSubCB->createInfo.commandPool); 78907bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski if (primary_pool && secondary_pool && (primary_pool->queueFamilyIndex != secondary_pool->queueFamilyIndex)) { 78913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 7892226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 78939b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pSubCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_FAMILY, "DS", 7894226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkCmdExecuteCommands(): Primary command buffer 0x%p" 7895226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis " created in queue family %d has secondary command buffer 0x%p created in queue family %d.", 7896226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCB->commandBuffer, primary_pool->queueFamilyIndex, pSubCB->commandBuffer, secondary_pool->queueFamilyIndex); 78977bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski } 78987bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 78993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 79005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 79015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7902bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount, 7903bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCommandBuffer *pCommandBuffers) { 79043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 790556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7906b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 79079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 79085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 79095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis GLOBAL_CB_NODE *pSubCB = NULL; 79105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < commandBuffersCount; i++) { 79119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis pSubCB = GetCBNode(dev_data, pCommandBuffers[i]); 79120a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis assert(pSubCB); 79130a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis if (VK_COMMAND_BUFFER_LEVEL_PRIMARY == pSubCB->createInfo.level) { 79143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 7915df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7916315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_1b2000b0, "DS", 7917df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdExecuteCommands() called w/ Primary Cmd Buffer 0x%p in element %u of pCommandBuffers " 7918df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "array. All cmd buffers in pCommandBuffers array must be secondary. %s", 7919315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis pCommandBuffers[i], i, validation_error_map[VALIDATION_ERROR_1b2000b0]); 7920cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (pCB->activeRenderPass) { // Secondary CB w/i RenderPass must have *CONTINUE_BIT set 79210de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski if (pSubCB->beginInfo.pInheritanceInfo != nullptr) { 79220de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski auto secondary_rp_state = GetRenderPassState(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass); 79230de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 79240de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski skip |= log_msg( 79250de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7926315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_1b2000c0, "DS", 79270de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) executed within render pass (0x%" PRIxLEAST64 79280de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski ") must have had vkBeginCommandBuffer() called w/ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT " 79290de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski "set. %s", 79300de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski pCommandBuffers[i], HandleToUint64(pCB->activeRenderPass->renderPass), 7931315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_1b2000c0]); 79320de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski } else { 79330de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski // Make sure render pass is compatible with parent command buffer pass if has continue 79340de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski if (pCB->activeRenderPass->renderPass != secondary_rp_state->renderPass) { 79350de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski skip |= 79360de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski validateRenderPassCompatibility(dev_data, commandBuffer, pCB->activeRenderPass->createInfo.ptr(), 79373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCommandBuffers[i], secondary_rp_state->createInfo.ptr()); 79380de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski } 79390de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski // If framebuffer for secondary CB is not NULL, then it must match active FB from primaryCB 79400de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski skip |= validateFramebuffer(dev_data, commandBuffer, pCB, pCommandBuffers[i], pSubCB); 79410de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski } 79420de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski string errorString = ""; 79430de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski // secondaryCB must have been created w/ RP compatible w/ primaryCB active renderpass 79440de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski if ((pCB->activeRenderPass->renderPass != secondary_rp_state->renderPass) && 79450de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(), 79460de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski secondary_rp_state->createInfo.ptr(), errorString)) { 79470de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski skip |= log_msg( 79480de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 79490de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski HandleToUint64(pCommandBuffers[i]), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 79500de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 79510de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski ") is incompatible w/ primary command buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 ") due to: %s", 79520de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski pCommandBuffers[i], HandleToUint64(pSubCB->beginInfo.pInheritanceInfo->renderPass), commandBuffer, 79530de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski HandleToUint64(pCB->activeRenderPass->renderPass), errorString.c_str()); 7954a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 79555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO(mlentine): Move more logic into this method 79583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateSecondaryCommandBufferState(dev_data, pCB, pSubCB); 7959315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= validateCommandBufferState(dev_data, pSubCB, "vkCmdExecuteCommands()", 0, VALIDATION_ERROR_1b2000b2); 79605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 79619b2582dc67737351a72fbeb82e9e6e8cdff7a026Chris Forbes if (pSubCB->in_use.load() || pCB->linkedCommandBuffers.count(pSubCB)) { 79623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 79639b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(pCB->commandBuffer), __LINE__, 7964315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1b2000b4, "DS", 79653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Attempt to simultaneously execute command buffer 0x%p" 79663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " without VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set! %s", 7967315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis pCB->commandBuffer, validation_error_map[VALIDATION_ERROR_1b2000b4]); 79685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) { 79705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Warn that non-simultaneous secondary cmd buffer renders primary non-simultaneous 79713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 79725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 79739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCommandBuffers[i]), __LINE__, DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS", 7974226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) " 7975226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set and will cause primary command buffer " 7976226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "(0x%p) to be treated as if it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT " 797783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "set, even though it does.", 7978226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], pCB->commandBuffer); 79795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->beginInfo.flags &= ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; 79805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7982f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes if (!pCB->activeQueries.empty() && !dev_data->enabled_features.inheritedQueries) { 79833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 7984cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7985315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_1b2000ca, "DS", 7986cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdExecuteCommands(): Secondary Command Buffer " 7987cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(0x%p) cannot be submitted with a query in " 7988cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "flight and inherited queries not " 7989cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "supported on this device. %s", 7990315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis pCommandBuffers[i], validation_error_map[VALIDATION_ERROR_1b2000ca]); 79915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79929b2582dc67737351a72fbeb82e9e6e8cdff7a026Chris Forbes // TODO: separate validate from update! This is very tangled. 79938567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis // Propagate layout transitions to the primary cmd buffer 79948567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis for (auto ilm_entry : pSubCB->imageLayoutMap) { 799555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetLayout(dev_data, pCB, ilm_entry.first, ilm_entry.second); 79968567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis } 79975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSubCB->primaryCommandBuffer = pCB->commandBuffer; 79981a3660584634742a3297915c94768d73f360e794Chris Forbes pCB->linkedCommandBuffers.insert(pSubCB); 79991a3660584634742a3297915c94768d73f360e794Chris Forbes pSubCB->linkedCommandBuffers.insert(pCB); 8000d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine for (auto &function : pSubCB->queryUpdates) { 8001d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine pCB->queryUpdates.push_back(function); 8002d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine } 80035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8004315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdExecuteCommands()", VALIDATION_ERROR_1b200019); 8005315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 8006315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ValidateCmdQueueFlags(dev_data, pCB, "vkCmdExecuteCommands()", 8007315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_1b202415); 8008f5a52627a6576d3d532cd1f2e1be6d9987aeda7fChris Forbes skip |= ValidateCmd(dev_data, pCB, CMD_EXECUTECOMMANDS, "vkCmdExecuteCommands()"); 80091ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_EXECUTECOMMANDS); 80105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8011b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 80123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdExecuteCommands(commandBuffer, commandBuffersCount, pCommandBuffers); 80135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 80145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8015bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkFlags flags, 8016bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski void **ppData) { 801756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 80185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 80193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 80205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 8021b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 80229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 8023cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis if (mem_info) { 8024f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis // TODO : This could me more fine-grained to track just region that is valid 8025f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis mem_info->global_valid = true; 8026623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis auto end_offset = (VK_WHOLE_SIZE == size) ? mem_info->alloc_info.allocationSize - 1 : offset + size - 1; 80273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateMapImageLayouts(dev_data, device, mem_info, offset, end_offset); 8028cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : Do we need to create new "bound_range" for the mapped range? 8029623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis SetMemRangesValid(dev_data, mem_info, offset, end_offset); 8030cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis if ((dev_data->phys_dev_mem_props.memoryTypes[mem_info->alloc_info.memoryTypeIndex].propertyFlags & 8031b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) { 80323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 8033315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(mem), __LINE__, VALIDATION_ERROR_31200554, "MEM", 80343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Mapping Memory without VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set: mem obj 0x%" PRIxLEAST64 ". %s", 8035315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(mem), validation_error_map[VALIDATION_ERROR_31200554]); 80365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateMapMemRange(dev_data, mem, offset, size); 8039b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 80405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 80413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 80424a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.MapMemory(device, mem, offset, size, flags, ppData); 80437c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis if (VK_SUCCESS == result) { 80447c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis lock.lock(); 8045cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : What's the point of this range? See comment on creating new "bound_range" above, which may replace this 80467c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis storeMemRanges(dev_data, mem, offset, size); 80475f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski initializeAndTrackMemory(dev_data, mem, offset, size, ppData); 80487c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis lock.unlock(); 80497c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis } 80505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 80525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 80535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 805489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL UnmapMemory(VkDevice device, VkDeviceMemory mem) { 805556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 80563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 80575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8058b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 80593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= deleteMemRanges(dev_data, mem); 8060b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 80613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 80624a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.UnmapMemory(device, mem); 80635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 80655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 80668860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool validateMemoryIsMapped(layer_data *dev_data, const char *funcName, uint32_t memRangeCount, 8067e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkMappedMemoryRange *pMemRanges) { 8068c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski bool skip = false; 80695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < memRangeCount; ++i) { 80709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, pMemRanges[i].memory); 807157fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 8072f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if (pMemRanges[i].size == VK_WHOLE_SIZE) { 8073f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if (mem_info->mem_range.offset > pMemRanges[i].offset) { 8074315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= 8075315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 8076315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pMemRanges[i].memory), __LINE__, VALIDATION_ERROR_0c20055c, "MEM", 8077315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "%s: Flush/Invalidate offset (" PRINTF_SIZE_T_SPECIFIER 8078315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis ") is less than Memory Object's offset " 8079315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis "(" PRINTF_SIZE_T_SPECIFIER "). %s", 8080315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis funcName, static_cast<size_t>(pMemRanges[i].offset), 8081315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis static_cast<size_t>(mem_info->mem_range.offset), validation_error_map[VALIDATION_ERROR_0c20055c]); 8082f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } 8083f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } else { 8084f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski const uint64_t data_end = (mem_info->mem_range.size == VK_WHOLE_SIZE) 8085f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski ? mem_info->alloc_info.allocationSize 8086f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski : (mem_info->mem_range.offset + mem_info->mem_range.size); 8087f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if ((mem_info->mem_range.offset > pMemRanges[i].offset) || 8088f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski (data_end < (pMemRanges[i].offset + pMemRanges[i].size))) { 8089c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski skip |= 8090f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 8091315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pMemRanges[i].memory), __LINE__, VALIDATION_ERROR_0c20055a, "MEM", 8092f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski "%s: Flush/Invalidate size or offset (" PRINTF_SIZE_T_SPECIFIER ", " PRINTF_SIZE_T_SPECIFIER 8093f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski ") exceed the Memory Object's upper-bound " 8094f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski "(" PRINTF_SIZE_T_SPECIFIER "). %s", 8095f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski funcName, static_cast<size_t>(pMemRanges[i].offset + pMemRanges[i].size), 8096f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski static_cast<size_t>(pMemRanges[i].offset), static_cast<size_t>(data_end), 8097315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_0c20055a]); 8098f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } 80995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8102c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski return skip; 81035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 81045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8105bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic bool ValidateAndCopyNoncoherentMemoryToDriver(layer_data *dev_data, uint32_t mem_range_count, 8106bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 8107bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski bool skip = false; 8108bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 81099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory); 811057fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 81115f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info->shadow_copy) { 81125f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE) 81135f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski ? mem_info->mem_range.size 8114d8a53ade6b5501256798a8b4ec0bc14f72adc1faTobin Ehlis : (mem_info->alloc_info.allocationSize - mem_info->mem_range.offset); 81155f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski char *data = static_cast<char *>(mem_info->shadow_copy); 81165f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski for (uint64_t j = 0; j < mem_info->shadow_pad_size; ++j) { 81175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (data[j] != NoncoherentMemoryFillValue) { 81189b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg( 81199b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 81209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem_ranges[i].memory), __LINE__, MEMTRACK_INVALID_MAP, "MEM", 81219b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Memory underflow was detected on mem obj 0x%" PRIxLEAST64, HandleToUint64(mem_ranges[i].memory)); 81225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81245f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski for (uint64_t j = (size + mem_info->shadow_pad_size); j < (2 * mem_info->shadow_pad_size + size); ++j) { 81255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (data[j] != NoncoherentMemoryFillValue) { 81269b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg( 81279b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 81289b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(mem_ranges[i].memory), __LINE__, MEMTRACK_INVALID_MAP, "MEM", 81299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Memory overflow was detected on mem obj 0x%" PRIxLEAST64, HandleToUint64(mem_ranges[i].memory)); 81305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81325f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski memcpy(mem_info->p_driver_data, static_cast<void *>(data + mem_info->shadow_pad_size), (size_t)(size)); 81335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8136bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski return skip; 81375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 81385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8139bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic void CopyNoncoherentMemoryFromDriver(layer_data *dev_data, uint32_t mem_range_count, const VkMappedMemoryRange *mem_ranges) { 8140bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 81419a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory); 81425f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info && mem_info->shadow_copy) { 81435f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE) 81445f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski ? mem_info->mem_range.size 81455f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski : (mem_info->alloc_info.allocationSize - mem_ranges[i].offset); 81465f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski char *data = static_cast<char *>(mem_info->shadow_copy); 81475f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski memcpy(data + mem_info->shadow_pad_size, mem_info->p_driver_data, (size_t)(size)); 81489e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski } 81499e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski } 81509e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski} 81519e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski 8152ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinskistatic bool ValidateMappedMemoryRangeDeviceLimits(layer_data *dev_data, const char *func_name, uint32_t mem_range_count, 8153ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 8154ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski bool skip = false; 8155ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 8156ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski uint64_t atom_size = dev_data->phys_dev_properties.properties.limits.nonCoherentAtomSize; 815716769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(mem_ranges[i].offset, atom_size) != 0) { 8158df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 8159315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(mem_ranges->memory), __LINE__, VALIDATION_ERROR_0c20055e, "MEM", 8160ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski "%s: Offset in pMemRanges[%d] is 0x%" PRIxLEAST64 8161ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s", 8162315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis func_name, i, mem_ranges[i].offset, atom_size, validation_error_map[VALIDATION_ERROR_0c20055e]); 8163ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 816416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if ((mem_ranges[i].size != VK_WHOLE_SIZE) && (SafeModulo(mem_ranges[i].size, atom_size) != 0)) { 8165df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 8166315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(mem_ranges->memory), __LINE__, VALIDATION_ERROR_0c200560, "MEM", 8167ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski "%s: Size in pMemRanges[%d] is 0x%" PRIxLEAST64 8168ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s", 8169315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis func_name, i, mem_ranges[i].size, atom_size, validation_error_map[VALIDATION_ERROR_0c200560]); 8170ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 8171ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 8172ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski return skip; 8173ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski} 8174ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski 817580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateFlushMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 817680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 817780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski bool skip = false; 817880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 817980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= ValidateAndCopyNoncoherentMemoryToDriver(dev_data, mem_range_count, mem_ranges); 818080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= validateMemoryIsMapped(dev_data, "vkFlushMappedMemoryRanges", mem_range_count, mem_ranges); 818180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski return skip; 818280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 818380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 8184bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, 8185bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *pMemRanges) { 81865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 818756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 81885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 818980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (!PreCallValidateFlushMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) { 81904a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.FlushMappedMemoryRanges(device, memRangeCount, pMemRanges); 81915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 81935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 81945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 819580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 819680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 819780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski bool skip = false; 819880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 819980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= validateMemoryIsMapped(dev_data, "vkInvalidateMappedMemoryRanges", mem_range_count, mem_ranges); 820080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski return skip; 820180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 820280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 820380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic void PostCallRecordInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 820480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 820580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 820680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski // Update our shadow copy with modified driver data 820780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski CopyNoncoherentMemoryFromDriver(dev_data, mem_range_count, mem_ranges); 820880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 820980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 8210bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL InvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, 8211bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *pMemRanges) { 82125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 821356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 82145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 821580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (!PreCallValidateInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) { 82164a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.InvalidateMappedMemoryRanges(device, memRangeCount, pMemRanges); 821780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (result == VK_SUCCESS) { 821880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski PostCallRecordInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges); 821980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski } 82205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 82215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 82225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 82235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8224160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic bool PreCallValidateBindImageMemory(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VkDeviceMemory mem, 8225160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton VkDeviceSize memoryOffset) { 82260109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski bool skip = false; 82271facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state) { 8228160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 822994c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis // Track objects tied to memory 82309b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus uint64_t image_handle = HandleToUint64(image); 82317a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski skip = ValidateSetMemBinding(dev_data, mem, image_handle, kVulkanObjectTypeImage, "vkBindImageMemory()"); 8232ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis if (!image_state->memory_requirements_checked) { 8233ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis // There's not an explicit requirement in the spec to call vkGetImageMemoryRequirements() prior to calling 8234341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton // BindImageMemory but it's implied in that memory being bound must conform with VkMemoryRequirements from 8235341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton // vkGetImageMemoryRequirements() 82360109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 82370109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski image_handle, __LINE__, DRAWSTATE_INVALID_IMAGE, "DS", 82380109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski "vkBindImageMemory(): Binding memory to image 0x%" PRIxLEAST64 82390109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski " but vkGetImageMemoryRequirements() has not been called on that image.", 82400109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski image_handle); 8241ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis // Make the call for them so we can verify the state 8242ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis lock.unlock(); 8243341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton dev_data->dispatch_table.GetImageMemoryRequirements(dev_data->device, image, &image_state->requirements); 8244ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis lock.lock(); 8245ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis } 824647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 82470ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Validate bound memory range information 82489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 824957fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 82500ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton skip |= ValidateInsertImageMemoryRange(dev_data, image, mem_info, memoryOffset, image_state->requirements, 82510ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton image_state->createInfo.tiling == VK_IMAGE_TILING_LINEAR, "vkBindImageMemory()"); 825274300755ed9ec780d6073af71e47f201217008d6Cort Stratton skip |= ValidateMemoryTypes(dev_data, mem_info, image_state->requirements.memoryTypeBits, "vkBindImageMemory()", 8253315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_1740082e); 825447aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 8255160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton 8256160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton // Validate memory requirements alignment 825716769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(memoryOffset, image_state->requirements.alignment) != 0) { 8258160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 8259315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis image_handle, __LINE__, VALIDATION_ERROR_17400830, "DS", 8260160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "vkBindImageMemory(): memoryOffset is 0x%" PRIxLEAST64 8261160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton " but must be an integer multiple of the " 8262160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64 8263160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton ", returned from a call to vkGetImageMemoryRequirements with image. %s", 8264315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis memoryOffset, image_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_17400830]); 8265160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton } 8266160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton 8267160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton // Validate memory requirements size 8268160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton if (image_state->requirements.size > mem_info->alloc_info.allocationSize - memoryOffset) { 8269160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 8270315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis image_handle, __LINE__, VALIDATION_ERROR_17400832, "DS", 8271160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "vkBindImageMemory(): memory size minus memoryOffset is 0x%" PRIxLEAST64 8272160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton " but must be at least as large as " 8273160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "VkMemoryRequirements::size value 0x%" PRIxLEAST64 8274160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton ", returned from a call to vkGetImageMemoryRequirements with image. %s", 8275160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton mem_info->alloc_info.allocationSize - memoryOffset, image_state->requirements.size, 8276315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_17400832]); 8277160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton } 8278341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton } 8279341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton return skip; 8280341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton} 828147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 8282160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic void PostCallRecordBindImageMemory(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VkDeviceMemory mem, 8283160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton VkDeviceSize memoryOffset) { 8284341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (image_state) { 8285160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 82860ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Track bound memory range information 82870ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton auto mem_info = GetMemObjInfo(dev_data, mem); 82880ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton if (mem_info) { 82890ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton InsertImageMemoryRange(dev_data, image, mem_info, memoryOffset, image_state->requirements, 82900ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton image_state->createInfo.tiling == VK_IMAGE_TILING_LINEAR); 82910ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 82920ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 8293c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // Track objects tied to memory 82949b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus uint64_t image_handle = HandleToUint64(image); 82957a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski SetMemBinding(dev_data, mem, image_handle, kVulkanObjectTypeImage, "vkBindImageMemory()"); 8296c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton 8297341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.mem = mem; 8298341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.offset = memoryOffset; 8299341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.size = image_state->requirements.size; 8300341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton } 8301341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton} 8302341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton 8303341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort StrattonVKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 8304341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 8305341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 8306160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton auto image_state = GetImageState(dev_data, image); 8307160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton bool skip = PreCallValidateBindImageMemory(dev_data, image, image_state, mem, memoryOffset); 8308341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (!skip) { 8309341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton result = dev_data->dispatch_table.BindImageMemory(device, image, mem, memoryOffset); 8310341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (result == VK_SUCCESS) { 8311160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton PostCallRecordBindImageMemory(dev_data, image, image_state, mem, memoryOffset); 831294c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis } 83135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 83145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 83155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 83165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 831789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL SetEvent(VkDevice device, VkEvent event) { 83183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 83193ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 832056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 8321b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 83229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 83234710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 83244710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->needsSignaled = false; 83254710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->stageMask = VK_PIPELINE_STAGE_HOST_BIT; 83264710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state->write_in_use) { 83273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, 83289b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(event), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 83293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Cannot call vkSetEvent() on event 0x%" PRIxLEAST64 " that is already in use by a command buffer.", 83309b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(event)); 83313ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis } 83323ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis } 8333b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 83346fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // Host setting event is visible to all queues immediately so update stageMask for any queue that's seen this event 83356fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // TODO : For correctness this needs separate fix to verify that app doesn't make incorrect assumptions about the 83366fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // ordering of this command in relation to vkCmd[Set|Reset]Events (see GH297) 83376fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis for (auto queue_data : dev_data->queueMap) { 83386fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis auto event_entry = queue_data.second.eventToStageMap.find(event); 83396fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis if (event_entry != queue_data.second.eventToStageMap.end()) { 83406fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis event_entry->second |= VK_PIPELINE_STAGE_HOST_BIT; 83416fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis } 83426fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis } 83433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) result = dev_data->dispatch_table.SetEvent(device, event); 83445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 83455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 83465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8347bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, 8348bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkFence fence) { 834956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 83505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 83513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 8352b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 83539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 83549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pQueue = GetQueueState(dev_data, queue); 8355651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 83564b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis // First verify that fence is not in use 83573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateFenceForSubmit(dev_data, pFence); 8358651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 83599867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence) { 836093ccd9708dad3ffb58a3fc09a3d61cc5fe1569f8Mark Lobodzinski SubmitFence(pQueue, pFence, std::max(1u, bindInfoCount)); 83614b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis } 8362651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 83631344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) { 83641344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx]; 83655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Track objects tied to memory 83661344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.bufferBindCount; j++) { 83671344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pBufferBinds[j].bindCount; k++) { 8368f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pBufferBinds[j].pBinds[k]; 8369f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size}, 83709b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(bindInfo.pBufferBinds[j].buffer), kVulkanObjectTypeBuffer)) 83713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = true; 83725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 83735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 83741344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.imageOpaqueBindCount; j++) { 83751344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pImageOpaqueBinds[j].bindCount; k++) { 8376f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pImageOpaqueBinds[j].pBinds[k]; 8377f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size}, 83789b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(bindInfo.pImageOpaqueBinds[j].image), kVulkanObjectTypeImage)) 83793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = true; 83805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 83815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 83821344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.imageBindCount; j++) { 83831344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pImageBinds[j].bindCount; k++) { 8384f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pImageBinds[j].pBinds[k]; 8385f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // TODO: This size is broken for non-opaque bindings, need to update to comprehend full sparse binding data 8386f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis VkDeviceSize size = sparse_binding.extent.depth * sparse_binding.extent.height * sparse_binding.extent.width * 4; 8387f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, size}, 83889b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(bindInfo.pImageBinds[j].image), kVulkanObjectTypeImage)) 83893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = true; 83905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 83915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 83929867daedbf52debc77d6568162ee21e071699b80Chris Forbes 83939867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::vector<SEMAPHORE_WAIT> semaphore_waits; 83949867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::vector<VkSemaphore> semaphore_signals; 83951344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t i = 0; i < bindInfo.waitSemaphoreCount; ++i) { 839601a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = bindInfo.pWaitSemaphores[i]; 83979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 839801a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 839901a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore->signaled) { 84009867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pSemaphore->signaler.first != VK_NULL_HANDLE) { 84019867daedbf52debc77d6568162ee21e071699b80Chris Forbes semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second}); 84029867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->in_use.fetch_add(1); 84039867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 84049867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 840501a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes pSemaphore->signaled = false; 84061344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } else { 84073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 84089b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 84093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkQueueBindSparse: Queue 0x%p is waiting on semaphore 0x%" PRIx64 84103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " that has no way to be signaled.", 84119b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus queue, HandleToUint64(semaphore)); 84125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 84135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 84145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 84151344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t i = 0; i < bindInfo.signalSemaphoreCount; ++i) { 841601a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = bindInfo.pSignalSemaphores[i]; 84179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 841801a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 841901a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore->signaled) { 84203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 84219b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 84223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkQueueBindSparse: Queue 0x%p is signaling semaphore 0x%" PRIx64 84233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ", but that semaphore is already signaled.", 84249b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus queue, HandleToUint64(semaphore)); 8425bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 84269867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = queue; 84279867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1; 84289867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaled = true; 84299867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->in_use.fetch_add(1); 84309867daedbf52debc77d6568162ee21e071699b80Chris Forbes semaphore_signals.push_back(semaphore); 84319867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 84325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 84335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 84349867daedbf52debc77d6568162ee21e071699b80Chris Forbes 8435bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), semaphore_waits, semaphore_signals, 84369867daedbf52debc77d6568162ee21e071699b80Chris Forbes bindIdx == bindInfoCount - 1 ? fence : VK_NULL_HANDLE); 84375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 84389867daedbf52debc77d6568162ee21e071699b80Chris Forbes 84399867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence && !bindInfoCount) { 84409867daedbf52debc77d6568162ee21e071699b80Chris Forbes // No work to do, just dropping a fence in the queue by itself. 8441bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(), std::vector<VkSemaphore>(), 84429867daedbf52debc77d6568162ee21e071699b80Chris Forbes fence); 84439867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 84449867daedbf52debc77d6568162ee21e071699b80Chris Forbes 8445b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 84465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 84473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) return dev_data->dispatch_table.QueueBindSparse(queue, bindInfoCount, pBindInfo, fence); 84485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 84495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 84505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 84515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 845289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, 845389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) { 845456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 84554a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore); 84565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 8457b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 8458bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SEMAPHORE_NODE *sNode = &dev_data->semaphoreMap[*pSemaphore]; 84599867daedbf52debc77d6568162ee21e071699b80Chris Forbes sNode->signaler.first = VK_NULL_HANDLE; 84609867daedbf52debc77d6568162ee21e071699b80Chris Forbes sNode->signaler.second = 0; 84611344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis sNode->signaled = false; 84625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 84635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 84645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 84655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8466bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, 8467bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) { 846856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 84694a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateEvent(device, pCreateInfo, pAllocator, pEvent); 84705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 8471b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 84725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->eventMap[*pEvent].needsSignaled = false; 8473293ecfc5e69ed3978a8c04518166d828294870a4Tony Barbour dev_data->eventMap[*pEvent].write_in_use = 0; 84745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->eventMap[*pEvent].stageMask = VkPipelineStageFlags(0); 84755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 84765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 84775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 84785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 84799ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinskistatic bool PreCallValidateCreateSwapchainKHR(layer_data *dev_data, const char *func_name, 84809ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski VkSwapchainCreateInfoKHR const *pCreateInfo, SURFACE_STATE *surface_state, 84819ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski SWAPCHAIN_NODE *old_swapchain_state) { 8482d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes auto most_recent_swapchain = surface_state->swapchain ? surface_state->swapchain : surface_state->old_swapchain; 8483d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 84844bd5f453535de3d3423ff1f9995b4acb15f791d2Chris Forbes // TODO: revisit this. some of these rules are being relaxed. 84850bbc015828bdb99e85e6731ce92428557902701fPetr Kraus 84860bbc015828bdb99e85e6731ce92428557902701fPetr Kraus // All physical devices and queue families are required to be able 84870bbc015828bdb99e85e6731ce92428557902701fPetr Kraus // to present to any native window on Android; require the 84880bbc015828bdb99e85e6731ce92428557902701fPetr Kraus // application to have established support on any other platform. 8489d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski if (!dev_data->instance_data->extensions.vk_khr_android_surface) { 84900bbc015828bdb99e85e6731ce92428557902701fPetr Kraus auto support_predicate = [dev_data](decltype(surface_state->gpu_queue_support)::const_reference qs) -> bool { 84910bbc015828bdb99e85e6731ce92428557902701fPetr Kraus // TODO: should restrict search only to queue families of VkDeviceQueueCreateInfos, not whole phys. device 84920bbc015828bdb99e85e6731ce92428557902701fPetr Kraus return (qs.first.gpu == dev_data->physical_device) && qs.second; 84930bbc015828bdb99e85e6731ce92428557902701fPetr Kraus }; 84940bbc015828bdb99e85e6731ce92428557902701fPetr Kraus const auto& support = surface_state->gpu_queue_support; 84950bbc015828bdb99e85e6731ce92428557902701fPetr Kraus bool is_supported = std::any_of(support.begin(), support.end(), support_predicate); 84960bbc015828bdb99e85e6731ce92428557902701fPetr Kraus 84970bbc015828bdb99e85e6731ce92428557902701fPetr Kraus if (!is_supported) { 84980bbc015828bdb99e85e6731ce92428557902701fPetr Kraus if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8499315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009ec, "DS", 85000bbc015828bdb99e85e6731ce92428557902701fPetr Kraus "%s: pCreateInfo->surface is not known at this time to be supported for presentation by this device. " 85010bbc015828bdb99e85e6731ce92428557902701fPetr Kraus "The vkGetPhysicalDeviceSurfaceSupportKHR() must be called beforehand, and it must return VK_TRUE support " 85020bbc015828bdb99e85e6731ce92428557902701fPetr Kraus "with this surface for at least one queue family of this device. %s", 8503315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis func_name, validation_error_map[VALIDATION_ERROR_146009ec])) 85040bbc015828bdb99e85e6731ce92428557902701fPetr Kraus return true; 85050bbc015828bdb99e85e6731ce92428557902701fPetr Kraus } 85060bbc015828bdb99e85e6731ce92428557902701fPetr Kraus } 85070bbc015828bdb99e85e6731ce92428557902701fPetr Kraus 8508d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (most_recent_swapchain != old_swapchain_state || (surface_state->old_swapchain && surface_state->swapchain)) { 8509d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 85109b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_ALREADY_EXISTS, "DS", 85119ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s: surface has an existing swapchain other than oldSwapchain", func_name)) 8512d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return true; 8513d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes } 8514d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (old_swapchain_state && old_swapchain_state->createInfo.surface != pCreateInfo->surface) { 8515d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 85169b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pCreateInfo->oldSwapchain), __LINE__, DRAWSTATE_SWAPCHAIN_WRONG_SURFACE, "DS", 85179b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "%s: pCreateInfo->oldSwapchain's surface is not pCreateInfo->surface", func_name)) 8518d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return true; 8519d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes } 85209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device); 85217de258f87ca1192db116a66b209253793d276ebcChris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState == UNCALLED) { 85227de258f87ca1192db116a66b209253793d276ebcChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 85239b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(dev_data->physical_device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 85249ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s: surface capabilities not retrieved for this physical device", func_name)) 85257de258f87ca1192db116a66b209253793d276ebcChris Forbes return true; 8526cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // have valid capabilities 85275c99b4daed164798f307244c9bde17b4f66014fbChris Forbes auto &capabilities = physical_device_state->surfaceCapabilities; 85289ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->minImageCount against VkSurfaceCapabilitiesKHR::{min|max}ImageCount: 85292fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (pCreateInfo->minImageCount < capabilities.minImageCount) { 85302fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8531315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009ee, "DS", 85329ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with minImageCount = %d, which is outside the bounds returned " 85332fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s", 85349ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount, 8535315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_146009ee])) 85362fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen return true; 85372fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen } 85382fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen 85392fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if ((capabilities.maxImageCount > 0) && (pCreateInfo->minImageCount > capabilities.maxImageCount)) { 85405c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8541315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f0, "DS", 85429ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with minImageCount = %d, which is outside the bounds returned " 85432fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s", 85449ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount, 8545315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_146009f0])) 85465c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 85475c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 85482fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen 85499ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageExtent against VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent: 85502e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill if ((capabilities.currentExtent.width == kSurfaceSizeFromSwapchain) && 85512e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill ((pCreateInfo->imageExtent.width < capabilities.minImageExtent.width) || 85522e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.width > capabilities.maxImageExtent.width) || 85532e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.height < capabilities.minImageExtent.height) || 85542e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.height > capabilities.maxImageExtent.height))) { 85555c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8556315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f4, "DS", 85579ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with imageExtent = (%d,%d), which is outside the bounds returned by " 85589ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): currentExtent = (%d,%d), minImageExtent = (%d,%d), " 85599ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "maxImageExtent = (%d,%d). %s", 85609ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, 85619ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski capabilities.currentExtent.width, capabilities.currentExtent.height, capabilities.minImageExtent.width, 85629ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski capabilities.minImageExtent.height, capabilities.maxImageExtent.width, capabilities.maxImageExtent.height, 8563315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_146009f4])) 85645c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 85655c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 85669ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // pCreateInfo->preTransform should have exactly one bit set, and that bit must also be set in 85679ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // VkSurfaceCapabilitiesKHR::supportedTransforms. 85685c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) || 85695c99b4daed164798f307244c9bde17b4f66014fbChris Forbes !(pCreateInfo->preTransform & capabilities.supportedTransforms)) { 85709ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message. Build 85719ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // it up a little at a time, and then log it: 85725c99b4daed164798f307244c9bde17b4f66014fbChris Forbes std::string errorString = ""; 85735c99b4daed164798f307244c9bde17b4f66014fbChris Forbes char str[1024]; 85745c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Here's the first part of the message: 85759ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski sprintf(str, "%s called with a non-supported pCreateInfo->preTransform (i.e. %s). Supported values are:\n", func_name, 85765c99b4daed164798f307244c9bde17b4f66014fbChris Forbes string_VkSurfaceTransformFlagBitsKHR(pCreateInfo->preTransform)); 85775c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 85785c99b4daed164798f307244c9bde17b4f66014fbChris Forbes for (int i = 0; i < 32; i++) { 85795c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Build up the rest of the message: 85805c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((1 << i) & capabilities.supportedTransforms) { 85815c99b4daed164798f307244c9bde17b4f66014fbChris Forbes const char *newStr = string_VkSurfaceTransformFlagBitsKHR((VkSurfaceTransformFlagBitsKHR)(1 << i)); 85825c99b4daed164798f307244c9bde17b4f66014fbChris Forbes sprintf(str, " %s\n", newStr); 85835c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 85845c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 85855c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 85865c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Log the message that we've built up: 85875c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8588315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009fe, "DS", "%s. %s", errorString.c_str(), 8589315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_146009fe])) 85905c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 85915c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 85927b0d28d116977b91892f354e002edd760bdb86cbChris Forbes 85939ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // pCreateInfo->compositeAlpha should have exactly one bit set, and that bit must also be set in 85949ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha 85955c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) || 85965c99b4daed164798f307244c9bde17b4f66014fbChris Forbes !((pCreateInfo->compositeAlpha) & capabilities.supportedCompositeAlpha)) { 85979ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message. Build 85989ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // it up a little at a time, and then log it: 85995c99b4daed164798f307244c9bde17b4f66014fbChris Forbes std::string errorString = ""; 86005c99b4daed164798f307244c9bde17b4f66014fbChris Forbes char str[1024]; 86015c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Here's the first part of the message: 86029ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski sprintf(str, "%s called with a non-supported pCreateInfo->compositeAlpha (i.e. %s). Supported values are:\n", 86039ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, string_VkCompositeAlphaFlagBitsKHR(pCreateInfo->compositeAlpha)); 86045c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 86055c99b4daed164798f307244c9bde17b4f66014fbChris Forbes for (int i = 0; i < 32; i++) { 86065c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Build up the rest of the message: 86075c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((1 << i) & capabilities.supportedCompositeAlpha) { 86085c99b4daed164798f307244c9bde17b4f66014fbChris Forbes const char *newStr = string_VkCompositeAlphaFlagBitsKHR((VkCompositeAlphaFlagBitsKHR)(1 << i)); 86095c99b4daed164798f307244c9bde17b4f66014fbChris Forbes sprintf(str, " %s\n", newStr); 86105c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 86115c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 86125c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 86135c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Log the message that we've built up: 86145c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8615315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_14600a00, "DS", "%s. %s", errorString.c_str(), 8616315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_14600a00])) 86175c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 86185c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 86199ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageArrayLayers against VkSurfaceCapabilitiesKHR::maxImageArrayLayers: 86205c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > capabilities.maxImageArrayLayers)) { 86215c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8622315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f6, "DS", 86239ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported imageArrayLayers (i.e. %d). Minimum value is 1, maximum value is %d. %s", 86249ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageArrayLayers, capabilities.maxImageArrayLayers, 8625315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_146009f6])) 86265c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 86275c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 86289ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageUsage against VkSurfaceCapabilitiesKHR::supportedUsageFlags: 86295c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & capabilities.supportedUsageFlags)) { 86305c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8631315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f8, "DS", 86329ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported pCreateInfo->imageUsage (i.e. 0x%08x). Supported flag bits are 0x%08x. %s", 86339ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageUsage, capabilities.supportedUsageFlags, 8634315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_146009f8])) 86355c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 86365c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 86377de258f87ca1192db116a66b209253793d276ebcChris Forbes } 8638d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 86399ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfaceFormatsKHR(): 86405faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState != QUERY_DETAILS) { 86415faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 86429b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 86439ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called before calling vkGetPhysicalDeviceSurfaceFormatsKHR().", func_name)) 86445faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return true; 86455faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } else { 86469ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageFormat against VkSurfaceFormatKHR::format: 86475faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundFormat = false; 86485faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundColorSpace = false; 86495faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundMatch = false; 86505faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes for (auto const &format : physical_device_state->surface_formats) { 86515faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageFormat == format.format) { 86529ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageColorSpace against VkSurfaceFormatKHR::colorSpace: 86535faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundFormat = true; 86545faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageColorSpace == format.colorSpace) { 86555faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundMatch = true; 86565faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes break; 86575faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 86585faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } else { 86595faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageColorSpace == format.colorSpace) { 86605faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundColorSpace = true; 86615faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 86625faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 86635faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 86645faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (!foundMatch) { 86655faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (!foundFormat) { 86665faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8667315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f2, "DS", 8668bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "%s called with a non-supported pCreateInfo->imageFormat (i.e. %d). %s", func_name, 8669315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis pCreateInfo->imageFormat, validation_error_map[VALIDATION_ERROR_146009f2])) 86702fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen return true; 86712fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen } 86722fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (!foundColorSpace) { 86732fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8674315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f2, "DS", 8675bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "%s called with a non-supported pCreateInfo->imageColorSpace (i.e. %d). %s", func_name, 8676315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis pCreateInfo->imageColorSpace, validation_error_map[VALIDATION_ERROR_146009f2])) 86775faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return true; 86785faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 86795faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 86805faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 86815faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 86829ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfacePresentModesKHR(): 86839e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState != QUERY_DETAILS) { 868425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // FIFO is required to always be supported 86859e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR) { 86869e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 86879b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 86889ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called before calling vkGetPhysicalDeviceSurfacePresentModesKHR().", func_name)) 86899e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return true; 86909e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 86919e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } else { 86929ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->presentMode against vkGetPhysicalDeviceSurfacePresentModesKHR(): 8693bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski bool foundMatch = std::find(physical_device_state->present_modes.begin(), physical_device_state->present_modes.end(), 86949e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes pCreateInfo->presentMode) != physical_device_state->present_modes.end(); 86959e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (!foundMatch) { 86969e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8697315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_14600a02, "DS", 86989ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported presentMode (i.e. %s). %s", func_name, 8699315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis string_VkPresentModeKHR(pCreateInfo->presentMode), validation_error_map[VALIDATION_ERROR_14600a02])) 87009e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return true; 87019e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 87029e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 870387a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis // Validate state for shared presentable case 870487a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis if (VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR == pCreateInfo->presentMode || 870587a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR == pCreateInfo->presentMode) { 8706a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinski if (!dev_data->extensions.vk_khr_shared_presentable_image) { 870787a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8708480a11822ef9a45f577f13644759c0895a49db19Tobin Ehlis HandleToUint64(dev_data->device), __LINE__, DRAWSTATE_EXTENSION_NOT_ENABLED, "DS", 87096084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski "%s called with presentMode %s which requires the VK_KHR_shared_presentable_image extension, which has not " 87106084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski "been enabled.", 87116084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski func_name, string_VkPresentModeKHR(pCreateInfo->presentMode))) 87126084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski return true; 87136084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski } else if (pCreateInfo->minImageCount != 1) { 87146084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8715315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_14600ace, "DS", 871687a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis "%s called with presentMode %s, but minImageCount value is %d. For shared presentable image, minImageCount " 87176084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski "must be 1. %s", 87186084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski func_name, string_VkPresentModeKHR(pCreateInfo->presentMode), pCreateInfo->minImageCount, 8719315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_14600ace])) 872087a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis return true; 872187a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis } 872287a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis } 87239e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 8724d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return false; 8725d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes} 8726d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 8727261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinskistatic void PostCallRecordCreateSwapchainKHR(layer_data *dev_data, VkResult result, const VkSwapchainCreateInfoKHR *pCreateInfo, 8728261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski VkSwapchainKHR *pSwapchain, SURFACE_STATE *surface_state, 8729261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski SWAPCHAIN_NODE *old_swapchain_state) { 87305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 8731b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 8732ddc5201048319558ce66701163a4546ee957af19Chris Forbes auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(pCreateInfo, *pSwapchain)); 873387a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis if (VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR == pCreateInfo->presentMode || 873487a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR == pCreateInfo->presentMode) { 873587a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis swapchain_state->shared_presentable = true; 873687a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis } 8737ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->swapchain = swapchain_state.get(); 873816a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes dev_data->swapchainMap[*pSwapchain] = std::move(swapchain_state); 8739ddc5201048319558ce66701163a4546ee957af19Chris Forbes } else { 8740ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->swapchain = nullptr; 87415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8742ddc5201048319558ce66701163a4546ee957af19Chris Forbes // Spec requires that even if CreateSwapchainKHR fails, oldSwapchain behaves as replaced. 87435b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes if (old_swapchain_state) { 87445b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes old_swapchain_state->replaced = true; 87455b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes } 8746ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->old_swapchain = old_swapchain_state; 8747261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski return; 8748261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski} 8749261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 8750261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, 8751261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) { 875256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 87539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, pCreateInfo->surface); 87549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto old_swapchain_state = GetSwapchainNode(dev_data, pCreateInfo->oldSwapchain); 8755261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 87569ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski if (PreCallValidateCreateSwapchainKHR(dev_data, "vkCreateSwapChainKHR()", pCreateInfo, surface_state, old_swapchain_state)) { 8757261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 8758261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski } 8759261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 8760261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski VkResult result = dev_data->dispatch_table.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); 8761261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 8762261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski PostCallRecordCreateSwapchainKHR(dev_data, result, pCreateInfo, pSwapchain, surface_state, old_swapchain_state); 8763ddc5201048319558ce66701163a4546ee957af19Chris Forbes 87645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 87655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 87665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8767bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) { 876856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 87693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 87705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8771b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 87729a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, swapchain); 8773b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data) { 8774b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data->images.size() > 0) { 8775b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis for (auto swapchain_image : swapchain_data->images) { 87765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto image_sub = dev_data->imageSubresourceMap.find(swapchain_image); 87775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (image_sub != dev_data->imageSubresourceMap.end()) { 87785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto imgsubpair : image_sub->second) { 87795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto image_item = dev_data->imageLayoutMap.find(imgsubpair); 87805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (image_item != dev_data->imageLayoutMap.end()) { 87815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap.erase(image_item); 87825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 87835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 87845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap.erase(image_sub); 87855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 87869b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip = ClearMemoryObjectBindings(dev_data, HandleToUint64(swapchain_image), kVulkanObjectTypeSwapchainKHR); 878794c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis dev_data->imageMap.erase(swapchain_image); 87885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 87895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8790ddc5201048319558ce66701163a4546ee957af19Chris Forbes 87919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface); 8792ddc5201048319558ce66701163a4546ee957af19Chris Forbes if (surface_state) { 8793cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (surface_state->swapchain == swapchain_data) surface_state->swapchain = nullptr; 8794cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (surface_state->old_swapchain == swapchain_data) surface_state->old_swapchain = nullptr; 8795ddc5201048319558ce66701163a4546ee957af19Chris Forbes } 8796ddc5201048319558ce66701163a4546ee957af19Chris Forbes 879716a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes dev_data->swapchainMap.erase(swapchain); 87985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8799b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 88003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.DestroySwapchainKHR(device, swapchain, pAllocator); 88015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 88025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8803991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic bool PreCallValidateGetSwapchainImagesKHR(layer_data *device_data, SWAPCHAIN_NODE *swapchain_state, VkDevice device, 8804991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) { 8805991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski bool skip = false; 8806991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (swapchain_state && pSwapchainImages) { 8807b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 8808991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski // Compare the preliminary value of *pSwapchainImageCount with the value this time: 8809991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (swapchain_state->vkGetSwapchainImagesKHRState == UNCALLED) { 8810991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8811991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski HandleToUint64(device), __LINE__, SWAPCHAIN_PRIOR_COUNT, "DS", 8812991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski "vkGetSwapchainImagesKHR() called with non-NULL pSwapchainImageCount; but no prior positive " 8813991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski "value has been seen for pSwapchainImages."); 8814991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } else if (*pSwapchainImageCount > swapchain_state->get_swapchain_image_count) { 8815991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 8816991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski HandleToUint64(device), __LINE__, SWAPCHAIN_INVALID_COUNT, "DS", 8817991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski "vkGetSwapchainImagesKHR() called with non-NULL pSwapchainImageCount, and with " 8818991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski "pSwapchainImages set to a value (%d) that is greater than the value (%d) that was returned when " 8819991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski "pSwapchainImageCount was NULL.", 8820991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski *pSwapchainImageCount, swapchain_state->get_swapchain_image_count); 8821991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 8822991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 8823991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski return skip; 8824991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski} 8825991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 8826991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic void PostCallRecordGetSwapchainImagesKHR(layer_data *device_data, SWAPCHAIN_NODE *swapchain_state, VkDevice device, 8827991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) { 8828991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 8829ee52d734440f0770b3ac5ebde5a137d2e40589deChris Forbes 8830991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (*pSwapchainImageCount > swapchain_state->images.size()) swapchain_state->images.resize(*pSwapchainImageCount); 8831ee52d734440f0770b3ac5ebde5a137d2e40589deChris Forbes 8832991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (pSwapchainImages) { 8833991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (swapchain_state->vkGetSwapchainImagesKHRState < QUERY_DETAILS) { 8834991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski swapchain_state->vkGetSwapchainImagesKHRState = QUERY_DETAILS; 8835991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 8836991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski for (uint32_t i = 0; i < *pSwapchainImageCount; ++i) { 8837991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (swapchain_state->images[i] != VK_NULL_HANDLE) continue; // Already retrieved this. 8838ee52d734440f0770b3ac5ebde5a137d2e40589deChris Forbes 88395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis IMAGE_LAYOUT_NODE image_layout_node; 88405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis image_layout_node.layout = VK_IMAGE_LAYOUT_UNDEFINED; 8841991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski image_layout_node.format = swapchain_state->createInfo.imageFormat; 88426d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis // Add imageMap entries for each swapchain image 88436d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis VkImageCreateInfo image_ci = {}; 8844eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.flags = 0; 8845eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.imageType = VK_IMAGE_TYPE_2D; 8846991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski image_ci.format = swapchain_state->createInfo.imageFormat; 8847991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski image_ci.extent.width = swapchain_state->createInfo.imageExtent.width; 8848991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski image_ci.extent.height = swapchain_state->createInfo.imageExtent.height; 8849d1a9776c1a22ec99a3ef0dd44e7f85a78a04d1edTony Barbour image_ci.extent.depth = 1; 8850eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.mipLevels = 1; 8851991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski image_ci.arrayLayers = swapchain_state->createInfo.imageArrayLayers; 8852eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.samples = VK_SAMPLE_COUNT_1_BIT; 8853eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.tiling = VK_IMAGE_TILING_OPTIMAL; 8854991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski image_ci.usage = swapchain_state->createInfo.imageUsage; 8855991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski image_ci.sharingMode = swapchain_state->createInfo.imageSharingMode; 8856991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski device_data->imageMap[pSwapchainImages[i]] = unique_ptr<IMAGE_STATE>(new IMAGE_STATE(pSwapchainImages[i], &image_ci)); 8857991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski auto &image_state = device_data->imageMap[pSwapchainImages[i]]; 88581facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->valid = false; 8859e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis image_state->binding.mem = MEMTRACKER_SWAP_CHAIN_IMAGE_KEY; 8860991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski swapchain_state->images[i] = pSwapchainImages[i]; 88615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ImageSubresourcePair subpair = {pSwapchainImages[i], false, VkImageSubresource()}; 8862991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski device_data->imageSubresourceMap[pSwapchainImages[i]].push_back(subpair); 8863991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski device_data->imageLayoutMap[subpair] = image_layout_node; 88645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8866991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 8867991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (*pSwapchainImageCount) { 8868991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (swapchain_state->vkGetSwapchainImagesKHRState < QUERY_COUNT) { 8869991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski swapchain_state->vkGetSwapchainImagesKHRState = QUERY_COUNT; 8870991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 8871991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski swapchain_state->get_swapchain_image_count = *pSwapchainImageCount; 8872991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 8873991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski} 8874991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 8875991f2555bc4f571e30b584937c7959805dff67c6Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, 8876991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski VkImage *pSwapchainImages) { 8877991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 8878991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 8879991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 8880991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski auto swapchain_state = GetSwapchainNode(device_data, swapchain); 8881991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski bool skip = PreCallValidateGetSwapchainImagesKHR(device_data, swapchain_state, device, pSwapchainImageCount, pSwapchainImages); 8882991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 8883991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (!skip) { 8884991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski result = device_data->dispatch_table.GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages); 8885991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 8886991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 8887991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if ((result == VK_SUCCESS || result == VK_INCOMPLETE)) { 8888991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski PostCallRecordGetSwapchainImagesKHR(device_data, swapchain_state, device, pSwapchainImageCount, pSwapchainImages); 8889991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 88905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 88915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 88925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 889389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) { 889456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 88953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 88965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 88976c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes std::lock_guard<std::mutex> lock(global_lock); 88989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto queue_state = GetQueueState(dev_data, queue); 88991671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 89006c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) { 89019a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]); 89026c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes if (pSemaphore && !pSemaphore->signaled) { 89033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 89043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 89053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue, 89069b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPresentInfo->pWaitSemaphores[i])); 89075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89086c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 8909249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 89106c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { 89119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); 8912a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (swapchain_data) { 8913a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (pPresentInfo->pImageIndices[i] >= swapchain_data->images.size()) { 89149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= 89159b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 89169b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS", 89179b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "vkQueuePresentKHR: Swapchain image index too large (%u). There are only %u images in this swapchain.", 89189b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus pPresentInfo->pImageIndices[i], (uint32_t)swapchain_data->images.size()); 8919bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 8920a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]]; 89219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 892287a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis 892387a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis if (image_state->shared_presentable) { 892487a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis image_state->layout_locked = true; 892587a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis } 8926c4f799ed5502f05ce97543e0500b4a19dc5f2461Mark Lobodzinski 89273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateImageMemoryIsValid(dev_data, image_state, "vkQueuePresentKHR()"); 8928a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes 89291facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (!image_state->acquired) { 89303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 8931bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 89329b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_IMAGE_NOT_ACQUIRED, "DS", 8933bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "vkQueuePresentKHR: Swapchain image index %u has not been acquired.", pPresentInfo->pImageIndices[i]); 8934a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes } 8935a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes 8936a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes vector<VkImageLayout> layouts; 8937a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (FindLayouts(dev_data, image, layouts)) { 8938a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes for (auto layout : layouts) { 89396084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski if ((layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) && 8940a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinski (!dev_data->extensions.vk_khr_shared_presentable_image || 89416084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski (layout != VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR))) { 89423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 89432fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, 8944315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(queue), __LINE__, VALIDATION_ERROR_11200a20, "DS", 89452fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "Images passed to present must be in layout " 89466084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR or VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR but is in %s. %s", 8947315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis string_VkImageLayout(layout), validation_error_map[VALIDATION_ERROR_11200a20]); 8948a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes } 89495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89521671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 89531671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // All physical devices and queue families are required to be able 89541671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // to present to any native window on Android; require the 89551671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // application to have established support on any other platform. 8956d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski if (!dev_data->instance_data->extensions.vk_khr_android_surface) { 89579a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface); 89581671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes auto support_it = surface_state->gpu_queue_support.find({dev_data->physical_device, queue_state->queueFamilyIndex}); 89591671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 89601671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes if (support_it == surface_state->gpu_queue_support.end()) { 89613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 89621671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 89639b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_UNSUPPORTED_QUEUE, "DS", 8964cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkQueuePresentKHR: Presenting image without calling " 8965cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceSupportKHR"); 89661671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } else if (!support_it->second) { 89679b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= 89689b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 8969315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, VALIDATION_ERROR_31800a18, "DS", 89709b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "vkQueuePresentKHR: Presenting image on queue that cannot " 89719b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "present to this surface. %s", 8972315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_31800a18]); 89731671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } 89741671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } 89755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8977c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis if (pPresentInfo && pPresentInfo->pNext) { 8978c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis // Verify ext struct 8979c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis struct std_header { 8980c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis VkStructureType sType; 8981c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis const void *pNext; 8982c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis }; 8983c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis std_header *pnext = (std_header *)pPresentInfo->pNext; 8984c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis while (pnext) { 8985c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis if (VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR == pnext->sType) { 8986c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis VkPresentRegionsKHR *present_regions = (VkPresentRegionsKHR *)pnext; 8987c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis for (uint32_t i = 0; i < present_regions->swapchainCount; ++i) { 8988c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); 8989c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis assert(swapchain_data); 8990c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis VkPresentRegionKHR region = present_regions->pRegions[i]; 8991c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis for (uint32_t j = 0; j < region.rectangleCount; ++j) { 8992c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis VkRectLayerKHR rect = region.pRectangles[j]; 8993c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis // TODO: Need to update these errors to their unique error ids when available 8994c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis if ((rect.offset.x + rect.extent.width) > swapchain_data->createInfo.imageExtent.width) { 89959b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg( 89969b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 89979b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS", 89989b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext " 89999b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "chain, pRegion[%i].pRectangles[%i], the sum of offset.x " 90009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "(%i) and extent.width (%i) is greater than the " 90019b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "corresponding swapchain's imageExtent.width (%i).", 90029b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus i, j, rect.offset.x, rect.extent.width, swapchain_data->createInfo.imageExtent.width); 9003c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 9004c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis if ((rect.offset.y + rect.extent.height) > swapchain_data->createInfo.imageExtent.height) { 90059b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus skip |= log_msg( 90069b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 90079b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS", 90089b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext " 90099b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "chain, pRegion[%i].pRectangles[%i], the sum of offset.y " 90109b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "(%i) and extent.height (%i) is greater than the " 90119b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "corresponding swapchain's imageExtent.height (%i).", 90129b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus i, j, rect.offset.y, rect.extent.height, swapchain_data->createInfo.imageExtent.height); 9013c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 9014c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis if (rect.layer > swapchain_data->createInfo.imageArrayLayers) { 90153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 9016c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 90179b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS", 9018c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext chain, pRegion[%i].pRectangles[%i], the " 9019c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis "layer (%i) is greater than the corresponding swapchain's imageArrayLayers (%i).", 9020c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis i, j, rect.layer, swapchain_data->createInfo.imageArrayLayers); 9021c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 9022c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 9023c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 90245f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis } else if (VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE == pnext->sType) { 90255f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis VkPresentTimesInfoGOOGLE *present_times_info = (VkPresentTimesInfoGOOGLE *)pnext; 90265f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis if (pPresentInfo->swapchainCount != present_times_info->swapchainCount) { 90275f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis skip |= 90285f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 90299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pPresentInfo->pSwapchains[0]), __LINE__, 90305f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis 9031315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis VALIDATION_ERROR_118009be, "DS", 90325f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis "vkQueuePresentKHR(): VkPresentTimesInfoGOOGLE.swapchainCount is %i but " 90335f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis "pPresentInfo->swapchainCount is %i. For VkPresentTimesInfoGOOGLE down pNext " 90345f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis "chain of VkPresentInfoKHR, VkPresentTimesInfoGOOGLE.swapchainCount " 90355f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis "must equal VkPresentInfoKHR.swapchainCount.", 90365f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis present_times_info->swapchainCount, pPresentInfo->swapchainCount); 90375f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis } 9038c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 9039c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis pnext = (std_header *)pnext->pNext; 9040c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 9041c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 90425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 90433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 90446c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes return VK_ERROR_VALIDATION_FAILED_EXT; 90456c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 90466c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes 90474a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.QueuePresentKHR(queue, pPresentInfo); 90486c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes 90496c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes if (result != VK_ERROR_VALIDATION_FAILED_EXT) { 90506c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes // Semaphore waits occur before error generation, if the call reached 90516c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes // the ICD. (Confirm?) 90526c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) { 90539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]); 90549867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pSemaphore) { 90559867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 90566c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes pSemaphore->signaled = false; 90576c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 90586c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 90599867daedbf52debc77d6568162ee21e071699b80Chris Forbes 9060220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { 9061220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Note: this is imperfect, in that we can get confused about what 9062220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // did or didn't succeed-- but if the app does that, it's confused 9063220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // itself just as much. 9064220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto local_result = pPresentInfo->pResults ? pPresentInfo->pResults[i] : result; 9065220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 9066cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (local_result != VK_SUCCESS && local_result != VK_SUBOPTIMAL_KHR) continue; // this present didn't actually happen. 9067220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 9068220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Mark the image as having been released to the WSI 90699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); 9070220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]]; 90719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 90721facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->acquired = false; 9073220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes } 9074220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 90759867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Note: even though presentation is directed to a queue, there is no 90769867daedbf52debc77d6568162ee21e071699b80Chris Forbes // direct ordering between QP and subsequent work, so QP (and its 90779867daedbf52debc77d6568162ee21e071699b80Chris Forbes // semaphore waits) /never/ participate in any completion proof. 90786c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 90791344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 90805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 90815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 90825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9083c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic bool PreCallValidateCreateSharedSwapchainsKHR(layer_data *dev_data, uint32_t swapchainCount, 9084c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains, 9085c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> &surface_state, 9086c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) { 90870342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (pCreateInfos) { 9088c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 90890342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 90909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis surface_state.push_back(GetSurfaceState(dev_data->instance_data, pCreateInfos[i].surface)); 90919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis old_swapchain_state.push_back(GetSwapchainNode(dev_data, pCreateInfos[i].oldSwapchain)); 90929ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski std::stringstream func_name; 90939ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name << "vkCreateSharedSwapchainsKHR[" << swapchainCount << "]"; 9094bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (PreCallValidateCreateSwapchainKHR(dev_data, func_name.str().c_str(), &pCreateInfos[i], surface_state[i], 9095bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski old_swapchain_state[i])) { 9096c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return true; 90970342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 90980342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 90990342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 9100c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return false; 9101c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski} 91020342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski 9103c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic void PostCallRecordCreateSharedSwapchainsKHR(layer_data *dev_data, VkResult result, uint32_t swapchainCount, 9104c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains, 9105c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> &surface_state, 9106c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) { 91070342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (VK_SUCCESS == result) { 91080342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 91090342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(&pCreateInfos[i], pSwapchains[i])); 911087a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis if (VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR == pCreateInfos[i].presentMode || 911187a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR == pCreateInfos[i].presentMode) { 911287a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis swapchain_state->shared_presentable = true; 911387a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis } 91140342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->swapchain = swapchain_state.get(); 911516a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes dev_data->swapchainMap[pSwapchains[i]] = std::move(swapchain_state); 91160342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 91170342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } else { 91180342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 91190342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->swapchain = nullptr; 91200342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 91210342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 91220342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski // Spec requires that even if CreateSharedSwapchainKHR fails, oldSwapchain behaves as replaced. 91230342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 91240342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (old_swapchain_state[i]) { 91250342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski old_swapchain_state[i]->replaced = true; 91260342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 91270342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->old_swapchain = old_swapchain_state[i]; 91280342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 9129c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return; 9130c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski} 9131c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 9132c6cd632d064579a64e61d8704b411d0e4ace7adaMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount, 9133c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, 9134c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains) { 913556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 9136c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> surface_state; 9137c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> old_swapchain_state; 9138c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 9139c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski if (PreCallValidateCreateSharedSwapchainsKHR(dev_data, swapchainCount, pCreateInfos, pSwapchains, surface_state, 9140c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski old_swapchain_state)) { 9141c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 9142c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski } 9143c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 9144c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski VkResult result = 9145c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski dev_data->dispatch_table.CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator, pSwapchains); 9146c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 9147c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski PostCallRecordCreateSharedSwapchainsKHR(dev_data, result, swapchainCount, pCreateInfos, pSwapchains, surface_state, 9148c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski old_swapchain_state); 91490342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski 9150c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young return result; 9151c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young} 9152c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young 915389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, 915489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) { 915556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 91563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 91571344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 9158b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 9159449670637ef4214b33018f497cf10daeff9dc85bChris Forbes 9160449670637ef4214b33018f497cf10daeff9dc85bChris Forbes if (fence == VK_NULL_HANDLE && semaphore == VK_NULL_HANDLE) { 91613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 91629b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(device), __LINE__, DRAWSTATE_SWAPCHAIN_NO_SYNC_FOR_ACQUIRE, "DS", 91633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkAcquireNextImageKHR: Semaphore and fence cannot both be VK_NULL_HANDLE. There would be no way " 91643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "to determine the completion of this operation."); 9165449670637ef4214b33018f497cf10daeff9dc85bChris Forbes } 9166449670637ef4214b33018f497cf10daeff9dc85bChris Forbes 91679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 9168f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pSemaphore && pSemaphore->signaled) { 91693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 9170315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis HandleToUint64(semaphore), __LINE__, VALIDATION_ERROR_16400a0c, "DS", 91713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkAcquireNextImageKHR: Semaphore must not be currently signaled or in a wait state. %s", 9172315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis validation_error_map[VALIDATION_ERROR_16400a0c]); 91735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9174f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 91759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 9176f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pFence) { 91773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateFenceForSubmit(dev_data, pFence); 91785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91794a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes 91809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, swapchain); 9181fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes 9182fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes if (swapchain_data->replaced) { 91833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 91849b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_REPLACED, "DS", 91853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkAcquireNextImageKHR: This swapchain has been replaced. The application can still " 91863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "present any images it has acquired, but cannot acquire any more."); 9187fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes } 9188fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes 91899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device); 91904a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState != UNCALLED) { 91916569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski uint64_t acquired_images = std::count_if(swapchain_data->images.begin(), swapchain_data->images.end(), 91929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis [=](VkImage image) { return GetImageState(dev_data, image)->acquired; }); 91934a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes if (acquired_images > swapchain_data->images.size() - physical_device_state->surfaceCapabilities.minImageCount) { 91943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 91956569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 91969b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_TOO_MANY_IMAGES, "DS", 91976569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski "vkAcquireNextImageKHR: Application has already acquired the maximum number of images (0x%" PRIxLEAST64 ")", 91986569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski acquired_images); 91994a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes } 92004a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes } 920175269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis 920275269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis if (swapchain_data->images.size() == 0) { 92033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 92049b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_IMAGES_NOT_FOUND, "DS", 92053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkAcquireNextImageKHR: No images found to acquire from. Application probably did not call " 92063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkGetSwapchainImagesKHR after swapchain creation."); 920775269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis } 920875269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis 9209b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 92101344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 92113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 9212f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 92134a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex); 9214f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 9215f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes lock.lock(); 9216f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { 9217f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pFence) { 9218f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes pFence->state = FENCE_INFLIGHT; 9219cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pFence->signaler.first = VK_NULL_HANDLE; // ANI isn't on a queue, so this can't participate in a completion proof. 9220f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes } 9221f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 9222f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes // A successful call to AcquireNextImageKHR counts as a signal operation on semaphore 9223f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pSemaphore) { 9224f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes pSemaphore->signaled = true; 92259867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 9226f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes } 9227220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 9228220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Mark the image as acquired. 9229220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto image = swapchain_data->images[*pImageIndex]; 92309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 92311facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->acquired = true; 923287a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis image_state->shared_presentable = swapchain_data->shared_presentable; 92335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9234f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes lock.unlock(); 92351344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 92365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 92375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 92385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9239f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, 9240f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski VkPhysicalDevice *pPhysicalDevices) { 92413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 924256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 9243bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis assert(instance_data); 9244219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes 9245bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // For this instance, flag when vkEnumeratePhysicalDevices goes to QUERY_COUNT and then QUERY_DETAILS 9246bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (NULL == pPhysicalDevices) { 9247bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->vkEnumeratePhysicalDevicesState = QUERY_COUNT; 9248f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } else { 9249bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (UNCALLED == instance_data->vkEnumeratePhysicalDevicesState) { 9250bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Flag warning here. You can call this without having queried the count, but it may not be 9251bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // robust on platforms with multiple physical devices. 92523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 92533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL", 92543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Call sequence has vkEnumeratePhysicalDevices() w/ non-NULL pPhysicalDevices. You should first " 92553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "call vkEnumeratePhysicalDevices() w/ NULL pPhysicalDevices to query pPhysicalDeviceCount."); 9256cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state 9257bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis else if (instance_data->physical_devices_count != *pPhysicalDeviceCount) { 9258bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Having actual count match count from app is not a requirement, so this can be a warning 92593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 92603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 92613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Call to vkEnumeratePhysicalDevices() w/ pPhysicalDeviceCount value %u, but actual count " 92623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "supported by this instance is %u.", 92633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski *pPhysicalDeviceCount, instance_data->physical_devices_count); 9264bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 9265bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->vkEnumeratePhysicalDevicesState = QUERY_DETAILS; 9266f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 92673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 9268bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 9269bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 9270bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis VkResult result = instance_data->dispatch_table.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices); 9271bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (NULL == pPhysicalDevices) { 9272bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->physical_devices_count = *pPhysicalDeviceCount; 9273cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (result == VK_SUCCESS) { // Save physical devices 9274bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) { 9275bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis auto &phys_device_state = instance_data->physical_device_map[pPhysicalDevices[i]]; 9276bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis phys_device_state.phys_device = pPhysicalDevices[i]; 9277bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Init actual features for each physical device 9278bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceFeatures(pPhysicalDevices[i], &phys_device_state.features); 9279bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 9280bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 9281bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis return result; 9282f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski} 9283f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 928443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to handle validation for GetPhysicalDeviceQueueFamilyProperties & 2KHR version 928543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data, 928643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, 92875770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus uint32_t requested_queue_family_property_count, bool qfp_null, 92885770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus const char *caller_name) { 928943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = false; 92905770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus if (!qfp_null) { 92915770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus // Verify that for each physical device, this command is called first with NULL pQueueFamilyProperties in order to get count 929243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (UNCALLED == pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) { 92935770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus skip |= log_msg( 92945770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 92959b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pd_state->phys_device), __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL", 92965770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus "%s is called with non-NULL pQueueFamilyProperties before obtaining pQueueFamilyPropertyCount. It is recommended " 92975770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus "to first call %s with NULL pQueueFamilyProperties in order to obtain the maximal pQueueFamilyPropertyCount.", 92985770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus caller_name, caller_name); 92995770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus // Then verify that pCount that is passed in on second call matches what was returned 93005770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus } else if (pd_state->queue_family_count != requested_queue_family_property_count) { 93015770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus skip |= log_msg( 93025770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 93039b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(pd_state->phys_device), __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 93045770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus "%s is called with non-NULL pQueueFamilyProperties and pQueueFamilyPropertyCount value %" PRIu32 93055770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus ", but the largest previously returned pQueueFamilyPropertyCount for this physicalDevice is %" PRIu32 93065770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus ". It is recommended to instead receive all the properties by calling %s with pQueueFamilyPropertyCount that was " 93075770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus "previously obtained by calling %s with NULL pQueueFamilyProperties.", 93085770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus caller_name, requested_queue_family_property_count, pd_state->queue_family_count, caller_name, caller_name); 930943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 931043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_DETAILS; 931143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 93125770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 931343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return skip; 931443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 931543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 931643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data, 93175770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus PHYSICAL_DEVICE_STATE *pd_state, 93185770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus uint32_t *pQueueFamilyPropertyCount, 931943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties *pQueueFamilyProperties) { 93205770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, *pQueueFamilyPropertyCount, 93215770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus (nullptr == pQueueFamilyProperties), 932243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "vkGetPhysicalDeviceQueueFamilyProperties()"); 932343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 932443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 932543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_layer_data *instance_data, 932643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, 932743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, 932843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 93295770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, *pQueueFamilyPropertyCount, 93305770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus (nullptr == pQueueFamilyProperties), 933143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "vkGetPhysicalDeviceQueueFamilyProperties2KHR()"); 933243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 933343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 933443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to update state for GetPhysicalDeviceQueueFamilyProperties & 2KHR version 933543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 933643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 933743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (!pQueueFamilyProperties) { 93385770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus if (UNCALLED == pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) 93395770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_COUNT; 93405770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus pd_state->queue_family_count = count; 934143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } else { // Save queue family properties 93425770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_DETAILS; 93435770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus pd_state->queue_family_count = std::max(pd_state->queue_family_count, count); 93445770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 93455770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus pd_state->queue_family_properties.resize(std::max(static_cast<uint32_t>(pd_state->queue_family_properties.size()), count)); 93465770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus for (uint32_t i = 0; i < count; ++i) { 934743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->queue_family_properties[i] = pQueueFamilyProperties[i].queueFamilyProperties; 934843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 934943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 935043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 935143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 935243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 935343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties *pQueueFamilyProperties) { 935443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pqfp = nullptr; 935543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis std::vector<VkQueueFamilyProperties2KHR> qfp; 935643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp.resize(count); 935743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (pQueueFamilyProperties) { 935843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis for (uint32_t i = 0; i < count; ++i) { 935943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR; 936043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].pNext = nullptr; 936143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].queueFamilyProperties = pQueueFamilyProperties[i]; 936243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 936343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pqfp = qfp.data(); 936443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 936543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pqfp); 936643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 936743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 936843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 936943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 937043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pQueueFamilyProperties); 937143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 937243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 93735770f8ad21c40b2475201e73e9368a899b6886d0Petr KrausVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, 93745770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus uint32_t *pQueueFamilyPropertyCount, 9375bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkQueueFamilyProperties *pQueueFamilyProperties) { 937656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 93779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 937843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis assert(physical_device_state); 93795770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus std::unique_lock<std::mutex> lock(global_lock); 93805770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 93815770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus bool skip = PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_data, physical_device_state, 93825770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus pQueueFamilyPropertyCount, pQueueFamilyProperties); 93835770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 93845770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus lock.unlock(); 93855770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 93865770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus if (skip) return; 93875770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 93885770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, 93895770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus pQueueFamilyProperties); 93905770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 93915770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus lock.lock(); 93925770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus PostCallRecordGetPhysicalDeviceQueueFamilyProperties(physical_device_state, *pQueueFamilyPropertyCount, pQueueFamilyProperties); 939343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 939443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 939543947a6175e3e942e04d902f4d18928168e2d0dbTobin EhlisVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice, 939643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, 939743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 939856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 93999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 940043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis assert(physical_device_state); 94015770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus std::unique_lock<std::mutex> lock(global_lock); 94025770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 940343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_data, physical_device_state, 940443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyPropertyCount, pQueueFamilyProperties); 94055770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 94065770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus lock.unlock(); 94075770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 94085770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus if (skip) return; 94095770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 941043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount, 941143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyProperties); 94125770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus 94135770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus lock.lock(); 941443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(physical_device_state, *pQueueFamilyPropertyCount, 941543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyProperties); 9416cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski} 9417cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski 9418bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskitemplate <typename TCreateInfo, typename FPtr> 9419bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VkResult CreateSurface(VkInstance instance, TCreateInfo const *pCreateInfo, VkAllocationCallbacks const *pAllocator, 9420bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkSurfaceKHR *pSurface, FPtr fptr) { 942156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 9422747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 9423747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes // Call down the call chain: 9424747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes VkResult result = (instance_data->dispatch_table.*fptr)(instance, pCreateInfo, pAllocator, pSurface); 9425747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 9426747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (result == VK_SUCCESS) { 9427747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 9428747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->surface_map[*pSurface] = SURFACE_STATE(*pSurface); 9429747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes lock.unlock(); 9430747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 9431747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 9432747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return result; 9433747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 9434747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 9435747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR void VKAPI_CALL DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) { 94363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 943756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 9438747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 94399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(instance_data, surface); 9440747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 9441991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if ((surface_state) && (surface_state->swapchain)) { 9442991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 9443991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski HandleToUint64(instance), __LINE__, VALIDATION_ERROR_26c009e4, "DS", 9444991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski "vkDestroySurfaceKHR() called before its associated VkSwapchainKHR was destroyed. %s", 9445991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski validation_error_map[VALIDATION_ERROR_26c009e4]); 9446747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 9447991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski instance_data->surface_map.erase(surface); 9448747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes lock.unlock(); 94493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 9450747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->dispatch_table.DestroySurfaceKHR(instance, surface, pAllocator); 9451747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 9452747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 9453747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 94546f2ed666809272002a31b3b4f8adf6581cb41819Norbert NopperVKAPI_ATTR VkResult VKAPI_CALL CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo, 94556f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 94566f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateDisplayPlaneSurfaceKHR); 94576f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper} 94586f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper 9459747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR 9460747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo, 9461747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 9462747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateAndroidSurfaceKHR); 9463747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 9464cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_ANDROID_KHR 9465747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 9466747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR 9467747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo, 9468747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 9469747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateMirSurfaceKHR); 9470747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 9471f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9472f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice, 9473f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus uint32_t queueFamilyIndex, MirConnection *connection) { 9474f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus bool skip = false; 9475f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 9476f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9477f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus std::unique_lock<std::mutex> lock(global_lock); 9478f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice); 9479f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9480315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2d2009e2, 9481f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus "vkGetPhysicalDeviceMirPresentationSupportKHR", "queueFamilyIndex"); 9482f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9483f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus lock.unlock(); 9484f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9485f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus if (skip) return VK_FALSE; 9486f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9487f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus // Call down the call chain: 9488f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus VkBool32 result = 9489f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus instance_data->dispatch_table.GetPhysicalDeviceMirPresentationSupportKHR(physicalDevice, queueFamilyIndex, connection); 9490f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9491f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus return result; 9492f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus} 9493cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_MIR_KHR 9494747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 9495747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR 9496747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo, 9497747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 9498a9c6cc532ce0ef61d48d1419a96aae51b0e4c64aTobin Ehlis return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWaylandSurfaceKHR); 9499747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 9500f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9501f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice, 9502f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus uint32_t queueFamilyIndex, 9503f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus struct wl_display *display) { 9504f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus bool skip = false; 9505f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 9506f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9507f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus std::unique_lock<std::mutex> lock(global_lock); 9508f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice); 9509f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9510315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2f000a34, 9511f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus "vkGetPhysicalDeviceWaylandPresentationSupportKHR", "queueFamilyIndex"); 9512f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9513f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus lock.unlock(); 9514f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9515f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus if (skip) return VK_FALSE; 9516f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9517f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus // Call down the call chain: 9518f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus VkBool32 result = 9519f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus instance_data->dispatch_table.GetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex, display); 9520f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9521f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus return result; 9522f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus} 9523cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WAYLAND_KHR 9524747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 9525747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR 9526747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo, 9527747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 9528747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWin32SurfaceKHR); 9529747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 9530f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9531f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, 9532f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus uint32_t queueFamilyIndex) { 9533f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus bool skip = false; 9534f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 9535f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9536f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus std::unique_lock<std::mutex> lock(global_lock); 9537f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice); 9538f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9539315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2f200a3a, 9540f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus "vkGetPhysicalDeviceWin32PresentationSupportKHR", "queueFamilyIndex"); 9541f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9542f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus lock.unlock(); 9543f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9544f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus if (skip) return VK_FALSE; 9545f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9546f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus // Call down the call chain: 9547f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus VkBool32 result = instance_data->dispatch_table.GetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex); 9548f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9549f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus return result; 9550f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus} 9551cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WIN32_KHR 9552747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 9553747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR 9554747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo, 9555747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 9556747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXcbSurfaceKHR); 9557747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 9558f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9559f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice, 9560f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus uint32_t queueFamilyIndex, xcb_connection_t *connection, 9561f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus xcb_visualid_t visual_id) { 9562f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus bool skip = false; 9563f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 9564f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9565f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus std::unique_lock<std::mutex> lock(global_lock); 9566f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice); 9567f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9568315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2f400a40, 9569f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus "vkGetPhysicalDeviceXcbPresentationSupportKHR", "queueFamilyIndex"); 9570f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9571f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus lock.unlock(); 9572f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9573f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus if (skip) return VK_FALSE; 9574f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9575f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus // Call down the call chain: 9576f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus VkBool32 result = instance_data->dispatch_table.GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex, 9577f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus connection, visual_id); 9578f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9579f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus return result; 9580f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus} 9581cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XCB_KHR 9582747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 9583747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR 9584747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, 9585bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 9586747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXlibSurfaceKHR); 9587747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 9588f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9589f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice, 9590f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus uint32_t queueFamilyIndex, Display *dpy, 9591f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus VisualID visualID) { 9592f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus bool skip = false; 9593f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 9594f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9595f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus std::unique_lock<std::mutex> lock(global_lock); 9596f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice); 9597f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9598315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2f600a46, 9599f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus "vkGetPhysicalDeviceXlibPresentationSupportKHR", "queueFamilyIndex"); 9600f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9601f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus lock.unlock(); 9602f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9603f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus if (skip) return VK_FALSE; 9604f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9605f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus // Call down the call chain: 9606f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus VkBool32 result = 9607f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus instance_data->dispatch_table.GetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex, dpy, visualID); 9608f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9609f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus return result; 9610f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus} 9611cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XLIB_KHR 9612747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 961340921785005eb449ec7c18229f0d84c879708b8aChris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 961440921785005eb449ec7c18229f0d84c879708b8aChris Forbes VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) { 961556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 961640921785005eb449ec7c18229f0d84c879708b8aChris Forbes 961740921785005eb449ec7c18229f0d84c879708b8aChris Forbes std::unique_lock<std::mutex> lock(global_lock); 96189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 961940921785005eb449ec7c18229f0d84c879708b8aChris Forbes lock.unlock(); 962040921785005eb449ec7c18229f0d84c879708b8aChris Forbes 9621bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 9622bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities); 962340921785005eb449ec7c18229f0d84c879708b8aChris Forbes 962440921785005eb449ec7c18229f0d84c879708b8aChris Forbes if (result == VK_SUCCESS) { 962540921785005eb449ec7c18229f0d84c879708b8aChris Forbes physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState = QUERY_DETAILS; 962640921785005eb449ec7c18229f0d84c879708b8aChris Forbes physical_device_state->surfaceCapabilities = *pSurfaceCapabilities; 962740921785005eb449ec7c18229f0d84c879708b8aChris Forbes } 962840921785005eb449ec7c18229f0d84c879708b8aChris Forbes 962940921785005eb449ec7c18229f0d84c879708b8aChris Forbes return result; 963040921785005eb449ec7c18229f0d84c879708b8aChris Forbes} 963140921785005eb449ec7c18229f0d84c879708b8aChris Forbes 963235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardtstatic void PostCallRecordGetPhysicalDeviceSurfaceCapabilities2KHR(instance_layer_data *instanceData, 963335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt VkPhysicalDevice physicalDevice, 963435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt VkSurfaceCapabilities2KHR *pSurfaceCapabilities) { 963535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt std::unique_lock<std::mutex> lock(global_lock); 963635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt auto physicalDeviceState = GetPhysicalDeviceState(instanceData, physicalDevice); 963735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState = QUERY_DETAILS; 963835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->surfaceCapabilities = pSurfaceCapabilities->surfaceCapabilities; 963935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt} 964035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt 964135b630211642e709485879a2e8859736f0ab16a0Mike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice, 964235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 964335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt VkSurfaceCapabilities2KHR *pSurfaceCapabilities) { 964435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt auto instanceData = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 964535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt 964635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt auto result = 964735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt instanceData->dispatch_table.GetPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice, pSurfaceInfo, pSurfaceCapabilities); 964835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt 964935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt if (result == VK_SUCCESS) { 965035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt PostCallRecordGetPhysicalDeviceSurfaceCapabilities2KHR(instanceData, physicalDevice, pSurfaceCapabilities); 965135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt } 965235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt 965335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt return result; 965435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt} 965535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt 965635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardtstatic void PostCallRecordGetPhysicalDeviceSurfaceCapabilities2EXT(instance_layer_data *instanceData, 965735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt VkPhysicalDevice physicalDevice, 965835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt VkSurfaceCapabilities2EXT *pSurfaceCapabilities) { 965935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt std::unique_lock<std::mutex> lock(global_lock); 966035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt auto physicalDeviceState = GetPhysicalDeviceState(instanceData, physicalDevice); 966135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState = QUERY_DETAILS; 966235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->surfaceCapabilities.minImageCount = pSurfaceCapabilities->minImageCount; 966335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->surfaceCapabilities.maxImageCount = pSurfaceCapabilities->maxImageCount; 966435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->surfaceCapabilities.currentExtent = pSurfaceCapabilities->currentExtent; 966535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->surfaceCapabilities.minImageExtent = pSurfaceCapabilities->minImageExtent; 966635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->surfaceCapabilities.maxImageExtent = pSurfaceCapabilities->maxImageExtent; 966735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->surfaceCapabilities.maxImageArrayLayers = pSurfaceCapabilities->maxImageArrayLayers; 966835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->surfaceCapabilities.supportedTransforms = pSurfaceCapabilities->supportedTransforms; 966935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->surfaceCapabilities.currentTransform = pSurfaceCapabilities->currentTransform; 967035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->surfaceCapabilities.supportedCompositeAlpha = pSurfaceCapabilities->supportedCompositeAlpha; 967135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->surfaceCapabilities.supportedUsageFlags = pSurfaceCapabilities->supportedUsageFlags; 967235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt} 967335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt 967435b630211642e709485879a2e8859736f0ab16a0Mike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 967535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt VkSurfaceCapabilities2EXT *pSurfaceCapabilities) { 967635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt auto instanceData = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 967735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt 967835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt auto result = 967935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt instanceData->dispatch_table.GetPhysicalDeviceSurfaceCapabilities2EXT(physicalDevice, surface, pSurfaceCapabilities); 968035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt 968135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt if (result == VK_SUCCESS) { 968235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt PostCallRecordGetPhysicalDeviceSurfaceCapabilities2EXT(instanceData, physicalDevice, pSurfaceCapabilities); 968335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt } 968435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt 968535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt return result; 968635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt} 968735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt 9688418a8711f3301f3027a900bb45daaf0892f4e644Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, 9689418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes VkSurfaceKHR surface, VkBool32 *pSupported) { 9690f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus bool skip = false; 969156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 9692f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9693418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 9694f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice); 96959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(instance_data, surface); 9696f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9697315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2ee009ea, 9698f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus "vkGetPhysicalDeviceSurfaceSupportKHR", "queueFamilyIndex"); 9699f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9700418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes lock.unlock(); 9701418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 9702f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 9703f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus 9704bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 9705bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported); 9706418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 9707418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes if (result == VK_SUCCESS) { 97080bbc015828bdb99e85e6731ce92428557902701fPetr Kraus surface_state->gpu_queue_support[{physicalDevice, queueFamilyIndex}] = (*pSupported == VK_TRUE); 9709418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes } 9710418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 9711418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes return result; 9712418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes} 9713418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 97149e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 97159e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes uint32_t *pPresentModeCount, 97169e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes VkPresentModeKHR *pPresentModes) { 97173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 971856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 97199e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 97209e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes // TODO: this isn't quite right. available modes may differ by surface AND physical device. 97219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 9722bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState; 97239e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 97249e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pPresentModes) { 97259e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes // Compare the preliminary value of *pPresentModeCount with the value this time: 9726bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto prev_mode_count = (uint32_t)physical_device_state->present_modes.size(); 97279e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes switch (call_state) { 9728cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case UNCALLED: 97293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 9730bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 97319b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 9732cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfacePresentModesKHR() called with non-NULL pPresentModeCount; but no prior positive " 9733cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "value has been seen for pPresentModeCount."); 9734cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9735cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 9736cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // both query count and query details 9737cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (*pPresentModeCount != prev_mode_count) { 97383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 97399b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, HandleToUint64(physicalDevice), __LINE__, 97409b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus DEVLIMITS_COUNT_MISMATCH, "DL", 97413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkGetPhysicalDeviceSurfacePresentModesKHR() called with *pPresentModeCount (%u) that " 97423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "differs from the value " 97433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "(%u) that was returned when pPresentModes was NULL.", 97443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski *pPresentModeCount, prev_mode_count); 9745cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 9746cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 97479e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 97489e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 97499e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes lock.unlock(); 97509e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 97513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 97529e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 9753bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, 9754bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pPresentModes); 97559e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 97569e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (result == VK_SUCCESS || result == VK_INCOMPLETE) { 97579e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes lock.lock(); 97589e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 97599e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (*pPresentModeCount) { 9760cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_COUNT) call_state = QUERY_COUNT; 97619e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (*pPresentModeCount > physical_device_state->present_modes.size()) 97629e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes physical_device_state->present_modes.resize(*pPresentModeCount); 97639e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 97649e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pPresentModes) { 9765cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS; 97669e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes for (uint32_t i = 0; i < *pPresentModeCount; i++) { 97679e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes physical_device_state->present_modes[i] = pPresentModes[i]; 97689e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 97699e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 97705faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 97715faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 97725faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return result; 97735faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes} 97745faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 97755faa662f6859b01c72d79027abde363d5f10dcd7Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 97765faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes uint32_t *pSurfaceFormatCount, 97775faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes VkSurfaceFormatKHR *pSurfaceFormats) { 97783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 977956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 97805faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 97819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 9782bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState; 97835faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 97845faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pSurfaceFormats) { 9785bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto prev_format_count = (uint32_t)physical_device_state->surface_formats.size(); 97865faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 97875faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes switch (call_state) { 9788cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case UNCALLED: 9789cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Since we haven't recorded a preliminary value of *pSurfaceFormatCount, that likely means that the application 9790cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // didn't 9791cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // previously call this function with a NULL value of pSurfaceFormats: 97923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 9793bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 97949b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 9795cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount; but no prior positive " 9796cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "value has been seen for pSurfaceFormats."); 9797cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9798cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 9799cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (prev_format_count != *pSurfaceFormatCount) { 98003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 9801cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 98029b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, HandleToUint64(physicalDevice), __LINE__, 9803cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DEVLIMITS_COUNT_MISMATCH, "DL", 9804cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount, and with pSurfaceFormats " 9805cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "set " 9806cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "to " 9807cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "a value (%u) that is greater than the value (%u) that was returned when pSurfaceFormatCount was NULL.", 9808cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski *pSurfaceFormatCount, prev_format_count); 9809cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 9810cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 98119e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 98129e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 98135faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes lock.unlock(); 98145faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 98153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 98169e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 98175faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes // Call down the call chain: 98185faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, 98195faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes pSurfaceFormats); 98205faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 98215faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (result == VK_SUCCESS || result == VK_INCOMPLETE) { 98225faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes lock.lock(); 98235faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 98245faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (*pSurfaceFormatCount) { 9825cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_COUNT) call_state = QUERY_COUNT; 98265faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (*pSurfaceFormatCount > physical_device_state->surface_formats.size()) 98275faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes physical_device_state->surface_formats.resize(*pSurfaceFormatCount); 98285faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 98295faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pSurfaceFormats) { 9830cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS; 98315faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) { 98325faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes physical_device_state->surface_formats[i] = pSurfaceFormats[i]; 98335faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 98345faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 98355faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 98369e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return result; 98379e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes} 98389e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 983935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardtstatic void PostCallRecordGetPhysicalDeviceSurfaceFormats2KHR(instance_layer_data *instanceData, VkPhysicalDevice physicalDevice, 984035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt uint32_t *pSurfaceFormatCount, VkSurfaceFormat2KHR *pSurfaceFormats) { 984135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt std::unique_lock<std::mutex> lock(global_lock); 984235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt auto physicalDeviceState = GetPhysicalDeviceState(instanceData, physicalDevice); 984335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt if (*pSurfaceFormatCount) { 984435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt if (physicalDeviceState->vkGetPhysicalDeviceSurfaceFormatsKHRState < QUERY_COUNT) { 984535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->vkGetPhysicalDeviceSurfaceFormatsKHRState = QUERY_COUNT; 984635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt } 984735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt if (*pSurfaceFormatCount > physicalDeviceState->surface_formats.size()) 984835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->surface_formats.resize(*pSurfaceFormatCount); 984935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt } 985035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt if (pSurfaceFormats) { 985135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt if (physicalDeviceState->vkGetPhysicalDeviceSurfaceFormatsKHRState < QUERY_DETAILS) { 985235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->vkGetPhysicalDeviceSurfaceFormatsKHRState = QUERY_DETAILS; 985335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt } 985435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) { 985535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt physicalDeviceState->surface_formats[i] = pSurfaceFormats[i].surfaceFormat; 985635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt } 985735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt } 985835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt} 985935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt 986035b630211642e709485879a2e8859736f0ab16a0Mike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice, 986135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 986235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt uint32_t *pSurfaceFormatCount, 986335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt VkSurfaceFormat2KHR *pSurfaceFormats) { 986435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt auto instanceData = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 986535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt auto result = instanceData->dispatch_table.GetPhysicalDeviceSurfaceFormats2KHR(physicalDevice, pSurfaceInfo, 986635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt pSurfaceFormatCount, pSurfaceFormats); 986735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt if (result == VK_SUCCESS || result == VK_INCOMPLETE) { 986835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt PostCallRecordGetPhysicalDeviceSurfaceFormats2KHR(instanceData, physicalDevice, pSurfaceFormatCount, pSurfaceFormats); 986935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt } 987035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt return result; 987135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt} 987235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt 9873bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance, 9874bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 9875bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 9876bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportCallbackEXT *pMsgCallback) { 987756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 98789172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes VkResult res = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); 98795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == res) { 9880b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 98818860b85a52096f9f9b28616bc37feed505497a54Chris Forbes res = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); 98825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return res; 98845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 98855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9886bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, 988789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator) { 988856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 98899172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); 9890b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 98918860b85a52096f9f9b28616bc37feed505497a54Chris Forbes layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator); 98925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 98935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9894bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, 9895bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, 9896bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { 989756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 98989172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); 98995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 99005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9901bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { 9902a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetLayerProperties(1, &global_layer, pCount, pProperties); 9903a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 9904a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 9905bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 9906bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 9907a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetLayerProperties(1, &global_layer, pCount, pProperties); 9908a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 9909a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 9910bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, 9911bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkExtensionProperties *pProperties) { 9912a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) 9913a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties); 9914a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 9915a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return VK_ERROR_LAYER_NOT_PRESENT; 9916a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 9917a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 9918bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, 9919bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t *pCount, VkExtensionProperties *pProperties) { 9920cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties); 9921a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu 9922a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu assert(physicalDevice); 9923a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu 992456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 99259172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes return instance_data->dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties); 992608939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 992708939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 9928582b6ed09649188d55ed3b6237352caf9f3384a9Mike WeiblenVKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDeviceGroupsKHX( 9929582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen VkInstance instance, uint32_t *pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupPropertiesKHX *pPhysicalDeviceGroupProperties) { 99303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 9931582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 9932582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen 9933582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen if (instance_data) { 9934582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // For this instance, flag when EnumeratePhysicalDeviceGroupsKHX goes to QUERY_COUNT and then QUERY_DETAILS. 9935582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen if (NULL == pPhysicalDeviceGroupProperties) { 9936582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_data->vkEnumeratePhysicalDeviceGroupsState = QUERY_COUNT; 9937582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } else { 9938582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen if (UNCALLED == instance_data->vkEnumeratePhysicalDeviceGroupsState) { 9939582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // Flag warning here. You can call this without having queried the count, but it may not be 9940582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // robust on platforms with multiple physical devices. 99413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 99423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL", 99433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Call sequence has vkEnumeratePhysicalDeviceGroupsKHX() w/ non-NULL " 99443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "pPhysicalDeviceGroupProperties. You should first " 99453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "call vkEnumeratePhysicalDeviceGroupsKHX() w/ NULL pPhysicalDeviceGroupProperties to query " 99463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "pPhysicalDeviceGroupCount."); 9947582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state 9948582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen else if (instance_data->physical_device_groups_count != *pPhysicalDeviceGroupCount) { 9949582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // Having actual count match count from app is not a requirement, so this can be a warning 99503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 9951582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 99523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 99533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Call to vkEnumeratePhysicalDeviceGroupsKHX() w/ pPhysicalDeviceGroupCount value %u, but actual count " 99543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "supported by this instance is %u.", 99553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski *pPhysicalDeviceGroupCount, instance_data->physical_device_groups_count); 9956582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 9957582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_data->vkEnumeratePhysicalDeviceGroupsState = QUERY_DETAILS; 9958582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 99593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 9960582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen return VK_ERROR_VALIDATION_FAILED_EXT; 9961582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 9962582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen VkResult result = instance_data->dispatch_table.EnumeratePhysicalDeviceGroupsKHX(instance, pPhysicalDeviceGroupCount, 9963582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen pPhysicalDeviceGroupProperties); 9964582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen if (NULL == pPhysicalDeviceGroupProperties) { 9965582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_data->physical_device_groups_count = *pPhysicalDeviceGroupCount; 9966582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } else if (result == VK_SUCCESS) { // Save physical devices 9967582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen for (uint32_t i = 0; i < *pPhysicalDeviceGroupCount; i++) { 9968582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen for (uint32_t j = 0; j < pPhysicalDeviceGroupProperties[i].physicalDeviceCount; j++) { 9969582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen VkPhysicalDevice cur_phys_dev = pPhysicalDeviceGroupProperties[i].physicalDevices[j]; 9970582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen auto &phys_device_state = instance_data->physical_device_map[cur_phys_dev]; 9971582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen phys_device_state.phys_device = cur_phys_dev; 9972582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // Init actual features for each physical device 9973582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_data->dispatch_table.GetPhysicalDeviceFeatures(cur_phys_dev, &phys_device_state.features); 9974582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 9975582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 9976582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 9977582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen return result; 9978582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } else { 9979582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__, 99809b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus DEVLIMITS_INVALID_INSTANCE, "DL", 99819b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus "Invalid instance (0x%" PRIxLEAST64 ") passed into vkEnumeratePhysicalDeviceGroupsKHX().", 99829b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus HandleToUint64(instance)); 9983582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 9984582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen return VK_ERROR_VALIDATION_FAILED_EXT; 9985582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen} 9986582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen 99876246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorUpdateTemplateKHR(VkDevice device, 99886246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const VkDescriptorUpdateTemplateCreateInfoKHR *pCreateInfo, 99896246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const VkAllocationCallbacks *pAllocator, 99906246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkDescriptorUpdateTemplateKHR *pDescriptorUpdateTemplate) { 99916246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 9992a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski VkResult result = 9993a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski dev_data->dispatch_table.CreateDescriptorUpdateTemplateKHR(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate); 99946246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski if (VK_SUCCESS == result) { 99956246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 99966246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski // Shadow template createInfo for later updates 9997a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski safe_VkDescriptorUpdateTemplateCreateInfoKHR *local_create_info = 9998a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski new safe_VkDescriptorUpdateTemplateCreateInfoKHR(pCreateInfo); 99996246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski std::unique_ptr<TEMPLATE_STATE> template_state(new TEMPLATE_STATE(*pDescriptorUpdateTemplate, local_create_info)); 100006246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->desc_template_map[*pDescriptorUpdateTemplate] = std::move(template_state); 100016246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski } 100026246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski return result; 100036246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 100046246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 100056246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorUpdateTemplateKHR(VkDevice device, 100066246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, 100076246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 100086246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 100096246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 100106246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->desc_template_map.erase(descriptorUpdateTemplate); 100116246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski lock.unlock(); 100126246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->dispatch_table.DestroyDescriptorUpdateTemplateKHR(device, descriptorUpdateTemplate, pAllocator); 100136246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 100146246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 1001525f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSetsWithTemplate() 1001625f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinskistatic void PostCallRecordUpdateDescriptorSetWithTemplateKHR(layer_data *device_data, VkDescriptorSet descriptorSet, 1001725f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, 1001825f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski const void *pData) { 1001967fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski auto const template_map_entry = device_data->desc_template_map.find(descriptorUpdateTemplate); 1002067fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski if (template_map_entry == device_data->desc_template_map.end()) { 1002167fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski assert(0); 1002267fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski } 1002367fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski 1002425f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski cvdescriptorset::PerformUpdateDescriptorSetsWithTemplateKHR(device_data, descriptorSet, template_map_entry->second, pData); 1002567fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski} 1002667fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski 100276246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL UpdateDescriptorSetWithTemplateKHR(VkDevice device, VkDescriptorSet descriptorSet, 100286246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, 100296246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const void *pData) { 1003067fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 1003167fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski device_data->dispatch_table.UpdateDescriptorSetWithTemplateKHR(device, descriptorSet, descriptorUpdateTemplate, pData); 1003267fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski 1003367fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski PostCallRecordUpdateDescriptorSetWithTemplateKHR(device_data, descriptorSet, descriptorUpdateTemplate, pData); 100346246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 100356246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 100366246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPushDescriptorSetWithTemplateKHR(VkCommandBuffer commandBuffer, 100376246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, 100386246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkPipelineLayout layout, uint32_t set, const void *pData) { 100396246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 100406246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->dispatch_table.CmdPushDescriptorSetWithTemplateKHR(commandBuffer, descriptorUpdateTemplate, layout, set, pData); 100416246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 100426246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 10043991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic void PostCallRecordGetPhysicalDeviceDisplayPlanePropertiesKHR(instance_layer_data *instanceData, 10044991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, 10045991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski VkDisplayPlanePropertiesKHR *pProperties) { 10046991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 10047991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski auto physical_device_state = GetPhysicalDeviceState(instanceData, physicalDevice); 10048991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 10049991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (*pPropertyCount) { 10050991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState < QUERY_COUNT) { 10051991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState = QUERY_COUNT; 10052991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 10053991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski physical_device_state->display_plane_property_count = *pPropertyCount; 10054991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 10055991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (pProperties) { 10056991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState < QUERY_DETAILS) { 10057991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState = QUERY_DETAILS; 10058991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 10059991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 10060991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski} 10061991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 10062991f2555bc4f571e30b584937c7959805dff67c6Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, 10063991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski VkDisplayPlanePropertiesKHR *pProperties) { 10064991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski VkResult result = VK_SUCCESS; 10065991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 10066991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 10067991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski result = instance_data->dispatch_table.GetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, pPropertyCount, pProperties); 10068991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 10069991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (result == VK_SUCCESS || result == VK_INCOMPLETE) { 10070991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski PostCallRecordGetPhysicalDeviceDisplayPlanePropertiesKHR(instance_data, physicalDevice, pPropertyCount, pProperties); 10071991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 10072991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 10073991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski return result; 10074991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski} 10075991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 10076991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic bool ValidateGetPhysicalDeviceDisplayPlanePropertiesKHRQuery(instance_layer_data *instance_data, 10077991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski VkPhysicalDevice physicalDevice, uint32_t planeIndex, 10078991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski const char *api_name) { 10079991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski bool skip = false; 10080991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 10081991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState == UNCALLED) { 10082991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski skip |= log_msg( 10083991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 10084991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski HandleToUint64(physicalDevice), __LINE__, SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY, "DL", 10085991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski "Potential problem with calling %s() without first querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.", api_name); 10086991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } else { 10087991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (planeIndex >= physical_device_state->display_plane_property_count) { 10088991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski skip |= log_msg( 10089991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 10090991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski HandleToUint64(physicalDevice), __LINE__, VALIDATION_ERROR_29c009c2, "DL", 10091991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski "%s(): planeIndex must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. " 10092991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski "Do you have the plane index hardcoded? %s", 10093991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski api_name, physical_device_state->display_plane_property_count - 1, validation_error_map[VALIDATION_ERROR_29c009c2]); 10094991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 10095991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 10096991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski return skip; 10097991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski} 10098991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 10099991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic bool PreCallValidateGetDisplayPlaneSupportedDisplaysKHR(instance_layer_data *instance_data, VkPhysicalDevice physicalDevice, 10100991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski uint32_t planeIndex) { 10101991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski bool skip = false; 10102991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 10103991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski skip |= ValidateGetPhysicalDeviceDisplayPlanePropertiesKHRQuery(instance_data, physicalDevice, planeIndex, 10104991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski "vkGetDisplayPlaneSupportedDisplaysKHR"); 10105991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski return skip; 10106991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski} 10107991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 10108991f2555bc4f571e30b584937c7959805dff67c6Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex, 10109991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski uint32_t *pDisplayCount, VkDisplayKHR *pDisplays) { 10110991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 10111991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 10112991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski bool skip = PreCallValidateGetDisplayPlaneSupportedDisplaysKHR(instance_data, physicalDevice, planeIndex); 10113991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (!skip) { 10114991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski result = 10115991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski instance_data->dispatch_table.GetDisplayPlaneSupportedDisplaysKHR(physicalDevice, planeIndex, pDisplayCount, pDisplays); 10116991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 10117991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski return result; 10118991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski} 10119991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 10120991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic bool PreCallValidateGetDisplayPlaneCapabilitiesKHR(instance_layer_data *instance_data, VkPhysicalDevice physicalDevice, 10121991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski uint32_t planeIndex) { 10122991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski bool skip = false; 10123991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 10124991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski skip |= ValidateGetPhysicalDeviceDisplayPlanePropertiesKHRQuery(instance_data, physicalDevice, planeIndex, 10125991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski "vkGetDisplayPlaneCapabilitiesKHR"); 10126991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski return skip; 10127991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski} 10128991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 10129991f2555bc4f571e30b584937c7959805dff67c6Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, 10130991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR *pCapabilities) { 10131991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 10132991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 10133991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski bool skip = PreCallValidateGetDisplayPlaneCapabilitiesKHR(instance_data, physicalDevice, planeIndex); 10134991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 10135991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski if (!skip) { 10136991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski result = instance_data->dispatch_table.GetDisplayPlaneCapabilitiesKHR(physicalDevice, mode, planeIndex, pCapabilities); 10137991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski } 10138991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 10139991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski return result; 10140991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski} 10141991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski 101423616276bb0053c612c0a8d223e81ae3808b1b2c4Mark LobodzinskiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName); 101433616276bb0053c612c0a8d223e81ae3808b1b2c4Mark LobodzinskiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName); 101443616276bb0053c612c0a8d223e81ae3808b1b2c4Mark LobodzinskiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName); 101453616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski 101463616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski// Map of all APIs to be intercepted by this layer 101473616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinskistatic const std::unordered_map<std::string, void*> name_to_funcptr_map = { 101483616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetInstanceProcAddr", (void*)GetInstanceProcAddr}, 101493616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vk_layerGetPhysicalDeviceProcAddr", (void*)GetPhysicalDeviceProcAddr}, 101503616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetDeviceProcAddr", (void*)GetDeviceProcAddr}, 101513616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateInstance", (void*)CreateInstance}, 101523616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateDevice", (void*)CreateDevice}, 101533616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkEnumeratePhysicalDevices", (void*)EnumeratePhysicalDevices}, 101543616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceQueueFamilyProperties", (void*)GetPhysicalDeviceQueueFamilyProperties}, 101553616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyInstance", (void*)DestroyInstance}, 101563616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkEnumerateInstanceLayerProperties", (void*)EnumerateInstanceLayerProperties}, 101573616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkEnumerateDeviceLayerProperties", (void*)EnumerateDeviceLayerProperties}, 101583616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkEnumerateInstanceExtensionProperties", (void*)EnumerateInstanceExtensionProperties}, 101593616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkEnumerateDeviceExtensionProperties", (void*)EnumerateDeviceExtensionProperties}, 101603616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateDescriptorUpdateTemplateKHR", (void*)CreateDescriptorUpdateTemplateKHR}, 101613616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyDescriptorUpdateTemplateKHR", (void*)DestroyDescriptorUpdateTemplateKHR}, 101623616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkUpdateDescriptorSetWithTemplateKHR", (void*)UpdateDescriptorSetWithTemplateKHR}, 101633616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdPushDescriptorSetWithTemplateKHR", (void*)CmdPushDescriptorSetWithTemplateKHR}, 101643616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateSwapchainKHR", (void*)CreateSwapchainKHR}, 101653616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroySwapchainKHR", (void*)DestroySwapchainKHR}, 101663616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetSwapchainImagesKHR", (void*)GetSwapchainImagesKHR}, 101673616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkAcquireNextImageKHR", (void*)AcquireNextImageKHR}, 101683616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkQueuePresentKHR", (void*)QueuePresentKHR}, 101693616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkQueueSubmit", (void*)QueueSubmit}, 101703616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkWaitForFences", (void*)WaitForFences}, 101713616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetFenceStatus", (void*)GetFenceStatus}, 101723616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkQueueWaitIdle", (void*)QueueWaitIdle}, 101733616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDeviceWaitIdle", (void*)DeviceWaitIdle}, 101743616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetDeviceQueue", (void*)GetDeviceQueue}, 101753616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyDevice", (void*)DestroyDevice}, 101763616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyFence", (void*)DestroyFence}, 101773616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkResetFences", (void*)ResetFences}, 101783616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroySemaphore", (void*)DestroySemaphore}, 101793616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyEvent", (void*)DestroyEvent}, 101803616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyQueryPool", (void*)DestroyQueryPool}, 101813616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyBuffer", (void*)DestroyBuffer}, 101823616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyBufferView", (void*)DestroyBufferView}, 101833616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyImage", (void*)DestroyImage}, 101843616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyImageView", (void*)DestroyImageView}, 101853616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyShaderModule", (void*)DestroyShaderModule}, 101863616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyPipeline", (void*)DestroyPipeline}, 101873616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyPipelineLayout", (void*)DestroyPipelineLayout}, 101883616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroySampler", (void*)DestroySampler}, 101893616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyDescriptorSetLayout", (void*)DestroyDescriptorSetLayout}, 101903616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyDescriptorPool", (void*)DestroyDescriptorPool}, 101913616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyFramebuffer", (void*)DestroyFramebuffer}, 101923616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyRenderPass", (void*)DestroyRenderPass}, 101933616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateBuffer", (void*)CreateBuffer}, 101943616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateBufferView", (void*)CreateBufferView}, 101953616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateImage", (void*)CreateImage}, 101963616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateImageView", (void*)CreateImageView}, 101973616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateFence", (void*)CreateFence}, 101983616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreatePipelineCache", (void*)CreatePipelineCache}, 101993616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyPipelineCache", (void*)DestroyPipelineCache}, 102003616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPipelineCacheData", (void*)GetPipelineCacheData}, 102013616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkMergePipelineCaches", (void*)MergePipelineCaches}, 102023616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateGraphicsPipelines", (void*)CreateGraphicsPipelines}, 102033616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateComputePipelines", (void*)CreateComputePipelines}, 102043616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateSampler", (void*)CreateSampler}, 102053616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateDescriptorSetLayout", (void*)CreateDescriptorSetLayout}, 102063616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreatePipelineLayout", (void*)CreatePipelineLayout}, 102073616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateDescriptorPool", (void*)CreateDescriptorPool}, 102083616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkResetDescriptorPool", (void*)ResetDescriptorPool}, 102093616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkAllocateDescriptorSets", (void*)AllocateDescriptorSets}, 102103616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkFreeDescriptorSets", (void*)FreeDescriptorSets}, 102113616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkUpdateDescriptorSets", (void*)UpdateDescriptorSets}, 102123616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateCommandPool", (void*)CreateCommandPool}, 102133616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyCommandPool", (void*)DestroyCommandPool}, 102143616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkResetCommandPool", (void*)ResetCommandPool}, 102153616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateQueryPool", (void*)CreateQueryPool}, 102163616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkAllocateCommandBuffers", (void*)AllocateCommandBuffers}, 102173616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkFreeCommandBuffers", (void*)FreeCommandBuffers}, 102183616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkBeginCommandBuffer", (void*)BeginCommandBuffer}, 102193616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkEndCommandBuffer", (void*)EndCommandBuffer}, 102203616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkResetCommandBuffer", (void*)ResetCommandBuffer}, 102213616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdBindPipeline", (void*)CmdBindPipeline}, 102223616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdSetViewport", (void*)CmdSetViewport}, 102233616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdSetScissor", (void*)CmdSetScissor}, 102243616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdSetLineWidth", (void*)CmdSetLineWidth}, 102253616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdSetDepthBias", (void*)CmdSetDepthBias}, 102263616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdSetBlendConstants", (void*)CmdSetBlendConstants}, 102273616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdSetDepthBounds", (void*)CmdSetDepthBounds}, 102283616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdSetStencilCompareMask", (void*)CmdSetStencilCompareMask}, 102293616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdSetStencilWriteMask", (void*)CmdSetStencilWriteMask}, 102303616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdSetStencilReference", (void*)CmdSetStencilReference}, 102313616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdBindDescriptorSets", (void*)CmdBindDescriptorSets}, 102323616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdBindVertexBuffers", (void*)CmdBindVertexBuffers}, 102333616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdBindIndexBuffer", (void*)CmdBindIndexBuffer}, 102343616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdDraw", (void*)CmdDraw}, 102353616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdDrawIndexed", (void*)CmdDrawIndexed}, 102363616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdDrawIndirect", (void*)CmdDrawIndirect}, 102373616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdDrawIndexedIndirect", (void*)CmdDrawIndexedIndirect}, 102383616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdDispatch", (void*)CmdDispatch}, 102393616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdDispatchIndirect", (void*)CmdDispatchIndirect}, 102403616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdCopyBuffer", (void*)CmdCopyBuffer}, 102413616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdCopyImage", (void*)CmdCopyImage}, 102423616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdBlitImage", (void*)CmdBlitImage}, 102433616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdCopyBufferToImage", (void*)CmdCopyBufferToImage}, 102443616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdCopyImageToBuffer", (void*)CmdCopyImageToBuffer}, 102453616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdUpdateBuffer", (void*)CmdUpdateBuffer}, 102463616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdFillBuffer", (void*)CmdFillBuffer}, 102473616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdClearColorImage", (void*)CmdClearColorImage}, 102483616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdClearDepthStencilImage", (void*)CmdClearDepthStencilImage}, 102493616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdClearAttachments", (void*)CmdClearAttachments}, 102503616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdResolveImage", (void*)CmdResolveImage}, 102513616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetImageSubresourceLayout", (void*)GetImageSubresourceLayout}, 102523616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdSetEvent", (void*)CmdSetEvent}, 102533616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdResetEvent", (void*)CmdResetEvent}, 102543616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdWaitEvents", (void*)CmdWaitEvents}, 102553616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdPipelineBarrier", (void*)CmdPipelineBarrier}, 102563616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdBeginQuery", (void*)CmdBeginQuery}, 102573616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdEndQuery", (void*)CmdEndQuery}, 102583616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdResetQueryPool", (void*)CmdResetQueryPool}, 102593616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdCopyQueryPoolResults", (void*)CmdCopyQueryPoolResults}, 102603616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdPushConstants", (void*)CmdPushConstants}, 102613616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdWriteTimestamp", (void*)CmdWriteTimestamp}, 102623616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateFramebuffer", (void*)CreateFramebuffer}, 102633616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateShaderModule", (void*)CreateShaderModule}, 102643616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateRenderPass", (void*)CreateRenderPass}, 102653616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdBeginRenderPass", (void*)CmdBeginRenderPass}, 102663616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdNextSubpass", (void*)CmdNextSubpass}, 102673616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdEndRenderPass", (void*)CmdEndRenderPass}, 102683616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCmdExecuteCommands", (void*)CmdExecuteCommands}, 102693616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkSetEvent", (void*)SetEvent}, 102703616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkMapMemory", (void*)MapMemory}, 102713616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkUnmapMemory", (void*)UnmapMemory}, 102723616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkFlushMappedMemoryRanges", (void*)FlushMappedMemoryRanges}, 102733616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkInvalidateMappedMemoryRanges", (void*)InvalidateMappedMemoryRanges}, 102743616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkAllocateMemory", (void*)AllocateMemory}, 102753616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkFreeMemory", (void*)FreeMemory}, 102763616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkBindBufferMemory", (void*)BindBufferMemory}, 102773616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetBufferMemoryRequirements", (void*)GetBufferMemoryRequirements}, 102783616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetImageMemoryRequirements", (void*)GetImageMemoryRequirements}, 102793616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetQueryPoolResults", (void*)GetQueryPoolResults}, 102803616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkBindImageMemory", (void*)BindImageMemory}, 102813616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkQueueBindSparse", (void*)QueueBindSparse}, 102823616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateSemaphore", (void*)CreateSemaphore}, 102833616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateEvent", (void*)CreateEvent}, 102843616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_ANDROID_KHR 102853616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateAndroidSurfaceKHR", (void*)CreateAndroidSurfaceKHR}, 102863616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif 102873616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_MIR_KHR 102883616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateMirSurfaceKHR", (void*)CreateMirSurfaceKHR}, 102893616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceMirPresentationSupportKHR", (void*)GetPhysicalDeviceMirPresentationSupportKHR}, 102903616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif 102913616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_WAYLAND_KHR 102923616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateWaylandSurfaceKHR", (void*)CreateWaylandSurfaceKHR}, 102933616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceWaylandPresentationSupportKHR", (void*)GetPhysicalDeviceWaylandPresentationSupportKHR}, 102943616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif 102953616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_WIN32_KHR 102963616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateWin32SurfaceKHR", (void*)CreateWin32SurfaceKHR}, 102973616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceWin32PresentationSupportKHR", (void*)GetPhysicalDeviceWin32PresentationSupportKHR}, 102983616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif 102993616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_XCB_KHR 103003616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateXcbSurfaceKHR", (void*)CreateXcbSurfaceKHR}, 103013616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceXcbPresentationSupportKHR", (void*)GetPhysicalDeviceXcbPresentationSupportKHR}, 103023616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif 103033616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_XLIB_KHR 103043616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateXlibSurfaceKHR", (void*)CreateXlibSurfaceKHR}, 103053616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceXlibPresentationSupportKHR", (void*)GetPhysicalDeviceXlibPresentationSupportKHR}, 103063616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif 103073616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateDisplayPlaneSurfaceKHR", (void*)CreateDisplayPlaneSurfaceKHR}, 103083616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroySurfaceKHR", (void*)DestroySurfaceKHR}, 103093616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", (void*)GetPhysicalDeviceSurfaceCapabilitiesKHR}, 103103616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceSurfaceCapabilities2KHR", (void*)GetPhysicalDeviceSurfaceCapabilities2KHR}, 103113616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceSurfaceCapabilities2EXT", (void*)GetPhysicalDeviceSurfaceCapabilities2EXT}, 103123616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceSurfaceSupportKHR", (void*)GetPhysicalDeviceSurfaceSupportKHR}, 103133616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceSurfacePresentModesKHR", (void*)GetPhysicalDeviceSurfacePresentModesKHR}, 103143616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceSurfaceFormatsKHR", (void*)GetPhysicalDeviceSurfaceFormatsKHR}, 103153616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceSurfaceFormats2KHR", (void*)GetPhysicalDeviceSurfaceFormats2KHR}, 103163616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkGetPhysicalDeviceQueueFamilyProperties2KHR", (void*)GetPhysicalDeviceQueueFamilyProperties2KHR}, 103173616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkEnumeratePhysicalDeviceGroupsKHX", (void*)EnumeratePhysicalDeviceGroupsKHX}, 103183616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkCreateDebugReportCallbackEXT", (void*)CreateDebugReportCallbackEXT}, 103193616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDestroyDebugReportCallbackEXT", (void*)DestroyDebugReportCallbackEXT}, 103203616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski {"vkDebugReportMessageEXT", (void*)DebugReportMessageEXT}, 10321991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski {"vkGetPhysicalDeviceDisplayPlanePropertiesKHR", (void*)GetPhysicalDeviceDisplayPlanePropertiesKHR}, 10322991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski {"GetDisplayPlaneSupportedDisplaysKHR", (void*)GetDisplayPlaneSupportedDisplaysKHR}, 10323991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski {"GetDisplayPlaneCapabilitiesKHR", (void*)GetDisplayPlaneCapabilitiesKHR}, 103243616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski}; 10325b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 103263616276bb0053c612c0a8d223e81ae3808b1b2c4Mark LobodzinskiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) { 103273616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski assert(device); 103283616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 103295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 103303616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski // Is API to be intercepted by this layer? 103313616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski const auto &item = name_to_funcptr_map.find(funcName); 103323616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski if (item != name_to_funcptr_map.end()) { 103333616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski return reinterpret_cast<PFN_vkVoidFunction>(item->second); 103343616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski } 1033509a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 103363616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski auto &table = device_data->dispatch_table; 10337cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetDeviceProcAddr) return nullptr; 103383616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski return table.GetDeviceProcAddr(device, funcName); 103395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 103405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1034189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) { 103423616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski instance_layer_data *instance_data; 103433616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski // Is API to be intercepted by this layer? 103443616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski const auto &item = name_to_funcptr_map.find(funcName); 103453616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski if (item != name_to_funcptr_map.end()) { 103463616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski return reinterpret_cast<PFN_vkVoidFunction>(item->second); 103473616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski } 10348b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 103493616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 103504a0754042cf090e131e9e769d8a3633c228625beChris Forbes auto &table = instance_data->dispatch_table; 10351cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetInstanceProcAddr) return nullptr; 103524a0754042cf090e131e9e769d8a3633c228625beChris Forbes return table.GetInstanceProcAddr(instance, funcName); 103535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 1035408939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 10355b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) { 10356b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(instance); 1035756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 10358b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 10359b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young auto &table = instance_data->dispatch_table; 10360cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetPhysicalDeviceProcAddr) return nullptr; 10361b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return table.GetPhysicalDeviceProcAddr(instance, funcName); 10362b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 10363b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 10364cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski} // namespace core_validation 10365d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 10366a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu// loader-layer interface v0, just wrappers since there is only a layer 10367d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 10368bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, 10369bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkExtensionProperties *pProperties) { 10370a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties); 1037108939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1037208939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 10373bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, 10374bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 10375a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateInstanceLayerProperties(pCount, pProperties); 1037608939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1037708939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 10378bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 10379bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 10380a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu // the layer command handles VK_NULL_HANDLE just fine internally 10381a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu assert(physicalDevice == VK_NULL_HANDLE); 10382a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties); 10383d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 10384d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 10385d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 10386d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu const char *pLayerName, uint32_t *pCount, 10387d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu VkExtensionProperties *pProperties) { 10388a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu // the layer command handles VK_NULL_HANDLE just fine internally 10389a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu assert(physicalDevice == VK_NULL_HANDLE); 10390a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu return core_validation::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties); 10391d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 10392d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 10393d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) { 1039489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::GetDeviceProcAddr(dev, funcName); 10395d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 10396d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 10397d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { 1039889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::GetInstanceProcAddr(instance, funcName); 1039908939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 10400b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 10401bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance, 10402bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const char *funcName) { 10403b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return core_validation::GetPhysicalDeviceProcAddr(instance, funcName); 10404b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 10405b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 10406b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) { 10407b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(pVersionStruct != NULL); 10408b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT); 10409b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 10410b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young // Fill in the function pointers if our version is at least capable of having the structure contain them. 10411b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young if (pVersionStruct->loaderLayerInterfaceVersion >= 2) { 10412b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr; 10413b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr; 10414b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr; 10415b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } 10416b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 10417b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young if (pVersionStruct->loaderLayerInterfaceVersion < CURRENT_LOADER_LAYER_INTERFACE_VERSION) { 10418b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young core_validation::loader_layer_if_version = pVersionStruct->loaderLayerInterfaceVersion; 10419b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } else if (pVersionStruct->loaderLayerInterfaceVersion > CURRENT_LOADER_LAYER_INTERFACE_VERSION) { 10420b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION; 10421b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } 10422b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 10423b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return VK_SUCCESS; 10424b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 10425