111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Copyright (c) 2015-2016 The Khronos Group Inc. 211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (c) 2015-2016 Valve Corporation 311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (c) 2015-2016 LunarG, Inc. 411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (C) 2015-2016 Google Inc. 511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * 611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Licensed under the Apache License, Version 2.0 (the "License"); 711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * you may not use this file except in compliance with the License. 811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * You may obtain a copy of the License at 911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * 1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * http://www.apache.org/licenses/LICENSE-2.0 1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * 1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Unless required by applicable law or agreed to in writing, software 1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * distributed under the License is distributed on an "AS IS" BASIS, 1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * See the License for the specific language governing permissions and 1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * limitations under the License. 1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * 1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Cody Northrop <cnorthrop@google.com> 1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Michael Lentine <mlentine@google.com> 2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Tobin Ehlis <tobine@google.com> 2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Chia-I Wu <olv@google.com> 2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Chris Forbes <chrisf@ijw.co.nz> 2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Mark Lobodzinski <mark@lunarg.com> 2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Ian Elliott <ianelliott@google.com> 2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Allow use of STL min and max functions in Windows 2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define NOMINMAX 2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Turn on mem_tracker merged code 3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define MTMERGESOURCE 1 3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <SPIRV/spirv.hpp> 3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <algorithm> 3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <assert.h> 3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <iostream> 3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <list> 3811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <map> 3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <mutex> 4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <set> 4111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdio.h> 4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdlib.h> 4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <string.h> 4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <string> 4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <tuple> 4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_loader_platform.h" 4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_dispatch_table_helper.h" 4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_struct_string_helper_cpp.h" 5011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if defined(__GNUC__) 5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#pragma GCC diagnostic ignored "-Wwrite-strings" 5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if defined(__GNUC__) 5411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#pragma GCC diagnostic warning "-Wwrite-strings" 5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_struct_size_helper.h" 5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "core_validation.h" 5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_layer_table.h" 5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_layer_data.h" 6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_layer_extension_utils.h" 6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_layer_utils.h" 6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "spirv-tools/libspirv.h" 6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if defined __ANDROID__ 6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <android/log.h> 6611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define LOGCONSOLE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "DS", __VA_ARGS__)) 6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#else 6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define LOGCONSOLE(...) \ 6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { \ 7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert printf(__VA_ARGS__); \ 7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert printf("\n"); \ 7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 7311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 7411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 7511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertusing namespace std; 7611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 7711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// TODO : CB really needs it's own class and files so this is just temp code until that happens 7811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGLOBAL_CB_NODE::~GLOBAL_CB_NODE() { 7911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i=0; i<VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { 8011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Make sure that no sets hold onto deleted CB binding 8111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto set : lastBound[i].uniqueBoundSets) { 8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set->RemoveBoundCommandBuffer(this); 8311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 8411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 8511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 8611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 8711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertnamespace core_validation { 8811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 8911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertusing std::unordered_map; 9011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertusing std::unordered_set; 9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// WSI Image Objects bypass usual Image Object creation methods. A special Memory 9311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Object value will be used to identify them internally. 9411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const VkDeviceMemory MEMTRACKER_SWAP_CHAIN_IMAGE_KEY = (VkDeviceMemory)(-1); 9511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Track command pools and their command buffers 9711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct CMD_POOL_INFO { 9811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkCommandPoolCreateFlags createFlags; 9911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t queueFamilyIndex; 10011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert list<VkCommandBuffer> commandBuffers; // list container of cmd buffers allocated from this pool 10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 10211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 10311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct devExts { 10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool wsi_enabled; 10511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> swapchainMap; 10611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkImage, VkSwapchainKHR> imageToSwapchainMap; 10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 10811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 10911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// fwd decls 11011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct shader_module; 11111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 11211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// TODO : Split this into separate structs for instance and device level data? 11311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct layer_data { 11411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkInstance instance; 11511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 11611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert debug_report_data *report_data; 11711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<VkDebugReportCallbackEXT> logging_callback; 11811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkLayerDispatchTable *device_dispatch_table; 11911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkLayerInstanceDispatchTable *instance_dispatch_table; 12011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 12111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert devExts device_extensions; 12211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_set<VkQueue> queues; // all queues under given device 12311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Global set of all cmdBuffers that are inFlight on this device 12411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_set<VkCommandBuffer> globalInFlightCmdBuffers; 12511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Layer specific data 12611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkSampler, unique_ptr<SAMPLER_NODE>> samplerMap; 12711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkImageView, VkImageViewCreateInfo> imageViewMap; 12811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkImage, IMAGE_NODE> imageMap; 12911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkBufferView, VkBufferViewCreateInfo> bufferViewMap; 13011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkBuffer, BUFFER_NODE> bufferMap; 13111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkPipeline, PIPELINE_NODE *> pipelineMap; 13211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkCommandPool, CMD_POOL_INFO> commandPoolMap; 13311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_NODE *> descriptorPoolMap; 13411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> setMap; 13511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkDescriptorSetLayout, cvdescriptorset::DescriptorSetLayout *> descriptorSetLayoutMap; 13611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkPipelineLayout, PIPELINE_LAYOUT_NODE> pipelineLayoutMap; 13711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkDeviceMemory, DEVICE_MEM_INFO> memObjMap; 13811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkFence, FENCE_NODE> fenceMap; 13911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkQueue, QUEUE_NODE> queueMap; 14011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkEvent, EVENT_NODE> eventMap; 14111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<QueryObject, bool> queryToStateMap; 14211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkQueryPool, QUERY_POOL_NODE> queryPoolMap; 14311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkSemaphore, SEMAPHORE_NODE> semaphoreMap; 14411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkCommandBuffer, GLOBAL_CB_NODE *> commandBufferMap; 14511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkFramebuffer, FRAMEBUFFER_NODE> frameBufferMap; 14611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkImage, vector<ImageSubresourcePair>> imageSubresourceMap; 14711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> imageLayoutMap; 14811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkRenderPass, RENDER_PASS_NODE *> renderPassMap; 14911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<VkShaderModule, unique_ptr<shader_module>> shaderModuleMap; 15011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDevice device; 15111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 15211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Device specific data 15311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PHYS_DEV_PROPERTIES_NODE phys_dev_properties; 15411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkPhysicalDeviceMemoryProperties phys_dev_mem_props; 15511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 15611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data() 15711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : report_data(nullptr), device_dispatch_table(nullptr), instance_dispatch_table(nullptr), device_extensions(), 15811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert device(VK_NULL_HANDLE), phys_dev_properties{}, phys_dev_mem_props{} {}; 15911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 16011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 16111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// TODO : Do we need to guard access to layer_data_map w/ lock? 16211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic unordered_map<void *, layer_data *> layer_data_map; 16311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 16411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const VkLayerProperties global_layer = { 16511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_LAYER_LUNARG_core_validation", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer", 16611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 16711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 16811cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class TCreateInfo> void ValidateLayerOrdering(const TCreateInfo &createInfo) { 16911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool foundLayer = false; 17011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < createInfo.enabledLayerCount; ++i) { 17111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!strcmp(createInfo.ppEnabledLayerNames[i], global_layer.layerName)) { 17211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert foundLayer = true; 17311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 17411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // This has to be logged to console as we don't have a callback at this point. 17511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!foundLayer && !strcmp(createInfo.ppEnabledLayerNames[0], "VK_LAYER_GOOGLE_unique_objects")) { 17611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert LOGCONSOLE("Cannot activate layer VK_LAYER_GOOGLE_unique_objects prior to activating %s.", 17711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert global_layer.layerName); 17811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 17911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 18011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 18111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 18211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Code imported from shader_checker 18311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void build_def_index(shader_module *); 18411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 18511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// A forward iterator over spirv instructions. Provides easy access to len, opcode, and content words 18611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// without the caller needing to care too much about the physical SPIRV module layout. 18711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct spirv_inst_iter { 18811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<uint32_t>::const_iterator zero; 18911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<uint32_t>::const_iterator it; 19011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 19111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t len() { 19211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto result = *it >> 16; 19311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(result > 0); 19411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 19511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 19611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 19711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t opcode() { return *it & 0x0ffffu; } 19811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 19911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t const &word(unsigned n) { 20011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(n < len()); 20111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return it[n]; 20211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 20311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 20411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t offset() { return (uint32_t)(it - zero); } 20511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 20611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter() {} 20711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 20811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter(std::vector<uint32_t>::const_iterator zero, std::vector<uint32_t>::const_iterator it) : zero(zero), it(it) {} 20911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 21011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool operator==(spirv_inst_iter const &other) { return it == other.it; } 21111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 21211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool operator!=(spirv_inst_iter const &other) { return it != other.it; } 21311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 21411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter operator++(int) { /* x++ */ 21511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter ii = *this; 21611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert it += len(); 21711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return ii; 21811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 21911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 22011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter operator++() { /* ++x; */ 22111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert it += len(); 22211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return *this; 22311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 22411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 22511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* The iterator and the value are the same thing. */ 22611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter &operator*() { return *this; } 22711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter const &operator*() const { return *this; } 22811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 22911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 23011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct shader_module { 23111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* the spirv image itself */ 23211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert vector<uint32_t> words; 23311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* a mapping of <id> to the first word of its def. this is useful because walking type 23411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * trees, constant expressions, etc requires jumping all over the instruction stream. 23511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 23611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<unsigned, unsigned> def_index; 23711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 23811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert shader_module(VkShaderModuleCreateInfo const *pCreateInfo) 23911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : words((uint32_t *)pCreateInfo->pCode, (uint32_t *)pCreateInfo->pCode + pCreateInfo->codeSize / sizeof(uint32_t)), 24011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert def_index() { 24111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 24211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert build_def_index(this); 24311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 24411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 24511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* expose begin() / end() to enable range-based for */ 24611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter begin() const { return spirv_inst_iter(words.begin(), words.begin() + 5); } /* first insn */ 24711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter end() const { return spirv_inst_iter(words.begin(), words.end()); } /* just past last insn */ 24811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* given an offset into the module, produce an iterator there. */ 24911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter at(unsigned offset) const { return spirv_inst_iter(words.begin(), words.begin() + offset); } 25011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 25111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* gets an iterator to the definition of an id */ 25211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter get_def(unsigned id) const { 25311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it = def_index.find(id); 25411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (it == def_index.end()) { 25511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return end(); 25611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 25711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return at(it->second); 25811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 25911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 26011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 26111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// TODO : This can be much smarter, using separate locks for separate global data 26211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic std::mutex global_lock; 26311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 26411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic VkDeviceMemory *get_object_mem_binding(layer_data *my_data, uint64_t handle, VkDebugReportObjectTypeEXT type) { 26511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (type) { 26611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: { 26711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it = my_data->imageMap.find(VkImage(handle)); 26811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (it != my_data->imageMap.end()) 26911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return &(*it).second.mem; 27011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 27111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 27211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: { 27311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it = my_data->bufferMap.find(VkBuffer(handle)); 27411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (it != my_data->bufferMap.end()) 27511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return &(*it).second.mem; 27611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 27711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 27811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 27911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 28011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 28111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return nullptr; 28211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 28311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 28411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// prototype 28511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic GLOBAL_CB_NODE *getCBNode(layer_data const *, const VkCommandBuffer); 28611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 28711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Helper function to validate correct usage bits set for buffers or images 28811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Verify that (actual & desired) flags != 0 or, 28911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// if strict is true, verify that (actual & desired) flags == desired 29011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// In case of error, report it via dbg callbacks 29111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_usage_flags(layer_data *my_data, VkFlags actual, VkFlags desired, VkBool32 strict, 29211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint64_t obj_handle, VkDebugReportObjectTypeEXT obj_type, char const *ty_str, 29311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char const *func_name, char const *usage_str) { 29411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool correct_usage = false; 29511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 29611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (strict) 29711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert correct_usage = ((actual & desired) == desired); 29811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert else 29911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert correct_usage = ((actual & desired) != 0); 30011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!correct_usage) { 30111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_type, obj_handle, __LINE__, 30211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MEMTRACK_INVALID_USAGE_FLAG, "MEM", "Invalid usage flag for %s 0x%" PRIxLEAST64 30311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " used by %s. In this case, %s should have %s set during creation.", 30411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ty_str, obj_handle, func_name, ty_str, usage_str); 30511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 30611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 30711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 30811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 30911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Helper function to validate usage flags for images 31011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Pulls image info and then sends actual vs. desired usage off to helper above where 31111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// an error will be flagged if usage is not correct 31211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_image_usage_flags(layer_data *dev_data, VkImage image, VkFlags desired, VkBool32 strict, 31311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char const *func_name, char const *usage_string) { 31411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 31511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto const image_node = dev_data->imageMap.find(image); 31611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_node != dev_data->imageMap.end()) { 31711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = validate_usage_flags(dev_data, image_node->second.createInfo.usage, desired, strict, (uint64_t)image, 31811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "image", func_name, usage_string); 31911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 32011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 32111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 32211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 32311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Helper function to validate usage flags for buffers 32411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Pulls buffer info and then sends actual vs. desired usage off to helper above where 32511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// an error will be flagged if usage is not correct 32611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_buffer_usage_flags(layer_data *dev_data, VkBuffer buffer, VkFlags desired, VkBool32 strict, 32711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char const *func_name, char const *usage_string) { 32811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 32911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto const buffer_node = dev_data->bufferMap.find(buffer); 33011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (buffer_node != dev_data->bufferMap.end()) { 33111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = validate_usage_flags(dev_data, buffer_node->second.createInfo.usage, desired, strict, (uint64_t)buffer, 33211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "buffer", func_name, usage_string); 33311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 33411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 33511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 33611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 33711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Return ptr to info in map container containing mem, or NULL if not found 33811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Calls to this function should be wrapped in mutex 33911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic DEVICE_MEM_INFO *get_mem_obj_info(layer_data *dev_data, const VkDeviceMemory mem) { 34011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto item = dev_data->memObjMap.find(mem); 34111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (item != dev_data->memObjMap.end()) { 34211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return &(*item).second; 34311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 34411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return NULL; 34511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 34611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 34711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 34811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void add_mem_obj_info(layer_data *my_data, void *object, const VkDeviceMemory mem, 34911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkMemoryAllocateInfo *pAllocateInfo) { 35011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(object != NULL); 35111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 35211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy(&my_data->memObjMap[mem].allocInfo, pAllocateInfo, sizeof(VkMemoryAllocateInfo)); 35311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Update for real hardware, actually process allocation info structures 35411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->memObjMap[mem].allocInfo.pNext = NULL; 35511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->memObjMap[mem].object = object; 35611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->memObjMap[mem].mem = mem; 35711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->memObjMap[mem].image = VK_NULL_HANDLE; 35811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->memObjMap[mem].memRange.offset = 0; 35911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->memObjMap[mem].memRange.size = 0; 36011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->memObjMap[mem].pData = 0; 36111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->memObjMap[mem].pDriverData = 0; 36211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->memObjMap[mem].valid = false; 36311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 36411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 36511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_memory_is_valid(layer_data *dev_data, VkDeviceMemory mem, const char *functionName, 36611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImage image = VK_NULL_HANDLE) { 36711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 36811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto const image_node = dev_data->imageMap.find(image); 36911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_node != dev_data->imageMap.end() && !image_node->second.valid) { 37011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 37111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(mem), __LINE__, MEMTRACK_INVALID_USAGE_FLAG, "MEM", 37211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s: Cannot read invalid swapchain image 0x%" PRIx64 ", please fill the memory before using.", 37311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert functionName, (uint64_t)(image)); 37411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 37511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 37611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DEVICE_MEM_INFO *pMemObj = get_mem_obj_info(dev_data, mem); 37711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pMemObj && !pMemObj->valid) { 37811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 37911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(mem), __LINE__, MEMTRACK_INVALID_USAGE_FLAG, "MEM", 38011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s: Cannot read invalid memory 0x%" PRIx64 ", please fill the memory before using.", functionName, 38111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(mem)); 38211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 38311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 38411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 38511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 38611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 38711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void set_memory_valid(layer_data *dev_data, VkDeviceMemory mem, bool valid, VkImage image = VK_NULL_HANDLE) { 38811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 38911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto image_node = dev_data->imageMap.find(image); 39011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_node != dev_data->imageMap.end()) { 39111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node->second.valid = valid; 39211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 39311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 39411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DEVICE_MEM_INFO *pMemObj = get_mem_obj_info(dev_data, mem); 39511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pMemObj) { 39611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pMemObj->valid = valid; 39711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 39811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 39911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 40011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 40111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Find CB Info and add mem reference to list container 40211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Find Mem Obj Info and add CB reference to list container 40311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool update_cmd_buf_and_mem_references(layer_data *dev_data, const VkCommandBuffer cb, const VkDeviceMemory mem, 40411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char *apiName) { 40511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 40611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 40711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Skip validation if this image was created through WSI 40811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 40911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 41011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // First update CB binding in MemObj mini CB list 41111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DEVICE_MEM_INFO *pMemInfo = get_mem_obj_info(dev_data, mem); 41211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pMemInfo) { 41311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pMemInfo->commandBufferBindings.insert(cb); 41411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Now update CBInfo's Mem reference list 41511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCBNode = getCBNode(dev_data, cb); 41611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: keep track of all destroyed CBs so we know if this is a stale or simply invalid object 41711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCBNode) { 41811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCBNode->memObjs.insert(mem); 41911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 42011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 42111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 42211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 42311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 42411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For every mem obj bound to particular CB, free bindings related to that CB 42511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void clear_cmd_buf_and_mem_references(layer_data *dev_data, GLOBAL_CB_NODE *pCBNode) { 42611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCBNode) { 42711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCBNode->memObjs.size() > 0) { 42811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto mem : pCBNode->memObjs) { 42911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DEVICE_MEM_INFO *pInfo = get_mem_obj_info(dev_data, mem); 43011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pInfo) { 43111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pInfo->commandBufferBindings.erase(pCBNode->commandBuffer); 43211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 43311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 43411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCBNode->memObjs.clear(); 43511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 43611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCBNode->validate_functions.clear(); 43711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 43811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 43911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Overloaded call to above function when GLOBAL_CB_NODE has not already been looked-up 44011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void clear_cmd_buf_and_mem_references(layer_data *dev_data, const VkCommandBuffer cb) { 44111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert clear_cmd_buf_and_mem_references(dev_data, getCBNode(dev_data, cb)); 44211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 44311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 44411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For given MemObjInfo, report Obj & CB bindings 44511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool reportMemReferencesAndCleanUp(layer_data *dev_data, DEVICE_MEM_INFO *pMemObjInfo) { 44611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 44711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t cmdBufRefCount = pMemObjInfo->commandBufferBindings.size(); 44811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t objRefCount = pMemObjInfo->objBindings.size(); 44911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 45011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((pMemObjInfo->commandBufferBindings.size()) != 0) { 45111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 45211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pMemObjInfo->mem, __LINE__, MEMTRACK_FREED_MEM_REF, "MEM", 45311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Attempting to free memory object 0x%" PRIxLEAST64 " which still contains " PRINTF_SIZE_T_SPECIFIER 45411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " references", 45511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pMemObjInfo->mem, (cmdBufRefCount + objRefCount)); 45611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 45711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 45811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cmdBufRefCount > 0 && pMemObjInfo->commandBufferBindings.size() > 0) { 45911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cb : pMemObjInfo->commandBufferBindings) { 46011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 46111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)cb, __LINE__, MEMTRACK_FREED_MEM_REF, "MEM", 46211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Command Buffer 0x%p still has a reference to mem obj 0x%" PRIxLEAST64, cb, (uint64_t)pMemObjInfo->mem); 46311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 46411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Clear the list of hanging references 46511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pMemObjInfo->commandBufferBindings.clear(); 46611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 46711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 46811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (objRefCount > 0 && pMemObjInfo->objBindings.size() > 0) { 46911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto obj : pMemObjInfo->objBindings) { 47011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, obj.type, obj.handle, __LINE__, 47111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MEMTRACK_FREED_MEM_REF, "MEM", "VK Object 0x%" PRIxLEAST64 " still has a reference to mem obj 0x%" PRIxLEAST64, 47211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert obj.handle, (uint64_t)pMemObjInfo->mem); 47311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 47411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Clear the list of hanging references 47511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pMemObjInfo->objBindings.clear(); 47611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 47711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 47811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 47911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 48011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool deleteMemObjInfo(layer_data *my_data, void *object, VkDeviceMemory mem) { 48111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 48211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto item = my_data->memObjMap.find(mem); 48311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (item != my_data->memObjMap.end()) { 48411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->memObjMap.erase(item); 48511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 48611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 48711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MEM_OBJ, "MEM", 48811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Request to delete memory object 0x%" PRIxLEAST64 " not present in memory Object Map", (uint64_t)mem); 48911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 49011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 49111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 49211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 49311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool freeMemObjInfo(layer_data *dev_data, void *object, VkDeviceMemory mem, bool internal) { 49411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 49511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Parse global list to find info w/ mem 49611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DEVICE_MEM_INFO *pInfo = get_mem_obj_info(dev_data, mem); 49711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pInfo) { 49811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pInfo->allocInfo.allocationSize == 0 && !internal) { 49911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Verify against Valid Use section 50011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 50111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MEM_OBJ, "MEM", 50211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Attempting to free memory associated with a Persistent Image, 0x%" PRIxLEAST64 ", " 50311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "this should not be explicitly freed\n", 50411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)mem); 50511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 50611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Clear any CB bindings for completed CBs 50711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Is there a better place to do this? 50811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 50911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(pInfo->object != VK_NULL_HANDLE); 51011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // clear_cmd_buf_and_mem_references removes elements from 51111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // pInfo->commandBufferBindings -- this copy not needed in c++14, 51211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // and probably not needed in practice in c++11 51311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto bindings = pInfo->commandBufferBindings; 51411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cb : bindings) { 51511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!dev_data->globalInFlightCmdBuffers.count(cb)) { 51611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert clear_cmd_buf_and_mem_references(dev_data, cb); 51711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 51811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 51911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 52011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Now verify that no references to this mem obj remain and remove bindings 52111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pInfo->commandBufferBindings.size() || pInfo->objBindings.size()) { 52211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= reportMemReferencesAndCleanUp(dev_data, pInfo); 52311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 52411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Delete mem obj info 52511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= deleteMemObjInfo(dev_data, object, mem); 52611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 52711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 52811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 52911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 53011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 53111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const char *object_type_to_string(VkDebugReportObjectTypeEXT type) { 53211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (type) { 53311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: 53411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "image"; 53511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: 53611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "buffer"; 53711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT: 53811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "swapchain"; 53911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 54011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "unknown"; 54111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 54211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 54311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 54411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Remove object binding performs 3 tasks: 54511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 1. Remove ObjectInfo from MemObjInfo list container of obj bindings & free it 54611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 2. Clear mem binding for image/buffer by setting its handle to 0 54711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// TODO : This only applied to Buffer, Image, and Swapchain objects now, how should it be updated/customized? 54811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool clear_object_binding(layer_data *dev_data, uint64_t handle, VkDebugReportObjectTypeEXT type) { 54911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Need to customize images/buffers/swapchains to track mem binding and clear it here appropriately 55011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 55111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory *pMemBinding = get_object_mem_binding(dev_data, handle, type); 55211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pMemBinding) { 55311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DEVICE_MEM_INFO *pMemObjInfo = get_mem_obj_info(dev_data, *pMemBinding); 55411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Make sure this is a reasonable way to reset mem binding 55511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *pMemBinding = VK_NULL_HANDLE; 55611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pMemObjInfo) { 55711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // This obj is bound to a memory object. Remove the reference to this object in that memory object's list, 55811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // and set the objects memory binding pointer to NULL. 55911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pMemObjInfo->objBindings.erase({handle, type})) { 56011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 56111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, type, handle, __LINE__, MEMTRACK_INVALID_OBJECT, 56211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "MEM", "While trying to clear mem binding for %s obj 0x%" PRIxLEAST64 56311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ", unable to find that object referenced by mem obj 0x%" PRIxLEAST64, 56411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert object_type_to_string(type), handle, (uint64_t)pMemObjInfo->mem); 56511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 56611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 56711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 56811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 56911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 57011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 57111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For NULL mem case, output warning 57211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Make sure given object is in global object map 57311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// IF a previous binding existed, output validation error 57411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Otherwise, add reference from objectInfo to memoryInfo 57511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Add reference off of objInfo 57611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool set_mem_binding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, 57711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDebugReportObjectTypeEXT type, const char *apiName) { 57811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 57911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Handle NULL case separately, just clear previous binding & decrement reference 58011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem == VK_NULL_HANDLE) { 58111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Verify against Valid Use section of spec. 58211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, type, handle, __LINE__, MEMTRACK_INVALID_MEM_OBJ, 58311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "MEM", "In %s, attempting to Bind Obj(0x%" PRIxLEAST64 ") to NULL", apiName, handle); 58411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 58511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory *pMemBinding = get_object_mem_binding(dev_data, handle, type); 58611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(pMemBinding); 58711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DEVICE_MEM_INFO *pMemInfo = get_mem_obj_info(dev_data, mem); 58811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pMemInfo) { 58911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DEVICE_MEM_INFO *pPrevBinding = get_mem_obj_info(dev_data, *pMemBinding); 59011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPrevBinding != NULL) { 59111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 59211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem, __LINE__, MEMTRACK_REBIND_OBJECT, 59311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "MEM", "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 59411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") which has already been bound to mem object 0x%" PRIxLEAST64, 59511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert apiName, (uint64_t)mem, handle, (uint64_t)pPrevBinding->mem); 59611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 59711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pMemInfo->objBindings.insert({handle, type}); 59811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // For image objects, make sure default memory state is correctly set 59911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : What's the best/correct way to handle this? 60011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT == type) { 60111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto const image_node = dev_data->imageMap.find(VkImage(handle)); 60211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_node != dev_data->imageMap.end()) { 60311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageCreateInfo ici = image_node->second.createInfo; 60411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (ici.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { 60511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO:: More memory state transition stuff. 60611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 60711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 60811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 60911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *pMemBinding = mem; 61011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 61111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 61211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 61311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 61411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 61511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 61611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For NULL mem case, clear any previous binding Else... 61711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Make sure given object is in its object map 61811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// IF a previous binding existed, update binding 61911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Add reference from objectInfo to memoryInfo 62011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Add reference off of object's binding info 62111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Return VK_TRUE if addition is successful, VK_FALSE otherwise 62211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool set_sparse_mem_binding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, 62311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDebugReportObjectTypeEXT type, const char *apiName) { 62411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = VK_FALSE; 62511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Handle NULL case separately, just clear previous binding & decrement reference 62611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem == VK_NULL_HANDLE) { 62711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = clear_object_binding(dev_data, handle, type); 62811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 62911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory *pMemBinding = get_object_mem_binding(dev_data, handle, type); 63011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(pMemBinding); 63111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DEVICE_MEM_INFO *pInfo = get_mem_obj_info(dev_data, mem); 63211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pInfo) { 63311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pInfo->objBindings.insert({handle, type}); 63411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Need to set mem binding for this object 63511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *pMemBinding = mem; 63611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 63711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 63811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 63911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 64011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 64111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For given Object, get 'mem' obj that it's bound to or NULL if no binding 64211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool get_mem_binding_from_object(layer_data *dev_data, const uint64_t handle, 64311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkDebugReportObjectTypeEXT type, VkDeviceMemory *mem) { 64411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 64511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *mem = VK_NULL_HANDLE; 64611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory *pMemBinding = get_object_mem_binding(dev_data, handle, type); 64711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pMemBinding) { 64811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *mem = *pMemBinding; 64911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 65011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, type, handle, __LINE__, MEMTRACK_INVALID_OBJECT, 65111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "MEM", "Trying to get mem binding for object 0x%" PRIxLEAST64 " but no such object in %s list", handle, 65211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert object_type_to_string(type)); 65311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 65411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 65511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 65611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 65711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Print details of MemObjInfo list 65811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void print_mem_list(layer_data *dev_data) { 65911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DEVICE_MEM_INFO *pInfo = NULL; 66011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 66111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Early out if info is not requested 66211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(dev_data->report_data->active_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)) { 66311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 66411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 66511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 66611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Just printing each msg individually for now, may want to package these into single large print 66711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__, 66811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MEMTRACK_NONE, "MEM", "Details of Memory Object list (of size " PRINTF_SIZE_T_SPECIFIER " elements)", 66911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->memObjMap.size()); 67011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__, 67111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MEMTRACK_NONE, "MEM", "============================="); 67211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 67311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->memObjMap.size() <= 0) 67411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 67511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 67611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto ii = dev_data->memObjMap.begin(); ii != dev_data->memObjMap.end(); ++ii) { 67711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pInfo = &(*ii).second; 67811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 67911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, 68011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, MEMTRACK_NONE, "MEM", " ===MemObjInfo at 0x%p===", (void *)pInfo); 68111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, 68211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, MEMTRACK_NONE, "MEM", " Mem object: 0x%" PRIxLEAST64, (uint64_t)(pInfo->mem)); 68311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, 68411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, MEMTRACK_NONE, "MEM", " Ref Count: " PRINTF_SIZE_T_SPECIFIER, 68511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pInfo->commandBufferBindings.size() + pInfo->objBindings.size()); 68611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (0 != pInfo->allocInfo.allocationSize) { 68711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string pAllocInfoMsg = vk_print_vkmemoryallocateinfo(&pInfo->allocInfo, "MEM(INFO): "); 68811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, 68911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, MEMTRACK_NONE, "MEM", " Mem Alloc info:\n%s", pAllocInfoMsg.c_str()); 69011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 69111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, 69211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, MEMTRACK_NONE, "MEM", " Mem Alloc info is NULL (alloc done by vkCreateSwapchainKHR())"); 69311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 69411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 69511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, 69611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, MEMTRACK_NONE, "MEM", " VK OBJECT Binding list of size " PRINTF_SIZE_T_SPECIFIER " elements:", 69711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pInfo->objBindings.size()); 69811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pInfo->objBindings.size() > 0) { 69911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto obj : pInfo->objBindings) { 70011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 70111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 0, __LINE__, MEMTRACK_NONE, "MEM", " VK OBJECT 0x%" PRIx64, obj.handle); 70211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 70311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 70411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 70511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, 70611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, MEMTRACK_NONE, "MEM", 70711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " VK Command Buffer (CB) binding list of size " PRINTF_SIZE_T_SPECIFIER " elements", 70811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pInfo->commandBufferBindings.size()); 70911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pInfo->commandBufferBindings.size() > 0) { 71011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cb : pInfo->commandBufferBindings) { 71111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 71211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 0, __LINE__, MEMTRACK_NONE, "MEM", " VK CB 0x%p", cb); 71311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 71411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 71511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 71611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 71711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 71811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void printCBList(layer_data *my_data) { 71911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCBInfo = NULL; 72011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 72111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Early out if info is not requested 72211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(my_data->report_data->active_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)) { 72311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 72411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 72511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 72611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__, 72711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MEMTRACK_NONE, "MEM", "Details of CB list (of size " PRINTF_SIZE_T_SPECIFIER " elements)", 72811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->commandBufferMap.size()); 72911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__, 73011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MEMTRACK_NONE, "MEM", "=================="); 73111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 73211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (my_data->commandBufferMap.size() <= 0) 73311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 73411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 73511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto &cb_node : my_data->commandBufferMap) { 73611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCBInfo = cb_node.second; 73711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 73811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, 73911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, MEMTRACK_NONE, "MEM", " CB Info (0x%p) has CB 0x%p", (void *)pCBInfo, (void *)pCBInfo->commandBuffer); 74011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 74111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCBInfo->memObjs.size() <= 0) 74211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 74311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto obj : pCBInfo->memObjs) { 74411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, 74511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, MEMTRACK_NONE, "MEM", " Mem obj 0x%" PRIx64, (uint64_t)obj); 74611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 74711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 74811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 74911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 75011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Return a string representation of CMD_TYPE enum 75111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic string cmdTypeToString(CMD_TYPE cmd) { 75211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (cmd) { 75311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BINDPIPELINE: 75411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_BINDPIPELINE"; 75511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BINDPIPELINEDELTA: 75611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_BINDPIPELINEDELTA"; 75711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETVIEWPORTSTATE: 75811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_SETVIEWPORTSTATE"; 75911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETLINEWIDTHSTATE: 76011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_SETLINEWIDTHSTATE"; 76111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETDEPTHBIASSTATE: 76211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_SETDEPTHBIASSTATE"; 76311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETBLENDSTATE: 76411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_SETBLENDSTATE"; 76511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETDEPTHBOUNDSSTATE: 76611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_SETDEPTHBOUNDSSTATE"; 76711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETSTENCILREADMASKSTATE: 76811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_SETSTENCILREADMASKSTATE"; 76911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETSTENCILWRITEMASKSTATE: 77011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_SETSTENCILWRITEMASKSTATE"; 77111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETSTENCILREFERENCESTATE: 77211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_SETSTENCILREFERENCESTATE"; 77311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BINDDESCRIPTORSETS: 77411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_BINDDESCRIPTORSETS"; 77511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BINDINDEXBUFFER: 77611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_BINDINDEXBUFFER"; 77711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BINDVERTEXBUFFER: 77811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_BINDVERTEXBUFFER"; 77911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_DRAW: 78011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_DRAW"; 78111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_DRAWINDEXED: 78211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_DRAWINDEXED"; 78311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_DRAWINDIRECT: 78411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_DRAWINDIRECT"; 78511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_DRAWINDEXEDINDIRECT: 78611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_DRAWINDEXEDINDIRECT"; 78711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_DISPATCH: 78811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_DISPATCH"; 78911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_DISPATCHINDIRECT: 79011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_DISPATCHINDIRECT"; 79111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_COPYBUFFER: 79211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_COPYBUFFER"; 79311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_COPYIMAGE: 79411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_COPYIMAGE"; 79511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BLITIMAGE: 79611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_BLITIMAGE"; 79711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_COPYBUFFERTOIMAGE: 79811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_COPYBUFFERTOIMAGE"; 79911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_COPYIMAGETOBUFFER: 80011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_COPYIMAGETOBUFFER"; 80111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_CLONEIMAGEDATA: 80211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_CLONEIMAGEDATA"; 80311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_UPDATEBUFFER: 80411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_UPDATEBUFFER"; 80511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_FILLBUFFER: 80611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_FILLBUFFER"; 80711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_CLEARCOLORIMAGE: 80811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_CLEARCOLORIMAGE"; 80911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_CLEARATTACHMENTS: 81011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_CLEARCOLORATTACHMENT"; 81111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_CLEARDEPTHSTENCILIMAGE: 81211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_CLEARDEPTHSTENCILIMAGE"; 81311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_RESOLVEIMAGE: 81411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_RESOLVEIMAGE"; 81511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETEVENT: 81611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_SETEVENT"; 81711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_RESETEVENT: 81811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_RESETEVENT"; 81911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_WAITEVENTS: 82011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_WAITEVENTS"; 82111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_PIPELINEBARRIER: 82211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_PIPELINEBARRIER"; 82311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BEGINQUERY: 82411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_BEGINQUERY"; 82511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_ENDQUERY: 82611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_ENDQUERY"; 82711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_RESETQUERYPOOL: 82811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_RESETQUERYPOOL"; 82911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_COPYQUERYPOOLRESULTS: 83011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_COPYQUERYPOOLRESULTS"; 83111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_WRITETIMESTAMP: 83211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_WRITETIMESTAMP"; 83311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_INITATOMICCOUNTERS: 83411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_INITATOMICCOUNTERS"; 83511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_LOADATOMICCOUNTERS: 83611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_LOADATOMICCOUNTERS"; 83711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SAVEATOMICCOUNTERS: 83811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_SAVEATOMICCOUNTERS"; 83911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BEGINRENDERPASS: 84011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_BEGINRENDERPASS"; 84111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_ENDRENDERPASS: 84211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "CMD_ENDRENDERPASS"; 84311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 84411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "UNKNOWN"; 84511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 84611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 84711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 84811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// SPIRV utility functions 84911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void build_def_index(shader_module *module) { 85011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto insn : *module) { 85111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (insn.opcode()) { 85211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Types */ 85311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeVoid: 85411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeBool: 85511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeInt: 85611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeFloat: 85711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeVector: 85811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeMatrix: 85911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeImage: 86011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeSampler: 86111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeSampledImage: 86211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeArray: 86311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeRuntimeArray: 86411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeStruct: 86511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeOpaque: 86611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypePointer: 86711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeFunction: 86811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeEvent: 86911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeDeviceEvent: 87011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeReserveId: 87111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeQueue: 87211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypePipe: 87311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert module->def_index[insn.word(1)] = insn.offset(); 87411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 87511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 87611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Fixed constants */ 87711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpConstantTrue: 87811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpConstantFalse: 87911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpConstant: 88011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpConstantComposite: 88111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpConstantSampler: 88211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpConstantNull: 88311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert module->def_index[insn.word(2)] = insn.offset(); 88411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 88511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 88611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Specialization constants */ 88711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpSpecConstantTrue: 88811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpSpecConstantFalse: 88911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpSpecConstant: 89011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpSpecConstantComposite: 89111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpSpecConstantOp: 89211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert module->def_index[insn.word(2)] = insn.offset(); 89311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 89411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 89511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Variables */ 89611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpVariable: 89711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert module->def_index[insn.word(2)] = insn.offset(); 89811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 89911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 90011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Functions */ 90111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpFunction: 90211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert module->def_index[insn.word(2)] = insn.offset(); 90311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 90411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 90511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 90611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* We don't care about any other defs for now. */ 90711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 90811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 90911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 91011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 91111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 91211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic spirv_inst_iter find_entrypoint(shader_module *src, char const *name, VkShaderStageFlagBits stageBits) { 91311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto insn : *src) { 91411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.opcode() == spv::OpEntryPoint) { 91511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto entrypointName = (char const *)&insn.word(3); 91611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto entrypointStageBits = 1u << insn.word(1); 91711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 91811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!strcmp(entrypointName, name) && (entrypointStageBits & stageBits)) { 91911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return insn; 92011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 92111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 92211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 92311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 92411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return src->end(); 92511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 92611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 92711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic char const *storage_class_name(unsigned sc) { 92811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (sc) { 92911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::StorageClassInput: 93011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "input"; 93111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::StorageClassOutput: 93211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "output"; 93311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::StorageClassUniformConstant: 93411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "const uniform"; 93511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::StorageClassUniform: 93611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "uniform"; 93711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::StorageClassWorkgroup: 93811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "workgroup local"; 93911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::StorageClassCrossWorkgroup: 94011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "workgroup global"; 94111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::StorageClassPrivate: 94211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "private global"; 94311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::StorageClassFunction: 94411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "function"; 94511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::StorageClassGeneric: 94611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "generic"; 94711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::StorageClassAtomicCounter: 94811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "atomic counter"; 94911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::StorageClassImage: 95011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "image"; 95111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::StorageClassPushConstant: 95211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "push constant"; 95311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 95411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return "unknown"; 95511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 95611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 95711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 95811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* get the value of an integral constant */ 95911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertunsigned get_constant_value(shader_module const *src, unsigned id) { 96011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto value = src->get_def(id); 96111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(value != src->end()); 96211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 96311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (value.opcode() != spv::OpConstant) { 96411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* TODO: Either ensure that the specialization transform is already performed on a module we're 96511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert considering here, OR -- specialize on the fly now. 96611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 96711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return 1; 96811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 96911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 97011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return value.word(3); 97111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 97211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 97311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 97411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void describe_type_inner(std::ostringstream &ss, shader_module const *src, unsigned type) { 97511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto insn = src->get_def(type); 97611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(insn != src->end()); 97711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 97811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (insn.opcode()) { 97911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeBool: 98011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << "bool"; 98111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 98211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeInt: 98311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << (insn.word(3) ? 's' : 'u') << "int" << insn.word(2); 98411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 98511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeFloat: 98611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << "float" << insn.word(2); 98711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 98811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeVector: 98911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << "vec" << insn.word(3) << " of "; 99011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert describe_type_inner(ss, src, insn.word(2)); 99111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 99211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeMatrix: 99311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << "mat" << insn.word(3) << " of "; 99411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert describe_type_inner(ss, src, insn.word(2)); 99511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 99611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeArray: 99711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << "arr[" << get_constant_value(src, insn.word(3)) << "] of "; 99811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert describe_type_inner(ss, src, insn.word(2)); 99911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 100011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypePointer: 100111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << "ptr to " << storage_class_name(insn.word(2)) << " "; 100211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert describe_type_inner(ss, src, insn.word(3)); 100311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 100411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeStruct: { 100511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << "struct of ("; 100611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (unsigned i = 2; i < insn.len(); i++) { 100711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert describe_type_inner(ss, src, insn.word(i)); 100811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (i == insn.len() - 1) { 100911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << ")"; 101011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 101111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << ", "; 101211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 101311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 101411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 101511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 101611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeSampler: 101711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << "sampler"; 101811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 101911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeSampledImage: 102011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << "sampler+"; 102111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert describe_type_inner(ss, src, insn.word(2)); 102211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 102311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeImage: 102411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << "image(dim=" << insn.word(3) << ", sampled=" << insn.word(7) << ")"; 102511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 102611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 102711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << "oddtype"; 102811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 102911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 103011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 103111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 103211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 103311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic std::string describe_type(shader_module const *src, unsigned type) { 103411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::ostringstream ss; 103511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert describe_type_inner(ss, src, type); 103611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return ss.str(); 103711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 103811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 103911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 104011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool is_narrow_numeric_type(spirv_inst_iter type) 104111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{ 104211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (type.opcode() != spv::OpTypeInt && type.opcode() != spv::OpTypeFloat) 104311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 104411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return type.word(2) < 64; 104511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 104611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 104711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 104811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool types_match(shader_module const *a, shader_module const *b, unsigned a_type, unsigned b_type, bool a_arrayed, bool b_arrayed, bool relaxed) { 104911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* walk two type trees together, and complain about differences */ 105011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto a_insn = a->get_def(a_type); 105111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto b_insn = b->get_def(b_type); 105211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(a_insn != a->end()); 105311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(b_insn != b->end()); 105411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 105511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (a_arrayed && a_insn.opcode() == spv::OpTypeArray) { 105611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return types_match(a, b, a_insn.word(2), b_type, false, b_arrayed, relaxed); 105711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 105811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 105911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (b_arrayed && b_insn.opcode() == spv::OpTypeArray) { 106011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* we probably just found the extra level of arrayness in b_type: compare the type inside it to a_type */ 106111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return types_match(a, b, a_type, b_insn.word(2), a_arrayed, false, relaxed); 106211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 106311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 106411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (a_insn.opcode() == spv::OpTypeVector && relaxed && is_narrow_numeric_type(b_insn)) { 106511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return types_match(a, b, a_insn.word(2), b_type, a_arrayed, b_arrayed, false); 106611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 106711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 106811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (a_insn.opcode() != b_insn.opcode()) { 106911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 107011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 107111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 107211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (a_insn.opcode() == spv::OpTypePointer) { 107311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* match on pointee type. storage class is expected to differ */ 107411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return types_match(a, b, a_insn.word(3), b_insn.word(3), a_arrayed, b_arrayed, relaxed); 107511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 107611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 107711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (a_arrayed || b_arrayed) { 107811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* if we havent resolved array-of-verts by here, we're not going to. */ 107911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 108011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 108111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 108211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (a_insn.opcode()) { 108311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeBool: 108411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 108511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeInt: 108611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* match on width, signedness */ 108711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return a_insn.word(2) == b_insn.word(2) && a_insn.word(3) == b_insn.word(3); 108811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeFloat: 108911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* match on width */ 109011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return a_insn.word(2) == b_insn.word(2); 109111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeVector: 109211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* match on element type, count. */ 109311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false)) 109411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 109511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (relaxed && is_narrow_numeric_type(a->get_def(a_insn.word(2)))) { 109611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return a_insn.word(3) >= b_insn.word(3); 109711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 109811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert else { 109911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return a_insn.word(3) == b_insn.word(3); 110011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 110111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeMatrix: 110211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* match on element type, count. */ 110311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) && a_insn.word(3) == b_insn.word(3); 110411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeArray: 110511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* match on element type, count. these all have the same layout. we don't get here if 110611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * b_arrayed. This differs from vector & matrix types in that the array size is the id of a constant instruction, 110711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * not a literal within OpTypeArray */ 110811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) && 110911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_constant_value(a, a_insn.word(3)) == get_constant_value(b, b_insn.word(3)); 111011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeStruct: 111111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* match on all element types */ 111211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 111311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (a_insn.len() != b_insn.len()) { 111411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; /* structs cannot match if member counts differ */ 111511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 111611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 111711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (unsigned i = 2; i < a_insn.len(); i++) { 111811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!types_match(a, b, a_insn.word(i), b_insn.word(i), a_arrayed, b_arrayed, false)) { 111911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 112011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 112111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 112211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 112311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 112411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 112511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 112611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* remaining types are CLisms, or may not appear in the interfaces we 112711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * are interested in. Just claim no match. 112811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 112911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 113011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 113111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 113211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 113311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic int value_or_default(std::unordered_map<unsigned, unsigned> const &map, unsigned id, int def) { 113411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it = map.find(id); 113511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (it == map.end()) 113611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return def; 113711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert else 113811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return it->second; 113911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 114011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 114111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic unsigned get_locations_consumed_by_type(shader_module const *src, unsigned type, bool strip_array_level) { 114211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto insn = src->get_def(type); 114311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(insn != src->end()); 114411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 114511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (insn.opcode()) { 114611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypePointer: 114711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* see through the ptr -- this is only ever at the toplevel for graphics shaders; 114811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * we're never actually passing pointers around. */ 114911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return get_locations_consumed_by_type(src, insn.word(3), strip_array_level); 115011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeArray: 115111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (strip_array_level) { 115211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return get_locations_consumed_by_type(src, insn.word(2), false); 115311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 115411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return get_constant_value(src, insn.word(3)) * get_locations_consumed_by_type(src, insn.word(2), false); 115511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 115611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeMatrix: 115711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* num locations is the dimension * element size */ 115811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return insn.word(3) * get_locations_consumed_by_type(src, insn.word(2), false); 115911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeVector: { 116011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto scalar_type = src->get_def(insn.word(2)); 116111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto bit_width = (scalar_type.opcode() == spv::OpTypeInt || scalar_type.opcode() == spv::OpTypeFloat) ? 116211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert scalar_type.word(2) : 32; 116311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 116411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* locations are 128-bit wide; 3- and 4-component vectors of 64 bit 116511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * types require two. */ 116611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return (bit_width * insn.word(3) + 127) / 128; 116711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 116811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 116911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* everything else is just 1. */ 117011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return 1; 117111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 117211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* TODO: extend to handle 64bit scalar types, whose vectors may need 117311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * multiple locations. */ 117411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 117511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 117611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 117711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic unsigned get_locations_consumed_by_format(VkFormat format) { 117811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (format) { 117911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64G64B64A64_SFLOAT: 118011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64G64B64A64_SINT: 118111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64G64B64A64_UINT: 118211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64G64B64_SFLOAT: 118311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64G64B64_SINT: 118411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64G64B64_UINT: 118511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return 2; 118611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 118711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return 1; 118811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 118911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 119011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 119111cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypedef std::pair<unsigned, unsigned> location_t; 119211cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypedef std::pair<unsigned, unsigned> descriptor_slot_t; 119311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 119411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct interface_var { 119511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t id; 119611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t type_id; 119711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t offset; 119811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool is_patch; 119911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool is_block_member; 120011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* TODO: collect the name, too? Isn't required to be present. */ 120111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 120211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 120311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct shader_stage_attributes { 120411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char const *const name; 120511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool arrayed_input; 120611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool arrayed_output; 120711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 120811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 120911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic shader_stage_attributes shader_stage_attribs[] = { 121011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vertex shader", false, false}, 121111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"tessellation control shader", true, true}, 121211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"tessellation evaluation shader", true, false}, 121311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"geometry shader", true, false}, 121411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"fragment shader", false, false}, 121511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 121611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 121711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic spirv_inst_iter get_struct_type(shader_module const *src, spirv_inst_iter def, bool is_array_of_verts) { 121811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (true) { 121911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 122011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (def.opcode() == spv::OpTypePointer) { 122111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert def = src->get_def(def.word(3)); 122211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (def.opcode() == spv::OpTypeArray && is_array_of_verts) { 122311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert def = src->get_def(def.word(2)); 122411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert is_array_of_verts = false; 122511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (def.opcode() == spv::OpTypeStruct) { 122611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return def; 122711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 122811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return src->end(); 122911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 123011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 123111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 123211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 123311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void collect_interface_block_members(shader_module const *src, 123411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::map<location_t, interface_var> &out, 123511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<unsigned, unsigned> const &blocks, bool is_array_of_verts, 123611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t id, uint32_t type_id, bool is_patch) { 123711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Walk down the type_id presented, trying to determine whether it's actually an interface block. */ 123811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto type = get_struct_type(src, src->get_def(type_id), is_array_of_verts && !is_patch); 123911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (type == src->end() || blocks.find(type.word(1)) == blocks.end()) { 124011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* this isn't an interface block. */ 124111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 124211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 124311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 124411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<unsigned, unsigned> member_components; 124511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 124611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Walk all the OpMemberDecorate for type's result id -- first pass, collect components. */ 124711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto insn : *src) { 124811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 124911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned member_index = insn.word(2); 125011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 125111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.word(3) == spv::DecorationComponent) { 125211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned component = insn.word(4); 125311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert member_components[member_index] = component; 125411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 125511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 125611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 125711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 125811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Second pass -- produce the output, from Location decorations */ 125911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto insn : *src) { 126011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 126111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned member_index = insn.word(2); 126211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned member_type_id = type.word(2 + member_index); 126311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 126411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.word(3) == spv::DecorationLocation) { 126511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned location = insn.word(4); 126611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned num_locations = get_locations_consumed_by_type(src, member_type_id, false); 126711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto component_it = member_components.find(member_index); 126811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned component = component_it == member_components.end() ? 0 : component_it->second; 126911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 127011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (unsigned int offset = 0; offset < num_locations; offset++) { 127111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert interface_var v; 127211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.id = id; 127311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* TODO: member index in interface_var too? */ 127411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.type_id = member_type_id; 127511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.offset = offset; 127611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.is_patch = is_patch; 127711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.is_block_member = true; 127811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert out[std::make_pair(location + offset, component)] = v; 127911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 128011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 128111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 128211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 128311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 128411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 128511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void collect_interface_by_location(shader_module const *src, spirv_inst_iter entrypoint, 128611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spv::StorageClass sinterface, std::map<location_t, interface_var> &out, 128711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool is_array_of_verts) { 128811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<unsigned, unsigned> var_locations; 128911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<unsigned, unsigned> var_builtins; 129011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<unsigned, unsigned> var_components; 129111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<unsigned, unsigned> blocks; 129211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<unsigned, unsigned> var_patch; 129311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 129411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto insn : *src) { 129511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 129611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* We consider two interface models: SSO rendezvous-by-location, and 129711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * builtins. Complain about anything that fits neither model. 129811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 129911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.opcode() == spv::OpDecorate) { 130011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.word(2) == spv::DecorationLocation) { 130111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert var_locations[insn.word(1)] = insn.word(3); 130211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 130311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 130411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.word(2) == spv::DecorationBuiltIn) { 130511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert var_builtins[insn.word(1)] = insn.word(3); 130611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 130711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 130811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.word(2) == spv::DecorationComponent) { 130911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert var_components[insn.word(1)] = insn.word(3); 131011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 131111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 131211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.word(2) == spv::DecorationBlock) { 131311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert blocks[insn.word(1)] = 1; 131411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 131511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 131611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.word(2) == spv::DecorationPatch) { 131711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert var_patch[insn.word(1)] = 1; 131811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 131911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 132011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 132111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 132211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* TODO: handle grouped decorations */ 132311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* TODO: handle index=1 dual source outputs from FS -- two vars will 132411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * have the same location, and we DON'T want to clobber. */ 132511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 132611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* find the end of the entrypoint's name string. additional zero bytes follow the actual null 132711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert terminator, to fill out the rest of the word - so we only need to look at the last byte in 132811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert the word to determine which word contains the terminator. */ 132911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t word = 3; 133011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (entrypoint.word(word) & 0xff000000u) { 133111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++word; 133211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 133311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++word; 133411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 133511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (; word < entrypoint.len(); word++) { 133611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto insn = src->get_def(entrypoint.word(word)); 133711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(insn != src->end()); 133811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(insn.opcode() == spv::OpVariable); 133911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 134011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.word(3) == static_cast<uint32_t>(sinterface)) { 134111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned id = insn.word(2); 134211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned type = insn.word(1); 134311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 134411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int location = value_or_default(var_locations, id, -1); 134511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int builtin = value_or_default(var_builtins, id, -1); 134611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned component = value_or_default(var_components, id, 0); /* unspecified is OK, is 0 */ 134711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool is_patch = var_patch.find(id) != var_patch.end(); 134811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 134911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* All variables and interface block members in the Input or Output storage classes 135011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * must be decorated with either a builtin or an explicit location. 135111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * 135211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * TODO: integrate the interface block support here. For now, don't complain -- 135311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * a valid SPIRV module will only hit this path for the interface block case, as the 135411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * individual members of the type are decorated, rather than variable declarations. 135511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 135611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 135711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (location != -1) { 135811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* A user-defined interface variable, with a location. Where a variable 135911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * occupied multiple locations, emit one result for each. */ 136011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned num_locations = get_locations_consumed_by_type(src, type, is_array_of_verts && !is_patch); 136111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (unsigned int offset = 0; offset < num_locations; offset++) { 136211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert interface_var v; 136311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.id = id; 136411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.type_id = type; 136511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.offset = offset; 136611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.is_patch = is_patch; 136711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.is_block_member = false; 136811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert out[std::make_pair(location + offset, component)] = v; 136911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 137011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (builtin == -1) { 137111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* An interface block instance */ 137211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert collect_interface_block_members(src, out, blocks, is_array_of_verts, id, type, is_patch); 137311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 137411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 137511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 137611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 137711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 137811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void collect_interface_by_descriptor_slot(debug_report_data *report_data, shader_module const *src, 137911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_set<uint32_t> const &accessible_ids, 138011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::map<descriptor_slot_t, interface_var> &out) { 138111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 138211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<unsigned, unsigned> var_sets; 138311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<unsigned, unsigned> var_bindings; 138411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 138511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto insn : *src) { 138611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* All variables in the Uniform or UniformConstant storage classes are required to be decorated with both 138711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * DecorationDescriptorSet and DecorationBinding. 138811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 138911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.opcode() == spv::OpDecorate) { 139011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.word(2) == spv::DecorationDescriptorSet) { 139111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert var_sets[insn.word(1)] = insn.word(3); 139211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 139311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 139411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.word(2) == spv::DecorationBinding) { 139511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert var_bindings[insn.word(1)] = insn.word(3); 139611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 139711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 139811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 139911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 140011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto id : accessible_ids) { 140111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto insn = src->get_def(id); 140211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(insn != src->end()); 140311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 140411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.opcode() == spv::OpVariable && 140511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (insn.word(3) == spv::StorageClassUniform || insn.word(3) == spv::StorageClassUniformConstant)) { 140611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned set = value_or_default(var_sets, insn.word(2), 0); 140711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned binding = value_or_default(var_bindings, insn.word(2), 0); 140811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 140911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto existing_it = out.find(std::make_pair(set, binding)); 141011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (existing_it != out.end()) { 141111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* conflict within spv image */ 141211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 141311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_INCONSISTENT_SPIRV, "SC", 141411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "var %d (type %d) in %s interface in descriptor slot (%u,%u) conflicts with existing definition", 141511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert insn.word(2), insn.word(1), storage_class_name(insn.word(3)), existing_it->first.first, 141611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert existing_it->first.second); 141711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 141811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 141911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert interface_var v; 142011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.id = insn.word(2); 142111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.type_id = insn.word(1); 142211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.offset = 0; 142311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.is_patch = false; 142411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert v.is_block_member = false; 142511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert out[std::make_pair(set, binding)] = v; 142611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 142711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 142811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 142911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 143011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_interface_between_stages(debug_report_data *report_data, shader_module const *producer, 143111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter producer_entrypoint, shader_stage_attributes const *producer_stage, 143211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert shader_module const *consumer, spirv_inst_iter consumer_entrypoint, 143311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert shader_stage_attributes const *consumer_stage) { 143411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::map<location_t, interface_var> outputs; 143511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::map<location_t, interface_var> inputs; 143611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 143711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool pass = true; 143811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 143911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert collect_interface_by_location(producer, producer_entrypoint, spv::StorageClassOutput, outputs, producer_stage->arrayed_output); 144011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert collect_interface_by_location(consumer, consumer_entrypoint, spv::StorageClassInput, inputs, consumer_stage->arrayed_input); 144111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 144211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto a_it = outputs.begin(); 144311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto b_it = inputs.begin(); 144411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 144511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* maps sorted by key (location); walk them together to find mismatches */ 144611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while ((outputs.size() > 0 && a_it != outputs.end()) || (inputs.size() && b_it != inputs.end())) { 144711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool a_at_end = outputs.size() == 0 || a_it == outputs.end(); 144811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool b_at_end = inputs.size() == 0 || b_it == inputs.end(); 144911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto a_first = a_at_end ? std::make_pair(0u, 0u) : a_it->first; 145011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto b_first = b_at_end ? std::make_pair(0u, 0u) : b_it->first; 145111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 145211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (b_at_end || ((!a_at_end) && (a_first < b_first))) { 145311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 145411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", 145511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s writes to output location %u.%u which is not consumed by %s", producer_stage->name, a_first.first, 145611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert a_first.second, consumer_stage->name)) { 145711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 145811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 145911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert a_it++; 146011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (a_at_end || a_first > b_first) { 146111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 146211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", 146311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s consumes input location %u.%u which is not written by %s", consumer_stage->name, b_first.first, b_first.second, 146411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert producer_stage->name)) { 146511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 146611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 146711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert b_it++; 146811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 146911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // subtleties of arrayed interfaces: 147011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // - if is_patch, then the member is not arrayed, even though the interface may be. 147111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // - if is_block_member, then the extra array level of an arrayed interface is not 147211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // expressed in the member type -- it's expressed in the block type. 147311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!types_match(producer, consumer, a_it->second.type_id, b_it->second.type_id, 147411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert producer_stage->arrayed_output && !a_it->second.is_patch && !a_it->second.is_block_member, 147511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert consumer_stage->arrayed_input && !b_it->second.is_patch && !b_it->second.is_block_member, 147611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert true)) { 147711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 147811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", "Type mismatch on location %u.%u: '%s' vs '%s'", 147911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert a_first.first, a_first.second, 148011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert describe_type(producer, a_it->second.type_id).c_str(), 148111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert describe_type(consumer, b_it->second.type_id).c_str())) { 148211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 148311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 148411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 148511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (a_it->second.is_patch != b_it->second.is_patch) { 148611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0, 148711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 148811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Decoration mismatch on location %u.%u: is per-%s in %s stage but " 148911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "per-%s in %s stage", a_first.first, a_first.second, 149011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert a_it->second.is_patch ? "patch" : "vertex", producer_stage->name, 149111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert b_it->second.is_patch ? "patch" : "vertex", consumer_stage->name)) { 149211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 149311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 149411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 149511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert a_it++; 149611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert b_it++; 149711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 149811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 149911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 150011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pass; 150111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 150211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 150311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertenum FORMAT_TYPE { 150411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert FORMAT_TYPE_UNDEFINED, 150511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert FORMAT_TYPE_FLOAT, /* UNORM, SNORM, FLOAT, USCALED, SSCALED, SRGB -- anything we consider float in the shader */ 150611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert FORMAT_TYPE_SINT, 150711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert FORMAT_TYPE_UINT, 150811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 150911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 151011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic unsigned get_format_type(VkFormat fmt) { 151111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (fmt) { 151211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_UNDEFINED: 151311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return FORMAT_TYPE_UNDEFINED; 151411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R8_SINT: 151511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R8G8_SINT: 151611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R8G8B8_SINT: 151711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R8G8B8A8_SINT: 151811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R16_SINT: 151911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R16G16_SINT: 152011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R16G16B16_SINT: 152111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R16G16B16A16_SINT: 152211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R32_SINT: 152311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R32G32_SINT: 152411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R32G32B32_SINT: 152511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R32G32B32A32_SINT: 152611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64_SINT: 152711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64G64_SINT: 152811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64G64B64_SINT: 152911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64G64B64A64_SINT: 153011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_B8G8R8_SINT: 153111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_B8G8R8A8_SINT: 153211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_A8B8G8R8_SINT_PACK32: 153311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_A2B10G10R10_SINT_PACK32: 153411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_A2R10G10B10_SINT_PACK32: 153511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return FORMAT_TYPE_SINT; 153611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R8_UINT: 153711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R8G8_UINT: 153811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R8G8B8_UINT: 153911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R8G8B8A8_UINT: 154011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R16_UINT: 154111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R16G16_UINT: 154211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R16G16B16_UINT: 154311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R16G16B16A16_UINT: 154411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R32_UINT: 154511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R32G32_UINT: 154611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R32G32B32_UINT: 154711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R32G32B32A32_UINT: 154811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64_UINT: 154911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64G64_UINT: 155011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64G64B64_UINT: 155111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_R64G64B64A64_UINT: 155211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_B8G8R8_UINT: 155311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_B8G8R8A8_UINT: 155411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_A8B8G8R8_UINT_PACK32: 155511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_A2B10G10R10_UINT_PACK32: 155611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_FORMAT_A2R10G10B10_UINT_PACK32: 155711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return FORMAT_TYPE_UINT; 155811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 155911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return FORMAT_TYPE_FLOAT; 156011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 156111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 156211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 156311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* characterizes a SPIR-V type appearing in an interface to a FF stage, 156411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * for comparison to a VkFormat's characterization above. */ 156511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic unsigned get_fundamental_type(shader_module const *src, unsigned type) { 156611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto insn = src->get_def(type); 156711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(insn != src->end()); 156811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 156911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (insn.opcode()) { 157011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeInt: 157111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return insn.word(3) ? FORMAT_TYPE_SINT : FORMAT_TYPE_UINT; 157211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeFloat: 157311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return FORMAT_TYPE_FLOAT; 157411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeVector: 157511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return get_fundamental_type(src, insn.word(2)); 157611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeMatrix: 157711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return get_fundamental_type(src, insn.word(2)); 157811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeArray: 157911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return get_fundamental_type(src, insn.word(2)); 158011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypePointer: 158111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return get_fundamental_type(src, insn.word(3)); 158211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 158311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return FORMAT_TYPE_UNDEFINED; 158411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 158511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 158611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 158711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic uint32_t get_shader_stage_id(VkShaderStageFlagBits stage) { 158811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t bit_pos = u_ffs(stage); 158911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return bit_pos - 1; 159011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 159111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 159211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_vi_consistency(debug_report_data *report_data, VkPipelineVertexInputStateCreateInfo const *vi) { 159311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* walk the binding descriptions, which describe the step rate and stride of each vertex buffer. 159411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * each binding should be specified only once. 159511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 159611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<uint32_t, VkVertexInputBindingDescription const *> bindings; 159711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool pass = true; 159811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 159911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (unsigned i = 0; i < vi->vertexBindingDescriptionCount; i++) { 160011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto desc = &vi->pVertexBindingDescriptions[i]; 160111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto &binding = bindings[desc->binding]; 160211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (binding) { 160311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 160411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_INCONSISTENT_VI, "SC", 160511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Duplicate vertex input binding descriptions for binding %d", desc->binding)) { 160611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 160711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 160811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 160911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert binding = desc; 161011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 161111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 161211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 161311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pass; 161411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 161511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 161611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_vi_against_vs_inputs(debug_report_data *report_data, VkPipelineVertexInputStateCreateInfo const *vi, 161711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert shader_module const *vs, spirv_inst_iter entrypoint) { 161811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::map<location_t, interface_var> inputs; 161911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool pass = true; 162011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 162111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert collect_interface_by_location(vs, entrypoint, spv::StorageClassInput, inputs, false); 162211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 162311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Build index by location */ 162411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::map<uint32_t, VkVertexInputAttributeDescription const *> attribs; 162511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (vi) { 162611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (unsigned i = 0; i < vi->vertexAttributeDescriptionCount; i++) { 162711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto num_locations = get_locations_consumed_by_format(vi->pVertexAttributeDescriptions[i].format); 162811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto j = 0u; j < num_locations; j++) { 162911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attribs[vi->pVertexAttributeDescriptions[i].location + j] = &vi->pVertexAttributeDescriptions[i]; 163011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 163111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 163211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 163311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 163411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it_a = attribs.begin(); 163511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it_b = inputs.begin(); 163611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 163711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while ((attribs.size() > 0 && it_a != attribs.end()) || (inputs.size() > 0 && it_b != inputs.end())) { 163811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool a_at_end = attribs.size() == 0 || it_a == attribs.end(); 163911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool b_at_end = inputs.size() == 0 || it_b == inputs.end(); 164011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto a_first = a_at_end ? 0 : it_a->first; 164111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto b_first = b_at_end ? 0 : it_b->first.first; 164211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!a_at_end && (b_at_end || a_first < b_first)) { 164311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 164411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", 164511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Vertex attribute at location %d not consumed by VS", a_first)) { 164611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 164711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 164811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert it_a++; 164911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (!b_at_end && (a_at_end || b_first < a_first)) { 165011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0, 165111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "VS consumes input at location %d but not provided", 165211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert b_first)) { 165311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 165411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 165511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert it_b++; 165611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 165711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned attrib_type = get_format_type(it_a->second->format); 165811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned input_type = get_fundamental_type(vs, it_b->second.type_id); 165911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 166011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* type checking */ 166111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attrib_type != FORMAT_TYPE_UNDEFINED && input_type != FORMAT_TYPE_UNDEFINED && attrib_type != input_type) { 166211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 166311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 166411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Attribute type of `%s` at location %d does not match VS input type of `%s`", 166511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkFormat(it_a->second->format), a_first, 166611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert describe_type(vs, it_b->second.type_id).c_str())) { 166711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 166811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 166911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 167011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 167111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* OK! */ 167211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert it_a++; 167311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert it_b++; 167411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 167511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 167611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 167711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pass; 167811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 167911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 168011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_fs_outputs_against_render_pass(debug_report_data *report_data, shader_module const *fs, 168111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter entrypoint, RENDER_PASS_NODE const *rp, uint32_t subpass) { 168211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::map<location_t, interface_var> outputs; 168311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::map<uint32_t, VkFormat> color_attachments; 168411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto i = 0u; i < rp->subpassColorFormats[subpass].size(); i++) { 168511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (rp->subpassColorFormats[subpass][i] != VK_FORMAT_UNDEFINED) { 168611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert color_attachments[i] = rp->subpassColorFormats[subpass][i]; 168711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 168811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 168911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 169011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool pass = true; 169111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 169211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* TODO: dual source blend index (spv::DecIndex, zero if not provided) */ 169311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 169411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert collect_interface_by_location(fs, entrypoint, spv::StorageClassOutput, outputs, false); 169511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 169611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it_a = outputs.begin(); 169711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it_b = color_attachments.begin(); 169811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 169911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Walk attachment list and outputs together */ 170011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 170111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while ((outputs.size() > 0 && it_a != outputs.end()) || (color_attachments.size() > 0 && it_b != color_attachments.end())) { 170211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool a_at_end = outputs.size() == 0 || it_a == outputs.end(); 170311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool b_at_end = color_attachments.size() == 0 || it_b == color_attachments.end(); 170411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 170511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!a_at_end && (b_at_end || it_a->first.first < it_b->first)) { 170611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 170711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", 170811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "FS writes to output location %d with no matching attachment", it_a->first.first)) { 170911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 171011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 171111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert it_a++; 171211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (!b_at_end && (a_at_end || it_a->first.first > it_b->first)) { 171311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 171411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "Attachment %d not written by FS", it_b->first)) { 171511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 171611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 171711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert it_b++; 171811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 171911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned output_type = get_fundamental_type(fs, it_a->second.type_id); 172011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned att_type = get_format_type(it_b->second); 172111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 172211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* type checking */ 172311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (att_type != FORMAT_TYPE_UNDEFINED && output_type != FORMAT_TYPE_UNDEFINED && att_type != output_type) { 172411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 172511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 172611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Attachment %d of type `%s` does not match FS output type of `%s`", it_b->first, 172711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkFormat(it_b->second), 172811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert describe_type(fs, it_a->second.type_id).c_str())) { 172911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 173011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 173111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 173211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 173311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* OK! */ 173411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert it_a++; 173511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert it_b++; 173611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 173711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 173811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 173911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pass; 174011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 174111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 174211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* For some analyses, we need to know about all ids referenced by the static call tree of a particular 174311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * entrypoint. This is important for identifying the set of shader resources actually used by an entrypoint, 174411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * for example. 174511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Note: we only explore parts of the image which might actually contain ids we care about for the above analyses. 174611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * - NOT the shader input/output interfaces. 174711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * 174811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * TODO: The set of interesting opcodes here was determined by eyeballing the SPIRV spec. It might be worth 174911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * converting parts of this to be generated from the machine-readable spec instead. 175011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 175111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void mark_accessible_ids(shader_module const *src, spirv_inst_iter entrypoint, std::unordered_set<uint32_t> &ids) { 175211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_set<uint32_t> worklist; 175311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert worklist.insert(entrypoint.word(2)); 175411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 175511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (!worklist.empty()) { 175611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto id_iter = worklist.begin(); 175711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto id = *id_iter; 175811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert worklist.erase(id_iter); 175911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 176011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto insn = src->get_def(id); 176111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn == src->end()) { 176211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* id is something we didn't collect in build_def_index. that's OK -- we'll stumble 176311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * across all kinds of things here that we may not care about. */ 176411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 176511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 176611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 176711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* try to add to the output set */ 176811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!ids.insert(id).second) { 176911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; /* if we already saw this id, we don't want to walk it again. */ 177011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 177111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 177211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (insn.opcode()) { 177311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpFunction: 177411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* scan whole body of the function, enlisting anything interesting */ 177511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (++insn, insn.opcode() != spv::OpFunctionEnd) { 177611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (insn.opcode()) { 177711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpLoad: 177811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicLoad: 177911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicExchange: 178011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicCompareExchange: 178111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicCompareExchangeWeak: 178211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicIIncrement: 178311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicIDecrement: 178411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicIAdd: 178511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicISub: 178611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicSMin: 178711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicUMin: 178811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicSMax: 178911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicUMax: 179011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicAnd: 179111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicOr: 179211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicXor: 179311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert worklist.insert(insn.word(3)); /* ptr */ 179411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 179511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpStore: 179611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAtomicStore: 179711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert worklist.insert(insn.word(1)); /* ptr */ 179811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 179911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpAccessChain: 180011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpInBoundsAccessChain: 180111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert worklist.insert(insn.word(3)); /* base ptr */ 180211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 180311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpSampledImage: 180411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSampleImplicitLod: 180511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSampleExplicitLod: 180611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSampleDrefImplicitLod: 180711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSampleDrefExplicitLod: 180811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSampleProjImplicitLod: 180911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSampleProjExplicitLod: 181011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSampleProjDrefImplicitLod: 181111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSampleProjDrefExplicitLod: 181211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageFetch: 181311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageGather: 181411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageDrefGather: 181511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageRead: 181611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImage: 181711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageQueryFormat: 181811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageQueryOrder: 181911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageQuerySizeLod: 182011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageQuerySize: 182111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageQueryLod: 182211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageQueryLevels: 182311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageQuerySamples: 182411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSparseSampleImplicitLod: 182511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSparseSampleExplicitLod: 182611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSparseSampleDrefImplicitLod: 182711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSparseSampleDrefExplicitLod: 182811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSparseSampleProjImplicitLod: 182911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSparseSampleProjExplicitLod: 183011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSparseSampleProjDrefImplicitLod: 183111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSparseSampleProjDrefExplicitLod: 183211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSparseFetch: 183311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSparseGather: 183411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageSparseDrefGather: 183511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageTexelPointer: 183611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert worklist.insert(insn.word(3)); /* image or sampled image */ 183711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 183811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpImageWrite: 183911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert worklist.insert(insn.word(1)); /* image -- different operand order to above */ 184011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 184111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpFunctionCall: 184211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 3; i < insn.len(); i++) { 184311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert worklist.insert(insn.word(i)); /* fn itself, and all args */ 184411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 184511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 184611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 184711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpExtInst: 184811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 5; i < insn.len(); i++) { 184911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert worklist.insert(insn.word(i)); /* operands to ext inst */ 185011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 185111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 185211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 185311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 185411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 185511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 185611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 185711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 185811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 185911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_push_constant_block_against_pipeline(debug_report_data *report_data, 186011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<VkPushConstantRange> const *pushConstantRanges, 186111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert shader_module const *src, spirv_inst_iter type, 186211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkShaderStageFlagBits stage) { 186311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool pass = true; 186411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 186511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* strip off ptrs etc */ 186611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert type = get_struct_type(src, type, false); 186711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(type != src->end()); 186811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 186911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* validate directly off the offsets. this isn't quite correct for arrays 187011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * and matrices, but is a good first step. TODO: arrays, matrices, weird 187111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * sizes */ 187211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto insn : *src) { 187311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 187411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 187511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.word(3) == spv::DecorationOffset) { 187611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned offset = insn.word(4); 187711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto size = 4; /* bytes; TODO: calculate this based on the type */ 187811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 187911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool found_range = false; 188011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto const &range : *pushConstantRanges) { 188111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (range.offset <= offset && range.offset + range.size >= offset + size) { 188211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert found_range = true; 188311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 188411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((range.stageFlags & stage) == 0) { 188511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 188611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_PUSH_CONSTANT_NOT_ACCESSIBLE_FROM_STAGE, "SC", 188711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Push constant range covering variable starting at " 188811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "offset %u not accessible from stage %s", 188911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert offset, string_VkShaderStageFlagBits(stage))) { 189011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 189111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 189211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 189311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 189411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 189511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 189611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 189711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 189811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!found_range) { 189911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 190011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_PUSH_CONSTANT_OUT_OF_RANGE, "SC", 190111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Push constant range covering variable starting at " 190211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "offset %u not declared in layout", 190311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert offset)) { 190411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 190511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 190611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 190711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 190811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 190911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 191011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 191111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pass; 191211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 191311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 191411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_push_constant_usage(debug_report_data *report_data, 191511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<VkPushConstantRange> const *pushConstantRanges, shader_module const *src, 191611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_set<uint32_t> accessible_ids, VkShaderStageFlagBits stage) { 191711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool pass = true; 191811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 191911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto id : accessible_ids) { 192011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto def_insn = src->get_def(id); 192111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (def_insn.opcode() == spv::OpVariable && def_insn.word(3) == spv::StorageClassPushConstant) { 192211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= validate_push_constant_block_against_pipeline(report_data, pushConstantRanges, src, 192311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert src->get_def(def_insn.word(1)), stage); 192411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 192511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 192611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 192711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pass; 192811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 192911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 193011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For given pipelineLayout verify that the set_layout_node at slot.first 193111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// has the requested binding at slot.second and return ptr to that binding 193211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic VkDescriptorSetLayoutBinding const * get_descriptor_binding(PIPELINE_LAYOUT_NODE const *pipelineLayout, descriptor_slot_t slot) { 193311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 193411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pipelineLayout) 193511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return nullptr; 193611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 193711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (slot.first >= pipelineLayout->descriptorSetLayouts.size()) 193811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return nullptr; 193911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 194011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pipelineLayout->setLayouts[slot.first]->GetDescriptorSetLayoutBindingPtrFromBinding(slot.second); 194111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 194211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 194311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Block of code at start here for managing/tracking Pipeline state that this layer cares about 194411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 194511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic uint64_t g_drawCount[NUM_DRAW_TYPES] = {0, 0, 0, 0}; 194611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 194711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// TODO : Should be tracking lastBound per commandBuffer and when draws occur, report based on that cmd buffer lastBound 194811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Then need to synchronize the accesses based on cmd buffer so that if I'm reading state on one cmd buffer, updates 194911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// to that same cmd buffer by separate thread are not changing state from underneath us 195011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Track the last cmd buffer touched by this thread 195111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 195211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool hasDrawCmd(GLOBAL_CB_NODE *pCB) { 195311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < NUM_DRAW_TYPES; i++) { 195411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->drawCount[i]) 195511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 195611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 195711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 195811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 195911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 196011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Check object status for selected flag state 196111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_status(layer_data *my_data, GLOBAL_CB_NODE *pNode, CBStatusFlags status_mask, VkFlags msg_flags, 196211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAW_STATE_ERROR error_code, const char *fail_msg) { 196311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(pNode->status & status_mask)) { 196411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return log_msg(my_data->report_data, msg_flags, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 196511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(pNode->commandBuffer), __LINE__, error_code, "DS", 196611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "CB object 0x%" PRIxLEAST64 ": %s", reinterpret_cast<const uint64_t &>(pNode->commandBuffer), fail_msg); 196711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 196811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 196911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 197011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 197111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Retrieve pipeline node ptr for given pipeline object 197211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PIPELINE_NODE *getPipeline(layer_data const *my_data, VkPipeline pipeline) { 197311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it = my_data->pipelineMap.find(pipeline); 197411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (it == my_data->pipelineMap.end()) { 197511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return nullptr; 197611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 197711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return it->second; 197811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 197911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 198011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic RENDER_PASS_NODE *getRenderPass(layer_data const *my_data, VkRenderPass renderpass) { 198111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it = my_data->renderPassMap.find(renderpass); 198211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (it == my_data->renderPassMap.end()) { 198311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return nullptr; 198411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 198511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return it->second; 198611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 198711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 198811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic FRAMEBUFFER_NODE *getFramebuffer(layer_data *my_data, VkFramebuffer framebuffer) { 198911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it = my_data->frameBufferMap.find(framebuffer); 199011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (it == my_data->frameBufferMap.end()) { 199111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return nullptr; 199211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 199311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return &it->second; 199411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 199511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 199611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic cvdescriptorset::DescriptorSetLayout const *getDescriptorSetLayout(layer_data const *my_data, VkDescriptorSetLayout dsLayout) { 199711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it = my_data->descriptorSetLayoutMap.find(dsLayout); 199811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (it == my_data->descriptorSetLayoutMap.end()) { 199911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return nullptr; 200011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 200111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return it->second; 200211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 200311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 200411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PIPELINE_LAYOUT_NODE const *getPipelineLayout(layer_data const *my_data, VkPipelineLayout pipeLayout) { 200511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it = my_data->pipelineLayoutMap.find(pipeLayout); 200611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (it == my_data->pipelineLayoutMap.end()) { 200711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return nullptr; 200811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 200911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return &it->second; 201011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 201111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 201211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Return true if for a given PSO, the given state enum is dynamic, else return false 201311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool isDynamic(const PIPELINE_NODE *pPipeline, const VkDynamicState state) { 201411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) { 201511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pPipeline->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) { 201611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (state == pPipeline->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) 201711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 201811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 201911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 202011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 202111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 202211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 202311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Validate state stored as flags at time of draw call 202411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_draw_state_flags(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const PIPELINE_NODE *pPipe, bool indexedDraw) { 202511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool result; 202611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = validate_status(dev_data, pCB, CBSTATUS_VIEWPORT_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_VIEWPORT_NOT_BOUND, 202711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Dynamic viewport state not set for this command buffer"); 202811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= validate_status(dev_data, pCB, CBSTATUS_SCISSOR_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_SCISSOR_NOT_BOUND, 202911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Dynamic scissor state not set for this command buffer"); 203011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipe->graphicsPipelineCI.pInputAssemblyState && 203111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ((pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) || 203211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP))) { 203311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= validate_status(dev_data, pCB, CBSTATUS_LINE_WIDTH_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 203411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_LINE_WIDTH_NOT_BOUND, "Dynamic line width state not set for this command buffer"); 203511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 203611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipe->graphicsPipelineCI.pRasterizationState && 203711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipe->graphicsPipelineCI.pRasterizationState->depthBiasEnable == VK_TRUE)) { 203811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BIAS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 203911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_DEPTH_BIAS_NOT_BOUND, "Dynamic depth bias state not set for this command buffer"); 204011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 204111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipe->blendConstantsEnabled) { 204211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= validate_status(dev_data, pCB, CBSTATUS_BLEND_CONSTANTS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 204311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_BLEND_NOT_BOUND, "Dynamic blend constants state not set for this command buffer"); 204411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 204511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipe->graphicsPipelineCI.pDepthStencilState && 204611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipe->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE)) { 204711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BOUNDS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 204811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_DEPTH_BOUNDS_NOT_BOUND, "Dynamic depth bounds state not set for this command buffer"); 204911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 205011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipe->graphicsPipelineCI.pDepthStencilState && 205111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipe->graphicsPipelineCI.pDepthStencilState->stencilTestEnable == VK_TRUE)) { 205211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_READ_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 205311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil read mask state not set for this command buffer"); 205411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 205511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil write mask state not set for this command buffer"); 205611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_REFERENCE_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 205711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil reference state not set for this command buffer"); 205811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 205911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (indexedDraw) { 206011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= validate_status(dev_data, pCB, CBSTATUS_INDEX_BUFFER_BOUND, VK_DEBUG_REPORT_ERROR_BIT_EXT, 206111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INDEX_BUFFER_NOT_BOUND, 206211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Index buffer object not bound to this command buffer when Indexed Draw attempted"); 206311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 206411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 206511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 206611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 206711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Verify attachment reference compatibility according to spec 206811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// If one array is larger, treat missing elements of shorter array as VK_ATTACHMENT_UNUSED & other array much match this 206911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// If both AttachmentReference arrays have requested index, check their corresponding AttachementDescriptions 207011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// to make sure that format and samples counts match. 207111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// If not, they are not compatible. 207211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool attachment_references_compatible(const uint32_t index, const VkAttachmentReference *pPrimary, 207311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t primaryCount, const VkAttachmentDescription *pPrimaryAttachments, 207411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAttachmentReference *pSecondary, const uint32_t secondaryCount, 207511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAttachmentDescription *pSecondaryAttachments) { 207611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (index >= primaryCount) { // Check secondary as if primary is VK_ATTACHMENT_UNUSED 207711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_ATTACHMENT_UNUSED == pSecondary[index].attachment) 207811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 207911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (index >= secondaryCount) { // Check primary as if secondary is VK_ATTACHMENT_UNUSED 208011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_ATTACHMENT_UNUSED == pPrimary[index].attachment) 208111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 208211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { // format and sample count must match 208311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((pPrimaryAttachments[pPrimary[index].attachment].format == 208411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pSecondaryAttachments[pSecondary[index].attachment].format) && 208511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPrimaryAttachments[pPrimary[index].attachment].samples == 208611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pSecondaryAttachments[pSecondary[index].attachment].samples)) 208711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 208811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 208911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Format and sample counts didn't match 209011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 209111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 209211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 209311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For give primary and secondary RenderPass objects, verify that they're compatible 209411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool verify_renderpass_compatibility(layer_data *my_data, const VkRenderPass primaryRP, const VkRenderPass secondaryRP, 209511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string &errorMsg) { 209611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto primary_render_pass = getRenderPass(my_data, primaryRP); 209711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto secondary_render_pass = getRenderPass(my_data, secondaryRP); 209811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 209911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!primary_render_pass) { 210011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert stringstream errorStr; 210111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorStr << "invalid VkRenderPass (" << primaryRP << ")"; 210211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorMsg = errorStr.str(); 210311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 210411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 210511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 210611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!secondary_render_pass) { 210711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert stringstream errorStr; 210811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorStr << "invalid VkRenderPass (" << secondaryRP << ")"; 210911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorMsg = errorStr.str(); 211011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 211111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 211211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Trivial pass case is exact same RP 211311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (primaryRP == secondaryRP) { 211411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 211511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 211611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkRenderPassCreateInfo *primaryRPCI = primary_render_pass->pCreateInfo; 211711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkRenderPassCreateInfo *secondaryRPCI = secondary_render_pass->pCreateInfo; 211811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (primaryRPCI->subpassCount != secondaryRPCI->subpassCount) { 211911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert stringstream errorStr; 212011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorStr << "RenderPass for primary cmdBuffer has " << primaryRPCI->subpassCount 212111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << " subpasses but renderPass for secondary cmdBuffer has " << secondaryRPCI->subpassCount << " subpasses."; 212211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorMsg = errorStr.str(); 212311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 212411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 212511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t spIndex = 0; 212611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (spIndex = 0; spIndex < primaryRPCI->subpassCount; ++spIndex) { 212711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // For each subpass, verify that corresponding color, input, resolve & depth/stencil attachment references are compatible 212811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t primaryColorCount = primaryRPCI->pSubpasses[spIndex].colorAttachmentCount; 212911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t secondaryColorCount = secondaryRPCI->pSubpasses[spIndex].colorAttachmentCount; 213011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t colorMax = std::max(primaryColorCount, secondaryColorCount); 213111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t cIdx = 0; cIdx < colorMax; ++cIdx) { 213211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pColorAttachments, primaryColorCount, 213311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pColorAttachments, 213411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryColorCount, secondaryRPCI->pAttachments)) { 213511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert stringstream errorStr; 213611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorStr << "color attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible."; 213711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorMsg = errorStr.str(); 213811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 213911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pResolveAttachments, 214011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert primaryColorCount, primaryRPCI->pAttachments, 214111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryRPCI->pSubpasses[spIndex].pResolveAttachments, 214211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryColorCount, secondaryRPCI->pAttachments)) { 214311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert stringstream errorStr; 214411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorStr << "resolve attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible."; 214511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorMsg = errorStr.str(); 214611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 214711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 214811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 214911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 215011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!attachment_references_compatible(0, primaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 215111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1, primaryRPCI->pAttachments, 215211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 215311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1, secondaryRPCI->pAttachments)) { 215411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert stringstream errorStr; 215511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorStr << "depth/stencil attachments of subpass index " << spIndex << " are not compatible."; 215611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorMsg = errorStr.str(); 215711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 215811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 215911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 216011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t primaryInputCount = primaryRPCI->pSubpasses[spIndex].inputAttachmentCount; 216111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t secondaryInputCount = secondaryRPCI->pSubpasses[spIndex].inputAttachmentCount; 216211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t inputMax = std::max(primaryInputCount, secondaryInputCount); 216311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < inputMax; ++i) { 216411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!attachment_references_compatible(i, primaryRPCI->pSubpasses[spIndex].pInputAttachments, primaryColorCount, 216511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pInputAttachments, 216611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryColorCount, secondaryRPCI->pAttachments)) { 216711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert stringstream errorStr; 216811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorStr << "input attachments at index " << i << " of subpass index " << spIndex << " are not compatible."; 216911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorMsg = errorStr.str(); 217011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 217111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 217211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 217311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 217411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 217511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 217611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 217711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For given cvdescriptorset::DescriptorSet, verify that its Set is compatible w/ the setLayout corresponding to 217811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// pipelineLayout[layoutIndex] 217911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool verify_set_layout_compatibility(layer_data *my_data, const cvdescriptorset::DescriptorSet *pSet, 218011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkPipelineLayout layout, const uint32_t layoutIndex, string &errorMsg) { 218111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pipeline_layout = getPipelineLayout(my_data, layout); 218211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pipeline_layout) { 218311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert stringstream errorStr; 218411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorStr << "invalid VkPipelineLayout (" << layout << ")"; 218511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorMsg = errorStr.str(); 218611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 218711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 218811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (layoutIndex >= pipeline_layout->descriptorSetLayouts.size()) { 218911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert stringstream errorStr; 219011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorStr << "VkPipelineLayout (" << layout << ") only contains " << pipeline_layout->descriptorSetLayouts.size() 219111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << " setLayouts corresponding to sets 0-" << pipeline_layout->descriptorSetLayouts.size() - 1 219211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert << ", but you're attempting to bind set to index " << layoutIndex; 219311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert errorMsg = errorStr.str(); 219411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 219511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 219611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto layout_node = pipeline_layout->setLayouts[layoutIndex]; 219711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pSet->IsCompatible(layout_node, &errorMsg); 219811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 219911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 220011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Validate that data for each specialization entry is fully contained within the buffer. 220111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_specialization_offsets(debug_report_data *report_data, VkPipelineShaderStageCreateInfo const *info) { 220211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool pass = true; 220311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 220411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkSpecializationInfo const *spec = info->pSpecializationInfo; 220511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 220611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (spec) { 220711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto i = 0u; i < spec->mapEntryCount; i++) { 220811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (spec->pMapEntries[i].offset + spec->pMapEntries[i].size > spec->dataSize) { 220911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 221011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /*dev*/ 0, __LINE__, SHADER_CHECKER_BAD_SPECIALIZATION, "SC", 221111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Specialization entry %u (for constant id %u) references memory outside provided " 221211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "specialization data (bytes %u.." PRINTF_SIZE_T_SPECIFIER "; " PRINTF_SIZE_T_SPECIFIER 221311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " bytes provided)", 221411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert i, spec->pMapEntries[i].constantID, spec->pMapEntries[i].offset, 221511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spec->pMapEntries[i].offset + spec->pMapEntries[i].size - 1, spec->dataSize)) { 221611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 221711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 221811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 221911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 222011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 222111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 222211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 222311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pass; 222411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 222511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 222611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool descriptor_type_match(shader_module const *module, uint32_t type_id, 222711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDescriptorType descriptor_type, unsigned &descriptor_count) { 222811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto type = module->get_def(type_id); 222911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 223011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert descriptor_count = 1; 223111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 223211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Strip off any array or ptrs. Where we remove array levels, adjust the 223311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * descriptor count for each dimension. */ 223411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (type.opcode() == spv::OpTypeArray || type.opcode() == spv::OpTypePointer) { 223511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (type.opcode() == spv::OpTypeArray) { 223611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert descriptor_count *= get_constant_value(module, type.word(3)); 223711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert type = module->get_def(type.word(2)); 223811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 223911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert else { 224011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert type = module->get_def(type.word(3)); 224111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 224211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 224311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 224411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (type.opcode()) { 224511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeStruct: { 224611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto insn : *module) { 224711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.opcode() == spv::OpDecorate && insn.word(1) == type.word(1)) { 224811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.word(2) == spv::DecorationBlock) { 224911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || 225011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; 225111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (insn.word(2) == spv::DecorationBufferBlock) { 225211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER || 225311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; 225411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 225511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 225611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 225711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 225811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Invalid */ 225911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 226011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 226111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 226211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeSampler: 226311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLER; 226411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 226511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeSampledImage: 226611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) { 226711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Slight relaxation for some GLSL historical madness: samplerBuffer 226811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * doesn't really have a sampler, and a texel buffer descriptor 226911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * doesn't really provide one. Allow this slight mismatch. 227011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 227111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto image_type = module->get_def(type.word(2)); 227211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto dim = image_type.word(3); 227311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto sampled = image_type.word(7); 227411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return dim == spv::DimBuffer && sampled == 1; 227511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 227611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 227711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 227811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::OpTypeImage: { 227911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Many descriptor types backing image types-- depends on dimension 228011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * and whether the image will be used with a sampler. SPIRV for 228111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Vulkan requires that sampled be 1 or 2 -- leaving the decision to 228211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * runtime is unacceptable. 228311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 228411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto dim = type.word(3); 228511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto sampled = type.word(7); 228611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 228711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dim == spv::DimSubpassData) { 228811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return descriptor_type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; 228911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (dim == spv::DimBuffer) { 229011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (sampled == 1) { 229111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; 229211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 229311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; 229411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 229511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (sampled == 1) { 229611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; 229711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 229811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; 229911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 230011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 230111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 230211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* We shouldn't really see any other junk types -- but if we do, they're 230311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * a mismatch. 230411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 230511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 230611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; /* Mismatch */ 230711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 230811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 230911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 231011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool require_feature(debug_report_data *report_data, VkBool32 feature, char const *feature_name) { 231111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!feature) { 231211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 231311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_FEATURE_NOT_ENABLED, "SC", 231411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Shader requires VkPhysicalDeviceFeatures::%s but is not " 231511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "enabled on the device", 231611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert feature_name)) { 231711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 231811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 231911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 232011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 232111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 232211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 232311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 232411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_shader_capabilities(debug_report_data *report_data, shader_module const *src, 232511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkPhysicalDeviceFeatures const *enabledFeatures) { 232611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool pass = true; 232711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 232811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 232911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto insn : *src) { 233011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (insn.opcode() == spv::OpCapability) { 233111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (insn.word(1)) { 233211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityMatrix: 233311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityShader: 233411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityInputAttachment: 233511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilitySampled1D: 233611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityImage1D: 233711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilitySampledBuffer: 233811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityImageBuffer: 233911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityImageQuery: 234011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityDerivativeControl: 234111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Always supported by a Vulkan 1.0 implementation -- no feature bits. 234211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 234311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 234411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityGeometry: 234511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->geometryShader, "geometryShader"); 234611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 234711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 234811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityTessellation: 234911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->tessellationShader, "tessellationShader"); 235011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 235111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 235211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityFloat64: 235311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderFloat64, "shaderFloat64"); 235411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 235511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 235611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityInt64: 235711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderInt64, "shaderInt64"); 235811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 235911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 236011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityTessellationPointSize: 236111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityGeometryPointSize: 236211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderTessellationAndGeometryPointSize, 236311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "shaderTessellationAndGeometryPointSize"); 236411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 236511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 236611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityImageGatherExtended: 236711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderImageGatherExtended, "shaderImageGatherExtended"); 236811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 236911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 237011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityStorageImageMultisample: 237111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderStorageImageMultisample, "shaderStorageImageMultisample"); 237211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 237311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 237411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityUniformBufferArrayDynamicIndexing: 237511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderUniformBufferArrayDynamicIndexing, 237611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "shaderUniformBufferArrayDynamicIndexing"); 237711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 237811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 237911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilitySampledImageArrayDynamicIndexing: 238011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderSampledImageArrayDynamicIndexing, 238111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "shaderSampledImageArrayDynamicIndexing"); 238211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 238311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 238411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityStorageBufferArrayDynamicIndexing: 238511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderStorageBufferArrayDynamicIndexing, 238611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "shaderStorageBufferArrayDynamicIndexing"); 238711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 238811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 238911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityStorageImageArrayDynamicIndexing: 239011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderStorageImageArrayDynamicIndexing, 239111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "shaderStorageImageArrayDynamicIndexing"); 239211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 239311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 239411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityClipDistance: 239511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderClipDistance, "shaderClipDistance"); 239611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 239711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 239811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityCullDistance: 239911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderCullDistance, "shaderCullDistance"); 240011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 240111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 240211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityImageCubeArray: 240311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->imageCubeArray, "imageCubeArray"); 240411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 240511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 240611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilitySampleRateShading: 240711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->sampleRateShading, "sampleRateShading"); 240811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 240911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 241011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilitySparseResidency: 241111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderResourceResidency, "shaderResourceResidency"); 241211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 241311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 241411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityMinLod: 241511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderResourceMinLod, "shaderResourceMinLod"); 241611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 241711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 241811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilitySampledCubeArray: 241911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->imageCubeArray, "imageCubeArray"); 242011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 242111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 242211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityImageMSArray: 242311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderStorageImageMultisample, "shaderStorageImageMultisample"); 242411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 242511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 242611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityStorageImageExtendedFormats: 242711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderStorageImageExtendedFormats, 242811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "shaderStorageImageExtendedFormats"); 242911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 243011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 243111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityInterpolationFunction: 243211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->sampleRateShading, "sampleRateShading"); 243311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 243411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 243511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityStorageImageReadWithoutFormat: 243611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderStorageImageReadWithoutFormat, 243711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "shaderStorageImageReadWithoutFormat"); 243811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 243911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 244011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityStorageImageWriteWithoutFormat: 244111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->shaderStorageImageWriteWithoutFormat, 244211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "shaderStorageImageWriteWithoutFormat"); 244311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 244411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 244511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case spv::CapabilityMultiViewport: 244611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= require_feature(report_data, enabledFeatures->multiViewport, "multiViewport"); 244711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 244811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 244911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 245011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 245111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_BAD_CAPABILITY, "SC", 245211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Shader declares capability %u, not supported in Vulkan.", 245311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert insn.word(1))) 245411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 245511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 245611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 245711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 245811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 245911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 246011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pass; 246111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 246211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 246311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_pipeline_shader_stage(debug_report_data *report_data, 246411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkPipelineShaderStageCreateInfo const *pStage, 246511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PIPELINE_NODE *pipeline, 246611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert shader_module **out_module, 246711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter *out_entrypoint, 246811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkPhysicalDeviceFeatures const *enabledFeatures, 246911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<VkShaderModule, 247011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_ptr<shader_module>> const &shaderModuleMap) { 247111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool pass = true; 247211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto module_it = shaderModuleMap.find(pStage->module); 247311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto module = *out_module = module_it->second.get(); 247411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= validate_specialization_offsets(report_data, pStage); 247511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 247611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* find the entrypoint */ 247711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto entrypoint = *out_entrypoint = find_entrypoint(module, pStage->pName, pStage->stage); 247811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (entrypoint == module->end()) { 247911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 248011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_MISSING_ENTRYPOINT, "SC", 248111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "No entrypoint found named `%s` for stage %s", pStage->pName, 248211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkShaderStageFlagBits(pStage->stage))) { 248311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 248411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 248511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 248611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 248711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* validate shader capabilities against enabled device features */ 248811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= validate_shader_capabilities(report_data, module, enabledFeatures); 248911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 249011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* mark accessible ids */ 249111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_set<uint32_t> accessible_ids; 249211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert mark_accessible_ids(module, entrypoint, accessible_ids); 249311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 249411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* validate descriptor set layout against what the entrypoint actually uses */ 249511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::map<descriptor_slot_t, interface_var> descriptor_uses; 249611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert collect_interface_by_descriptor_slot(report_data, module, accessible_ids, descriptor_uses); 249711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 249811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pipelineLayout = pipeline->pipelineLayout; 249911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 250011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* validate push constant usage */ 250111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= validate_push_constant_usage(report_data, &pipelineLayout->pushConstantRanges, 250211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert module, accessible_ids, pStage->stage); 250311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 250411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* validate descriptor use */ 250511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto use : descriptor_uses) { 250611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // While validating shaders capture which slots are used by the pipeline 250711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pipeline->active_slots[use.first.first].insert(use.first.second); 250811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 250911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* verify given pipelineLayout has requested setLayout with requested binding */ 251011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const auto & binding = get_descriptor_binding(pipelineLayout, use.first); 251111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned required_descriptor_count; 251211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 251311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!binding) { 251411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 251511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_MISSING_DESCRIPTOR, "SC", 251611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Shader uses descriptor slot %u.%u (used as type `%s`) but not declared in pipeline layout", 251711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str())) { 251811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 251911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 252011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (~binding->stageFlags & pStage->stage) { 252111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 252211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /*dev*/ 0, __LINE__, SHADER_CHECKER_DESCRIPTOR_NOT_ACCESSIBLE_FROM_STAGE, "SC", 252311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Shader uses descriptor slot %u.%u (used " 252411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "as type `%s`) but descriptor not " 252511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "accessible from stage %s", 252611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str(), 252711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkShaderStageFlagBits(pStage->stage))) { 252811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 252911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 253011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (!descriptor_type_match(module, use.second.type_id, binding->descriptorType, 253111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /*out*/ required_descriptor_count)) { 253211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 253311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH, "SC", "Type mismatch on descriptor slot " 253411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%u.%u (used as type `%s`) but " 253511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "descriptor of type %s", 253611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str(), 253711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkDescriptorType(binding->descriptorType))) { 253811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 253911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 254011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (binding->descriptorCount < required_descriptor_count) { 254111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 254211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH, "SC", 254311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Shader expects at least %u descriptors for binding %u.%u (used as type `%s`) but only %u provided", 254411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert required_descriptor_count, use.first.first, use.first.second, 254511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert describe_type(module, use.second.type_id).c_str(), binding->descriptorCount)) { 254611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass = false; 254711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 254811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 254911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 255011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 255111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pass; 255211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 255311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 255411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 255511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Validate that the shaders used by the given pipeline and store the active_slots 255611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// that are actually used by the pipeline into pPipeline->active_slots 255711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_and_capture_pipeline_shader_state(debug_report_data *report_data, PIPELINE_NODE *pPipeline, 255811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkPhysicalDeviceFeatures const *enabledFeatures, 255911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<VkShaderModule, unique_ptr<shader_module>> const & shaderModuleMap) { 256011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pCreateInfo = pPipeline->graphicsPipelineCI.ptr(); 256111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int vertex_stage = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT); 256211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int fragment_stage = get_shader_stage_id(VK_SHADER_STAGE_FRAGMENT_BIT); 256311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 256411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert shader_module *shaders[5]; 256511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memset(shaders, 0, sizeof(shaders)); 256611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter entrypoints[5]; 256711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memset(entrypoints, 0, sizeof(entrypoints)); 256811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkPipelineVertexInputStateCreateInfo const *vi = 0; 256911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool pass = true; 257011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 257111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { 257211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pStage = &pCreateInfo->pStages[i]; 257311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto stage_id = get_shader_stage_id(pStage->stage); 257411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= validate_pipeline_shader_stage(report_data, pStage, pPipeline, 257511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert &shaders[stage_id], &entrypoints[stage_id], 257611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert enabledFeatures, shaderModuleMap); 257711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 257811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 257911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert vi = pCreateInfo->pVertexInputState; 258011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 258111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (vi) { 258211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= validate_vi_consistency(report_data, vi); 258311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 258411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 258511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (shaders[vertex_stage]) { 258611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= validate_vi_against_vs_inputs(report_data, vi, shaders[vertex_stage], entrypoints[vertex_stage]); 258711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 258811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 258911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int producer = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT); 259011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int consumer = get_shader_stage_id(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); 259111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 259211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (!shaders[producer] && producer != fragment_stage) { 259311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert producer++; 259411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert consumer++; 259511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 259611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 259711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (; producer != fragment_stage && consumer <= fragment_stage; consumer++) { 259811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(shaders[producer]); 259911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (shaders[consumer]) { 260011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= validate_interface_between_stages(report_data, 260111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert shaders[producer], entrypoints[producer], &shader_stage_attribs[producer], 260211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert shaders[consumer], entrypoints[consumer], &shader_stage_attribs[consumer]); 260311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 260411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert producer = consumer; 260511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 260611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 260711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 260811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (shaders[fragment_stage] && pPipeline->renderPass) { 260911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass &= validate_fs_outputs_against_render_pass(report_data, shaders[fragment_stage], entrypoints[fragment_stage], 261011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeline->renderPass, pCreateInfo->subpass); 261111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 261211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 261311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pass; 261411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 261511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 261611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_compute_pipeline(debug_report_data *report_data, PIPELINE_NODE *pPipeline, VkPhysicalDeviceFeatures const *enabledFeatures, 261711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<VkShaderModule, unique_ptr<shader_module>> const & shaderModuleMap) { 261811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pCreateInfo = pPipeline->computePipelineCI.ptr(); 261911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 262011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert shader_module *module; 262111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spirv_inst_iter entrypoint; 262211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 262311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return validate_pipeline_shader_stage(report_data, &pCreateInfo->stage, pPipeline, 262411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert &module, &entrypoint, enabledFeatures, shaderModuleMap); 262511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 262611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 262711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Return Set node ptr for specified set or else NULL 262811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic cvdescriptorset::DescriptorSet *getSetNode(layer_data *my_data, const VkDescriptorSet set) { 262911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (my_data->setMap.find(set) == my_data->setMap.end()) { 263011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return NULL; 263111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 263211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return my_data->setMap[set]; 263311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 263411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For the given command buffer, verify and update the state for activeSetBindingsPairs 263511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This includes: 263611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 1. Verifying that any dynamic descriptor in that set has a valid dynamic offset bound. 263711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// To be valid, the dynamic offset combined with the offset and range from its 263811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// descriptor update must not overflow the size of its buffer being updated 263911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 2. Grow updateImages for given pCB to include any bound STORAGE_IMAGE descriptor images 264011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 3. Grow updateBuffers for pCB to include buffers from STORAGE*_BUFFER descriptor buffers 264111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_and_update_drawtime_descriptor_state( 264211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data, GLOBAL_CB_NODE *pCB, 264311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const vector<std::tuple<cvdescriptorset::DescriptorSet *, unordered_set<uint32_t>, 264411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<uint32_t> const *>> &activeSetBindingsPairs) { 264511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool result = false; 264611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto set_bindings_pair : activeSetBindingsPairs) { 264711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cvdescriptorset::DescriptorSet *set_node = std::get<0>(set_bindings_pair); 264811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string err_str; 264911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!set_node->ValidateDrawState(std::get<1>(set_bindings_pair), *std::get<2>(set_bindings_pair), 265011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert &err_str)) { 265111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Report error here 265211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto set = set_node->GetSet(); 265311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 265411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(set), __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 265511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "DS 0x%" PRIxLEAST64 " encountered the following validation error at draw time: %s", 265611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(set), err_str.c_str()); 265711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 265811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_node->GetStorageUpdates(std::get<1>(set_bindings_pair), &pCB->updateBuffers, &pCB->updateImages); 265911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 266011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 266111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 266211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// TODO : This is a temp function that naively updates bound storage images and buffers based on which descriptor sets are bound. 266311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// When validate_and_update_draw_state() handles compute shaders so that active_slots is correct for compute pipelines, this 266411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// function can be killed and validate_and_update_draw_state() used instead 266511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void update_shader_storage_images_and_buffers(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { 266611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // For the bound descriptor sets, pull off any storage images and buffers 266711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // This may be more than are actually updated depending on which are active, but for now this is a stop-gap for compute 266811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // pipelines 266911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto set : pCB->lastBound[VK_PIPELINE_BIND_POINT_COMPUTE].uniqueBoundSets) { 267011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set->GetAllStorageUpdates(&pCB->updateBuffers, &pCB->updateImages); 267111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 267211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 267311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 267411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For given pipeline, return number of MSAA samples, or one if MSAA disabled 267511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic VkSampleCountFlagBits getNumSamples(PIPELINE_NODE const *pipe) { 267611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pipe->graphicsPipelineCI.pMultisampleState != NULL && 267711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO == pipe->graphicsPipelineCI.pMultisampleState->sType) { 267811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pipe->graphicsPipelineCI.pMultisampleState->rasterizationSamples; 267911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 268011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_SAMPLE_COUNT_1_BIT; 268111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 268211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 268311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Validate draw-time state related to the PSO 268411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validatePipelineDrawtimeState(layer_data const *my_data, const GLOBAL_CB_NODE *pCB, 268511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkPipelineBindPoint pipelineBindPoint, PIPELINE_NODE const *pPipeline) { 268611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 268711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) { 268811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Verify that any MSAA request in PSO matches sample# in bound FB 268911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Skip the check if rasterization is disabled. 269011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pPipeline->graphicsPipelineCI.pRasterizationState || 269111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) { 269211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkSampleCountFlagBits pso_num_samples = getNumSamples(pPipeline); 269311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->activeRenderPass) { 269411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkRenderPassCreateInfo *render_pass_info = pCB->activeRenderPass->pCreateInfo; 269511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pCB->activeSubpass]; 269611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkSampleCountFlagBits subpass_num_samples = VkSampleCountFlagBits(0); 269711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t i; 269811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 269911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState; 270011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((color_blend_state != NULL) && (pCB->activeSubpass == pPipeline->graphicsPipelineCI.subpass) && 270111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount)) { 270211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 270311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 270411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 270511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Render pass subpass %u mismatch with blending state defined and blend state attachment " 270611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "count %u while subpass color attachment count %u in Pipeline (0x%" PRIxLEAST64 ")! These " 270711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "must be the same at draw-time.", 270811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeSubpass, color_blend_state->attachmentCount, subpass_desc->colorAttachmentCount, 270911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(pPipeline->pipeline)); 271011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 271111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 271211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (i = 0; i < subpass_desc->colorAttachmentCount; i++) { 271311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkSampleCountFlagBits samples; 271411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 271511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass_desc->pColorAttachments[i].attachment == VK_ATTACHMENT_UNUSED) 271611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 271711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 271811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert samples = render_pass_info->pAttachments[subpass_desc->pColorAttachments[i].attachment].samples; 271911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass_num_samples == static_cast<VkSampleCountFlagBits>(0)) { 272011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass_num_samples = samples; 272111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (subpass_num_samples != samples) { 272211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass_num_samples = static_cast<VkSampleCountFlagBits>(-1); 272311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 272411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 272511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 272611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((subpass_desc->pDepthStencilAttachment != NULL) && 272711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)) { 272811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSampleCountFlagBits samples = 272911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert render_pass_info->pAttachments[subpass_desc->pDepthStencilAttachment->attachment].samples; 273011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass_num_samples == static_cast<VkSampleCountFlagBits>(0)) 273111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass_num_samples = samples; 273211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert else if (subpass_num_samples != samples) 273311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass_num_samples = static_cast<VkSampleCountFlagBits>(-1); 273411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 273511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 273611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (((subpass_desc->colorAttachmentCount > 0) || (subpass_desc->pDepthStencilAttachment != NULL)) && 273711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pso_num_samples != subpass_num_samples)) { 273811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 273911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 274011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS", 274111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Num samples mismatch! At draw-time in Pipeline (0x%" PRIxLEAST64 274211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") with %u samples while current RenderPass (0x%" PRIxLEAST64 ") w/ %u samples!", 274311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(pPipeline->pipeline), pso_num_samples, 274411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(pCB->activeRenderPass->renderPass), subpass_num_samples); 274511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 274611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 274711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 274811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS", 274911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "No active render pass found at draw-time in Pipeline (0x%" PRIxLEAST64 ")!", 275011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(pPipeline->pipeline)); 275111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 275211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 275311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Add more checks here 275411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 275511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Validate non-gfx pipeline updates 275611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 275711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 275811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 275911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 276011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Validate overall state at the time of a draw call 276111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_and_update_draw_state(layer_data *my_data, GLOBAL_CB_NODE *pCB, const bool indexedDraw, 276211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkPipelineBindPoint bindPoint) { 276311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool result = false; 276411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto const &state = pCB->lastBound[bindPoint]; 276511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PIPELINE_NODE *pPipe = getPipeline(my_data, state.pipeline); 276611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (nullptr == pPipe) { 276711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= log_msg( 276811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 276911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_PIPELINE, "DS", 277011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "At Draw/Dispatch time no valid VkPipeline is bound! This is illegal. Please bind one with vkCmdBindPipeline()."); 277111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Early return as any further checks below will be busted w/o a pipeline 277211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result) 277311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 277411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 277511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // First check flag states 277611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_PIPELINE_BIND_POINT_GRAPHICS == bindPoint) 277711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = validate_draw_state_flags(my_data, pCB, pPipe, indexedDraw); 277811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert else { 277911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // First block of code below to validate active sets should eventually 278011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // work for the compute case but currently doesn't so return early for now 278111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : When active sets in compute shaders are correctly parsed, 278211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // stop returning early here and handle them in top block below 278311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 278411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 278511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 278611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Now complete other state checks 278711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : When Compute shaders are properly parsed, fix this section to validate them as well 278811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (state.pipelineLayout) { 278911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string errorString; 279011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Need a vector (vs. std::set) of active Sets for dynamicOffset validation in case same set bound w/ different offsets 279111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert vector<std::tuple<cvdescriptorset::DescriptorSet *, unordered_set<uint32_t>, std::vector<uint32_t> const *>> activeSetBindingsPairs; 279211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto & setBindingPair : pPipe->active_slots) { 279311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t setIndex = setBindingPair.first; 279411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If valid set is not bound throw an error 279511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((state.boundDescriptorSets.size() <= setIndex) || (!state.boundDescriptorSets[setIndex])) { 279611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 279711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS", 279811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VkPipeline 0x%" PRIxLEAST64 " uses set #%u but that set is not bound.", (uint64_t)pPipe->pipeline, 279911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert setIndex); 280011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (!verify_set_layout_compatibility(my_data, state.boundDescriptorSets[setIndex], 280111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipe->graphicsPipelineCI.layout, setIndex, errorString)) { 280211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Set is bound but not compatible w/ overlapping pipelineLayout from PSO 280311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDescriptorSet setHandle = state.boundDescriptorSets[setIndex]->GetSet(); 280411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= 280511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 280611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)setHandle, __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS", 280711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VkDescriptorSet (0x%" PRIxLEAST64 280811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") bound as set #%u is not compatible with overlapping VkPipelineLayout 0x%" PRIxLEAST64 " due to: %s", 280911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)setHandle, setIndex, (uint64_t)pPipe->graphicsPipelineCI.layout, errorString.c_str()); 281011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { // Valid set is bound and layout compatible, validate that it's updated 281111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Pull the set node 281211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cvdescriptorset::DescriptorSet *pSet = state.boundDescriptorSets[setIndex]; 281311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Save vector of all active sets to verify dynamicOffsets below 281411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert activeSetBindingsPairs.push_back(std::make_tuple(pSet, setBindingPair.second, 281511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert &state.dynamicOffsets[setIndex])); 281611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Make sure set has been updated if it has no immutable samplers 281711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If it has immutable samplers, we'll flag error later as needed depending on binding 281811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pSet->IsUpdated()) { 281911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto binding : setBindingPair.second) { 282011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pSet->GetImmutableSamplerPtrFromBinding(binding)) { 282111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= log_msg( 282211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 282311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pSet->GetSet(), __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 282411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "DS 0x%" PRIxLEAST64 " bound but it was never updated. It is now being used to draw so " 282511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "this will result in undefined behavior.", 282611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pSet->GetSet()); 282711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 282811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 282911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 283011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 283111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 283211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // For given active slots, verify any dynamic descriptors and record updated images & buffers 283311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= validate_and_update_drawtime_descriptor_state(my_data, pCB, activeSetBindingsPairs); 283411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 283511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : If/when compute pipelines/shaders are handled above, code below is only for gfx bind poing 283611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert //if (VK_PIPELINE_BIND_POINT_GRAPHICS == bindPoint) { 283711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Verify Vtx binding 283811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipe->vertexBindingDescriptions.size() > 0) { 283911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (size_t i = 0; i < pPipe->vertexBindingDescriptions.size(); i++) { 284011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((pCB->currentDrawData.buffers.size() < (i + 1)) || (pCB->currentDrawData.buffers[i] == VK_NULL_HANDLE)) { 284111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 284211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", 284311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "The Pipeline State Object (0x%" PRIxLEAST64 284411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") expects that this Command Buffer's vertex binding Index " PRINTF_SIZE_T_SPECIFIER 284511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " should be set via vkCmdBindVertexBuffers.", 284611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)state.pipeline, i); 284711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 284811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 284911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 285011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCB->currentDrawData.buffers.empty()) { 285111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 285211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 0, __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", 285311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Vertex buffers are bound to command buffer (0x%" PRIxLEAST64 285411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") but no vertex buffers are attached to this Pipeline State Object (0x%" PRIxLEAST64 ").", 285511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pCB->commandBuffer, (uint64_t)state.pipeline); 285611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 285711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 285811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count. 285911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Skip check if rasterization is disabled or there is no viewport. 286011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((!pPipe->graphicsPipelineCI.pRasterizationState || 286111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipe->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) && 286211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipe->graphicsPipelineCI.pViewportState) { 286311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool dynViewport = isDynamic(pPipe, VK_DYNAMIC_STATE_VIEWPORT); 286411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool dynScissor = isDynamic(pPipe, VK_DYNAMIC_STATE_SCISSOR); 286511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dynViewport) { 286611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->viewports.size() != pPipe->graphicsPipelineCI.pViewportState->viewportCount) { 286711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 286811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", 286911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Dynamic viewportCount from vkCmdSetViewport() is " PRINTF_SIZE_T_SPECIFIER 287011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ", but PSO viewportCount is %u. These counts must match.", 287111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->viewports.size(), pPipe->graphicsPipelineCI.pViewportState->viewportCount); 287211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 287311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 287411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dynScissor) { 287511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->scissors.size() != pPipe->graphicsPipelineCI.pViewportState->scissorCount) { 287611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 287711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", 287811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Dynamic scissorCount from vkCmdSetScissor() is " PRINTF_SIZE_T_SPECIFIER 287911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ", but PSO scissorCount is %u. These counts must match.", 288011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->scissors.size(), pPipe->graphicsPipelineCI.pViewportState->scissorCount); 288111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 288211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 288311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 288411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert //} // end of "if (VK_PIPELINE_BIND_POINT_GRAPHICS == bindPoint) {" block 288511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 288611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Check general pipeline state that needs to be validated at drawtime 288711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= validatePipelineDrawtimeState(my_data, pCB, bindPoint, pPipe); 288811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 288911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 289011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 289111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 289211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Validate HW line width capabilities prior to setting requested line width. 289311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool verifyLineWidth(layer_data *my_data, DRAW_STATE_ERROR dsError, const uint64_t &target, float lineWidth) { 289411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 289511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 289611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // First check to see if the physical device supports wide lines. 289711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((VK_FALSE == my_data->phys_dev_properties.features.wideLines) && (1.0f != lineWidth)) { 289811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, target, __LINE__, 289911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dsError, "DS", "Attempt to set lineWidth to %f but physical device wideLines feature " 290011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "not supported/enabled so lineWidth must be 1.0f!", 290111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lineWidth); 290211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 290311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Otherwise, make sure the width falls in the valid range. 290411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((my_data->phys_dev_properties.properties.limits.lineWidthRange[0] > lineWidth) || 290511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (my_data->phys_dev_properties.properties.limits.lineWidthRange[1] < lineWidth)) { 290611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, target, 290711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, dsError, "DS", "Attempt to set lineWidth to %f but physical device limits line width " 290811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "to between [%f, %f]!", 290911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lineWidth, my_data->phys_dev_properties.properties.limits.lineWidthRange[0], 291011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->phys_dev_properties.properties.limits.lineWidthRange[1]); 291111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 291211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 291311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 291411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 291511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 291611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 291711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Verify that create state for a pipeline is valid 291811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool verifyPipelineCreateState(layer_data *my_data, const VkDevice device, std::vector<PIPELINE_NODE *> pPipelines, 291911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int pipelineIndex) { 292011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 292111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 292211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PIPELINE_NODE *pPipeline = pPipelines[pipelineIndex]; 292311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 292411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If create derivative bit is set, check that we've specified a base 292511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // pipeline correctly, and that the base pipeline was created to allow 292611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // derivatives. 292711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT) { 292811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PIPELINE_NODE *pBasePipeline = nullptr; 292911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!((pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) ^ 293011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipeline->graphicsPipelineCI.basePipelineIndex != -1))) { 293111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 293211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 293311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid Pipeline CreateInfo: exactly one of base pipeline index and handle must be specified"); 293411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (pPipeline->graphicsPipelineCI.basePipelineIndex != -1) { 293511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipeline->graphicsPipelineCI.basePipelineIndex >= pipelineIndex) { 293611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 293711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 293811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 293911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid Pipeline CreateInfo: base pipeline must occur earlier in array than derivative pipeline."); 294011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 294111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pBasePipeline = pPipelines[pPipeline->graphicsPipelineCI.basePipelineIndex]; 294211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 294311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) { 294411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pBasePipeline = getPipeline(my_data, pPipeline->graphicsPipelineCI.basePipelineHandle); 294511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 294611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 294711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pBasePipeline && !(pBasePipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT)) { 294811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 294911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 295011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid Pipeline CreateInfo: base pipeline does not allow derivatives."); 295111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 295211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 295311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 295411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipeline->graphicsPipelineCI.pColorBlendState != NULL) { 295511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!my_data->phys_dev_properties.features.independentBlend) { 295611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipeline->attachments.size() > 1) { 295711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkPipelineColorBlendAttachmentState *pAttachments = &pPipeline->attachments[0]; 295811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (size_t i = 1; i < pPipeline->attachments.size(); i++) { 295911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((pAttachments[0].blendEnable != pAttachments[i].blendEnable) || 296011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pAttachments[0].srcColorBlendFactor != pAttachments[i].srcColorBlendFactor) || 296111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pAttachments[0].dstColorBlendFactor != pAttachments[i].dstColorBlendFactor) || 296211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pAttachments[0].colorBlendOp != pAttachments[i].colorBlendOp) || 296311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pAttachments[0].srcAlphaBlendFactor != pAttachments[i].srcAlphaBlendFactor) || 296411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pAttachments[0].dstAlphaBlendFactor != pAttachments[i].dstAlphaBlendFactor) || 296511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pAttachments[0].alphaBlendOp != pAttachments[i].alphaBlendOp) || 296611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pAttachments[0].colorWriteMask != pAttachments[i].colorWriteMask)) { 296711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 296811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 296911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INDEPENDENT_BLEND, "DS", "Invalid Pipeline CreateInfo: If independent blend feature not " 297011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "enabled, all elements of pAttachments must be identical"); 297111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 297211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 297311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 297411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 297511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!my_data->phys_dev_properties.features.logicOp && 297611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipeline->graphicsPipelineCI.pColorBlendState->logicOpEnable != VK_FALSE)) { 297711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 297811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 297911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_DISABLED_LOGIC_OP, "DS", 298011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid Pipeline CreateInfo: If logic operations feature not enabled, logicOpEnable must be VK_FALSE"); 298111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 298211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((pPipeline->graphicsPipelineCI.pColorBlendState->logicOpEnable == VK_TRUE) && 298311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ((pPipeline->graphicsPipelineCI.pColorBlendState->logicOp < VK_LOGIC_OP_CLEAR) || 298411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipeline->graphicsPipelineCI.pColorBlendState->logicOp > VK_LOGIC_OP_SET))) { 298511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 298611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 298711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_LOGIC_OP, "DS", 298811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid Pipeline CreateInfo: If logicOpEnable is VK_TRUE, logicOp must be a valid VkLogicOp value"); 298911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 299011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 299111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 299211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Ensure the subpass index is valid. If not, then validate_and_capture_pipeline_shader_state 299311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // produces nonsense errors that confuse users. Other layers should already 299411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // emit errors for renderpass being invalid. 299511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto renderPass = getRenderPass(my_data, pPipeline->graphicsPipelineCI.renderPass); 299611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (renderPass && 299711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeline->graphicsPipelineCI.subpass >= renderPass->pCreateInfo->subpassCount) { 299811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 299911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: Subpass index %u " 300011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "is out of range for this renderpass (0..%u)", 300111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeline->graphicsPipelineCI.subpass, renderPass->pCreateInfo->subpassCount - 1); 300211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 300311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 300411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!validate_and_capture_pipeline_shader_state(my_data->report_data, pPipeline, &my_data->phys_dev_properties.features, 300511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->shaderModuleMap)) { 300611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = true; 300711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 300811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Each shader's stage must be unique 300911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipeline->duplicate_shaders) { 301011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t stage = VK_SHADER_STAGE_VERTEX_BIT; stage & VK_SHADER_STAGE_ALL_GRAPHICS; stage <<= 1) { 301111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipeline->duplicate_shaders & stage) { 301211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 301311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 301411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid Pipeline CreateInfo State: Multiple shaders provided for stage %s", 301511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkShaderStageFlagBits(VkShaderStageFlagBits(stage))); 301611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 301711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 301811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 301911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // VS is required 302011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(pPipeline->active_shaders & VK_SHADER_STAGE_VERTEX_BIT)) { 302111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 302211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 302311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: Vtx Shader required"); 302411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 302511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Either both or neither TC/TE shaders should be defined 302611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (((pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) == 0) != 302711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ((pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) == 0)) { 302811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 302911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 303011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair"); 303111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 303211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Compute shaders should be specified independent of Gfx shaders 303311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((pPipeline->active_shaders & VK_SHADER_STAGE_COMPUTE_BIT) && 303411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipeline->active_shaders & 303511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | 303611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_FRAGMENT_BIT))) { 303711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 303811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 303911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid Pipeline CreateInfo State: Do not specify Compute Shader for Gfx Pipeline"); 304011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 304111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology is only valid for tessellation pipelines. 304211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Mismatching primitive topology and tessellation fails graphics pipeline creation. 304311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipeline->active_shaders & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) && 304411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (!pPipeline->graphicsPipelineCI.pInputAssemblyState || 304511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeline->graphicsPipelineCI.pInputAssemblyState->topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)) { 304611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 304711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: " 304811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST must be set as IA " 304911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "topology for tessellation pipelines"); 305011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 305111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipeline->graphicsPipelineCI.pInputAssemblyState && 305211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeline->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) { 305311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (~pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) { 305411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 305511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: " 305611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " 305711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "topology is only valid for tessellation pipelines"); 305811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 305911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pPipeline->graphicsPipelineCI.pTessellationState) { 306011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 306111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 306211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Invalid Pipeline CreateInfo State: " 306311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "pTessellationState is NULL when VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " 306411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "topology used. pTessellationState must not be NULL in this case."); 306511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (!pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints || 306611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints > 32)) { 306711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 306811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: " 306911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " 307011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "topology used with patchControlPoints value %u." 307111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " patchControlPoints should be >0 and <=32.", 307211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints); 307311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 307411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 307511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If a rasterization state is provided, make sure that the line width conforms to the HW. 307611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipeline->graphicsPipelineCI.pRasterizationState) { 307711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!isDynamic(pPipeline, VK_DYNAMIC_STATE_LINE_WIDTH)) { 307811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= verifyLineWidth(my_data, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, reinterpret_cast<uint64_t &>(pPipeline), 307911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeline->graphicsPipelineCI.pRasterizationState->lineWidth); 308011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 308111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 308211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Viewport state must be included if rasterization is enabled. 308311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If the viewport state is included, the viewport and scissor counts should always match. 308411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // NOTE : Even if these are flagged as dynamic, counts need to be set correctly for shader compiler 308511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pPipeline->graphicsPipelineCI.pRasterizationState || 308611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) { 308711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pPipeline->graphicsPipelineCI.pViewportState) { 308811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 308911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "Gfx Pipeline pViewportState is null. Even if viewport " 309011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "and scissors are dynamic PSO must include " 309111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "viewportCount and scissorCount in pViewportState."); 309211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (pPipeline->graphicsPipelineCI.pViewportState->scissorCount != 309311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeline->graphicsPipelineCI.pViewportState->viewportCount) { 309411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 309511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", 309611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Gfx Pipeline viewport count (%u) must match scissor count (%u).", 309711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeline->graphicsPipelineCI.pViewportState->viewportCount, 309811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeline->graphicsPipelineCI.pViewportState->scissorCount); 309911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 310011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If viewport or scissor are not dynamic, then verify that data is appropriate for count 310111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT); 310211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR); 310311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!dynViewport) { 310411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipeline->graphicsPipelineCI.pViewportState->viewportCount && 310511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert !pPipeline->graphicsPipelineCI.pViewportState->pViewports) { 310611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 310711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", 310811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Gfx Pipeline viewportCount is %u, but pViewports is NULL. For non-zero viewportCount, you " 310911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "must either include pViewports data, or include viewport in pDynamicState and set it with " 311011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdSetViewport().", 311111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeline->graphicsPipelineCI.pViewportState->viewportCount); 311211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 311311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 311411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!dynScissor) { 311511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipeline->graphicsPipelineCI.pViewportState->scissorCount && 311611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert !pPipeline->graphicsPipelineCI.pViewportState->pScissors) { 311711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 311811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", 311911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Gfx Pipeline scissorCount is %u, but pScissors is NULL. For non-zero scissorCount, you " 312011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "must either include pScissors data, or include scissor in pDynamicState and set it with " 312111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdSetScissor().", 312211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeline->graphicsPipelineCI.pViewportState->scissorCount); 312311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 312411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 312511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 312611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 312711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 312811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 312911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 313011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Free the Pipeline nodes 313111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void deletePipelines(layer_data *my_data) { 313211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (my_data->pipelineMap.size() <= 0) 313311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 313411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto &pipe_map_pair : my_data->pipelineMap) { 313511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete pipe_map_pair.second; 313611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 313711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->pipelineMap.clear(); 313811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 313911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 314011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Block of code at start here specifically for managing/tracking DSs 314111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 314211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Return Pool node ptr for specified pool or else NULL 314311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic DESCRIPTOR_POOL_NODE *getPoolNode(layer_data *my_data, const VkDescriptorPool pool) { 314411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (my_data->descriptorPoolMap.find(pool) == my_data->descriptorPoolMap.end()) { 314511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return NULL; 314611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 314711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return my_data->descriptorPoolMap[pool]; 314811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 314911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 315011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Return false if update struct is of valid type, otherwise flag error and return code from callback 315111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validUpdateStruct(layer_data *my_data, const VkDevice device, const GENERIC_HEADER *pUpdateStruct) { 315211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (pUpdateStruct->sType) { 315311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET: 315411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET: 315511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 315611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 315711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 315811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_UPDATE_STRUCT, "DS", 315911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", 316011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType); 316111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 316211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 316311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 316411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Set count for given update struct in the last parameter 316511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic uint32_t getUpdateCount(layer_data *my_data, const VkDevice device, const GENERIC_HEADER *pUpdateStruct) { 316611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (pUpdateStruct->sType) { 316711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET: 316811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return ((VkWriteDescriptorSet *)pUpdateStruct)->descriptorCount; 316911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET: 317011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Need to understand this case better and make sure code is correct 317111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return ((VkCopyDescriptorSet *)pUpdateStruct)->descriptorCount; 317211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 317311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return 0; 317411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 317511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 317611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 317711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For given layout and update, return the first overall index of the layout that is updated 317811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic uint32_t getUpdateStartIndex(layer_data *my_data, const VkDevice device, const uint32_t binding_start_index, 317911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t arrayIndex, const GENERIC_HEADER *pUpdateStruct) { 318011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return binding_start_index + arrayIndex; 318111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 318211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For given layout and update, return the last overall index of the layout that is updated 318311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic uint32_t getUpdateEndIndex(layer_data *my_data, const VkDevice device, const uint32_t binding_start_index, 318411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t arrayIndex, const GENERIC_HEADER *pUpdateStruct) { 318511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t count = getUpdateCount(my_data, device, pUpdateStruct); 318611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return binding_start_index + arrayIndex + count - 1; 318711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 318811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Verify that the descriptor type in the update struct matches what's expected by the layout 318911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateUpdateConsistency(layer_data *my_data, const VkDevice device, const VkDescriptorType layout_type, 319011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const GENERIC_HEADER *pUpdateStruct, uint32_t startIndex, uint32_t endIndex) { 319111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // First get actual type of update 319211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 319311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDescriptorType actualType = VK_DESCRIPTOR_TYPE_MAX_ENUM; 319411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (pUpdateStruct->sType) { 319511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET: 319611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert actualType = ((VkWriteDescriptorSet *)pUpdateStruct)->descriptorType; 319711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 319811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET: 319911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* no need to validate */ 320011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 320111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 320211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 320311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 320411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_UPDATE_STRUCT, "DS", 320511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", 320611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType); 320711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 320811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 320911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (layout_type != actualType) { 321011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 321111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 321211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_DESCRIPTOR_TYPE_MISMATCH, "DS", 321311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Write descriptor update has descriptor type %s that does not match overlapping binding descriptor type of %s!", 321411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkDescriptorType(actualType), string_VkDescriptorType(layout_type)); 321511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 321611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 321711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 321811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 321911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//TODO: Consolidate functions 322011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool FindLayout(const GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, IMAGE_CMD_BUF_LAYOUT_NODE &node, const VkImageAspectFlags aspectMask) { 322111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(pCB->commandBuffer), layer_data_map); 322211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(imgpair.subresource.aspectMask & aspectMask)) { 322311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 322411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 322511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageAspectFlags oldAspectMask = imgpair.subresource.aspectMask; 322611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert imgpair.subresource.aspectMask = aspectMask; 322711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto imgsubIt = pCB->imageLayoutMap.find(imgpair); 322811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (imgsubIt == pCB->imageLayoutMap.end()) { 322911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 323011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 323111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (node.layout != VK_IMAGE_LAYOUT_MAX_ENUM && node.layout != imgsubIt->second.layout) { 323211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 323311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t&>(imgpair.image), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", 323411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot query for VkImage 0x%" PRIx64 " layout when combined aspect mask %d has multiple layout types: %s and %s", 323511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t&>(imgpair.image), oldAspectMask, string_VkImageLayout(node.layout), string_VkImageLayout(imgsubIt->second.layout)); 323611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 323711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (node.initialLayout != VK_IMAGE_LAYOUT_MAX_ENUM && node.initialLayout != imgsubIt->second.initialLayout) { 323811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 323911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t&>(imgpair.image), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", 324011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot query for VkImage 0x%" PRIx64 " layout when combined aspect mask %d has multiple initial layout types: %s and %s", 324111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t&>(imgpair.image), oldAspectMask, string_VkImageLayout(node.initialLayout), string_VkImageLayout(imgsubIt->second.initialLayout)); 324211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 324311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert node = imgsubIt->second; 324411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 324511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 324611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 324711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool FindLayout(const layer_data *my_data, ImageSubresourcePair imgpair, VkImageLayout &layout, const VkImageAspectFlags aspectMask) { 324811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(imgpair.subresource.aspectMask & aspectMask)) { 324911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 325011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 325111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageAspectFlags oldAspectMask = imgpair.subresource.aspectMask; 325211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert imgpair.subresource.aspectMask = aspectMask; 325311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto imgsubIt = my_data->imageLayoutMap.find(imgpair); 325411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (imgsubIt == my_data->imageLayoutMap.end()) { 325511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 325611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 325711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (layout != VK_IMAGE_LAYOUT_MAX_ENUM && layout != imgsubIt->second.layout) { 325811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 325911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t&>(imgpair.image), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", 326011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot query for VkImage 0x%" PRIx64 " layout when combined aspect mask %d has multiple layout types: %s and %s", 326111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t&>(imgpair.image), oldAspectMask, string_VkImageLayout(layout), string_VkImageLayout(imgsubIt->second.layout)); 326211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 326311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layout = imgsubIt->second.layout; 326411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 326511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 326611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 326711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// find layout(s) on the cmd buf level 326811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool FindLayout(const GLOBAL_CB_NODE *pCB, VkImage image, VkImageSubresource range, IMAGE_CMD_BUF_LAYOUT_NODE &node) { 326911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ImageSubresourcePair imgpair = {image, true, range}; 327011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert node = IMAGE_CMD_BUF_LAYOUT_NODE(VK_IMAGE_LAYOUT_MAX_ENUM, VK_IMAGE_LAYOUT_MAX_ENUM); 327111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert FindLayout(pCB, imgpair, node, VK_IMAGE_ASPECT_COLOR_BIT); 327211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert FindLayout(pCB, imgpair, node, VK_IMAGE_ASPECT_DEPTH_BIT); 327311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert FindLayout(pCB, imgpair, node, VK_IMAGE_ASPECT_STENCIL_BIT); 327411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert FindLayout(pCB, imgpair, node, VK_IMAGE_ASPECT_METADATA_BIT); 327511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (node.layout == VK_IMAGE_LAYOUT_MAX_ENUM) { 327611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert imgpair = {image, false, VkImageSubresource()}; 327711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto imgsubIt = pCB->imageLayoutMap.find(imgpair); 327811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (imgsubIt == pCB->imageLayoutMap.end()) 327911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 328011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert node = imgsubIt->second; 328111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 328211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 328311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 328411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 328511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// find layout(s) on the global level 328611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool FindLayout(const layer_data *my_data, ImageSubresourcePair imgpair, VkImageLayout &layout) { 328711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layout = VK_IMAGE_LAYOUT_MAX_ENUM; 328811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert FindLayout(my_data, imgpair, layout, VK_IMAGE_ASPECT_COLOR_BIT); 328911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert FindLayout(my_data, imgpair, layout, VK_IMAGE_ASPECT_DEPTH_BIT); 329011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert FindLayout(my_data, imgpair, layout, VK_IMAGE_ASPECT_STENCIL_BIT); 329111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert FindLayout(my_data, imgpair, layout, VK_IMAGE_ASPECT_METADATA_BIT); 329211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (layout == VK_IMAGE_LAYOUT_MAX_ENUM) { 329311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert imgpair = {imgpair.image, false, VkImageSubresource()}; 329411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto imgsubIt = my_data->imageLayoutMap.find(imgpair); 329511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (imgsubIt == my_data->imageLayoutMap.end()) 329611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 329711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layout = imgsubIt->second.layout; 329811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 329911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 330011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 330111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 330211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool FindLayout(const layer_data *my_data, VkImage image, VkImageSubresource range, VkImageLayout &layout) { 330311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ImageSubresourcePair imgpair = {image, true, range}; 330411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return FindLayout(my_data, imgpair, layout); 330511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 330611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 330711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool FindLayouts(const layer_data *my_data, VkImage image, std::vector<VkImageLayout> &layouts) { 330811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto sub_data = my_data->imageSubresourceMap.find(image); 330911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (sub_data == my_data->imageSubresourceMap.end()) 331011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 331111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto imgIt = my_data->imageMap.find(image); 331211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (imgIt == my_data->imageMap.end()) 331311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 331411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool ignoreGlobal = false; 331511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Make this robust for >1 aspect mask. Now it will just say ignore 331611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // potential errors in this case. 331711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (sub_data->second.size() >= (imgIt->second.createInfo.arrayLayers * imgIt->second.createInfo.mipLevels + 1)) { 331811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ignoreGlobal = true; 331911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 332011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto imgsubpair : sub_data->second) { 332111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (ignoreGlobal && !imgsubpair.hasSubresource) 332211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 332311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto img_data = my_data->imageLayoutMap.find(imgsubpair); 332411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (img_data != my_data->imageLayoutMap.end()) { 332511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layouts.push_back(img_data->second.layout); 332611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 332711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 332811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 332911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 333011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 333111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Set the layout on the global level 333211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid SetLayout(layer_data *my_data, ImageSubresourcePair imgpair, const VkImageLayout &layout) { 333311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImage &image = imgpair.image; 333411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO (mlentine): Maybe set format if new? Not used atm. 333511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->imageLayoutMap[imgpair].layout = layout; 333611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO (mlentine): Maybe make vector a set? 333711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto subresource = std::find(my_data->imageSubresourceMap[image].begin(), my_data->imageSubresourceMap[image].end(), imgpair); 333811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subresource == my_data->imageSubresourceMap[image].end()) { 333911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->imageSubresourceMap[image].push_back(imgpair); 334011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 334111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 334211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 334311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Set the layout on the cmdbuf level 334411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid SetLayout(GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, const IMAGE_CMD_BUF_LAYOUT_NODE &node) { 334511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->imageLayoutMap[imgpair] = node; 334611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO (mlentine): Maybe make vector a set? 334711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto subresource = 334811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::find(pCB->imageSubresourceMap[imgpair.image].begin(), pCB->imageSubresourceMap[imgpair.image].end(), imgpair); 334911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subresource == pCB->imageSubresourceMap[imgpair.image].end()) { 335011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->imageSubresourceMap[imgpair.image].push_back(imgpair); 335111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 335211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 335311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 335411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid SetLayout(GLOBAL_CB_NODE *pCB, ImageSubresourcePair imgpair, const VkImageLayout &layout) { 335511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO (mlentine): Maybe make vector a set? 335611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (std::find(pCB->imageSubresourceMap[imgpair.image].begin(), pCB->imageSubresourceMap[imgpair.image].end(), imgpair) != 335711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->imageSubresourceMap[imgpair.image].end()) { 335811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->imageLayoutMap[imgpair].layout = layout; 335911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 336011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO (mlentine): Could be expensive and might need to be removed. 336111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(imgpair.hasSubresource); 336211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert IMAGE_CMD_BUF_LAYOUT_NODE node; 336311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!FindLayout(pCB, imgpair.image, imgpair.subresource, node)) { 336411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert node.initialLayout = layout; 336511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 336611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(pCB, imgpair, {node.initialLayout, layout}); 336711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 336811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 336911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 337011cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class OBJECT, class LAYOUT> 337111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid SetLayout(OBJECT *pObject, ImageSubresourcePair imgpair, const LAYOUT &layout, VkImageAspectFlags aspectMask) { 337211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (imgpair.subresource.aspectMask & aspectMask) { 337311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert imgpair.subresource.aspectMask = aspectMask; 337411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(pObject, imgpair, layout); 337511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 337611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 337711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 337811cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class OBJECT, class LAYOUT> 337911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid SetLayout(OBJECT *pObject, VkImage image, VkImageSubresource range, const LAYOUT &layout) { 338011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ImageSubresourcePair imgpair = {image, true, range}; 338111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_COLOR_BIT); 338211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_DEPTH_BIT); 338311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_STENCIL_BIT); 338411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(pObject, imgpair, layout, VK_IMAGE_ASPECT_METADATA_BIT); 338511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 338611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 338711cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class OBJECT, class LAYOUT> void SetLayout(OBJECT *pObject, VkImage image, const LAYOUT &layout) { 338811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ImageSubresourcePair imgpair = {image, false, VkImageSubresource()}; 338911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(pObject, image, imgpair, layout); 339011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 339111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 339211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid SetLayout(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkImageView imageView, const VkImageLayout &layout) { 339311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto image_view_data = dev_data->imageViewMap.find(imageView); 339411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(image_view_data != dev_data->imageViewMap.end()); 339511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImage &image = image_view_data->second.image; 339611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImageSubresourceRange &subRange = image_view_data->second.subresourceRange; 339711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Do not iterate over every possibility - consolidate where possible 339811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subRange.levelCount; j++) { 339911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t level = subRange.baseMipLevel + j; 340011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t k = 0; k < subRange.layerCount; k++) { 340111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t layer = subRange.baseArrayLayer + k; 340211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageSubresource sub = {subRange.aspectMask, level, layer}; 340311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(pCB, image, sub, layout); 340411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 340511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 340611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 340711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 340811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Validate that given set is valid and that it's not being used by an in-flight CmdBuffer 340911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// func_str is the name of the calling function 341011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Return false if no errors occur 341111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Return true if validation error occurs and callback returns true (to skip upcoming API call down the chain) 341211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateIdleDescriptorSet(const layer_data *my_data, VkDescriptorSet set, std::string func_str) { 341311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 341411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto set_node = my_data->setMap.find(set); 341511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (set_node == my_data->setMap.end()) { 341611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 341711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", 341811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", func_str.c_str(), 341911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(set)); 342011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 342111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (set_node->second->in_use.load()) { 342211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 342311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)(set), __LINE__, DRAWSTATE_OBJECT_INUSE, 342411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "DS", "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that is in use by a command buffer.", 342511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert func_str.c_str(), (uint64_t)(set)); 342611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 342711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 342811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 342911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 343011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 343111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Free the descriptor set, remove it from setMap and invalidate any cmd buffers that it was bound to 343211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void freeDescriptorSet(layer_data *dev_data, cvdescriptorset::DescriptorSet *descriptor_set) { 343311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->setMap.erase(descriptor_set->GetSet()); 343411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete descriptor_set; 343511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 343611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Free all DS Pools including their Sets & related sub-structs 343711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// NOTE : Calls to this function should be wrapped in mutex 343811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void deletePools(layer_data *my_data) { 343911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (my_data->descriptorPoolMap.size() <= 0) 344011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 344111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto ii = my_data->descriptorPoolMap.begin(); ii != my_data->descriptorPoolMap.end(); ++ii) { 344211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Remove this pools' sets from setMap and delete them 344311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto ds : (*ii).second->sets) { 344411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert freeDescriptorSet(my_data, ds); 344511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 344611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (*ii).second->sets.clear(); 344711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 344811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->descriptorPoolMap.clear(); 344911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 345011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 345111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void clearDescriptorPool(layer_data *my_data, const VkDevice device, const VkDescriptorPool pool, 345211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDescriptorPoolResetFlags flags) { 345311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DESCRIPTOR_POOL_NODE *pPool = getPoolNode(my_data, pool); 345411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pPool) { 345511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 345611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pool, __LINE__, DRAWSTATE_INVALID_POOL, "DS", 345711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Unable to find pool node for pool 0x%" PRIxLEAST64 " specified in vkResetDescriptorPool() call", (uint64_t)pool); 345811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 345911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: validate flags 346011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // For every set off of this pool, clear it, remove from setMap, and free cvdescriptorset::DescriptorSet 346111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto ds : pPool->sets) { 346211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert freeDescriptorSet(my_data, ds); 346311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 346411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPool->sets.clear(); 346511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Reset available count for each type and available sets for this pool 346611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pPool->availableDescriptorTypeCount.size(); ++i) { 346711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPool->availableDescriptorTypeCount[i] = pPool->maxDescriptorTypeCount[i]; 346811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 346911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPool->availableSets = pPool->maxSets; 347011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 347111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 347211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 347311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For given CB object, fetch associated CB Node from map 347411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic GLOBAL_CB_NODE *getCBNode(layer_data const *my_data, const VkCommandBuffer cb) { 347511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it = my_data->commandBufferMap.find(cb); 347611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (it == my_data->commandBufferMap.end()) { 347711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 347811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(cb), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 347911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Attempt to use CommandBuffer 0x%" PRIxLEAST64 " that doesn't exist!", (uint64_t)(cb)); 348011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return NULL; 348111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 348211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return it->second; 348311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 348411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Free all CB Nodes 348511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// NOTE : Calls to this function should be wrapped in mutex 348611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void deleteCommandBuffers(layer_data *my_data) { 348711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (my_data->commandBufferMap.empty()) { 348811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 348911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 349011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto ii = my_data->commandBufferMap.begin(); ii != my_data->commandBufferMap.end(); ++ii) { 349111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete (*ii).second; 349211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 349311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->commandBufferMap.clear(); 349411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 349511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 349611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool report_error_no_cb_begin(const layer_data *dev_data, const VkCommandBuffer cb, const char *caller_name) { 349711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 349811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)cb, __LINE__, DRAWSTATE_NO_BEGIN_COMMAND_BUFFER, "DS", 349911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "You must call vkBeginCommandBuffer() before this call to %s", caller_name); 350011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 350111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 350211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool validateCmdsInCmdBuffer(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd_type) { 350311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCB->activeRenderPass) 350411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 350511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 350611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS && 350711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (cmd_type != CMD_EXECUTECOMMANDS && cmd_type != CMD_NEXTSUBPASS && cmd_type != CMD_ENDRENDERPASS)) { 350811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 350911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 351011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Commands cannot be called in a subpass using secondary command buffers."); 351111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_INLINE && cmd_type == CMD_EXECUTECOMMANDS) { 351211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 351311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 351411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands() cannot be called in a subpass using inline commands."); 351511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 351611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 351711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 351811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 351911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool checkGraphicsBit(const layer_data *my_data, VkQueueFlags flags, const char *name) { 352011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(flags & VK_QUEUE_GRAPHICS_BIT)) 352111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 352211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 352311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot call %s on a command buffer allocated from a pool without graphics capabilities.", name); 352411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 352511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 352611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 352711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool checkComputeBit(const layer_data *my_data, VkQueueFlags flags, const char *name) { 352811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(flags & VK_QUEUE_COMPUTE_BIT)) 352911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 353011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 353111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot call %s on a command buffer allocated from a pool without compute capabilities.", name); 353211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 353311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 353411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 353511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool checkGraphicsOrComputeBit(const layer_data *my_data, VkQueueFlags flags, const char *name) { 353611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!((flags & VK_QUEUE_GRAPHICS_BIT) || (flags & VK_QUEUE_COMPUTE_BIT))) 353711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 353811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 353911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot call %s on a command buffer allocated from a pool without graphics capabilities.", name); 354011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 354111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 354211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 354311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Add specified CMD to the CmdBuffer in given pCB, flagging errors if CB is not 354411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// in the recording state or if there's an issue with the Cmd ordering 354511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool addCmd(const layer_data *my_data, GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd, const char *caller_name) { 354611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 354711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pool_data = my_data->commandPoolMap.find(pCB->createInfo.commandPool); 354811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pool_data != my_data->commandPoolMap.end()) { 354911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkQueueFlags flags = my_data->phys_dev_properties.queue_family_properties[pool_data->second.queueFamilyIndex].queueFlags; 355011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (cmd) { 355111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BINDPIPELINE: 355211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BINDPIPELINEDELTA: 355311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BINDDESCRIPTORSETS: 355411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_FILLBUFFER: 355511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_CLEARCOLORIMAGE: 355611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETEVENT: 355711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_RESETEVENT: 355811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_WAITEVENTS: 355911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BEGINQUERY: 356011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_ENDQUERY: 356111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_RESETQUERYPOOL: 356211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_COPYQUERYPOOLRESULTS: 356311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_WRITETIMESTAMP: 356411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= checkGraphicsOrComputeBit(my_data, flags, cmdTypeToString(cmd).c_str()); 356511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 356611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETVIEWPORTSTATE: 356711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETSCISSORSTATE: 356811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETLINEWIDTHSTATE: 356911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETDEPTHBIASSTATE: 357011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETBLENDSTATE: 357111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETDEPTHBOUNDSSTATE: 357211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETSTENCILREADMASKSTATE: 357311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETSTENCILWRITEMASKSTATE: 357411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_SETSTENCILREFERENCESTATE: 357511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BINDINDEXBUFFER: 357611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BINDVERTEXBUFFER: 357711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_DRAW: 357811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_DRAWINDEXED: 357911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_DRAWINDIRECT: 358011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_DRAWINDEXEDINDIRECT: 358111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BLITIMAGE: 358211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_CLEARATTACHMENTS: 358311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_CLEARDEPTHSTENCILIMAGE: 358411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_RESOLVEIMAGE: 358511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_BEGINRENDERPASS: 358611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_NEXTSUBPASS: 358711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_ENDRENDERPASS: 358811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= checkGraphicsBit(my_data, flags, cmdTypeToString(cmd).c_str()); 358911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 359011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_DISPATCH: 359111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_DISPATCHINDIRECT: 359211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= checkComputeBit(my_data, flags, cmdTypeToString(cmd).c_str()); 359311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 359411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_COPYBUFFER: 359511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_COPYIMAGE: 359611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_COPYBUFFERTOIMAGE: 359711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_COPYIMAGETOBUFFER: 359811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_CLONEIMAGEDATA: 359911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_UPDATEBUFFER: 360011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_PIPELINEBARRIER: 360111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_EXECUTECOMMANDS: 360211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case CMD_END: 360311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 360411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 360511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 360611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 360711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 360811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->state != CB_RECORDING) { 360911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= report_error_no_cb_begin(my_data, pCB->commandBuffer, caller_name); 361011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 361111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validateCmdsInCmdBuffer(my_data, pCB, cmd); 361211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert CMD_NODE cmdNode = {}; 361311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // init cmd node and append to end of cmd LL 361411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cmdNode.cmdNumber = ++pCB->numCmds; 361511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cmdNode.type = cmd; 361611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->cmds.push_back(cmdNode); 361711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 361811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 361911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 362011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Reset the command buffer state 362111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Maintain the createInfo and set state to CB_NEW, but clear all other state 362211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { 362311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = dev_data->commandBufferMap[cb]; 362411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 362511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->in_use.store(0); 362611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->cmds.clear(); 362711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Reset CB state (note that createInfo is not cleared) 362811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->commandBuffer = cb; 362911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memset(&pCB->beginInfo, 0, sizeof(VkCommandBufferBeginInfo)); 363011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memset(&pCB->inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo)); 363111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->numCmds = 0; 363211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memset(pCB->drawCount, 0, NUM_DRAW_TYPES * sizeof(uint64_t)); 363311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->state = CB_NEW; 363411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->submitCount = 0; 363511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->status = 0; 363611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->viewports.clear(); 363711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->scissors.clear(); 363811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 363911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { 364011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Before clearing lastBoundState, remove any CB bindings from all uniqueBoundSets 364111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto set : pCB->lastBound[i].uniqueBoundSets) { 364211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set->RemoveBoundCommandBuffer(pCB); 364311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 364411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->lastBound[i].reset(); 364511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 364611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 364711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memset(&pCB->activeRenderPassBeginInfo, 0, sizeof(pCB->activeRenderPassBeginInfo)); 364811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeRenderPass = nullptr; 364911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeSubpassContents = VK_SUBPASS_CONTENTS_INLINE; 365011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeSubpass = 0; 365111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->lastSubmittedFence = VK_NULL_HANDLE; 365211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->lastSubmittedQueue = VK_NULL_HANDLE; 365311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->destroyedSets.clear(); 365411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->updatedSets.clear(); 365511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->destroyedFramebuffers.clear(); 365611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->waitedEvents.clear(); 365711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->semaphores.clear(); 365811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->events.clear(); 365911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->waitedEventsBeforeQueryReset.clear(); 366011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->queryToStateMap.clear(); 366111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeQueries.clear(); 366211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->startedQueries.clear(); 366311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->imageSubresourceMap.clear(); 366411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->imageLayoutMap.clear(); 366511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->eventToStageMap.clear(); 366611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->drawData.clear(); 366711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->currentDrawData.buffers.clear(); 366811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->primaryCommandBuffer = VK_NULL_HANDLE; 366911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Make sure any secondaryCommandBuffers are removed from globalInFlight 367011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto secondary_cb : pCB->secondaryCommandBuffers) { 367111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->globalInFlightCmdBuffers.erase(secondary_cb); 367211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 367311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->secondaryCommandBuffers.clear(); 367411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->updateImages.clear(); 367511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->updateBuffers.clear(); 367611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert clear_cmd_buf_and_mem_references(dev_data, pCB); 367711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->eventUpdates.clear(); 367811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->queryUpdates.clear(); 367911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 368011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Remove this cmdBuffer's reference from each FrameBuffer's CB ref list 368111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto framebuffer : pCB->framebuffers) { 368211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto fbNode = getFramebuffer(dev_data, framebuffer); 368311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fbNode) 368411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fbNode->referencingCmdBuffers.erase(pCB->commandBuffer); 368511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 368611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->framebuffers.clear(); 368711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeFramebuffer = VK_NULL_HANDLE; 368811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 368911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 369011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 369111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Set PSO-related status bits for CB, including dynamic state set via PSO 369211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void set_cb_pso_status(GLOBAL_CB_NODE *pCB, const PIPELINE_NODE *pPipe) { 369311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Account for any dynamic state not set via this PSO 369411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pPipe->graphicsPipelineCI.pDynamicState || 369511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert !pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount) { // All state is static 369611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->status = CBSTATUS_ALL; 369711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 369811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // First consider all state on 369911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Then unset any state that's noted as dynamic in PSO 370011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Finally OR that into CB statemask 370111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert CBStatusFlags psoDynStateMask = CBSTATUS_ALL; 370211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) { 370311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (pPipe->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) { 370411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DYNAMIC_STATE_VIEWPORT: 370511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert psoDynStateMask &= ~CBSTATUS_VIEWPORT_SET; 370611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 370711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DYNAMIC_STATE_SCISSOR: 370811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert psoDynStateMask &= ~CBSTATUS_SCISSOR_SET; 370911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 371011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DYNAMIC_STATE_LINE_WIDTH: 371111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert psoDynStateMask &= ~CBSTATUS_LINE_WIDTH_SET; 371211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 371311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DYNAMIC_STATE_DEPTH_BIAS: 371411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert psoDynStateMask &= ~CBSTATUS_DEPTH_BIAS_SET; 371511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 371611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DYNAMIC_STATE_BLEND_CONSTANTS: 371711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert psoDynStateMask &= ~CBSTATUS_BLEND_CONSTANTS_SET; 371811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 371911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DYNAMIC_STATE_DEPTH_BOUNDS: 372011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert psoDynStateMask &= ~CBSTATUS_DEPTH_BOUNDS_SET; 372111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 372211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: 372311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert psoDynStateMask &= ~CBSTATUS_STENCIL_READ_MASK_SET; 372411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 372511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: 372611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert psoDynStateMask &= ~CBSTATUS_STENCIL_WRITE_MASK_SET; 372711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 372811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_DYNAMIC_STATE_STENCIL_REFERENCE: 372911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert psoDynStateMask &= ~CBSTATUS_STENCIL_REFERENCE_SET; 373011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 373111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 373211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Flag error here 373311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 373411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 373511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 373611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->status |= psoDynStateMask; 373711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 373811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 373911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 374011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Print the last bound Gfx Pipeline 374111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool printPipeline(layer_data *my_data, const VkCommandBuffer cb) { 374211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 374311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(my_data, cb); 374411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 374511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PIPELINE_NODE *pPipeTrav = getPipeline(my_data, pCB->lastBound[VK_PIPELINE_BIND_POINT_GRAPHICS].pipeline); 374611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pPipeTrav) { 374711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // nothing to print 374811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 374911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 375011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_NONE, "DS", "%s", 375111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert vk_print_vkgraphicspipelinecreateinfo( 375211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const VkGraphicsPipelineCreateInfo *>(&pPipeTrav->graphicsPipelineCI), "{DS}") 375311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert .c_str()); 375411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 375511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 375611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 375711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 375811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 375911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void printCB(layer_data *my_data, const VkCommandBuffer cb) { 376011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(my_data, cb); 376111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB && pCB->cmds.size() > 0) { 376211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 376311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_NONE, "DS", "Cmds in CB 0x%p", (void *)cb); 376411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert vector<CMD_NODE> cmds = pCB->cmds; 376511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto ii = cmds.begin(); ii != cmds.end(); ++ii) { 376611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Need to pass cb as srcObj here 376711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 376811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_NONE, "DS", " CMD 0x%" PRIx64 ": %s", (*ii).cmdNumber, cmdTypeToString((*ii).type).c_str()); 376911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 377011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 377111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Nothing to print 377211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 377311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 377411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 377511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool synchAndPrintDSConfig(layer_data *my_data, const VkCommandBuffer cb) { 377611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 377711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(my_data->report_data->active_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)) { 377811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 377911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 378011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= printPipeline(my_data, cb); 378111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 378211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 378311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 378411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Flags validation error if the associated call is made inside a render pass. The apiName 378511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// routine should ONLY be called outside a render pass. 378611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool insideRenderPass(const layer_data *my_data, GLOBAL_CB_NODE *pCB, const char *apiName) { 378711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool inside = false; 378811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->activeRenderPass) { 378911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inside = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 379011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pCB->commandBuffer, __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS", 379111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s: It is invalid to issue this call inside an active render pass (0x%" PRIxLEAST64 ")", apiName, 379211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pCB->activeRenderPass->renderPass); 379311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 379411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return inside; 379511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 379611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 379711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Flags validation error if the associated call is made outside a render pass. The apiName 379811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// routine should ONLY be called inside a render pass. 379911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool outsideRenderPass(const layer_data *my_data, GLOBAL_CB_NODE *pCB, const char *apiName) { 380011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool outside = false; 380111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) && (!pCB->activeRenderPass)) || 380211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) && (!pCB->activeRenderPass) && 380311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))) { 380411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert outside = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 380511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pCB->commandBuffer, __LINE__, DRAWSTATE_NO_ACTIVE_RENDERPASS, "DS", 380611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s: This call must be issued inside an active render pass.", apiName); 380711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 380811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return outside; 380911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 381011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 381111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void init_core_validation(layer_data *instance_data, const VkAllocationCallbacks *pAllocator) { 381211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 381311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_core_validation"); 381411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 381511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 381611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 381711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 381811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) { 381911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 382011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 382111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(chain_info->u.pLayerInfo); 382211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 382311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance"); 382411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fpCreateInstance == NULL) 382511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_INITIALIZATION_FAILED; 382611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 382711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Advance the link info for the next element on the chain 382811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 382911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 383011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); 383111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result != VK_SUCCESS) 383211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 383311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 383411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *instance_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map); 383511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert instance_data->instance = *pInstance; 383611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert instance_data->instance_dispatch_table = new VkLayerInstanceDispatchTable; 383711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_init_instance_dispatch_table(*pInstance, instance_data->instance_dispatch_table, fpGetInstanceProcAddr); 383811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 383911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert instance_data->report_data = 384011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert debug_report_create_instance(instance_data->instance_dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, 384111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCreateInfo->ppEnabledExtensionNames); 384211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 384311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert init_core_validation(instance_data, pAllocator); 384411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 384511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ValidateLayerOrdering(*pCreateInfo); 384611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 384711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 384811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 384911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 385011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* hook DestroyInstance to remove tableInstanceMap entry */ 385111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) { 385211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODOSC : Shouldn't need any customization here 385311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dispatch_key key = get_dispatch_key(instance); 385411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TBD: Need any locking this early, in case this function is called at the 385511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // same time by more than one thread? 385611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(key, layer_data_map); 385711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table; 385811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pTable->DestroyInstance(instance, pAllocator); 385911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 386011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 386111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Clean up logging callback, if any 386211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (my_data->logging_callback.size() > 0) { 386311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDebugReportCallbackEXT callback = my_data->logging_callback.back(); 386411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_destroy_msg_callback(my_data->report_data, callback, pAllocator); 386511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->logging_callback.pop_back(); 386611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 386711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 386811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_debug_report_destroy_instance(my_data->report_data); 386911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete my_data->instance_dispatch_table; 387011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data_map.erase(key); 387111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 387211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 387311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void createDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo, VkDevice device) { 387411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t i; 387511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TBD: Need any locking, in case this function is called at the same time 387611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // by more than one thread? 387711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 387811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_extensions.wsi_enabled = false; 387911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 388011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkLayerDispatchTable *pDisp = dev_data->device_dispatch_table; 388111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr; 388211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)gpa(device, "vkCreateSwapchainKHR"); 388311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)gpa(device, "vkDestroySwapchainKHR"); 388411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)gpa(device, "vkGetSwapchainImagesKHR"); 388511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)gpa(device, "vkAcquireNextImageKHR"); 388611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR)gpa(device, "vkQueuePresentKHR"); 388711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 388811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 388911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) 389011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_extensions.wsi_enabled = true; 389111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 389211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 389311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 389411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo, 389511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) { 389611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map); 389711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 389811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 389911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(chain_info->u.pLayerInfo); 390011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 390111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; 390211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice"); 390311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fpCreateDevice == NULL) { 390411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_INITIALIZATION_FAILED; 390511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 390611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 390711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Advance the link info for the next element on the chain 390811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 390911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 391011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice); 391111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result != VK_SUCCESS) { 391211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 391311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 391411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 391511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 391611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map); 391711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 391811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Setup device dispatch table 391911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_device_data->device_dispatch_table = new VkLayerDispatchTable; 392011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr); 392111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_device_data->device = *pDevice; 392211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 392311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice); 392411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert createDeviceRegisterExtensions(pCreateInfo, *pDevice); 392511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Get physical device limits for this device 392611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(gpu, &(my_device_data->phys_dev_properties.properties)); 392711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t count; 392811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_instance_data->instance_dispatch_table->GetPhysicalDeviceQueueFamilyProperties(gpu, &count, nullptr); 392911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_device_data->phys_dev_properties.queue_family_properties.resize(count); 393011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_instance_data->instance_dispatch_table->GetPhysicalDeviceQueueFamilyProperties( 393111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert gpu, &count, &my_device_data->phys_dev_properties.queue_family_properties[0]); 393211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: device limits should make sure these are compatible 393311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCreateInfo->pEnabledFeatures) { 393411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_device_data->phys_dev_properties.features = *pCreateInfo->pEnabledFeatures; 393511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 393611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memset(&my_device_data->phys_dev_properties.features, 0, sizeof(VkPhysicalDeviceFeatures)); 393711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 393811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Store physical device mem limits into device layer_data struct 393911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_instance_data->instance_dispatch_table->GetPhysicalDeviceMemoryProperties(gpu, &my_device_data->phys_dev_mem_props); 394011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 394111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 394211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ValidateLayerOrdering(*pCreateInfo); 394311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 394411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 394511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 394611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 394711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// prototype 394811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void deleteRenderPasses(layer_data *); 394911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) { 395011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODOSC : Shouldn't need any customization here 395111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dispatch_key key = get_dispatch_key(device); 395211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(key, layer_data_map); 395311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Free all the memory 395411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 395511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert deletePipelines(dev_data); 395611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert deleteRenderPasses(dev_data); 395711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert deleteCommandBuffers(dev_data); 395811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // This will also delete all sets in the pool & remove them from setMap 395911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert deletePools(dev_data); 396011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // All sets should be removed 396111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(dev_data->setMap.empty()); 396211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto del_layout : dev_data->descriptorSetLayoutMap) { 396311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete del_layout.second; 396411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 396511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->descriptorSetLayoutMap.clear(); 396611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageViewMap.clear(); 396711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageMap.clear(); 396811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageSubresourceMap.clear(); 396911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageLayoutMap.clear(); 397011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->bufferViewMap.clear(); 397111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->bufferMap.clear(); 397211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Queues persist until device is destroyed 397311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->queueMap.clear(); 397411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 397511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if MTMERGESOURCE 397611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 397711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 397811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 397911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)device, __LINE__, MEMTRACK_NONE, "MEM", "Printing List details prior to vkDestroyDevice()"); 398011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 398111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)device, __LINE__, MEMTRACK_NONE, "MEM", "================================================"); 398211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert print_mem_list(dev_data); 398311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert printCBList(dev_data); 398411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Report any memory leaks 398511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DEVICE_MEM_INFO *pInfo = NULL; 398611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!dev_data->memObjMap.empty()) { 398711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto ii = dev_data->memObjMap.begin(); ii != dev_data->memObjMap.end(); ++ii) { 398811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pInfo = &(*ii).second; 398911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pInfo->allocInfo.allocationSize != 0) { 399011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Valid Usage: All child objects created on device must have been destroyed prior to destroying device 399111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 399211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 399311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)pInfo->mem, __LINE__, MEMTRACK_MEMORY_LEAK, 399411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "MEM", "Mem Object 0x%" PRIx64 " has not been freed. You should clean up this memory by calling " 399511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkFreeMemory(0x%" PRIx64 ") prior to vkDestroyDevice().", 399611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(pInfo->mem), (uint64_t)(pInfo->mem)); 399711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 399811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 399911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 400011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_debug_report_destroy_device(device); 400111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 400211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 400311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if DISPATCH_MAP_DEBUG 400411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fprintf(stderr, "Device: 0x%p, key: 0x%p\n", device, key); 400511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 400611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkLayerDispatchTable *pDisp = dev_data->device_dispatch_table; 400711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 400811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDisp->DestroyDevice(device, pAllocator); 400911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 401011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#else 401111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->DestroyDevice(device, pAllocator); 401211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 401311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete dev_data->device_dispatch_table; 401411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data_map.erase(key); 401511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 401611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 401711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}}; 401811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 401911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This validates that the initial layout specified in the command buffer for 402011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// the IMAGE is the same 402111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// as the global IMAGE layout 402211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool ValidateCmdBufImageLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { 402311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 402411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cb_image_data : pCB->imageLayoutMap) { 402511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageLayout imageLayout; 402611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!FindLayout(dev_data, cb_image_data.first, imageLayout)) { 402711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 402811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 402911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Cannot submit cmd buffer using deleted image 0x%" PRIx64 ".", 403011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(cb_image_data.first)); 403111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 403211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_image_data.second.initialLayout == VK_IMAGE_LAYOUT_UNDEFINED) { 403311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Set memory invalid which is in mem_tracker currently 403411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (imageLayout != cb_image_data.second.initialLayout) { 403511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_image_data.first.hasSubresource) { 403611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg( 403711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 403811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 403911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot submit cmd buffer using image (0x%" PRIx64 ") [sub-resource: aspectMask 0x%X array layer %u, mip level %u], " 404011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "with layout %s when first use is %s.", 404111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(cb_image_data.first.image), cb_image_data.first.subresource.aspectMask, 404211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_image_data.first.subresource.arrayLayer, 404311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_image_data.first.subresource.mipLevel, string_VkImageLayout(imageLayout), 404411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkImageLayout(cb_image_data.second.initialLayout)); 404511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 404611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg( 404711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 404811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 404911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot submit cmd buffer using image (0x%" PRIx64 ") with layout %s when " 405011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "first use is %s.", 405111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(cb_image_data.first.image), string_VkImageLayout(imageLayout), 405211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkImageLayout(cb_image_data.second.initialLayout)); 405311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 405411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 405511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(dev_data, cb_image_data.first, cb_image_data.second.layout); 405611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 405711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 405811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 405911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 406011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 406111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Track which resources are in-flight by atomically incrementing their "in_use" count 406211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateAndIncrementResources(layer_data *my_data, GLOBAL_CB_NODE *pCB) { 406311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 406411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto drawDataElement : pCB->drawData) { 406511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto buffer : drawDataElement.buffers) { 406611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto buffer_data = my_data->bufferMap.find(buffer); 406711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (buffer_data == my_data->bufferMap.end()) { 406811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 406911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(buffer), __LINE__, DRAWSTATE_INVALID_BUFFER, "DS", 407011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot submit cmd buffer using deleted buffer 0x%" PRIx64 ".", (uint64_t)(buffer)); 407111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 407211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert buffer_data->second.in_use.fetch_add(1); 407311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 407411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 407511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 407611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { 407711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto set : pCB->lastBound[i].uniqueBoundSets) { 407811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!my_data->setMap.count(set->GetSet())) { 407911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 408011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 408111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS", 408211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot submit cmd buffer using deleted descriptor set 0x%" PRIx64 ".", (uint64_t)(set)); 408311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 408411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set->in_use.fetch_add(1); 408511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 408611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 408711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 408811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto semaphore : pCB->semaphores) { 408911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto semaphoreNode = my_data->semaphoreMap.find(semaphore); 409011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (semaphoreNode == my_data->semaphoreMap.end()) { 409111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 409211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 409311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(semaphore), __LINE__, DRAWSTATE_INVALID_SEMAPHORE, "DS", 409411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot submit cmd buffer using deleted semaphore 0x%" PRIx64 ".", reinterpret_cast<uint64_t &>(semaphore)); 409511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 409611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert semaphoreNode->second.in_use.fetch_add(1); 409711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 409811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 409911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto event : pCB->events) { 410011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto eventNode = my_data->eventMap.find(event); 410111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (eventNode == my_data->eventMap.end()) { 410211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 410311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 410411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(event), __LINE__, DRAWSTATE_INVALID_EVENT, "DS", 410511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot submit cmd buffer using deleted event 0x%" PRIx64 ".", reinterpret_cast<uint64_t &>(event)); 410611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 410711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert eventNode->second.in_use.fetch_add(1); 410811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 410911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 411011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto event : pCB->writeEventsBeforeWait) { 411111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto eventNode = my_data->eventMap.find(event); 411211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert eventNode->second.write_in_use++; 411311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 411411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 411511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 411611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 411711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Note: This function assumes that the global lock is held by the calling 411811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// thread. 411911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool cleanInFlightCmdBuffer(layer_data *my_data, VkCommandBuffer cmdBuffer) { 412011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 412111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(my_data, cmdBuffer); 412211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 412311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto queryEventsPair : pCB->waitedEventsBeforeQueryReset) { 412411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto event : queryEventsPair.second) { 412511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (my_data->eventMap[event].needsSignaled) { 412611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 412711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 0, DRAWSTATE_INVALID_QUERY, "DS", 412811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot get query results on queryPool 0x%" PRIx64 412911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " with index %d which was guarded by unsignaled event 0x%" PRIx64 ".", 413011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(queryEventsPair.first.pool), queryEventsPair.first.index, (uint64_t)(event)); 413111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 413211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 413311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 413411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 413511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 413611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 413711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Decrement cmd_buffer in_use and if it goes to 0 remove cmd_buffer from globalInFlightCmdBuffers 413811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic inline void removeInFlightCmdBuffer(layer_data *dev_data, VkCommandBuffer cmd_buffer) { 413911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Pull it off of global list initially, but if we find it in any other queue list, add it back in 414011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmd_buffer); 414111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->in_use.fetch_sub(1); 414211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCB->in_use.load()) { 414311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->globalInFlightCmdBuffers.erase(cmd_buffer); 414411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 414511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 414611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 414711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void decrementResources(layer_data *my_data, VkCommandBuffer cmdBuffer) { 414811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(my_data, cmdBuffer); 414911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto drawDataElement : pCB->drawData) { 415011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto buffer : drawDataElement.buffers) { 415111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto buffer_data = my_data->bufferMap.find(buffer); 415211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (buffer_data != my_data->bufferMap.end()) { 415311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert buffer_data->second.in_use.fetch_sub(1); 415411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 415511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 415611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 415711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { 415811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto set : pCB->lastBound[i].uniqueBoundSets) { 415911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set->in_use.fetch_sub(1); 416011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 416111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 416211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto semaphore : pCB->semaphores) { 416311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto semaphoreNode = my_data->semaphoreMap.find(semaphore); 416411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (semaphoreNode != my_data->semaphoreMap.end()) { 416511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert semaphoreNode->second.in_use.fetch_sub(1); 416611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 416711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 416811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto event : pCB->events) { 416911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto eventNode = my_data->eventMap.find(event); 417011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (eventNode != my_data->eventMap.end()) { 417111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert eventNode->second.in_use.fetch_sub(1); 417211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 417311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 417411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto event : pCB->writeEventsBeforeWait) { 417511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto eventNode = my_data->eventMap.find(event); 417611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (eventNode != my_data->eventMap.end()) { 417711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert eventNode->second.write_in_use--; 417811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 417911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 418011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto queryStatePair : pCB->queryToStateMap) { 418111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->queryToStateMap[queryStatePair.first] = queryStatePair.second; 418211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 418311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto eventStagePair : pCB->eventToStageMap) { 418411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->eventMap[eventStagePair.first].stageMask = eventStagePair.second; 418511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 418611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 418711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// For fenceCount fences in pFences, mark fence signaled, decrement in_use, and call 418811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// decrementResources for all priorFences and cmdBuffers associated with fence. 418911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool decrementResources(layer_data *my_data, uint32_t fenceCount, const VkFence *pFences) { 419011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 419111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<std::pair<VkFence, FENCE_NODE *>> fence_pairs; 419211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < fenceCount; ++i) { 419311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto fence_data = my_data->fenceMap.find(pFences[i]); 419411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence_data == my_data->fenceMap.end() || !fence_data->second.needsSignaled) 419511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 419611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.needsSignaled = false; 419711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence_data->second.in_use.load()) { 419811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_pairs.push_back(std::make_pair(fence_data->first, &fence_data->second)); 419911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.in_use.fetch_sub(1); 420011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 420111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert decrementResources(my_data, static_cast<uint32_t>(fence_data->second.priorFences.size()), 420211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.priorFences.data()); 420311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cmdBuffer : fence_data->second.cmdBuffers) { 420411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert decrementResources(my_data, cmdBuffer); 420511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= cleanInFlightCmdBuffer(my_data, cmdBuffer); 420611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert removeInFlightCmdBuffer(my_data, cmdBuffer); 420711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 420811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.cmdBuffers.clear(); 420911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.priorFences.clear(); 421011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 421111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto fence_pair : fence_pairs) { 421211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto queue : fence_pair.second->queues) { 421311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queue_pair = my_data->queueMap.find(queue); 421411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queue_pair != my_data->queueMap.end()) { 421511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto last_fence_data = 421611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::find(queue_pair->second.lastFences.begin(), queue_pair->second.lastFences.end(), fence_pair.first); 421711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (last_fence_data != queue_pair->second.lastFences.end()) 421811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_pair->second.lastFences.erase(last_fence_data); 421911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 422011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 422111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto& fence_data : my_data->fenceMap) { 422211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto prior_fence_data = 422311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::find(fence_data.second.priorFences.begin(), fence_data.second.priorFences.end(), fence_pair.first); 422411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (prior_fence_data != fence_data.second.priorFences.end()) 422511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data.second.priorFences.erase(prior_fence_data); 422611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 422711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 422811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 422911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 423011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Decrement in_use for all outstanding cmd buffers that were submitted on this queue 423111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool decrementResources(layer_data *my_data, VkQueue queue) { 423211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 423311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queue_data = my_data->queueMap.find(queue); 423411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queue_data != my_data->queueMap.end()) { 423511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cmdBuffer : queue_data->second.untrackedCmdBuffers) { 423611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert decrementResources(my_data, cmdBuffer); 423711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= cleanInFlightCmdBuffer(my_data, cmdBuffer); 423811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert removeInFlightCmdBuffer(my_data, cmdBuffer); 423911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 424011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_data->second.untrackedCmdBuffers.clear(); 424111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= decrementResources(my_data, static_cast<uint32_t>(queue_data->second.lastFences.size()), 424211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_data->second.lastFences.data()); 424311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 424411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 424511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 424611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 424711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This function merges command buffer tracking between queues when there is a semaphore dependency 424811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// between them (see below for details as to how tracking works). When this happens, the prior 424911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// fences from the signaling queue are merged into the wait queue as well as any untracked command 425011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// buffers. 425111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void updateTrackedCommandBuffers(layer_data *dev_data, VkQueue queue, VkQueue other_queue, VkFence fence) { 425211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queue == other_queue) { 425311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 425411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 425511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queue_data = dev_data->queueMap.find(queue); 425611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto other_queue_data = dev_data->queueMap.find(other_queue); 425711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queue_data == dev_data->queueMap.end() || other_queue_data == dev_data->queueMap.end()) { 425811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 425911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 426011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto fenceInner : other_queue_data->second.lastFences) { 426111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_data->second.lastFences.push_back(fenceInner); 426211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto fence_node = dev_data->fenceMap.find(fenceInner); 426311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence_node != dev_data->fenceMap.end()) { 426411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_node->second.queues.insert(other_queue_data->first); 426511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 426611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 426711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence != VK_NULL_HANDLE) { 426811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto fence_data = dev_data->fenceMap.find(fence); 426911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence_data == dev_data->fenceMap.end()) { 427011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 427111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 427211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cmdbuffer : other_queue_data->second.untrackedCmdBuffers) { 427311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.cmdBuffers.push_back(cmdbuffer); 427411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 427511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert other_queue_data->second.untrackedCmdBuffers.clear(); 427611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 427711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cmdbuffer : other_queue_data->second.untrackedCmdBuffers) { 427811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_data->second.untrackedCmdBuffers.push_back(cmdbuffer); 427911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 428011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert other_queue_data->second.untrackedCmdBuffers.clear(); 428111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 428211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto eventStagePair : other_queue_data->second.eventToStageMap) { 428311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_data->second.eventToStageMap[eventStagePair.first] = eventStagePair.second; 428411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 428511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto queryStatePair : other_queue_data->second.queryToStateMap) { 428611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_data->second.queryToStateMap[queryStatePair.first] = queryStatePair.second; 428711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 428811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 428911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 429011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This is the core function for tracking command buffers. There are two primary ways command 429111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// buffers are tracked. When submitted they are stored in the command buffer list associated 429211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// with a fence or the untracked command buffer list associated with a queue if no fence is used. 429311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Each queue also stores the last fence that was submitted onto the queue. This allows us to 429411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// create a linked list of fences and their associated command buffers so if one fence is 429511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// waited on, prior fences on that queue are also considered to have been waited on. When a fence is 429611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// waited on (either via a queue, device or fence), we free the cmd buffers for that fence and 429711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// recursively call with the prior fences. 429811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void trackCommandBuffers(layer_data *my_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, 429911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkFence fence) { 430011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queue_data = my_data->queueMap.find(queue); 430111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence != VK_NULL_HANDLE) { 430211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert vector<VkFence> prior_fences; 430311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto fence_data = my_data->fenceMap.find(fence); 430411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence_data == my_data->fenceMap.end()) { 430511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 430611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 430711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.cmdBuffers.clear(); 430811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queue_data != my_data->queueMap.end()) { 430911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert prior_fences = queue_data->second.lastFences; 431011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_data->second.lastFences.clear(); 431111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_data->second.lastFences.push_back(fence); 431211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cmdbuffer : queue_data->second.untrackedCmdBuffers) { 431311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.cmdBuffers.push_back(cmdbuffer); 431411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 431511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_data->second.untrackedCmdBuffers.clear(); 431611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 431711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.priorFences = prior_fences; 431811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.needsSignaled = true; 431911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.queues.insert(queue); 432011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.in_use.fetch_add(1); 432111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 432211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubmitInfo *submit = &pSubmits[submit_idx]; 432311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < submit->commandBufferCount; ++i) { 432411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto secondaryCmdBuffer : my_data->commandBufferMap[submit->pCommandBuffers[i]]->secondaryCommandBuffers) { 432511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.cmdBuffers.push_back(secondaryCmdBuffer); 432611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 432711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.cmdBuffers.push_back(submit->pCommandBuffers[i]); 432811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 432911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 433011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 433111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queue_data != my_data->queueMap.end()) { 433211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 433311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubmitInfo *submit = &pSubmits[submit_idx]; 433411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < submit->commandBufferCount; ++i) { 433511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto secondaryCmdBuffer : my_data->commandBufferMap[submit->pCommandBuffers[i]]->secondaryCommandBuffers) { 433611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_data->second.untrackedCmdBuffers.push_back(secondaryCmdBuffer); 433711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 433811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_data->second.untrackedCmdBuffers.push_back(submit->pCommandBuffers[i]); 433911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 434011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 434111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 434211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 434311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 434411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 434511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void markCommandBuffersInFlight(layer_data *my_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, 434611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkFence fence) { 434711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queue_data = my_data->queueMap.find(queue); 434811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queue_data != my_data->queueMap.end()) { 434911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 435011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubmitInfo *submit = &pSubmits[submit_idx]; 435111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < submit->commandBufferCount; ++i) { 435211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Add cmdBuffers to the global set and increment count 435311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(my_data, submit->pCommandBuffers[i]); 435411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto secondaryCmdBuffer : my_data->commandBufferMap[submit->pCommandBuffers[i]]->secondaryCommandBuffers) { 435511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->globalInFlightCmdBuffers.insert(secondaryCmdBuffer); 435611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pSubCB = getCBNode(my_data, secondaryCmdBuffer); 435711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pSubCB->in_use.fetch_add(1); 435811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 435911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->globalInFlightCmdBuffers.insert(submit->pCommandBuffers[i]); 436011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->in_use.fetch_add(1); 436111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 436211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 436311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 436411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 436511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 436611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateCommandBufferSimultaneousUse(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { 436711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 436811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->globalInFlightCmdBuffers.count(pCB->commandBuffer) && 436911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 437011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 437111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 437211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS", 437311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Command Buffer 0x%" PRIx64 " is already in use and is not marked for simultaneous use.", 437411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t>(pCB->commandBuffer)); 437511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 437611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 437711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 437811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 437911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { 438011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 438111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate ONE_TIME_SUBMIT_BIT CB is not being submitted more than once 438211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) && (pCB->submitCount > 1)) { 438311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 438411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS", 438511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "CB 0x%" PRIxLEAST64 " was begun w/ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT " 438611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "set, but has been submitted 0x%" PRIxLEAST64 " times.", 438711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(pCB->commandBuffer), pCB->submitCount); 438811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 438911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate that cmd buffers have been updated 439011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (CB_RECORDED != pCB->state) { 439111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (CB_INVALID == pCB->state) { 439211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Inform app of reason CB invalid 439311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool causeReported = false; 439411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCB->destroyedSets.empty()) { 439511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::stringstream set_string; 439611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto set : pCB->destroyedSets) 439711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_string << " " << set; 439811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 439911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 440011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 440111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 440211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "You are submitting command buffer 0x%" PRIxLEAST64 440311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " that is invalid because it had the following bound descriptor set(s) destroyed: %s", 440411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(pCB->commandBuffer), set_string.str().c_str()); 440511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert causeReported = true; 440611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 440711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCB->updatedSets.empty()) { 440811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::stringstream set_string; 440911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto set : pCB->updatedSets) 441011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_string << " " << set; 441111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 441211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 441311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 441411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 441511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "You are submitting command buffer 0x%" PRIxLEAST64 441611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " that is invalid because it had the following bound descriptor set(s) updated: %s", 441711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(pCB->commandBuffer), set_string.str().c_str()); 441811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert causeReported = true; 441911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 442011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCB->destroyedFramebuffers.empty()) { 442111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::stringstream fb_string; 442211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto fb : pCB->destroyedFramebuffers) 442311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fb_string << " " << fb; 442411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 442511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 442611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 442711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 442811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "You are submitting command buffer 0x%" PRIxLEAST64 " that is invalid because it had the following " 442911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "referenced framebuffers destroyed: %s", 443011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(pCB->commandBuffer), fb_string.str().c_str()); 443111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert causeReported = true; 443211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 443311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : This is defensive programming to make sure an error is 443411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // flagged if we hit this INVALID cmd buffer case and none of the 443511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // above cases are hit. As the number of INVALID cases grows, this 443611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // code should be updated to seemlessly handle all the cases. 443711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!causeReported) { 443811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 443911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 444011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 444111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "You are submitting command buffer 0x%" PRIxLEAST64 " that is invalid due to an unknown cause. Validation " 444211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "should " 444311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "be improved to report the exact cause.", 444411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(pCB->commandBuffer)); 444511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 444611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { // Flag error for using CB w/o vkEndCommandBuffer() called 444711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 444811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 444911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(pCB->commandBuffer), __LINE__, DRAWSTATE_NO_END_COMMAND_BUFFER, "DS", 445011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "You must call vkEndCommandBuffer() on CB 0x%" PRIxLEAST64 " before this call to vkQueueSubmit()!", 445111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(pCB->commandBuffer)); 445211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 445311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 445411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 445511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 445611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 445711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { 445811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Track in-use for resources off of primary and any secondary CBs 445911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = validateAndIncrementResources(dev_data, pCB); 446011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCB->secondaryCommandBuffers.empty()) { 446111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto secondaryCmdBuffer : pCB->secondaryCommandBuffers) { 446211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validateAndIncrementResources(dev_data, dev_data->commandBufferMap[secondaryCmdBuffer]); 446311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pSubCB = getCBNode(dev_data, secondaryCmdBuffer); 446411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((pSubCB->primaryCommandBuffer != pCB->commandBuffer) && 446511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert !(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 446611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 446711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS", 446811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "CB 0x%" PRIxLEAST64 " was submitted with secondary buffer 0x%" PRIxLEAST64 446911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " but that buffer has subsequently been bound to " 447011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "primary cmd buffer 0x%" PRIxLEAST64 447111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set.", 447211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t>(pCB->commandBuffer), reinterpret_cast<uint64_t>(secondaryCmdBuffer), 447311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t>(pSubCB->primaryCommandBuffer)); 447411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 447511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 447611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 447711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validateCommandBufferState(dev_data, pCB); 447811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If USAGE_SIMULTANEOUS_USE_BIT not set then CB cannot already be executing 447911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // on device 448011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validateCommandBufferSimultaneousUse(dev_data, pCB); 448111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 448211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 448311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 448411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 448511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) { 448611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 448711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map); 448811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 448911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 449011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // First verify that fence is not in use 449111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence != VK_NULL_HANDLE) { 449211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((submitCount != 0) && dev_data->fenceMap[fence].in_use.load()) { 449311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 449411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", 449511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Fence 0x%" PRIx64 " is already in use by another submission.", (uint64_t)(fence)); 449611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 449711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!dev_data->fenceMap[fence].needsSignaled) { 449811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 449911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 450011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted", 450111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(fence)); 450211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 450311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 450411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Review these old print functions and clean up as appropriate 450511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert print_mem_list(dev_data); 450611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert printCBList(dev_data); 450711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Update cmdBuffer-related data structs and mark fence in-use 450811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert trackCommandBuffers(dev_data, queue, submitCount, pSubmits, fence); 450911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Now verify each individual submit 451011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_set<VkQueue> processed_other_queues; 451111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 451211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubmitInfo *submit = &pSubmits[submit_idx]; 451311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert vector<VkSemaphore> semaphoreList; 451411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) { 451511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSemaphore &semaphore = submit->pWaitSemaphores[i]; 451611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert semaphoreList.push_back(semaphore); 451711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->semaphoreMap.find(semaphore) != dev_data->semaphoreMap.end()) { 451811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->semaphoreMap[semaphore].signaled) { 451911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->semaphoreMap[semaphore].signaled = false; 452011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 452111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 452211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 452311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 452411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Queue 0x%" PRIx64 " is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", 452511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(queue), reinterpret_cast<const uint64_t &>(semaphore)); 452611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 452711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkQueue &other_queue = dev_data->semaphoreMap[semaphore].queue; 452811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (other_queue != VK_NULL_HANDLE && !processed_other_queues.count(other_queue)) { 452911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert updateTrackedCommandBuffers(dev_data, queue, other_queue, fence); 453011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert processed_other_queues.insert(other_queue); 453111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 453211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 453311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 453411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) { 453511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSemaphore &semaphore = submit->pSignalSemaphores[i]; 453611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->semaphoreMap.find(semaphore) != dev_data->semaphoreMap.end()) { 453711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert semaphoreList.push_back(semaphore); 453811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->semaphoreMap[semaphore].signaled) { 453911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 454011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 454111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 454211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Queue 0x%" PRIx64 " is signaling semaphore 0x%" PRIx64 454311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " that has already been signaled but not waited on by queue 0x%" PRIx64 ".", 454411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(queue), reinterpret_cast<const uint64_t &>(semaphore), 454511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(dev_data->semaphoreMap[semaphore].queue)); 454611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 454711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->semaphoreMap[semaphore].signaled = true; 454811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->semaphoreMap[semaphore].queue = queue; 454911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 455011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 455111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 455211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < submit->commandBufferCount; i++) { 455311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pCBNode = getCBNode(dev_data, submit->pCommandBuffers[i]); 455411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= ValidateCmdBufImageLayouts(dev_data, pCBNode); 455511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCBNode) { 455611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCBNode->semaphores = semaphoreList; 455711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCBNode->submitCount++; // increment submit count 455811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCBNode->lastSubmittedFence = fence; 455911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCBNode->lastSubmittedQueue = queue; 456011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validatePrimaryCommandBufferState(dev_data, pCBNode); 456111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Call submit-time functions to validate/update state 456211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto &function : pCBNode->validate_functions) { 456311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= function(); 456411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 456511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto &function : pCBNode->eventUpdates) { 456611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= function(queue); 456711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 456811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto &function : pCBNode->queryUpdates) { 456911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= function(queue); 457011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 457111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 457211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 457311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 457411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert markCommandBuffersInFlight(dev_data, queue, submitCount, pSubmits, fence); 457511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 457611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 457711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = dev_data->device_dispatch_table->QueueSubmit(queue, submitCount, pSubmits, fence); 457811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 457911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 458011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 458111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 458211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo, 458311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) { 458411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 458511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = my_data->device_dispatch_table->AllocateMemory(device, pAllocateInfo, pAllocator, pMemory); 458611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Track allocations and overall size here 458711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 458811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert add_mem_obj_info(my_data, device, *pMemory, pAllocateInfo); 458911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert print_mem_list(my_data); 459011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 459111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 459211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 459311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 459411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertFreeMemory(VkDevice device, VkDeviceMemory mem, const VkAllocationCallbacks *pAllocator) { 459511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 459611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 459711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // From spec : A memory object is freed by calling vkFreeMemory() when it is no longer needed. 459811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Before freeing a memory object, an application must ensure the memory object is no longer 459911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // in use by the device—for example by command buffers queued for execution. The memory need 460011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // not yet be unbound from all images and buffers, but any further use of those images or 460111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // buffers (on host or device) for anything other than destroying those objects will result in 460211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // undefined behavior. 460311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 460411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 460511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert freeMemObjInfo(my_data, device, mem, false); 460611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert print_mem_list(my_data); 460711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert printCBList(my_data); 460811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 460911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->device_dispatch_table->FreeMemory(device, mem, pAllocator); 461011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 461111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 461211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateMemRange(layer_data *my_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) { 461311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 461411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 461511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (size == 0) { 461611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 461711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 461811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VkMapMemory: Attempting to map memory range of size zero"); 461911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 462011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 462111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto mem_element = my_data->memObjMap.find(mem); 462211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_element != my_data->memObjMap.end()) { 462311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // It is an application error to call VkMapMemory on an object that is already mapped 462411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_element->second.memRange.size != 0) { 462511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 462611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 462711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VkMapMemory: Attempting to map memory on an already-mapped object 0x%" PRIxLEAST64, (uint64_t)mem); 462811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 462911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 463011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate that offset + size is within object's allocationSize 463111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (size == VK_WHOLE_SIZE) { 463211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (offset >= mem_element->second.allocInfo.allocationSize) { 463311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 463411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, 463511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "MEM", "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " with size of VK_WHOLE_SIZE oversteps total array size 0x%" PRIx64, offset, 463611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert mem_element->second.allocInfo.allocationSize, mem_element->second.allocInfo.allocationSize); 463711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 463811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 463911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((offset + size) > mem_element->second.allocInfo.allocationSize) { 464011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 464111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, 464211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "MEM", "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " oversteps total array size 0x%" PRIx64, offset, 464311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size + offset, mem_element->second.allocInfo.allocationSize); 464411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 464511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 464611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 464711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 464811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 464911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 465011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void storeMemRanges(layer_data *my_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) { 465111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto mem_element = my_data->memObjMap.find(mem); 465211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_element != my_data->memObjMap.end()) { 465311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MemRange new_range; 465411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert new_range.offset = offset; 465511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert new_range.size = size; 465611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert mem_element->second.memRange = new_range; 465711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 465811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 465911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 466011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool deleteMemRanges(layer_data *my_data, VkDeviceMemory mem) { 466111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 466211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto mem_element = my_data->memObjMap.find(mem); 466311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_element != my_data->memObjMap.end()) { 466411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!mem_element->second.memRange.size) { 466511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Valid Usage: memory must currently be mapped 466611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 466711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 466811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Unmapping Memory without memory being mapped: mem obj 0x%" PRIxLEAST64, (uint64_t)mem); 466911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 467011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert mem_element->second.memRange.size = 0; 467111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_element->second.pData) { 467211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert free(mem_element->second.pData); 467311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert mem_element->second.pData = 0; 467411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 467511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 467611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 467711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 467811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 467911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic char NoncoherentMemoryFillValue = 0xb; 468011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 468111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void initializeAndTrackMemory(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize size, void **ppData) { 468211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto mem_element = dev_data->memObjMap.find(mem); 468311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_element != dev_data->memObjMap.end()) { 468411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert mem_element->second.pDriverData = *ppData; 468511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t index = mem_element->second.allocInfo.memoryTypeIndex; 468611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->phys_dev_mem_props.memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) { 468711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert mem_element->second.pData = 0; 468811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 468911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (size == VK_WHOLE_SIZE) { 469011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size = mem_element->second.allocInfo.allocationSize; 469111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 469211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t convSize = (size_t)(size); 469311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert mem_element->second.pData = malloc(2 * convSize); 469411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memset(mem_element->second.pData, NoncoherentMemoryFillValue, 2 * convSize); 469511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *ppData = static_cast<char *>(mem_element->second.pData) + (convSize / 2); 469611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 469711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 469811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 469911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Verify that state for fence being waited on is appropriate. That is, 470011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// a fence being waited on should not already be signalled and 470111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// it should have been submitted on a queue or during acquire next image 470211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic inline bool verifyWaitFenceState(VkDevice device, VkFence fence, const char *apiCall) { 470311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 470411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 470511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pFenceInfo = my_data->fenceMap.find(fence); 470611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pFenceInfo != my_data->fenceMap.end()) { 470711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pFenceInfo->second.firstTimeFlag) { 470811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pFenceInfo->second.needsSignaled) { 470911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 471011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 471111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)fence, __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 471211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s specified fence 0x%" PRIxLEAST64 " already in SIGNALED state.", apiCall, (uint64_t)fence); 471311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 471411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pFenceInfo->second.queues.empty() && !pFenceInfo->second.swapchain) { // Checking status of unsubmitted fence 471511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 471611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 471711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s called for fence 0x%" PRIxLEAST64 " which has not been submitted on a Queue or during " 471811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "acquire next image.", 471911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert apiCall, reinterpret_cast<uint64_t &>(fence)); 472011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 472111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 472211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pFenceInfo->second.firstTimeFlag = false; 472311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 472411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 472511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 472611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 472711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 472811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 472911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout) { 473011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 473111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 473211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Verify fence status of submitted fences 473311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 473411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < fenceCount; i++) { 473511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= verifyWaitFenceState(device, pFences[i], "vkWaitForFences"); 473611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 473711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 473811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skip_call) 473911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 474011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 474111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->WaitForFences(device, fenceCount, pFences, waitAll, timeout); 474211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 474311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result == VK_SUCCESS) { 474411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 474511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // When we know that all fences are complete we can clean/remove their CBs 474611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (waitAll || fenceCount == 1) { 474711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= decrementResources(dev_data, fenceCount, pFences); 474811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 474911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // NOTE : Alternate case not handled here is when some fences have completed. In 475011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // this case for app to guarantee which fences completed it will have to call 475111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // vkGetFenceStatus() at which point we'll clean/remove their CBs if complete. 475211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 475311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 475411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skip_call) 475511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 475611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 475711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 475811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 475911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL GetFenceStatus(VkDevice device, VkFence fence) { 476011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 476111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 476211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 476311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 476411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = verifyWaitFenceState(device, fence, "vkGetFenceStatus"); 476511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 476611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 476711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skipCall) 476811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 476911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 477011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = dev_data->device_dispatch_table->GetFenceStatus(device, fence); 477111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 477211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 477311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result == VK_SUCCESS) { 477411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= decrementResources(dev_data, 1, &fence); 477511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 477611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 477711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skip_call) 477811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 477911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 478011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 478111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 478211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, 478311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkQueue *pQueue) { 478411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 478511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue); 478611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 478711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 478811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Add queue to tracking set only if it is new 478911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto result = dev_data->queues.emplace(*pQueue); 479011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result.second == true) { 479111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert QUEUE_NODE *pQNode = &dev_data->queueMap[*pQueue]; 479211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pQNode->device = device; 479311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 479411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 479511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 479611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL QueueWaitIdle(VkQueue queue) { 479711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map); 479811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 479911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= decrementResources(dev_data, queue); 480011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skip_call) 480111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 480211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->QueueWaitIdle(queue); 480311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 480411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 480511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 480611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL DeviceWaitIdle(VkDevice device) { 480711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 480811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 480911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 481011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto queue : dev_data->queues) { 481111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= decrementResources(dev_data, queue); 481211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 481311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->globalInFlightCmdBuffers.clear(); 481411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 481511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skip_call) 481611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 481711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->DeviceWaitIdle(device); 481811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 481911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 482011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 482111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL DestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) { 482211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 482311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 482411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 482511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto fence_pair = dev_data->fenceMap.find(fence); 482611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence_pair != dev_data->fenceMap.end()) { 482711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence_pair->second.in_use.load()) { 482811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 482911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", 483011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Fence 0x%" PRIx64 " is in use by a command buffer.", (uint64_t)(fence)); 483111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 483211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->fenceMap.erase(fence_pair); 483311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 483411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 483511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 483611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 483711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->DestroyFence(device, fence, pAllocator); 483811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 483911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 484011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 484111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) { 484211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 484311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->DestroySemaphore(device, semaphore, pAllocator); 484411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 484511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto item = dev_data->semaphoreMap.find(semaphore); 484611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (item != dev_data->semaphoreMap.end()) { 484711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (item->second.in_use.load()) { 484811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 484911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(semaphore), __LINE__, DRAWSTATE_INVALID_SEMAPHORE, "DS", 485011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot delete semaphore 0x%" PRIx64 " which is in use.", reinterpret_cast<uint64_t &>(semaphore)); 485111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 485211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->semaphoreMap.erase(semaphore); 485311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 485411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Clean up any internal data structures using this obj. 485511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 485611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 485711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL DestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) { 485811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 485911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 486011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 486111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto event_data = dev_data->eventMap.find(event); 486211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (event_data != dev_data->eventMap.end()) { 486311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (event_data->second.in_use.load()) { 486411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg( 486511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 486611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(event), __LINE__, DRAWSTATE_INVALID_EVENT, "DS", 486711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot delete event 0x%" PRIx64 " which is in use by a command buffer.", reinterpret_cast<uint64_t &>(event)); 486811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 486911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->eventMap.erase(event_data); 487011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 487111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 487211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skip_call) 487311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->DestroyEvent(device, event, pAllocator); 487411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Clean up any internal data structures using this obj. 487511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 487611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 487711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 487811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks *pAllocator) { 487911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_my_data_ptr(get_dispatch_key(device), layer_data_map) 488011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ->device_dispatch_table->DestroyQueryPool(device, queryPool, pAllocator); 488111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Clean up any internal data structures using this obj. 488211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 488311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 488411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, 488511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t queryCount, size_t dataSize, void *pData, VkDeviceSize stride, 488611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkQueryResultFlags flags) { 488711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 488811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_map<QueryObject, vector<VkCommandBuffer>> queriesInFlight; 488911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 489011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cmdBuffer : dev_data->globalInFlightCmdBuffers) { 489111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pCB = getCBNode(dev_data, cmdBuffer); 489211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto queryStatePair : pCB->queryToStateMap) { 489311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queriesInFlight[queryStatePair.first].push_back(cmdBuffer); 489411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 489511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 489611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 489711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < queryCount; ++i) { 489811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert QueryObject query = {queryPool, firstQuery + i}; 489911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queryElement = queriesInFlight.find(query); 490011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queryToStateElement = dev_data->queryToStateMap.find(query); 490111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queryToStateElement != dev_data->queryToStateMap.end()) { 490211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Available and in flight 490311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queryElement != queriesInFlight.end() && queryToStateElement != dev_data->queryToStateMap.end() && 490411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queryToStateElement->second) { 490511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cmdBuffer : queryElement->second) { 490611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pCB = getCBNode(dev_data, cmdBuffer); 490711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queryEventElement = pCB->waitedEventsBeforeQueryReset.find(query); 490811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queryEventElement == pCB->waitedEventsBeforeQueryReset.end()) { 490911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 491011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 491111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is in flight.", 491211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(queryPool), firstQuery + i); 491311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 491411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto event : queryEventElement->second) { 491511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->eventMap[event].needsSignaled = true; 491611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 491711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 491811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 491911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Unavailable and in flight 492011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (queryElement != queriesInFlight.end() && queryToStateElement != dev_data->queryToStateMap.end() && 492111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert !queryToStateElement->second) { 492211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Can there be the same query in use by multiple command buffers in flight? 492311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool make_available = false; 492411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cmdBuffer : queryElement->second) { 492511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pCB = getCBNode(dev_data, cmdBuffer); 492611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert make_available |= pCB->queryToStateMap[query]; 492711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 492811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(((flags & VK_QUERY_RESULT_PARTIAL_BIT) || (flags & VK_QUERY_RESULT_WAIT_BIT)) && make_available)) { 492911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 493011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 493111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.", 493211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(queryPool), firstQuery + i); 493311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 493411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Unavailable 493511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (queryToStateElement != dev_data->queryToStateMap.end() && !queryToStateElement->second) { 493611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 493711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 493811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.", 493911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(queryPool), firstQuery + i); 494011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Unitialized 494111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (queryToStateElement == dev_data->queryToStateMap.end()) { 494211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 494311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 494411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot get query results on queryPool 0x%" PRIx64 494511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " with index %d as data has not been collected for this index.", 494611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(queryPool), firstQuery + i); 494711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 494811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 494911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 495011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 495111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skip_call) 495211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 495311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return dev_data->device_dispatch_table->GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, 495411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert flags); 495511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 495611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 495711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateIdleBuffer(const layer_data *my_data, VkBuffer buffer) { 495811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 495911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto buffer_data = my_data->bufferMap.find(buffer); 496011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (buffer_data == my_data->bufferMap.end()) { 496111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 496211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(buffer), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", 496311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot free buffer 0x%" PRIxLEAST64 " that has not been allocated.", (uint64_t)(buffer)); 496411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 496511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (buffer_data->second.in_use.load()) { 496611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 496711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(buffer), __LINE__, DRAWSTATE_OBJECT_INUSE, "DS", 496811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot free buffer 0x%" PRIxLEAST64 " that is in use by a command buffer.", (uint64_t)(buffer)); 496911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 497011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 497111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 497211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 497311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 497411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool print_memory_range_error(layer_data *dev_data, const uint64_t object_handle, const uint64_t other_handle, 497511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDebugReportObjectTypeEXT object_type) { 497611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (object_type == VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT) { 497711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle, 0, 497811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MEMTRACK_INVALID_ALIASING, "MEM", "Buffer 0x%" PRIx64 " is aliased with image 0x%" PRIx64, object_handle, 497911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert other_handle); 498011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 498111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle, 0, 498211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MEMTRACK_INVALID_ALIASING, "MEM", "Image 0x%" PRIx64 " is aliased with buffer 0x%" PRIx64, object_handle, 498311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert other_handle); 498411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 498511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 498611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 498711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_memory_range(layer_data *dev_data, const vector<MEMORY_RANGE> &ranges, const MEMORY_RANGE &new_range, 498811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDebugReportObjectTypeEXT object_type) { 498911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 499011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 499111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto range : ranges) { 499211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((range.end & ~(dev_data->phys_dev_properties.properties.limits.bufferImageGranularity - 1)) < 499311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (new_range.start & ~(dev_data->phys_dev_properties.properties.limits.bufferImageGranularity - 1))) 499411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 499511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((range.start & ~(dev_data->phys_dev_properties.properties.limits.bufferImageGranularity - 1)) > 499611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (new_range.end & ~(dev_data->phys_dev_properties.properties.limits.bufferImageGranularity - 1))) 499711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 499811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= print_memory_range_error(dev_data, new_range.handle, range.handle, object_type); 499911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 500011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 500111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 500211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 500311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic MEMORY_RANGE insert_memory_ranges(uint64_t handle, VkDeviceMemory mem, VkDeviceSize memoryOffset, 500411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkMemoryRequirements memRequirements, vector<MEMORY_RANGE> &ranges) { 500511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MEMORY_RANGE range; 500611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert range.handle = handle; 500711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert range.memory = mem; 500811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert range.start = memoryOffset; 500911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert range.end = memoryOffset + memRequirements.size - 1; 501011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ranges.push_back(range); 501111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return range; 501211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 501311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 501411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void remove_memory_ranges(uint64_t handle, VkDeviceMemory mem, vector<MEMORY_RANGE> &ranges) { 501511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t item = 0; item < ranges.size(); item++) { 501611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((ranges[item].handle == handle) && (ranges[item].memory == mem)) { 501711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ranges.erase(ranges.begin() + item); 501811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 501911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 502011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 502111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 502211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 502311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL DestroyBuffer(VkDevice device, VkBuffer buffer, 502411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator) { 502511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 502611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 502711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 502811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!validateIdleBuffer(dev_data, buffer) && !skipCall) { 502911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 503011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->DestroyBuffer(device, buffer, pAllocator); 503111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 503211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 503311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Clean up memory binding and range information for buffer 503411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const auto &bufferEntry = dev_data->bufferMap.find(buffer); 503511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (bufferEntry != dev_data->bufferMap.end()) { 503611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const auto &memEntry = dev_data->memObjMap.find(bufferEntry->second.mem); 503711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (memEntry != dev_data->memObjMap.end()) { 503811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert remove_memory_ranges(reinterpret_cast<uint64_t &>(buffer), bufferEntry->second.mem, memEntry->second.bufferRanges); 503911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 504011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert clear_object_binding(dev_data, reinterpret_cast<uint64_t &>(buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT); 504111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->bufferMap.erase(bufferEntry); 504211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 504311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 504411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 504511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 504611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator) { 504711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 504811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->DestroyBufferView(device, bufferView, pAllocator); 504911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 505011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto item = dev_data->bufferViewMap.find(bufferView); 505111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (item != dev_data->bufferViewMap.end()) { 505211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->bufferViewMap.erase(item); 505311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 505411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 505511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 505611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) { 505711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 505811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 505911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 506011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->DestroyImage(device, image, pAllocator); 506111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 506211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 506311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 506411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const auto &imageEntry = dev_data->imageMap.find(image); 506511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (imageEntry != dev_data->imageMap.end()) { 506611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Clean up memory mapping, bindings and range references for image 506711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto memEntry = dev_data->memObjMap.find(imageEntry->second.mem); 506811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (memEntry != dev_data->memObjMap.end()) { 506911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert remove_memory_ranges(reinterpret_cast<uint64_t &>(image), imageEntry->second.mem, memEntry->second.imageRanges); 507011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert clear_object_binding(dev_data, reinterpret_cast<uint64_t &>(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT); 507111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memEntry->second.image = VK_NULL_HANDLE; 507211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 507311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Remove image from imageMap 507411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageMap.erase(imageEntry); 507511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 507611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const auto& subEntry = dev_data->imageSubresourceMap.find(image); 507711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subEntry != dev_data->imageSubresourceMap.end()) { 507811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (const auto& pair : subEntry->second) { 507911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageLayoutMap.erase(pair); 508011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 508111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageSubresourceMap.erase(subEntry); 508211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 508311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 508411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 508511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 508611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 508711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 508811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 508911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 509011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Track objects tied to memory 509111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint64_t buffer_handle = (uint64_t)(buffer); 509211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = 509311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_mem_binding(dev_data, mem, buffer_handle, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "vkBindBufferMemory"); 509411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto buffer_node = dev_data->bufferMap.find(buffer); 509511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (buffer_node != dev_data->bufferMap.end()) { 509611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert buffer_node->second.mem = mem; 509711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkMemoryRequirements memRequirements; 509811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->GetBufferMemoryRequirements(device, buffer, &memRequirements); 509911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 510011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Track and validate bound memory range information 510111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const auto &memEntry = dev_data->memObjMap.find(mem); 510211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (memEntry != dev_data->memObjMap.end()) { 510311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const MEMORY_RANGE range = 510411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert insert_memory_ranges(buffer_handle, mem, memoryOffset, memRequirements, memEntry->second.bufferRanges); 510511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 510611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert validate_memory_range(dev_data, memEntry->second.imageRanges, range, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT); 510711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 510811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 510911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate memory requirements alignment 511011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (vk_safe_modulo(memoryOffset, memRequirements.alignment) != 0) { 511111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 511211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 511311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_BUFFER_MEMORY_OFFSET, "DS", 511411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkBindBufferMemory(): memoryOffset is 0x%" PRIxLEAST64 " but must be an integer multiple of the " 511511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64 511611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ", returned from a call to vkGetBufferMemoryRequirements with buffer", 511711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memoryOffset, memRequirements.alignment); 511811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 511911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate device limits alignments 512011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkBufferUsageFlags usage = dev_data->bufferMap[buffer].createInfo.usage; 512111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) { 512211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (vk_safe_modulo(memoryOffset, dev_data->phys_dev_properties.properties.limits.minTexelBufferOffsetAlignment) != 0) { 512311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 512411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 512511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 0, __LINE__, DRAWSTATE_INVALID_TEXEL_BUFFER_OFFSET, "DS", 512611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkBindBufferMemory(): memoryOffset is 0x%" PRIxLEAST64 " but must be a multiple of " 512711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "device limit minTexelBufferOffsetAlignment 0x%" PRIxLEAST64, 512811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memoryOffset, dev_data->phys_dev_properties.properties.limits.minTexelBufferOffsetAlignment); 512911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 513011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 513111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) { 513211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (vk_safe_modulo(memoryOffset, dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment) != 513311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 0) { 513411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 513511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 513611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 0, __LINE__, DRAWSTATE_INVALID_UNIFORM_BUFFER_OFFSET, "DS", 513711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkBindBufferMemory(): memoryOffset is 0x%" PRIxLEAST64 " but must be a multiple of " 513811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "device limit minUniformBufferOffsetAlignment 0x%" PRIxLEAST64, 513911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memoryOffset, dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment); 514011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 514111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 514211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) { 514311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (vk_safe_modulo(memoryOffset, dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment) != 514411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 0) { 514511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 514611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 514711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 0, __LINE__, DRAWSTATE_INVALID_STORAGE_BUFFER_OFFSET, "DS", 514811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkBindBufferMemory(): memoryOffset is 0x%" PRIxLEAST64 " but must be a multiple of " 514911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "device limit minStorageBufferOffsetAlignment 0x%" PRIxLEAST64, 515011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memoryOffset, dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment); 515111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 515211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 515311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 515411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert print_mem_list(dev_data); 515511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 515611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 515711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = dev_data->device_dispatch_table->BindBufferMemory(device, buffer, mem, memoryOffset); 515811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 515911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 516011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 516111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 516211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 516311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements *pMemoryRequirements) { 516411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 516511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : What to track here? 516611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Could potentially save returned mem requirements and validate values passed into BindBufferMemory 516711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->device_dispatch_table->GetBufferMemoryRequirements(device, buffer, pMemoryRequirements); 516811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 516911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 517011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 517111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) { 517211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 517311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : What to track here? 517411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Could potentially save returned mem requirements and validate values passed into BindImageMemory 517511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->device_dispatch_table->GetImageMemoryRequirements(device, image, pMemoryRequirements); 517611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 517711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 517811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 517911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) { 518011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_my_data_ptr(get_dispatch_key(device), layer_data_map) 518111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ->device_dispatch_table->DestroyImageView(device, imageView, pAllocator); 518211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Clean up any internal data structures using this obj. 518311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 518411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 518511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 518611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks *pAllocator) { 518711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 518811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 518911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 519011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->shaderModuleMap.erase(shaderModule); 519111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 519211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 519311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->device_dispatch_table->DestroyShaderModule(device, shaderModule, pAllocator); 519411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 519511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 519611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 519711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) { 519811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroyPipeline(device, pipeline, pAllocator); 519911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Clean up any internal data structures using this obj. 520011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 520111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 520211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 520311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks *pAllocator) { 520411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_my_data_ptr(get_dispatch_key(device), layer_data_map) 520511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ->device_dispatch_table->DestroyPipelineLayout(device, pipelineLayout, pAllocator); 520611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Clean up any internal data structures using this obj. 520711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 520811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 520911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 521011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) { 521111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroySampler(device, sampler, pAllocator); 521211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Clean up any internal data structures using this obj. 521311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 521411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 521511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 521611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks *pAllocator) { 521711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_my_data_ptr(get_dispatch_key(device), layer_data_map) 521811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ->device_dispatch_table->DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator); 521911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Clean up any internal data structures using this obj. 522011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 522111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 522211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 522311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks *pAllocator) { 522411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_my_data_ptr(get_dispatch_key(device), layer_data_map) 522511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ->device_dispatch_table->DestroyDescriptorPool(device, descriptorPool, pAllocator); 522611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Clean up any internal data structures using this obj. 522711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 522811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Verify cmdBuffer in given cb_node is not in global in-flight set, and return skip_call result 522911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// If this is a secondary command buffer, then make sure its primary is also in-flight 523011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// If primary is not in-flight, then remove secondary from global in-flight set 523111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This function is only valid at a point when cmdBuffer is being reset or freed 523211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool checkAndClearCommandBufferInFlight(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const char *action) { 523311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 523411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->globalInFlightCmdBuffers.count(cb_node->commandBuffer)) { 523511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Primary CB or secondary where primary is also in-flight is an error 523611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_SECONDARY) || 523711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (dev_data->globalInFlightCmdBuffers.count(cb_node->primaryCommandBuffer))) { 523811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg( 523911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 524011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER_RESET, "DS", 524111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Attempt to %s command buffer (0x%" PRIxLEAST64 ") which is in use.", action, 524211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(cb_node->commandBuffer)); 524311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { // Secondary CB w/o primary in-flight, remove from in-flight 524411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->globalInFlightCmdBuffers.erase(cb_node->commandBuffer); 524511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 524611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 524711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 524811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 524911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Iterate over all cmdBuffers in given commandPool and verify that each is not in use 525011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool checkAndClearCommandBuffersInFlight(layer_data *dev_data, const VkCommandPool commandPool, const char *action) { 525111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 525211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pool_data = dev_data->commandPoolMap.find(commandPool); 525311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pool_data != dev_data->commandPoolMap.end()) { 525411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cmd_buffer : pool_data->second.commandBuffers) { 525511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->globalInFlightCmdBuffers.count(cmd_buffer)) { 525611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= checkAndClearCommandBufferInFlight(dev_data, getCBNode(dev_data, cmd_buffer), action); 525711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 525811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 525911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 526011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 526111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 526211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 526311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 526411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) { 526511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 526611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 526711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 526811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 526911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < commandBufferCount; i++) { 527011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_pair = dev_data->commandBufferMap.find(pCommandBuffers[i]); 527111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= checkAndClearCommandBufferInFlight(dev_data, cb_pair->second, "free"); 527211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Delete CB information structure, and remove from commandBufferMap 527311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_pair != dev_data->commandBufferMap.end()) { 527411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // reset prior to delete for data clean-up 527511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert resetCB(dev_data, (*cb_pair).second->commandBuffer); 527611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete (*cb_pair).second; 527711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->commandBufferMap.erase(cb_pair); 527811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 527911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 528011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Remove commandBuffer reference from commandPoolMap 528111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->commandPoolMap[commandPool].commandBuffers.remove(pCommandBuffers[i]); 528211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 528311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert printCBList(dev_data); 528411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 528511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 528611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skip_call) 528711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers); 528811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 528911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 529011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, 529111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, 529211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkCommandPool *pCommandPool) { 529311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 529411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 529511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool); 529611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 529711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 529811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 529911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->commandPoolMap[*pCommandPool].createFlags = pCreateInfo->flags; 530011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->commandPoolMap[*pCommandPool].queueFamilyIndex = pCreateInfo->queueFamilyIndex; 530111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 530211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 530311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 530411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 530511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo, 530611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) { 530711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 530811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 530911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool); 531011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result == VK_SUCCESS) { 531111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 531211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->queryPoolMap[*pQueryPool].createInfo = *pCreateInfo; 531311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 531411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 531511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 531611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 531711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Destroy commandPool along with all of the commandBuffers allocated from that pool 531811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 531911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) { 532011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 532111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 532211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 532311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Verify that command buffers in pool are complete (not in-flight) 532411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkBool32 result = checkAndClearCommandBuffersInFlight(dev_data, commandPool, "destroy command pool with"); 532511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Must remove cmdpool from cmdpoolmap, after removing all cmdbuffers in its list from the commandPoolMap 532611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pool_it = dev_data->commandPoolMap.find(commandPool); 532711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pool_it != dev_data->commandPoolMap.end()) { 532811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cb : pool_it->second.commandBuffers) { 532911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert clear_cmd_buf_and_mem_references(dev_data, cb); 533011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto del_cb = dev_data->commandBufferMap.find(cb); 533111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete del_cb->second; // delete CB info structure 533211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->commandBufferMap.erase(del_cb); // Remove this command buffer 533311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 533411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 533511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->commandPoolMap.erase(commandPool); 533611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 533711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 533811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 533911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result) 534011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 534111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 534211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 534311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->DestroyCommandPool(device, commandPool, pAllocator); 534411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 534511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 534611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 534711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) { 534811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 534911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 535011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 535111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 535211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (checkAndClearCommandBuffersInFlight(dev_data, commandPool, "reset command pool with")) 535311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 535411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 535511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 535611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = dev_data->device_dispatch_table->ResetCommandPool(device, commandPool, flags); 535711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 535811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Reset all of the CBs allocated from this pool 535911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 536011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 536111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto it = dev_data->commandPoolMap[commandPool].commandBuffers.begin(); 536211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (it != dev_data->commandPoolMap[commandPool].commandBuffers.end()) { 536311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert resetCB(dev_data, (*it)); 536411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++it; 536511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 536611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 536711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 536811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 536911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 537011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) { 537111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 537211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 537311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 537411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 537511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < fenceCount; ++i) { 537611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto fence_item = dev_data->fenceMap.find(pFences[i]); 537711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence_item != dev_data->fenceMap.end()) { 537811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_item->second.needsSignaled = true; 537911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_item->second.queues.clear(); 538011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_item->second.priorFences.clear(); 538111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence_item->second.in_use.load()) { 538211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 538311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 538411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(pFences[i]), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", 538511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Fence 0x%" PRIx64 " is in use by a command buffer.", reinterpret_cast<const uint64_t &>(pFences[i])); 538611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 538711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 538811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 538911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 539011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 539111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = dev_data->device_dispatch_table->ResetFences(device, fenceCount, pFences); 539211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 539311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 539411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 539511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 539611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) { 539711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 539811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 539911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto fbNode = dev_data->frameBufferMap.find(framebuffer); 540011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fbNode != dev_data->frameBufferMap.end()) { 540111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto cb : fbNode->second.referencingCmdBuffers) { 540211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cbNode = dev_data->commandBufferMap.find(cb); 540311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cbNode != dev_data->commandBufferMap.end()) { 540411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Set CB as invalid and record destroyed framebuffer 540511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cbNode->second->state = CB_INVALID; 540611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cbNode->second->destroyedFramebuffers.insert(framebuffer); 540711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 540811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 540911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete [] fbNode->second.createInfo.pAttachments; 541011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->frameBufferMap.erase(fbNode); 541111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 541211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 541311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->DestroyFramebuffer(device, framebuffer, pAllocator); 541411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 541511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 541611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 541711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) { 541811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 541911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->DestroyRenderPass(device, renderPass, pAllocator); 542011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 542111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->renderPassMap.erase(renderPass); 542211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 542311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 542411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, 542511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) { 542611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 542711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 542811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateBuffer(device, pCreateInfo, pAllocator, pBuffer); 542911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 543011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 543111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 543211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : This doesn't create deep copy of pQueueFamilyIndices so need to fix that if/when we want that data to be valid 543311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->bufferMap.insert(std::make_pair(*pBuffer, BUFFER_NODE(pCreateInfo))); 543411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 543511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 543611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 543711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 543811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo, 543911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkBufferView *pView) { 544011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 544111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateBufferView(device, pCreateInfo, pAllocator, pView); 544211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 544311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 544411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->bufferViewMap[*pView] = VkBufferViewCreateInfo(*pCreateInfo); 544511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // In order to create a valid buffer view, the buffer must have been created with at least one of the 544611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // following flags: UNIFORM_TEXEL_BUFFER_BIT or STORAGE_TEXEL_BUFFER_BIT 544711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert validate_buffer_usage_flags(dev_data, pCreateInfo->buffer, 544811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, false, 544911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCreateBufferView()", "VK_BUFFER_USAGE_[STORAGE|UNIFORM]_TEXEL_BUFFER_BIT"); 545011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 545111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 545211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 545311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 545411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, 545511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkImage *pImage) { 545611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 545711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 545811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateImage(device, pCreateInfo, pAllocator, pImage); 545911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 546011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 546111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 546211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert IMAGE_LAYOUT_NODE image_node; 546311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node.layout = pCreateInfo->initialLayout; 546411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node.format = pCreateInfo->format; 546511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageMap.insert(std::make_pair(*pImage, IMAGE_NODE(pCreateInfo))); 546611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ImageSubresourcePair subpair = {*pImage, false, VkImageSubresource()}; 546711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageSubresourceMap[*pImage].push_back(subpair); 546811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageLayoutMap[subpair] = image_node; 546911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 547011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 547111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 547211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 547311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void ResolveRemainingLevelsLayers(layer_data *dev_data, VkImageSubresourceRange *range, VkImage image) { 547411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* expects global_lock to be held by caller */ 547511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 547611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto image_node_it = dev_data->imageMap.find(image); 547711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_node_it != dev_data->imageMap.end()) { 547811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* If the caller used the special values VK_REMAINING_MIP_LEVELS and 547911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * VK_REMAINING_ARRAY_LAYERS, resolve them now in our internal state to 548011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * the actual values. 548111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 548211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (range->levelCount == VK_REMAINING_MIP_LEVELS) { 548311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert range->levelCount = image_node_it->second.createInfo.mipLevels - range->baseMipLevel; 548411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 548511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 548611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (range->layerCount == VK_REMAINING_ARRAY_LAYERS) { 548711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert range->layerCount = image_node_it->second.createInfo.arrayLayers - range->baseArrayLayer; 548811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 548911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 549011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 549111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 549211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Return the correct layer/level counts if the caller used the special 549311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// values VK_REMAINING_MIP_LEVELS or VK_REMAINING_ARRAY_LAYERS. 549411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void ResolveRemainingLevelsLayers(layer_data *dev_data, uint32_t *levels, uint32_t *layers, VkImageSubresourceRange range, 549511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImage image) { 549611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* expects global_lock to be held by caller */ 549711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 549811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *levels = range.levelCount; 549911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *layers = range.layerCount; 550011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto image_node_it = dev_data->imageMap.find(image); 550111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_node_it != dev_data->imageMap.end()) { 550211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (range.levelCount == VK_REMAINING_MIP_LEVELS) { 550311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *levels = image_node_it->second.createInfo.mipLevels - range.baseMipLevel; 550411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 550511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (range.layerCount == VK_REMAINING_ARRAY_LAYERS) { 550611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *layers = image_node_it->second.createInfo.arrayLayers - range.baseArrayLayer; 550711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 550811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 550911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 551011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 551111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo, 551211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkImageView *pView) { 551311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 551411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 551511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 551611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 551711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate that img has correct usage flags set 551811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 551911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_image_usage_flags(dev_data, pCreateInfo->image, 552011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | 552111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 552211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert false, "vkCreateImageView()", "VK_IMAGE_USAGE_[SAMPLED|STORAGE|COLOR_ATTACHMENT]_BIT"); 552311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 552411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 552511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 552611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = dev_data->device_dispatch_table->CreateImageView(device, pCreateInfo, pAllocator, pView); 552711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 552811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 552911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 553011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 553111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageViewCreateInfo localCI = VkImageViewCreateInfo(*pCreateInfo); 553211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ResolveRemainingLevelsLayers(dev_data, &localCI.subresourceRange, pCreateInfo->image); 553311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageViewMap[*pView] = localCI; 553411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 553511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 553611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 553711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 553811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 553911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 554011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence) { 554111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 554211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateFence(device, pCreateInfo, pAllocator, pFence); 554311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 554411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 554511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto &fence_node = dev_data->fenceMap[*pFence]; 554611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_node.createInfo = *pCreateInfo; 554711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_node.needsSignaled = true; 554811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) { 554911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_node.firstTimeFlag = true; 555011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_node.needsSignaled = false; 555111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 555211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_node.in_use.store(0); 555311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 555411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 555511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 555611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 555711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// TODO handle pipeline caches 555811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo, 555911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkPipelineCache *pPipelineCache) { 556011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 556111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache); 556211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 556311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 556411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 556511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 556611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks *pAllocator) { 556711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 556811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->DestroyPipelineCache(device, pipelineCache, pAllocator); 556911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 557011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 557111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 557211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize, void *pData) { 557311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 557411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->GetPipelineCacheData(device, pipelineCache, pDataSize, pData); 557511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 557611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 557711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 557811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 557911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertMergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache *pSrcCaches) { 558011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 558111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches); 558211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 558311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 558411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 558511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// utility function to set collective state for pipeline 558611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid set_pipeline_state(PIPELINE_NODE *pPipe) { 558711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If any attachment used by this pipeline has blendEnable, set top-level blendEnable 558811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipe->graphicsPipelineCI.pColorBlendState) { 558911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (size_t i = 0; i < pPipe->attachments.size(); ++i) { 559011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_TRUE == pPipe->attachments[i].blendEnable) { 559111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (((pPipe->attachments[i].dstAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 559211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipe->attachments[i].dstAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 559311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ((pPipe->attachments[i].dstColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 559411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipe->attachments[i].dstColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 559511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ((pPipe->attachments[i].srcAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 559611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipe->attachments[i].srcAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 559711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ((pPipe->attachments[i].srcColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 559811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pPipe->attachments[i].srcColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA))) { 559911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipe->blendConstantsEnabled = true; 560011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 560111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 560211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 560311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 560411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 560511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 560611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 560711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, 560811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkGraphicsPipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator, 560911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkPipeline *pPipelines) { 561011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_SUCCESS; 561111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO What to do with pipelineCache? 561211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // The order of operations here is a little convoluted but gets the job done 561311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // 1. Pipeline create state is first shadowed into PIPELINE_NODE struct 561411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // 2. Create state is then validated (which uses flags setup during shadowing) 561511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // 3. If everything looks good, we'll then create the pipeline and add NODE to pipelineMap 561611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 561711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic 561811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert vector<PIPELINE_NODE *> pPipeNode(count); 561911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 562011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 562111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t i = 0; 562211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 562311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 562411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (i = 0; i < count; i++) { 562511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeNode[i] = new PIPELINE_NODE; 562611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeNode[i]->initGraphicsPipeline(&pCreateInfos[i]); 562711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeNode[i]->renderPass = getRenderPass(dev_data, pCreateInfos[i].renderPass); 562811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeNode[i]->pipelineLayout = getPipelineLayout(dev_data, pCreateInfos[i].layout); 562911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 563011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode, i); 563111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 563211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 563311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 563411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 563511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = dev_data->device_dispatch_table->CreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator, 563611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipelines); 563711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 563811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (i = 0; i < count; i++) { 563911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeNode[i]->pipeline = pPipelines[i]; 564011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->pipelineMap[pPipeNode[i]->pipeline] = pPipeNode[i]; 564111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 564211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 564311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 564411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (i = 0; i < count; i++) { 564511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete pPipeNode[i]; 564611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 564711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 564811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 564911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 565011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 565111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 565211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 565311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 565411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, 565511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkComputePipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator, 565611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkPipeline *pPipelines) { 565711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_SUCCESS; 565811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 565911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 566011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic 566111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert vector<PIPELINE_NODE *> pPipeNode(count); 566211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 566311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 566411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t i = 0; 566511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 566611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (i = 0; i < count; i++) { 566711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Verify compute stage bits 566811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 566911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Create and initialize internal tracking data structure 567011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeNode[i] = new PIPELINE_NODE; 567111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeNode[i]->initComputePipeline(&pCreateInfos[i]); 567211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeNode[i]->pipelineLayout = getPipelineLayout(dev_data, pCreateInfos[i].layout); 567311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // memcpy(&pPipeNode[i]->computePipelineCI, (const void *)&pCreateInfos[i], sizeof(VkComputePipelineCreateInfo)); 567411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 567511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Add Compute Pipeline Verification 567611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode[i]); 567711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 567811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 567911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 568011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 568111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = dev_data->device_dispatch_table->CreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, 568211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipelines); 568311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 568411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (i = 0; i < count; i++) { 568511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPipeNode[i]->pipeline = pPipelines[i]; 568611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->pipelineMap[pPipeNode[i]->pipeline] = pPipeNode[i]; 568711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 568811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 568911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 569011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (i = 0; i < count; i++) { 569111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Clean up any locally allocated data structures 569211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete pPipeNode[i]; 569311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 569411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 569511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 569611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 569711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 569811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 569911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 570011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo, 570111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) { 570211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 570311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateSampler(device, pCreateInfo, pAllocator, pSampler); 570411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 570511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 570611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->samplerMap[*pSampler] = unique_ptr<SAMPLER_NODE>(new SAMPLER_NODE(pSampler, pCreateInfo)); 570711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 570811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 570911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 571011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 571111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 571211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 571311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout) { 571411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 571511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout); 571611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 571711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODOSC : Capture layout bindings set 571811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 571911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->descriptorSetLayoutMap[*pSetLayout] = 572011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert new cvdescriptorset::DescriptorSetLayout(dev_data->report_data, pCreateInfo, *pSetLayout); 572111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 572211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 572311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 572411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 572511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Used by CreatePipelineLayout and CmdPushConstants. 572611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Note that the index argument is optional and only used by CreatePipelineLayout. 572711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validatePushConstantRange(const layer_data *dev_data, const uint32_t offset, const uint32_t size, 572811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char *caller_name, uint32_t index = 0) { 572911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t const maxPushConstantsSize = dev_data->phys_dev_properties.properties.limits.maxPushConstantsSize; 573011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 573111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Check that offset + size don't exceed the max. 573211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Prevent arithetic overflow here by avoiding addition and testing in this order. 573311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((offset >= maxPushConstantsSize) || (size > maxPushConstantsSize - offset)) { 573411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // 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. 573511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 573611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 573711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 573811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "%s call has push constants index %u with offset %u and size %u that " 573911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "exceeds this device's maxPushConstantSize of %u.", 574011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert caller_name, index, offset, size, maxPushConstantsSize); 574111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 574211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 574311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "%s call has push constants with offset %u and size %u that " 574411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "exceeds this device's maxPushConstantSize of %u.", 574511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert caller_name, offset, size, maxPushConstantsSize); 574611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 574711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 574811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 574911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 575011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 575111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // size needs to be non-zero and a multiple of 4. 575211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((size == 0) || ((size & 0x3) != 0)) { 575311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 575411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 575511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 575611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "%s call has push constants index %u with " 575711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "size %u. Size must be greater than zero and a multiple of 4.", 575811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert caller_name, index, size); 575911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 576011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 576111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 576211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "%s call has push constants with " 576311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "size %u. Size must be greater than zero and a multiple of 4.", 576411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert caller_name, size); 576511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 576611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 576711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 576811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 576911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 577011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // offset needs to be a multiple of 4. 577111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((offset & 0x3) != 0) { 577211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 577311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 577411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "%s call has push constants index %u with " 577511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "offset %u. Offset must be a multiple of 4.", 577611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert caller_name, index, offset); 577711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 577811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 577911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "%s call has push constants with " 578011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "offset %u. Offset must be a multiple of 4.", 578111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert caller_name, offset); 578211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 578311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 578411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 578511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 578611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 578711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 578811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 578911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 579011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo, 579111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout) { 579211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 579311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 579411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Push Constant Range checks 579511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t i = 0; 579611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 579711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validatePushConstantRange(dev_data, pCreateInfo->pPushConstantRanges[i].offset, 579811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCreateInfo->pPushConstantRanges[i].size, "vkCreatePipelineLayout()", i); 579911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (0 == pCreateInfo->pPushConstantRanges[i].stageFlags) { 580011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 580111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "vkCreatePipelineLayout() call has no stageFlags set."); 580211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 580311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 580411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Each range has been validated. Now check for overlap between ranges (if they are good). 580511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 580611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t i, j; 580711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 580811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (j = i + 1; j < pCreateInfo->pushConstantRangeCount; ++j) { 580911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t minA = pCreateInfo->pPushConstantRanges[i].offset; 581011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t maxA = minA + pCreateInfo->pPushConstantRanges[i].size; 581111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t minB = pCreateInfo->pPushConstantRanges[j].offset; 581211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t maxB = minB + pCreateInfo->pPushConstantRanges[j].size; 581311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((minA <= minB && maxA > minB) || (minB <= minA && maxB > minA)) { 581411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 581511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 581611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "vkCreatePipelineLayout() call has push constants with " 581711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "overlapping ranges: %u:[%u, %u), %u:[%u, %u)", 581811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert i, minA, maxA, j, minB, maxB); 581911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 582011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 582111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 582211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 582311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 582411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skipCall) 582511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 582611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 582711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout); 582811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 582911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 583011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PIPELINE_LAYOUT_NODE &plNode = dev_data->pipelineLayoutMap[*pPipelineLayout]; 583111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert plNode.descriptorSetLayouts.resize(pCreateInfo->setLayoutCount); 583211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert plNode.setLayouts.resize(pCreateInfo->setLayoutCount); 583311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (i = 0; i < pCreateInfo->setLayoutCount; ++i) { 583411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert plNode.descriptorSetLayouts[i] = pCreateInfo->pSetLayouts[i]; 583511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert plNode.setLayouts[i] = getDescriptorSetLayout(dev_data, pCreateInfo->pSetLayouts[i]); 583611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 583711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert plNode.pushConstantRanges.resize(pCreateInfo->pushConstantRangeCount); 583811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 583911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert plNode.pushConstantRanges[i] = pCreateInfo->pPushConstantRanges[i]; 584011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 584111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 584211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 584311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 584411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 584511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 584611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, 584711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDescriptorPool *pDescriptorPool) { 584811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 584911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool); 585011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 585111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Insert this pool into Global Pool LL at head 585211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 585311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)*pDescriptorPool, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS", "Created Descriptor Pool 0x%" PRIxLEAST64, 585411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)*pDescriptorPool)) 585511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 585611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DESCRIPTOR_POOL_NODE *pNewNode = new DESCRIPTOR_POOL_NODE(*pDescriptorPool, pCreateInfo); 585711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (NULL == pNewNode) { 585811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 585911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)*pDescriptorPool, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS", 586011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Out of memory while attempting to allocate DESCRIPTOR_POOL_NODE in vkCreateDescriptorPool()")) 586111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 586211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 586311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 586411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->descriptorPoolMap[*pDescriptorPool] = pNewNode; 586511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 586611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 586711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Need to do anything if pool create fails? 586811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 586911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 587011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 587111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 587211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 587311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) { 587411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 587511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->ResetDescriptorPool(device, descriptorPool, flags); 587611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 587711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 587811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert clearDescriptorPool(dev_data, device, descriptorPool, flags); 587911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 588011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 588111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 588211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 588311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Ensure the pool contains enough descriptors and descriptor sets to satisfy 588411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// an allocation request. Fills requiredDescriptorsByType with the total number 588511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// of descriptors of each type required, for later update. 588611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, DESCRIPTOR_POOL_NODE *pPoolNode, uint32_t count, 588711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<cvdescriptorset::DescriptorSetLayout const *> const & layout_nodes, 588811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t requiredDescriptorsByType[]) { 588911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 589011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 589111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Track number of descriptorSets allowable in this pool 589211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPoolNode->availableSets < count) { 589311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 589411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(pPoolNode->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", 589511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64 589611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ". This pool only has %d descriptorSets remaining.", 589711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert count, reinterpret_cast<uint64_t &>(pPoolNode->pool), pPoolNode->availableSets); 589811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 589911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 590011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Count total descriptors required per type 590111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto layout_node : layout_nodes) { 590211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (layout_node) { 590311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < layout_node->GetBindingCount(); ++j) { 590411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const auto &binding_layout = layout_node->GetDescriptorSetLayoutBindingPtrFromIndex(j); 590511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t typeIndex = static_cast<uint32_t>(binding_layout->descriptorType); 590611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert requiredDescriptorsByType[typeIndex] += binding_layout->descriptorCount; 590711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 590811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 590911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 591011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 591111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Determine whether descriptor counts are satisfiable 591211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { 591311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (requiredDescriptorsByType[i] > pPoolNode->availableDescriptorTypeCount[i]) { 591411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 591511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 591611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(pPoolNode->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", 591711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64 591811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ". This pool only has %d descriptors of this type remaining.", 591911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert requiredDescriptorsByType[i], string_VkDescriptorType(VkDescriptorType(i)), (uint64_t)pPoolNode->pool, 592011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPoolNode->availableDescriptorTypeCount[i]); 592111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 592211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 592311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 592411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 592511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 592611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 592711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 592811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets) { 592911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 593011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 593111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 593211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t requiredDescriptorsByType[VK_DESCRIPTOR_TYPE_RANGE_SIZE] {}; 593311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<cvdescriptorset::DescriptorSetLayout const *> layout_nodes(pAllocateInfo->descriptorSetCount, nullptr); 593411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 593511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 593611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 593711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) { 593811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layout_nodes[i] = getDescriptorSetLayout(dev_data, pAllocateInfo->pSetLayouts[i]); 593911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!layout_nodes[i]) { 594011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, 594111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pAllocateInfo->pSetLayouts[i], __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", 594211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Unable to find set layout node for layout 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", 594311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pAllocateInfo->pSetLayouts[i]); 594411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 594511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 594611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 594711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, pAllocateInfo->descriptorPool); 594811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 594911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pPoolNode) { 595011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 595111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pAllocateInfo->descriptorPool, __LINE__, DRAWSTATE_INVALID_POOL, "DS", 595211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Unable to find pool node for pool 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", 595311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pAllocateInfo->descriptorPool); 595411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { // Make sure pool has all the available descriptors before calling down chain 595511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= PreCallValidateAllocateDescriptorSets(dev_data, pPoolNode, pAllocateInfo->descriptorSetCount, 595611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layout_nodes, requiredDescriptorsByType); 595711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 595811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 595911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 596011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skipCall) 596111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 596211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 596311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets); 596411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 596511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 596611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 596711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPoolNode) { 596811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Account for sets and descriptors allocated */ 596911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPoolNode->availableSets -= pAllocateInfo->descriptorSetCount; 597011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { 597111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPoolNode->availableDescriptorTypeCount[i] -= requiredDescriptorsByType[i]; 597211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 597311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 597411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Create tracking object for each descriptor set; insert into 597511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * global map and the pool's set. 597611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 597711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) { 597811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (layout_nodes[i]) { 597911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pNewNode = new cvdescriptorset::DescriptorSet( 598011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDescriptorSets[i], layout_nodes[i], &dev_data->bufferMap, &dev_data->memObjMap, &dev_data->bufferViewMap, 598111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert &dev_data->samplerMap, &dev_data->imageViewMap, &dev_data->imageMap, 598211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert &dev_data->device_extensions.imageToSwapchainMap, &dev_data->device_extensions.swapchainMap); 598311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 598411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPoolNode->sets.insert(pNewNode); 598511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pNewNode->in_use.store(0); 598611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->setMap[pDescriptorSets[i]] = pNewNode; 598711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 598811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 598911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 599011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 599111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 599211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 599311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 599411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 599511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 599611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, const VkDescriptorSet *pDescriptorSets) { 599711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 599811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 599911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Make sure that no sets being destroyed are in-flight 600011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 600111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < count; ++i) 600211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validateIdleDescriptorSet(dev_data, pDescriptorSets[i], "vkFreeDescriptorSets"); 600311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, descriptorPool); 600411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPoolNode && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pPoolNode->createInfo.flags)) { 600511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Can't Free from a NON_FREE pool 600611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 600711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)device, __LINE__, DRAWSTATE_CANT_FREE_FROM_NON_FREE_POOL, "DS", 600811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "It is invalid to call vkFreeDescriptorSets() with a pool created without setting " 600911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT."); 601011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 601111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 601211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skipCall) 601311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 601411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets); 601511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 601611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 601711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 601811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Update available descriptor sets in pool 601911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPoolNode->availableSets += count; 602011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 602111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // For each freed descriptor add its resources back into the pool as available and remove from pool and setMap 602211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < count; ++i) { 602311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cvdescriptorset::DescriptorSet *pSet = dev_data->setMap[pDescriptorSets[i]]; // getSetNode() without locking 602411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t typeIndex = 0, poolSizeCount = 0; 602511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < pSet->GetBindingCount(); ++j) { 602611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typeIndex = static_cast<uint32_t>(pSet->GetTypeFromIndex(j)); 602711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert poolSizeCount = pSet->GetDescriptorCountFromIndex(j); 602811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPoolNode->availableDescriptorTypeCount[typeIndex] += poolSizeCount; 602911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 603011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert freeDescriptorSet(dev_data, pSet); 603111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPoolNode->sets.erase(pSet); 603211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 603311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 603411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 603511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Any other clean-up or book-keeping to do here? 603611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 603711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 603811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// TODO : This is a Proof-of-concept for core validation architecture 603911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Really we'll want to break out these functions to separate files but 604011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// keeping it all together here to prove out design 604111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// PreCallValidate* handles validating all of the state prior to calling down chain to UpdateDescriptorSets() 604211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool PreCallValidateUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, 604311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 604411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkCopyDescriptorSet *pDescriptorCopies) { 604511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // First thing to do is perform map look-ups. 604611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // NOTE : UpdateDescriptorSets is somewhat unique in that it's operating on a number of DescriptorSets 604711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // so we can't just do a single map look-up up-front, but do them individually in functions below 604811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 604911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Now make call(s) that validate state, but don't perform state updates in this function 605011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Note, here DescriptorSets is unique in that we don't yet have an instance. Using a helper function in the 605111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // namespace which will parse params and make calls into specific class instances 605211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return cvdescriptorset::ValidateUpdateDescriptorSets(dev_data->report_data, dev_data->setMap, descriptorWriteCount, 605311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDescriptorWrites, descriptorCopyCount, pDescriptorCopies); 605411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 605511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSets() 605611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void PostCallRecordUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, 605711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 605811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkCopyDescriptorSet *pDescriptorCopies) { 605911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cvdescriptorset::PerformUpdateDescriptorSets(dev_data->setMap, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 606011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDescriptorCopies); 606111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 606211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 606311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 606411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites, 606511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) { 606611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Only map look-up at top level is for device-level layer_data 606711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 606811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 606911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = PreCallValidateUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 607011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDescriptorCopies); 607111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 607211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skip_call) { 607311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 607411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDescriptorCopies); 607511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 607611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Since UpdateDescriptorSets() is void, nothing to check prior to updating state 607711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PostCallRecordUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 607811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDescriptorCopies); 607911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 608011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 608111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 608211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 608311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pCreateInfo, VkCommandBuffer *pCommandBuffer) { 608411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 608511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->AllocateCommandBuffers(device, pCreateInfo, pCommandBuffer); 608611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 608711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 608811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto const &cp_it = dev_data->commandPoolMap.find(pCreateInfo->commandPool); 608911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cp_it != dev_data->commandPoolMap.end()) { 609011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pCreateInfo->commandBufferCount; i++) { 609111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Add command buffer to its commandPool map 609211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cp_it->second.commandBuffers.push_back(pCommandBuffer[i]); 609311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = new GLOBAL_CB_NODE; 609411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Add command buffer to map 609511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->commandBufferMap[pCommandBuffer[i]] = pCB; 609611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert resetCB(dev_data, pCommandBuffer[i]); 609711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->createInfo = *pCreateInfo; 609811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->device = device; 609911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 610011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 610111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert printCBList(dev_data); 610211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 610311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 610411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 610511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 610611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 610711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 610811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) { 610911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 611011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 611111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 611211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate command buffer level 611311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 611411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 611511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // This implicitly resets the Cmd Buffer so make sure any fence is done and then clear memory references 611611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->globalInFlightCmdBuffers.count(commandBuffer)) { 611711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 611811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 611911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)commandBuffer, __LINE__, MEMTRACK_RESET_CB_WHILE_IN_FLIGHT, "MEM", 612011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Calling vkBeginCommandBuffer() on active CB 0x%p before it has completed. " 612111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "You must check CB fence before this call.", 612211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert commandBuffer); 612311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 612411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert clear_cmd_buf_and_mem_references(dev_data, pCB); 612511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 612611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Secondary Command Buffer 612711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkCommandBufferInheritanceInfo *pInfo = pBeginInfo->pInheritanceInfo; 612811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pInfo) { 612911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 613011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 613111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS", 613211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must have inheritance info.", 613311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<void *>(commandBuffer)); 613411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 613511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) { 613611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pInfo->renderPass) { // renderpass should NOT be null for a Secondary CB 613711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 613811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 613911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS", 614011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) must specify a valid renderpass parameter.", 614111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<void *>(commandBuffer)); 614211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 614311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pInfo->framebuffer) { // framebuffer may be null for a Secondary CB, but this affects perf 614411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 614511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 614611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, 614711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "DS", "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) may perform better if a " 614811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "valid framebuffer parameter is specified.", 614911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<void *>(commandBuffer)); 615011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 615111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string errorString = ""; 615211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto framebuffer = getFramebuffer(dev_data, pInfo->framebuffer); 615311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (framebuffer) { 615411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkRenderPass fbRP = framebuffer->createInfo.renderPass; 615511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!verify_renderpass_compatibility(dev_data, fbRP, pInfo->renderPass, errorString)) { 615611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // renderPass that framebuffer was created with must be compatible with local renderPass 615711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 615811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 615911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 616011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, 616111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "DS", "vkBeginCommandBuffer(): Secondary Command " 616211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Buffer (0x%p) renderPass (0x%" PRIxLEAST64 ") is incompatible w/ framebuffer " 616311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "(0x%" PRIxLEAST64 ") w/ render pass (0x%" PRIxLEAST64 ") due to: %s", 616411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<void *>(commandBuffer), (uint64_t)(pInfo->renderPass), 616511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(pInfo->framebuffer), (uint64_t)(fbRP), errorString.c_str()); 616611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 616711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Connect this framebuffer to this cmdBuffer 616811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert framebuffer->referencingCmdBuffers.insert(pCB->commandBuffer); 616911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 617011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 617111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 617211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((pInfo->occlusionQueryEnable == VK_FALSE || 617311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->phys_dev_properties.features.occlusionQueryPrecise == VK_FALSE) && 617411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pInfo->queryFlags & VK_QUERY_CONTROL_PRECISE_BIT)) { 617511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 617611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(commandBuffer), 617711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS", 617811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must not have " 617911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_QUERY_CONTROL_PRECISE_BIT if occulusionQuery is disabled or the device does not " 618011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "support precise occlusion queries.", 618111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<void *>(commandBuffer)); 618211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 618311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 618411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pInfo && pInfo->renderPass != VK_NULL_HANDLE) { 618511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto renderPass = getRenderPass(dev_data, pInfo->renderPass); 618611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (renderPass) { 618711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pInfo->subpass >= renderPass->pCreateInfo->subpassCount) { 618811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 618911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__, 619011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS", 619111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) must has a subpass index (%d) " 619211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "that is less than the number of subpasses (%d).", 619311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)commandBuffer, pInfo->subpass, renderPass->pCreateInfo->subpassCount); 619411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 619511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 619611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 619711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 619811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (CB_RECORDING == pCB->state) { 619911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 620011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 620111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)commandBuffer, __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS", 620211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkBeginCommandBuffer(): Cannot call Begin on CB (0x%" PRIxLEAST64 620311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") in the RECORDING state. Must first call vkEndCommandBuffer().", 620411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)commandBuffer); 620511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (CB_RECORDED == pCB->state || (CB_INVALID == pCB->state && CMD_END == pCB->cmds.back().type)) { 620611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkCommandPool cmdPool = pCB->createInfo.commandPool; 620711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & dev_data->commandPoolMap[cmdPool].createFlags)) { 620811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 620911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 621011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER_RESET, "DS", 621111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Call to vkBeginCommandBuffer() on command buffer (0x%" PRIxLEAST64 621211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") attempts to implicitly reset cmdBuffer created from command pool (0x%" PRIxLEAST64 621311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set.", 621411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)commandBuffer, (uint64_t)cmdPool); 621511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 621611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert resetCB(dev_data, commandBuffer); 621711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 621811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Set updated state here in case implicit reset occurs above 621911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->state = CB_RECORDING; 622011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->beginInfo = *pBeginInfo; 622111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->beginInfo.pInheritanceInfo) { 622211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->inheritanceInfo = *(pCB->beginInfo.pInheritanceInfo); 622311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->beginInfo.pInheritanceInfo = &pCB->inheritanceInfo; 622411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If we are a secondary command-buffer and inheriting. Update the items we should inherit. 622511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) && 622611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 622711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeRenderPass = getRenderPass(dev_data, pCB->beginInfo.pInheritanceInfo->renderPass); 622811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeSubpass = pCB->beginInfo.pInheritanceInfo->subpass; 622911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->framebuffers.insert(pCB->beginInfo.pInheritanceInfo->framebuffer); 623011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 623111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 623211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 623311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 623411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 623511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "In vkBeginCommandBuffer() and unable to find CommandBuffer Node for CB 0x%p!", (void *)commandBuffer); 623611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 623711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 623811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skipCall) { 623911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 624011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 624111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->BeginCommandBuffer(commandBuffer, pBeginInfo); 624211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 624311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 624411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 624511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 624611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL EndCommandBuffer(VkCommandBuffer commandBuffer) { 624711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 624811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_SUCCESS; 624911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 625011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 625111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 625211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 625311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((VK_COMMAND_BUFFER_LEVEL_PRIMARY == pCB->createInfo.level) || !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 625411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // This needs spec clarification to update valid usage, see comments in PR: 625511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/pull/516#discussion_r63013756 625611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, pCB, "vkEndCommandBuffer"); 625711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 625811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_END, "vkEndCommandBuffer()"); 625911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto query : pCB->activeQueries) { 626011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 626111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_QUERY, "DS", 626211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Ending command buffer with in progress query: queryPool 0x%" PRIx64 ", index %d", 626311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(query.pool), query.index); 626411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 626511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 626611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 626711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 626811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = dev_data->device_dispatch_table->EndCommandBuffer(commandBuffer); 626911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 627011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 627111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->state = CB_RECORDED; 627211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Reset CB status flags 627311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->status = 0; 627411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert printCB(dev_data, commandBuffer); 627511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 627611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 627711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = VK_ERROR_VALIDATION_FAILED_EXT; 627811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 627911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 628011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 628111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 628211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 628311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 628411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) { 628511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 628611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 628711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 628811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 628911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkCommandPool cmdPool = pCB->createInfo.commandPool; 629011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & dev_data->commandPoolMap[cmdPool].createFlags)) { 629111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 629211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER_RESET, "DS", 629311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Attempt to reset command buffer (0x%" PRIxLEAST64 ") created from command pool (0x%" PRIxLEAST64 629411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set.", 629511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)commandBuffer, (uint64_t)cmdPool); 629611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 629711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= checkAndClearCommandBufferInFlight(dev_data, pCB, "reset"); 629811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 629911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skip_call) 630011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 630111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->ResetCommandBuffer(commandBuffer, flags); 630211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 630311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 630411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert resetCB(dev_data, commandBuffer); 630511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 630611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 630711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 630811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 630911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 631011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 631111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) { 631211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 631311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 631411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 631511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 631611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 631711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_BINDPIPELINE, "vkCmdBindPipeline()"); 631811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((VK_PIPELINE_BIND_POINT_COMPUTE == pipelineBindPoint) && (pCB->activeRenderPass)) { 631911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 632011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 632111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pipeline, __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS", 632211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Incorrectly binding compute pipeline (0x%" PRIxLEAST64 ") during active RenderPass (0x%" PRIxLEAST64 ")", 632311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pipeline, (uint64_t)pCB->activeRenderPass->renderPass); 632411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 632511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 632611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PIPELINE_NODE *pPN = getPipeline(dev_data, pipeline); 632711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPN) { 632811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->lastBound[pipelineBindPoint].pipeline = pipeline; 632911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_cb_pso_status(pCB, pPN); 633011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_pipeline_state(pPN); 633111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 633211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 633311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pipeline, __LINE__, DRAWSTATE_INVALID_PIPELINE, "DS", 633411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Attempt to bind Pipeline 0x%" PRIxLEAST64 " that doesn't exist!", (uint64_t)(pipeline)); 633511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 633611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 633711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 633811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 633911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline); 634011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 634111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 634211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 634311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports) { 634411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 634511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 634611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 634711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 634811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 634911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_SETVIEWPORTSTATE, "vkCmdSetViewport()"); 635011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->status |= CBSTATUS_VIEWPORT_SET; 635111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->viewports.resize(viewportCount); 635211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy(pCB->viewports.data(), pViewports, viewportCount * sizeof(VkViewport)); 635311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 635411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 635511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 635611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports); 635711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 635811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 635911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 636011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors) { 636111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 636211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 636311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 636411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 636511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 636611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_SETSCISSORSTATE, "vkCmdSetScissor()"); 636711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->status |= CBSTATUS_SCISSOR_SET; 636811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->scissors.resize(scissorCount); 636911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy(pCB->scissors.data(), pScissors, scissorCount * sizeof(VkRect2D)); 637011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 637111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 637211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 637311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors); 637411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 637511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 637611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) { 637711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 637811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 637911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 638011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 638111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 638211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= addCmd(dev_data, pCB, CMD_SETLINEWIDTHSTATE, "vkCmdSetLineWidth()"); 638311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->status |= CBSTATUS_LINE_WIDTH_SET; 638411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 638511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PIPELINE_NODE *pPipeTrav = getPipeline(dev_data, pCB->lastBound[VK_PIPELINE_BIND_POINT_GRAPHICS].pipeline); 638611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPipeTrav != NULL && !isDynamic(pPipeTrav, VK_DYNAMIC_STATE_LINE_WIDTH)) { 638711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 638811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(commandBuffer), __LINE__, DRAWSTATE_INVALID_SET, "DS", 638911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdSetLineWidth called but pipeline was created without VK_DYNAMIC_STATE_LINE_WIDTH " 639011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "flag. This is undefined behavior and could be ignored."); 639111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 639211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= verifyLineWidth(dev_data, DRAWSTATE_INVALID_SET, reinterpret_cast<uint64_t &>(commandBuffer), lineWidth); 639311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 639411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 639511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 639611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skip_call) 639711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdSetLineWidth(commandBuffer, lineWidth); 639811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 639911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 640011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 640111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) { 640211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 640311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 640411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 640511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 640611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 640711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_SETDEPTHBIASSTATE, "vkCmdSetDepthBias()"); 640811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->status |= CBSTATUS_DEPTH_BIAS_SET; 640911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 641011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 641111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 641211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, 641311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert depthBiasSlopeFactor); 641411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 641511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 641611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) { 641711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 641811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 641911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 642011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 642111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 642211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_SETBLENDSTATE, "vkCmdSetBlendConstants()"); 642311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->status |= CBSTATUS_BLEND_CONSTANTS_SET; 642411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 642511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 642611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 642711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdSetBlendConstants(commandBuffer, blendConstants); 642811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 642911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 643011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 643111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) { 643211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 643311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 643411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 643511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 643611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 643711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_SETDEPTHBOUNDSSTATE, "vkCmdSetDepthBounds()"); 643811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->status |= CBSTATUS_DEPTH_BOUNDS_SET; 643911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 644011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 644111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 644211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds); 644311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 644411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 644511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 644611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask) { 644711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 644811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 644911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 645011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 645111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 645211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_SETSTENCILREADMASKSTATE, "vkCmdSetStencilCompareMask()"); 645311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->status |= CBSTATUS_STENCIL_READ_MASK_SET; 645411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 645511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 645611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 645711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask); 645811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 645911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 646011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 646111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) { 646211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 646311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 646411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 646511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 646611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 646711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_SETSTENCILWRITEMASKSTATE, "vkCmdSetStencilWriteMask()"); 646811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->status |= CBSTATUS_STENCIL_WRITE_MASK_SET; 646911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 647011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 647111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 647211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask); 647311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 647411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 647511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 647611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) { 647711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 647811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 647911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 648011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 648111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 648211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_SETSTENCILREFERENCESTATE, "vkCmdSetStencilReference()"); 648311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->status |= CBSTATUS_STENCIL_REFERENCE_SET; 648411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 648511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 648611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 648711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdSetStencilReference(commandBuffer, faceMask, reference); 648811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 648911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 649011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 649111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, 649211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t firstSet, uint32_t setCount, const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount, 649311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t *pDynamicOffsets) { 649411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 649511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 649611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 649711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 649811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 649911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->state == CB_RECORDING) { 650011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Track total count of dynamic descriptor types to make sure we have an offset for each one 650111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t totalDynamicDescriptors = 0; 650211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string errorString = ""; 650311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t lastSetIndex = firstSet + setCount - 1; 650411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (lastSetIndex >= pCB->lastBound[pipelineBindPoint].boundDescriptorSets.size()) { 650511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->lastBound[pipelineBindPoint].boundDescriptorSets.resize(lastSetIndex + 1); 650611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->lastBound[pipelineBindPoint].dynamicOffsets.resize(lastSetIndex + 1); 650711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 650811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto oldFinalBoundSet = pCB->lastBound[pipelineBindPoint].boundDescriptorSets[lastSetIndex]; 650911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < setCount; i++) { 651011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cvdescriptorset::DescriptorSet *pSet = getSetNode(dev_data, pDescriptorSets[i]); 651111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pSet) { 651211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->lastBound[pipelineBindPoint].uniqueBoundSets.insert(pSet); 651311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pSet->BindCommandBuffer(pCB); 651411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->lastBound[pipelineBindPoint].pipelineLayout = layout; 651511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i + firstSet] = pSet; 651611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 651711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__, 651811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_NONE, "DS", "DS 0x%" PRIxLEAST64 " bound on pipeline %s", 651911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pDescriptorSets[i], string_VkPipelineBindPoint(pipelineBindPoint)); 652011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pSet->IsUpdated() && (pSet->GetTotalDescriptorCount() != 0)) { 652111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 652211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], 652311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 652411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "DS 0x%" PRIxLEAST64 652511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " bound but it was never updated. You may want to either update it or not bind it.", 652611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pDescriptorSets[i]); 652711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 652811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Verify that set being bound is compatible with overlapping setLayout of pipelineLayout 652911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!verify_set_layout_compatibility(dev_data, pSet, layout, i + firstSet, errorString)) { 653011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 653111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__, 653211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS", 653311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "descriptorSet #%u being bound is not compatible with overlapping descriptorSetLayout " 653411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "at index %u of pipelineLayout 0x%" PRIxLEAST64 " due to: %s", 653511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert i, i + firstSet, reinterpret_cast<uint64_t &>(layout), errorString.c_str()); 653611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 653711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 653811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto setDynamicDescriptorCount = pSet->GetDynamicDescriptorCount(); 653911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 654011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + i].clear(); 654111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 654211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (setDynamicDescriptorCount) { 654311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // First make sure we won't overstep bounds of pDynamicOffsets array 654411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((totalDynamicDescriptors + setDynamicDescriptorCount) > dynamicOffsetCount) { 654511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 654611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 654711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__, 654811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS", 654911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "descriptorSet #%u (0x%" PRIxLEAST64 655011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") requires %u dynamicOffsets, but only %u dynamicOffsets are left in pDynamicOffsets " 655111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "array. There must be one dynamic offset for each dynamic descriptor being bound.", 655211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert i, (uint64_t)pDescriptorSets[i], pSet->GetDynamicDescriptorCount(), 655311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (dynamicOffsetCount - totalDynamicDescriptors)); 655411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { // Validate and store dynamic offsets with the set 655511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate Dynamic Offset Minimums 655611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t cur_dyn_offset = totalDynamicDescriptors; 655711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t d = 0; d < pSet->GetTotalDescriptorCount(); d++) { 655811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pSet->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) { 655911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (vk_safe_modulo( 656011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDynamicOffsets[cur_dyn_offset], 656111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment) != 0) { 656211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 656311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 656411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, 656511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_UNIFORM_BUFFER_OFFSET, "DS", 656611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of " 656711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "device limit minUniformBufferOffsetAlignment 0x%" PRIxLEAST64, 656811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cur_dyn_offset, pDynamicOffsets[cur_dyn_offset], 656911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment); 657011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 657111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cur_dyn_offset++; 657211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (pSet->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) { 657311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (vk_safe_modulo( 657411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDynamicOffsets[cur_dyn_offset], 657511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment) != 0) { 657611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 657711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 657811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, 657911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_STORAGE_BUFFER_OFFSET, "DS", 658011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of " 658111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "device limit minStorageBufferOffsetAlignment 0x%" PRIxLEAST64, 658211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cur_dyn_offset, pDynamicOffsets[cur_dyn_offset], 658311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment); 658411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 658511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cur_dyn_offset++; 658611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 658711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 658811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 658911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + i] = 659011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<uint32_t>(pDynamicOffsets + totalDynamicDescriptors, 659111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDynamicOffsets + totalDynamicDescriptors + setDynamicDescriptorCount); 659211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Keep running total of dynamic descriptor count to verify at the end 659311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert totalDynamicDescriptors += setDynamicDescriptorCount; 659411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 659511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 659611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 659711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 659811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 659911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__, 660011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_SET, "DS", "Attempt to bind DS 0x%" PRIxLEAST64 " that doesn't exist!", 660111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pDescriptorSets[i]); 660211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 660311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_BINDDESCRIPTORSETS, "vkCmdBindDescriptorSets()"); 660411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // For any previously bound sets, need to set them to "invalid" if they were disturbed by this update 660511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (firstSet > 0) { // Check set #s below the first bound set 660611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < firstSet; ++i) { 660711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i] && 660811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert !verify_set_layout_compatibility(dev_data, pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i], 660911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layout, i, errorString)) { 661011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 661111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 661211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 661311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i], __LINE__, DRAWSTATE_NONE, "DS", 661411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "DescriptorSetDS 0x%" PRIxLEAST64 661511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " previously bound as set #%u was disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")", 661611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i], i, (uint64_t)layout); 661711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i] = VK_NULL_HANDLE; 661811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 661911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 662011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 662111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Check if newly last bound set invalidates any remaining bound sets 662211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((pCB->lastBound[pipelineBindPoint].boundDescriptorSets.size() - 1) > (lastSetIndex)) { 662311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (oldFinalBoundSet && 662411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert !verify_set_layout_compatibility(dev_data, oldFinalBoundSet, layout, lastSetIndex, errorString)) { 662511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto old_set = oldFinalBoundSet->GetSet(); 662611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 662711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 662811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast<uint64_t &>(old_set), __LINE__, 662911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_NONE, "DS", "DescriptorSetDS 0x%" PRIxLEAST64 663011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " previously bound as set #%u is incompatible with set 0x%" PRIxLEAST64 663111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " newly bound as set #%u so set #%u and any subsequent sets were " 663211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")", 663311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(old_set), lastSetIndex, 663411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pCB->lastBound[pipelineBindPoint].boundDescriptorSets[lastSetIndex], lastSetIndex, 663511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lastSetIndex + 1, (uint64_t)layout); 663611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->lastBound[pipelineBindPoint].boundDescriptorSets.resize(lastSetIndex + 1); 663711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 663811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 663911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 664011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound 664111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (totalDynamicDescriptors != dynamicOffsetCount) { 664211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 664311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__, 664411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS", 664511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Attempting to bind %u descriptorSets with %u dynamic descriptors, but dynamicOffsetCount " 664611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "is %u. It should exactly match the number of dynamic descriptors.", 664711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert setCount, totalDynamicDescriptors, dynamicOffsetCount); 664811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 664911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 665011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdBindDescriptorSets()"); 665111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 665211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 665311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 665411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 665511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, setCount, 665611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pDescriptorSets, dynamicOffsetCount, pDynamicOffsets); 665711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 665811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 665911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 666011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) { 666111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 666211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 666311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Somewhere need to verify that IBs have correct usage state flagged 666411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 666511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory mem; 666611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = 666711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_mem_binding_from_object(dev_data, (uint64_t)buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, &mem); 666811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_data = dev_data->commandBufferMap.find(commandBuffer); 666911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_data != dev_data->commandBufferMap.end()) { 667011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { return validate_memory_is_valid(dev_data, mem, "vkCmdBindIndexBuffer()"); }; 667111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 667211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, cb_data->second, CMD_BINDINDEXBUFFER, "vkCmdBindIndexBuffer()"); 667311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceSize offset_align = 0; 667411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (indexType) { 667511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_INDEX_TYPE_UINT16: 667611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert offset_align = 2; 667711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 667811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_INDEX_TYPE_UINT32: 667911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert offset_align = 4; 668011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 668111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 668211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // ParamChecker should catch bad enum, we'll also throw alignment error below if offset_align stays 0 668311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 668411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 668511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!offset_align || (offset % offset_align)) { 668611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 668711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_VTX_INDEX_ALIGNMENT_ERROR, "DS", 668811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdBindIndexBuffer() offset (0x%" PRIxLEAST64 ") does not fall on alignment (%s) boundary.", 668911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert offset, string_VkIndexType(indexType)); 669011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 669111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->status |= CBSTATUS_INDEX_BUFFER_BOUND; 669211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 669311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 669411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 669511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType); 669611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 669711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 669811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid updateResourceTracking(GLOBAL_CB_NODE *pCB, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *pBuffers) { 669911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t end = firstBinding + bindingCount; 670011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->currentDrawData.buffers.size() < end) { 670111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->currentDrawData.buffers.resize(end); 670211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 670311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < bindingCount; ++i) { 670411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->currentDrawData.buffers[i + firstBinding] = pBuffers[i]; 670511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 670611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 670711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 670811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic inline void updateResourceTrackingOnDraw(GLOBAL_CB_NODE *pCB) { pCB->drawData.push_back(pCB->currentDrawData); } 670911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 671011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, 671111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t bindingCount, const VkBuffer *pBuffers, 671211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkDeviceSize *pOffsets) { 671311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 671411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 671511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Somewhere need to verify that VBs have correct usage state flagged 671611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 671711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_data = dev_data->commandBufferMap.find(commandBuffer); 671811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_data != dev_data->commandBufferMap.end()) { 671911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < bindingCount; ++i) { 672011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory mem; 672111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= get_mem_binding_from_object(dev_data, (uint64_t)pBuffers[i], VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, &mem); 672211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 672311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { return validate_memory_is_valid(dev_data, mem, "vkCmdBindVertexBuffers()"); }; 672411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 672511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 672611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert addCmd(dev_data, cb_data->second, CMD_BINDVERTEXBUFFER, "vkCmdBindVertexBuffer()"); 672711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert updateResourceTracking(cb_data->second, firstBinding, bindingCount, pBuffers); 672811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 672911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdBindVertexBuffer()"); 673011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 673111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 673211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 673311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets); 673411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 673511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 673611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* expects global_lock to be held by caller */ 673711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool markStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { 673811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 673911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 674011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto imageView : pCB->updateImages) { 674111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto iv_data = dev_data->imageViewMap.find(imageView); 674211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (iv_data == dev_data->imageViewMap.end()) 674311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 674411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImage image = iv_data->second.image; 674511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory mem; 674611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 674711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_mem_binding_from_object(dev_data, (uint64_t)image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &mem); 674811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 674911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, mem, true, image); 675011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 675111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 675211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->validate_functions.push_back(function); 675311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 675411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto buffer : pCB->updateBuffers) { 675511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory mem; 675611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= get_mem_binding_from_object(dev_data, (uint64_t)buffer, 675711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, &mem); 675811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 675911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, mem, true); 676011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 676111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 676211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->validate_functions.push_back(function); 676311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 676411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 676511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 676611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 676711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, 676811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t firstVertex, uint32_t firstInstance) { 676911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 677011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 677111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 677211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 677311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 677411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_DRAW, "vkCmdDraw()"); 677511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->drawCount[DRAW]++; 677611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_and_update_draw_state(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_GRAPHICS); 677711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= markStoreImagesAndBuffersAsWritten(dev_data, pCB); 677811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Need to pass commandBuffer as srcObj here 677911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 678011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 678111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_NONE, "DS", "vkCmdDraw() call 0x%" PRIx64 ", reporting DS state:", g_drawCount[DRAW]++); 678211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= synchAndPrintDSConfig(dev_data, commandBuffer); 678311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 678411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert updateResourceTrackingOnDraw(pCB); 678511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 678611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdDraw"); 678711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 678811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 678911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 679011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance); 679111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 679211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 679311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, 679411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, 679511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t firstInstance) { 679611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 679711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 679811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 679911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 680011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 680111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_DRAWINDEXED, "vkCmdDrawIndexed()"); 680211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->drawCount[DRAW_INDEXED]++; 680311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_and_update_draw_state(dev_data, pCB, true, VK_PIPELINE_BIND_POINT_GRAPHICS); 680411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= markStoreImagesAndBuffersAsWritten(dev_data, pCB); 680511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Need to pass commandBuffer as srcObj here 680611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 680711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_NONE, "DS", 680811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdDrawIndexed() call 0x%" PRIx64 ", reporting DS state:", g_drawCount[DRAW_INDEXED]++); 680911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= synchAndPrintDSConfig(dev_data, commandBuffer); 681011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 681111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert updateResourceTrackingOnDraw(pCB); 681211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 681311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdDrawIndexed"); 681411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 681511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 681611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 681711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, 681811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert firstInstance); 681911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 682011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 682111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 682211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) { 682311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 682411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 682511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 682611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory mem; 682711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // MTMTODO : merge with code below 682811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = 682911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_mem_binding_from_object(dev_data, (uint64_t)buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, &mem); 683011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, mem, "vkCmdDrawIndirect"); 683111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 683211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 683311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_DRAWINDIRECT, "vkCmdDrawIndirect()"); 683411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->drawCount[DRAW_INDIRECT]++; 683511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_and_update_draw_state(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_GRAPHICS); 683611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= markStoreImagesAndBuffersAsWritten(dev_data, pCB); 683711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Need to pass commandBuffer as srcObj here 683811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 683911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_NONE, "DS", 684011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdDrawIndirect() call 0x%" PRIx64 ", reporting DS state:", g_drawCount[DRAW_INDIRECT]++); 684111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= synchAndPrintDSConfig(dev_data, commandBuffer); 684211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 684311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert updateResourceTrackingOnDraw(pCB); 684411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 684511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdDrawIndirect"); 684611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 684711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 684811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 684911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdDrawIndirect(commandBuffer, buffer, offset, count, stride); 685011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 685111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 685211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 685311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) { 685411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 685511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 685611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 685711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory mem; 685811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // MTMTODO : merge with code below 685911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = 686011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_mem_binding_from_object(dev_data, (uint64_t)buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, &mem); 686111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, mem, "vkCmdDrawIndexedIndirect"); 686211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 686311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 686411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_DRAWINDEXEDINDIRECT, "vkCmdDrawIndexedIndirect()"); 686511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->drawCount[DRAW_INDEXED_INDIRECT]++; 686611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_and_update_draw_state(dev_data, pCB, true, VK_PIPELINE_BIND_POINT_GRAPHICS); 686711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= markStoreImagesAndBuffersAsWritten(dev_data, pCB); 686811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Need to pass commandBuffer as srcObj here 686911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 687011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 687111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_NONE, "DS", "vkCmdDrawIndexedIndirect() call 0x%" PRIx64 ", reporting DS state:", 687211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert g_drawCount[DRAW_INDEXED_INDIRECT]++); 687311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= synchAndPrintDSConfig(dev_data, commandBuffer); 687411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 687511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert updateResourceTrackingOnDraw(pCB); 687611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 687711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdDrawIndexedIndirect"); 687811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 687911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 688011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 688111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride); 688211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 688311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 688411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) { 688511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 688611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 688711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 688811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 688911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 689011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_and_update_draw_state(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_COMPUTE); 689111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Call below is temporary until call above can be re-enabled 689211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert update_shader_storage_images_and_buffers(dev_data, pCB); 689311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= markStoreImagesAndBuffersAsWritten(dev_data, pCB); 689411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_DISPATCH, "vkCmdDispatch()"); 689511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, pCB, "vkCmdDispatch"); 689611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 689711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 689811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 689911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdDispatch(commandBuffer, x, y, z); 690011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 690111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 690211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 690311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) { 690411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 690511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 690611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 690711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory mem; 690811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = 690911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_mem_binding_from_object(dev_data, (uint64_t)buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, &mem); 691011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, mem, "vkCmdDispatchIndirect"); 691111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 691211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 691311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_and_update_draw_state(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_COMPUTE); 691411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Call below is temporary until call above can be re-enabled 691511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert update_shader_storage_images_and_buffers(dev_data, pCB); 691611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= markStoreImagesAndBuffersAsWritten(dev_data, pCB); 691711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_DISPATCHINDIRECT, "vkCmdDispatchIndirect()"); 691811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, pCB, "vkCmdDispatchIndirect"); 691911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 692011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 692111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 692211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdDispatchIndirect(commandBuffer, buffer, offset); 692311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 692411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 692511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, 692611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t regionCount, const VkBufferCopy *pRegions) { 692711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 692811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 692911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 693011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory src_mem, dst_mem; 693111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = get_mem_binding_from_object(dev_data, (uint64_t)srcBuffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, &src_mem); 693211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, src_mem, "vkCmdCopyBuffer"); 693311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= get_mem_binding_from_object(dev_data, (uint64_t)dstBuffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, &dst_mem); 693411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 693511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, dst_mem, "vkCmdCopyBuffer"); 693611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate that SRC & DST buffers have correct usage flags set 693711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_buffer_usage_flags(dev_data, srcBuffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, true, 693811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdCopyBuffer()", "VK_BUFFER_USAGE_TRANSFER_SRC_BIT"); 693911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_buffer_usage_flags(dev_data, dstBuffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, 694011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdCopyBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 694111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_data = dev_data->commandBufferMap.find(commandBuffer); 694211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_data != dev_data->commandBufferMap.end()) { 694311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { return validate_memory_is_valid(dev_data, src_mem, "vkCmdCopyBuffer()"); }; 694411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 694511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert function = [=]() { 694611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, dst_mem, true); 694711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 694811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 694911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 695011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 695111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, cb_data->second, CMD_COPYBUFFER, "vkCmdCopyBuffer()"); 695211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, cb_data->second, "vkCmdCopyBuffer"); 695311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 695411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 695511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 695611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions); 695711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 695811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 695911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool VerifySourceImageLayout(VkCommandBuffer cmdBuffer, VkImage srcImage, VkImageSubresourceLayers subLayers, 696011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageLayout srcImageLayout) { 696111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 696211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 696311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); 696411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer); 696511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < subLayers.layerCount; ++i) { 696611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t layer = i + subLayers.baseArrayLayer; 696711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageSubresource sub = {subLayers.aspectMask, subLayers.mipLevel, layer}; 696811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert IMAGE_CMD_BUF_LAYOUT_NODE node; 696911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!FindLayout(pCB, srcImage, sub, node)) { 697011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(pCB, srcImage, sub, IMAGE_CMD_BUF_LAYOUT_NODE(srcImageLayout, srcImageLayout)); 697111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 697211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 697311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (node.layout != srcImageLayout) { 697411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Improve log message in the next pass 697511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 697611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 697711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Cannot copy from an image whose source layout is %s " 697811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "and doesn't match the current layout %s.", 697911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkImageLayout(srcImageLayout), string_VkImageLayout(node.layout)); 698011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 698111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 698211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (srcImageLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) { 698311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (srcImageLayout == VK_IMAGE_LAYOUT_GENERAL) { 698411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning. 698511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 698611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 698711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Layout for input image should be TRANSFER_SRC_OPTIMAL instead of GENERAL."); 698811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 698911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 699011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Layout for input image is %s but can only be " 699111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "TRANSFER_SRC_OPTIMAL or GENERAL.", 699211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkImageLayout(srcImageLayout)); 699311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 699411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 699511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 699611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 699711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 699811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool VerifyDestImageLayout(VkCommandBuffer cmdBuffer, VkImage destImage, VkImageSubresourceLayers subLayers, 699911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageLayout destImageLayout) { 700011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 700111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 700211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); 700311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer); 700411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < subLayers.layerCount; ++i) { 700511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t layer = i + subLayers.baseArrayLayer; 700611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageSubresource sub = {subLayers.aspectMask, subLayers.mipLevel, layer}; 700711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert IMAGE_CMD_BUF_LAYOUT_NODE node; 700811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!FindLayout(pCB, destImage, sub, node)) { 700911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(pCB, destImage, sub, IMAGE_CMD_BUF_LAYOUT_NODE(destImageLayout, destImageLayout)); 701011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 701111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 701211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (node.layout != destImageLayout) { 701311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 701411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 701511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Cannot copy from an image whose dest layout is %s and " 701611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "doesn't match the current layout %s.", 701711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkImageLayout(destImageLayout), string_VkImageLayout(node.layout)); 701811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 701911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 702011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (destImageLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { 702111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (destImageLayout == VK_IMAGE_LAYOUT_GENERAL) { 702211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning. 702311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 702411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 702511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Layout for output image should be TRANSFER_DST_OPTIMAL instead of GENERAL."); 702611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 702711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 702811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Layout for output image is %s but can only be " 702911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "TRANSFER_DST_OPTIMAL or GENERAL.", 703011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkImageLayout(destImageLayout)); 703111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 703211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 703311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 703411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 703511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 703611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 703711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, 703811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy *pRegions) { 703911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 704011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 704111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 704211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory src_mem, dst_mem; 704311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate that src & dst images have correct usage flags set 704411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = get_mem_binding_from_object(dev_data, (uint64_t)srcImage, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &src_mem); 704511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, src_mem, "vkCmdCopyImage"); 704611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 704711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= get_mem_binding_from_object(dev_data, (uint64_t)dstImage, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &dst_mem); 704811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, dst_mem, "vkCmdCopyImage"); 704911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_image_usage_flags(dev_data, srcImage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, 705011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdCopyImage()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT"); 705111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_image_usage_flags(dev_data, dstImage, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, 705211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdCopyImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT"); 705311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_data = dev_data->commandBufferMap.find(commandBuffer); 705411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_data != dev_data->commandBufferMap.end()) { 705511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 705611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return validate_memory_is_valid(dev_data, src_mem, "vkCmdCopyImage()", srcImage); 705711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 705811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 705911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert function = [=]() { 706011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, dst_mem, true, dstImage); 706111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 706211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 706311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 706411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 706511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, cb_data->second, CMD_COPYIMAGE, "vkCmdCopyImage()"); 706611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, cb_data->second, "vkCmdCopyImage"); 706711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < regionCount; ++i) { 706811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= VerifySourceImageLayout(commandBuffer, srcImage, pRegions[i].srcSubresource, srcImageLayout); 706911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= VerifyDestImageLayout(commandBuffer, dstImage, pRegions[i].dstSubresource, dstImageLayout); 707011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 707111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 707211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 707311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 707411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, 707511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert regionCount, pRegions); 707611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 707711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 707811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 707911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, 708011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) { 708111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 708211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 708311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 708411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory src_mem, dst_mem; 708511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate that src & dst images have correct usage flags set 708611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = get_mem_binding_from_object(dev_data, (uint64_t)srcImage, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &src_mem); 708711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, src_mem, "vkCmdBlitImage"); 708811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 708911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= get_mem_binding_from_object(dev_data, (uint64_t)dstImage, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &dst_mem); 709011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, dst_mem, "vkCmdBlitImage"); 709111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_image_usage_flags(dev_data, srcImage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, 709211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdBlitImage()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT"); 709311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_image_usage_flags(dev_data, dstImage, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, 709411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdBlitImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT"); 709511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 709611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_data = dev_data->commandBufferMap.find(commandBuffer); 709711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_data != dev_data->commandBufferMap.end()) { 709811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 709911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return validate_memory_is_valid(dev_data, src_mem, "vkCmdBlitImage()", srcImage); 710011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 710111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 710211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert function = [=]() { 710311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, dst_mem, true, dstImage); 710411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 710511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 710611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 710711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 710811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, cb_data->second, CMD_BLITIMAGE, "vkCmdBlitImage()"); 710911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, cb_data->second, "vkCmdBlitImage"); 711011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 711111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 711211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 711311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, 711411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert regionCount, pRegions, filter); 711511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 711611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 711711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, 711811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImage dstImage, VkImageLayout dstImageLayout, 711911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t regionCount, const VkBufferImageCopy *pRegions) { 712011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 712111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 712211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 712311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory dst_mem, src_mem; 712411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = get_mem_binding_from_object(dev_data, (uint64_t)dstImage, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &dst_mem); 712511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, dst_mem, "vkCmdCopyBufferToImage"); 712611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 712711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= get_mem_binding_from_object(dev_data, (uint64_t)srcBuffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, &src_mem); 712811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, src_mem, "vkCmdCopyBufferToImage"); 712911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate that src buff & dst image have correct usage flags set 713011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_buffer_usage_flags(dev_data, srcBuffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, true, "vkCmdCopyBufferToImage()", 713111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_BUFFER_USAGE_TRANSFER_SRC_BIT"); 713211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_image_usage_flags(dev_data, dstImage, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, "vkCmdCopyBufferToImage()", 713311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_IMAGE_USAGE_TRANSFER_DST_BIT"); 713411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_data = dev_data->commandBufferMap.find(commandBuffer); 713511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_data != dev_data->commandBufferMap.end()) { 713611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 713711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, dst_mem, true, dstImage); 713811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 713911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 714011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 714111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert function = [=]() { return validate_memory_is_valid(dev_data, src_mem, "vkCmdCopyBufferToImage()"); }; 714211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 714311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 714411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, cb_data->second, CMD_COPYBUFFERTOIMAGE, "vkCmdCopyBufferToImage()"); 714511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, cb_data->second, "vkCmdCopyBufferToImage"); 714611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < regionCount; ++i) { 714711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= VerifyDestImageLayout(commandBuffer, dstImage, pRegions[i].imageSubresource, dstImageLayout); 714811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 714911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 715011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 715111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 715211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, 715311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pRegions); 715411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 715511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 715611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, 715711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageLayout srcImageLayout, VkBuffer dstBuffer, 715811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t regionCount, const VkBufferImageCopy *pRegions) { 715911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 716011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 716111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 716211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory src_mem, dst_mem; 716311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = get_mem_binding_from_object(dev_data, (uint64_t)srcImage, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &src_mem); 716411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, src_mem, "vkCmdCopyImageToBuffer"); 716511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 716611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= get_mem_binding_from_object(dev_data, (uint64_t)dstBuffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, &dst_mem); 716711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, dst_mem, "vkCmdCopyImageToBuffer"); 716811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate that dst buff & src image have correct usage flags set 716911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_image_usage_flags(dev_data, srcImage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, "vkCmdCopyImageToBuffer()", 717011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_IMAGE_USAGE_TRANSFER_SRC_BIT"); 717111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_buffer_usage_flags(dev_data, dstBuffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, "vkCmdCopyImageToBuffer()", 717211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 717311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 717411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_data = dev_data->commandBufferMap.find(commandBuffer); 717511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_data != dev_data->commandBufferMap.end()) { 717611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 717711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return validate_memory_is_valid(dev_data, src_mem, "vkCmdCopyImageToBuffer()", srcImage); 717811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 717911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 718011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert function = [=]() { 718111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, dst_mem, true); 718211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 718311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 718411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 718511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 718611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, cb_data->second, CMD_COPYIMAGETOBUFFER, "vkCmdCopyImageToBuffer()"); 718711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, cb_data->second, "vkCmdCopyImageToBuffer"); 718811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < regionCount; ++i) { 718911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= VerifySourceImageLayout(commandBuffer, srcImage, pRegions[i].imageSubresource, srcImageLayout); 719011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 719111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 719211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 719311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 719411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, 719511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pRegions); 719611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 719711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 719811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, 719911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint32_t *pData) { 720011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 720111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 720211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 720311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory mem; 720411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = 720511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_mem_binding_from_object(dev_data, (uint64_t)dstBuffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, &mem); 720611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, mem, "vkCmdUpdateBuffer"); 720711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate that dst buff has correct usage flags set 720811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_buffer_usage_flags(dev_data, dstBuffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, "vkCmdUpdateBuffer()", 720911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 721011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 721111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_data = dev_data->commandBufferMap.find(commandBuffer); 721211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_data != dev_data->commandBufferMap.end()) { 721311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 721411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, mem, true); 721511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 721611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 721711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 721811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 721911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, cb_data->second, CMD_UPDATEBUFFER, "vkCmdUpdateBuffer()"); 722011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, cb_data->second, "vkCmdCopyUpdateBuffer"); 722111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 722211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 722311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 722411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData); 722511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 722611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 722711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 722811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) { 722911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 723011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 723111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 723211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory mem; 723311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = 723411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_mem_binding_from_object(dev_data, (uint64_t)dstBuffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, &mem); 723511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, mem, "vkCmdFillBuffer"); 723611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate that dst buff has correct usage flags set 723711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_buffer_usage_flags(dev_data, dstBuffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, "vkCmdFillBuffer()", 723811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 723911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 724011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_data = dev_data->commandBufferMap.find(commandBuffer); 724111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_data != dev_data->commandBufferMap.end()) { 724211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 724311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, mem, true); 724411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 724511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 724611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 724711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 724811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, cb_data->second, CMD_FILLBUFFER, "vkCmdFillBuffer()"); 724911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, cb_data->second, "vkCmdCopyFillBuffer"); 725011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 725111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 725211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 725311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data); 725411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 725511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 725611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount, 725711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkClearAttachment *pAttachments, uint32_t rectCount, 725811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkClearRect *pRects) { 725911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 726011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 726111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 726211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 726311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 726411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_CLEARATTACHMENTS, "vkCmdClearAttachments()"); 726511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Warn if this is issued prior to Draw Cmd and clearing the entire attachment 726611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!hasDrawCmd(pCB) && (pCB->activeRenderPassBeginInfo.renderArea.extent.width == pRects[0].rect.extent.width) && 726711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pCB->activeRenderPassBeginInfo.renderArea.extent.height == pRects[0].rect.extent.height)) { 726811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : commandBuffer should be srcObj 726911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // There are times where app needs to use ClearAttachments (generally when reusing a buffer inside of a render pass) 727011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Can we make this warning more specific? I'd like to avoid triggering this test if we can tell it's a use that must 727111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // call CmdClearAttachments 727211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Otherwise this seems more like a performance warning. 727311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 727411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 0, DRAWSTATE_CLEAR_CMD_BEFORE_DRAW, "DS", 727511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdClearAttachments() issued on CB object 0x%" PRIxLEAST64 " prior to any Draw Cmds." 727611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw.", 727711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(commandBuffer)); 727811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 727911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdClearAttachments"); 728011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 728111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 728211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate that attachment is in reference list of active subpass 728311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->activeRenderPass) { 728411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkRenderPassCreateInfo *pRPCI = pCB->activeRenderPass->pCreateInfo; 728511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubpassDescription *pSD = &pRPCI->pSubpasses[pCB->activeSubpass]; 728611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 728711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t attachment_idx = 0; attachment_idx < attachmentCount; attachment_idx++) { 728811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkClearAttachment *attachment = &pAttachments[attachment_idx]; 728911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachment->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { 729011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool found = false; 729111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pSD->colorAttachmentCount; i++) { 729211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachment->colorAttachment == pSD->pColorAttachments[i].attachment) { 729311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert found = true; 729411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 729511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 729611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 729711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!found) { 729811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 729911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 730011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)commandBuffer, __LINE__, DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS", 730111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdClearAttachments() attachment index %d not found in attachment reference array of active subpass %d", 730211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment->colorAttachment, pCB->activeSubpass); 730311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 730411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (attachment->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { 730511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pSD->pDepthStencilAttachment || // Says no DS will be used in active subpass 730611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pSD->pDepthStencilAttachment->attachment == 730711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_ATTACHMENT_UNUSED)) { // Says no DS will be used in active subpass 730811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 730911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 731011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 731111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)commandBuffer, __LINE__, DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS", 731211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdClearAttachments() attachment index %d does not match depthStencilAttachment.attachment (%d) found " 731311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "in active subpass %d", 731411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment->colorAttachment, 731511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pSD->pDepthStencilAttachment) ? pSD->pDepthStencilAttachment->attachment : VK_ATTACHMENT_UNUSED, 731611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeSubpass); 731711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 731811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 731911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 732011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 732111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 732211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 732311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects); 732411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 732511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 732611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, 732711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageLayout imageLayout, const VkClearColorValue *pColor, 732811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t rangeCount, const VkImageSubresourceRange *pRanges) { 732911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 733011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 733111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 733211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state 733311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory mem; 733411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = get_mem_binding_from_object(dev_data, (uint64_t)image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &mem); 733511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, mem, "vkCmdClearColorImage"); 733611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_data = dev_data->commandBufferMap.find(commandBuffer); 733711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_data != dev_data->commandBufferMap.end()) { 733811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 733911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, mem, true, image); 734011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 734111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 734211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 734311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 734411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, cb_data->second, CMD_CLEARCOLORIMAGE, "vkCmdClearColorImage()"); 734511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, cb_data->second, "vkCmdClearColorImage"); 734611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 734711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 734811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 734911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges); 735011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 735111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 735211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 735311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, 735411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount, 735511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImageSubresourceRange *pRanges) { 735611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 735711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 735811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 735911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Verify memory is in VK_IMAGE_STATE_CLEAR state 736011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory mem; 736111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = get_mem_binding_from_object(dev_data, (uint64_t)image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &mem); 736211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, mem, "vkCmdClearDepthStencilImage"); 736311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_data = dev_data->commandBufferMap.find(commandBuffer); 736411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_data != dev_data->commandBufferMap.end()) { 736511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 736611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, mem, true, image); 736711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 736811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 736911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 737011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 737111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, cb_data->second, CMD_CLEARDEPTHSTENCILIMAGE, "vkCmdClearDepthStencilImage()"); 737211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, cb_data->second, "vkCmdClearDepthStencilImage"); 737311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 737411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 737511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 737611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, 737711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pRanges); 737811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 737911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 738011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 738111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, 738211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *pRegions) { 738311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 738411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 738511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 738611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory src_mem, dst_mem; 738711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = get_mem_binding_from_object(dev_data, (uint64_t)srcImage, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &src_mem); 738811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, src_mem, "vkCmdResolveImage"); 738911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 739011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= get_mem_binding_from_object(dev_data, (uint64_t)dstImage, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &dst_mem); 739111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, dst_mem, "vkCmdResolveImage"); 739211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_data = dev_data->commandBufferMap.find(commandBuffer); 739311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_data != dev_data->commandBufferMap.end()) { 739411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 739511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return validate_memory_is_valid(dev_data, src_mem, "vkCmdResolveImage()", srcImage); 739611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 739711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 739811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert function = [=]() { 739911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, dst_mem, true, dstImage); 740011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 740111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 740211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 740311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 740411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, cb_data->second, CMD_RESOLVEIMAGE, "vkCmdResolveImage()"); 740511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, cb_data->second, "vkCmdResolveImage"); 740611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 740711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 740811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 740911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, 741011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert regionCount, pRegions); 741111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 741211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 741311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool setEventStageMask(VkQueue queue, VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 741411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 741511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 741611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 741711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->eventToStageMap[event] = stageMask; 741811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 741911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queue_data = dev_data->queueMap.find(queue); 742011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queue_data != dev_data->queueMap.end()) { 742111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_data->second.eventToStageMap[event] = stageMask; 742211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 742311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 742411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 742511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 742611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 742711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 742811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 742911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 743011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 743111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 743211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 743311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_SETEVENT, "vkCmdSetEvent()"); 743411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, pCB, "vkCmdSetEvent"); 743511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->events.push_back(event); 743611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCB->waitedEvents.count(event)) { 743711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->writeEventsBeforeWait.push_back(event); 743811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 743911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool(VkQueue)> eventUpdate = 744011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, stageMask); 744111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->eventUpdates.push_back(eventUpdate); 744211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 744311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 744411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 744511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdSetEvent(commandBuffer, event, stageMask); 744611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 744711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 744811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 744911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 745011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 745111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 745211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 745311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 745411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 745511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_RESETEVENT, "vkCmdResetEvent()"); 745611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, pCB, "vkCmdResetEvent"); 745711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->events.push_back(event); 745811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCB->waitedEvents.count(event)) { 745911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->writeEventsBeforeWait.push_back(event); 746011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 746111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool(VkQueue)> eventUpdate = 746211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, VkPipelineStageFlags(0)); 746311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->eventUpdates.push_back(eventUpdate); 746411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 746511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 746611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 746711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdResetEvent(commandBuffer, event, stageMask); 746811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 746911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 747011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool TransitionImageLayouts(VkCommandBuffer cmdBuffer, uint32_t memBarrierCount, 747111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImageMemoryBarrier *pImgMemBarriers) { 747211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); 747311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer); 747411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip = false; 747511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t levelCount = 0; 747611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t layerCount = 0; 747711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 747811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < memBarrierCount; ++i) { 747911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto mem_barrier = &pImgMemBarriers[i]; 748011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!mem_barrier) 748111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 748211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Do not iterate over every possibility - consolidate where 748311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // possible 748411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ResolveRemainingLevelsLayers(dev_data, &levelCount, &layerCount, mem_barrier->subresourceRange, mem_barrier->image); 748511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 748611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < levelCount; j++) { 748711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t level = mem_barrier->subresourceRange.baseMipLevel + j; 748811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t k = 0; k < layerCount; k++) { 748911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t layer = mem_barrier->subresourceRange.baseArrayLayer + k; 749011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageSubresource sub = {mem_barrier->subresourceRange.aspectMask, level, layer}; 749111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert IMAGE_CMD_BUF_LAYOUT_NODE node; 749211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!FindLayout(pCB, mem_barrier->image, sub, node)) { 749311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(pCB, mem_barrier->image, sub, 749411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert IMAGE_CMD_BUF_LAYOUT_NODE(mem_barrier->oldLayout, mem_barrier->newLayout)); 749511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 749611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 749711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_barrier->oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) { 749811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Set memory invalid which is in mem_tracker currently 749911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (node.layout != mem_barrier->oldLayout) { 750011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 750111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "You cannot transition the layout from %s " 750211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "when current layout is %s.", 750311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkImageLayout(mem_barrier->oldLayout), string_VkImageLayout(node.layout)); 750411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 750511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(pCB, mem_barrier->image, sub, mem_barrier->newLayout); 750611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 750711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 750811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 750911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip; 751011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 751111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 751211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Print readable FlagBits in FlagMask 751311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic std::string string_VkAccessFlags(VkAccessFlags accessMask) { 751411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string result; 751511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string separator; 751611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 751711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (accessMask == 0) { 751811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = "[None]"; 751911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 752011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = "["; 752111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto i = 0; i < 32; i++) { 752211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (accessMask & (1 << i)) { 752311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = result + separator + string_VkAccessFlagBits((VkAccessFlagBits)(1 << i)); 752411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert separator = " | "; 752511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 752611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 752711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = result + "]"; 752811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 752911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 753011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 753111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 753211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// AccessFlags MUST have 'required_bit' set, and may have one or more of 'optional_bits' set. 753311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// If required_bit is zero, accessMask must have at least one of 'optional_bits' set 753411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// TODO: Add tracking to ensure that at least one barrier has been set for these layout transitions 753511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool ValidateMaskBits(const layer_data *my_data, VkCommandBuffer cmdBuffer, const VkAccessFlags &accessMask, 753611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImageLayout &layout, VkAccessFlags required_bit, VkAccessFlags optional_bits, 753711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char *type) { 753811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 753911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 754011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((accessMask & required_bit) || (!required_bit && (accessMask & optional_bits))) { 754111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (accessMask & ~(required_bit | optional_bits)) { 754211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Verify against Valid Use 754311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 754411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 754511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.", 754611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert type, accessMask, string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout)); 754711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 754811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 754911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!required_bit) { 755011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 755111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_BARRIER, "DS", "%s AccessMask %d %s must contain at least one of access bits %d " 755211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s when layout is %s, unless the app has previously added a " 755311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "barrier for this transition.", 755411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert type, accessMask, string_VkAccessFlags(accessMask).c_str(), optional_bits, 755511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkAccessFlags(optional_bits).c_str(), string_VkImageLayout(layout)); 755611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 755711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string opt_bits; 755811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (optional_bits != 0) { 755911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::stringstream ss; 756011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ss << optional_bits; 756111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert opt_bits = "and may have optional bits " + ss.str() + ' ' + string_VkAccessFlags(optional_bits); 756211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 756311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 756411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_BARRIER, "DS", "%s AccessMask %d %s must have required access bit %d %s %s when " 756511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "layout is %s, unless the app has previously added a barrier for " 756611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "this transition.", 756711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert type, accessMask, string_VkAccessFlags(accessMask).c_str(), required_bit, 756811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkAccessFlags(required_bit).c_str(), opt_bits.c_str(), string_VkImageLayout(layout)); 756911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 757011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 757111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 757211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 757311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 757411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool ValidateMaskBitsFromLayouts(const layer_data *my_data, VkCommandBuffer cmdBuffer, const VkAccessFlags &accessMask, 757511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImageLayout &layout, const char *type) { 757611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 757711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (layout) { 757811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: { 757911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 758011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, type); 758111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 758211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 758311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: { 758411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, 758511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, type); 758611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 758711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 758811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: { 758911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_WRITE_BIT, 0, type); 759011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 759111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 759211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_IMAGE_LAYOUT_PREINITIALIZED: { 759311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_HOST_WRITE_BIT, 0, type); 759411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 759511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 759611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: { 759711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, 0, 759811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT, type); 759911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 760011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 760111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: { 760211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, 0, 760311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT, type); 760411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 760511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 760611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: { 760711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_READ_BIT, 0, type); 760811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 760911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 761011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_IMAGE_LAYOUT_UNDEFINED: { 761111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (accessMask != 0) { 761211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Verify against Valid Use section spec 761311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 761411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 761511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.", 761611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert type, accessMask, string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout)); 761711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 761811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 761911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 762011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case VK_IMAGE_LAYOUT_GENERAL: 762111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: { break; } 762211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 762311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 762411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 762511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 762611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, uint32_t memBarrierCount, 762711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkMemoryBarrier *pMemBarriers, uint32_t bufferBarrierCount, 762811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkBufferMemoryBarrier *pBufferMemBarriers, uint32_t imageMemBarrierCount, 762911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImageMemoryBarrier *pImageMemBarriers) { 763011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 763111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); 763211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer); 763311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->activeRenderPass && memBarrierCount) { 763411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCB->activeRenderPass->hasSelfDependency[pCB->activeSubpass]) { 763511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 763611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_BARRIER, "DS", "%s: Barriers cannot be set during subpass %d " 763711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "with no self dependency specified.", 763811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcName, pCB->activeSubpass); 763911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 764011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 764111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < imageMemBarrierCount; ++i) { 764211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto mem_barrier = &pImageMemBarriers[i]; 764311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto image_data = dev_data->imageMap.find(mem_barrier->image); 764411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_data != dev_data->imageMap.end()) { 764511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t src_q_f_index = mem_barrier->srcQueueFamilyIndex; 764611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t dst_q_f_index = mem_barrier->dstQueueFamilyIndex; 764711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_data->second.createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { 764811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // srcQueueFamilyIndex and dstQueueFamilyIndex must both 764911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // be VK_QUEUE_FAMILY_IGNORED 765011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) { 765111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 765211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 765311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s: Image Barrier for image 0x%" PRIx64 " was created with sharingMode of " 765411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_SHARING_MODE_CONCURRENT. Src and dst " 765511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " queueFamilyIndices must be VK_QUEUE_FAMILY_IGNORED.", 765611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image)); 765711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 765811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 765911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Sharing mode is VK_SHARING_MODE_EXCLUSIVE. srcQueueFamilyIndex and 766011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // dstQueueFamilyIndex must either both be VK_QUEUE_FAMILY_IGNORED, 766111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // or both be a valid queue family 766211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (((src_q_f_index == VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index == VK_QUEUE_FAMILY_IGNORED)) && 766311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (src_q_f_index != dst_q_f_index)) { 766411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 766511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 766611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_QUEUE_INDEX, "DS", "%s: Image 0x%" PRIx64 " was created with sharingMode " 766711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "of VK_SHARING_MODE_EXCLUSIVE. If one of src- or " 766811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "dstQueueFamilyIndex is VK_QUEUE_FAMILY_IGNORED, both " 766911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "must be.", 767011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image)); 767111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) && (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) && 767211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ((src_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()) || 767311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (dst_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()))) { 767411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 767511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 767611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s: Image 0x%" PRIx64 " was created with sharingMode " 767711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "of VK_SHARING_MODE_EXCLUSIVE, but srcQueueFamilyIndex %d" 767811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " or dstQueueFamilyIndex %d is greater than " PRINTF_SIZE_T_SPECIFIER 767911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "queueFamilies crated for this device.", 768011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image), src_q_f_index, 768111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dst_q_f_index, dev_data->phys_dev_properties.queue_family_properties.size()); 768211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 768311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 768411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 768511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 768611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_barrier) { 768711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 768811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->srcAccessMask, mem_barrier->oldLayout, "Source"); 768911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 769011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->dstAccessMask, mem_barrier->newLayout, "Dest"); 769111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_barrier->newLayout == VK_IMAGE_LAYOUT_UNDEFINED || mem_barrier->newLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) { 769211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 769311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_BARRIER, "DS", "%s: Image Layout cannot be transitioned to UNDEFINED or " 769411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "PREINITIALIZED.", 769511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcName); 769611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 769711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto image_data = dev_data->imageMap.find(mem_barrier->image); 769811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkFormat format = VK_FORMAT_UNDEFINED; 769911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t arrayLayers = 0, mipLevels = 0; 770011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool imageFound = false; 770111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_data != dev_data->imageMap.end()) { 770211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert format = image_data->second.createInfo.format; 770311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert arrayLayers = image_data->second.createInfo.arrayLayers; 770411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert mipLevels = image_data->second.createInfo.mipLevels; 770511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert imageFound = true; 770611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (dev_data->device_extensions.wsi_enabled) { 770711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto imageswap_data = dev_data->device_extensions.imageToSwapchainMap.find(mem_barrier->image); 770811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (imageswap_data != dev_data->device_extensions.imageToSwapchainMap.end()) { 770911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto swapchain_data = dev_data->device_extensions.swapchainMap.find(imageswap_data->second); 771011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (swapchain_data != dev_data->device_extensions.swapchainMap.end()) { 771111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert format = swapchain_data->second->createInfo.imageFormat; 771211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert arrayLayers = swapchain_data->second->createInfo.imageArrayLayers; 771311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert mipLevels = 1; 771411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert imageFound = true; 771511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 771611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 771711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 771811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (imageFound) { 771911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (vk_format_is_depth_and_stencil(format) && 772011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (!(mem_barrier->subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) || 772111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert !(mem_barrier->subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT))) { 772211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 772311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_BARRIER, "DS", "%s: Image is a depth and stencil format and thus must " 772411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "have both VK_IMAGE_ASPECT_DEPTH_BIT and " 772511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "VK_IMAGE_ASPECT_STENCIL_BIT set.", 772611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcName); 772711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 772811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int layerCount = (mem_barrier->subresourceRange.layerCount == VK_REMAINING_ARRAY_LAYERS) 772911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ? 1 773011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : mem_barrier->subresourceRange.layerCount; 773111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((mem_barrier->subresourceRange.baseArrayLayer + layerCount) > arrayLayers) { 773211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 773311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_BARRIER, "DS", "%s: Subresource must have the sum of the " 773411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "baseArrayLayer (%d) and layerCount (%d) be less " 773511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "than or equal to the total number of layers (%d).", 773611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcName, mem_barrier->subresourceRange.baseArrayLayer, mem_barrier->subresourceRange.layerCount, 773711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert arrayLayers); 773811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 773911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int levelCount = (mem_barrier->subresourceRange.levelCount == VK_REMAINING_MIP_LEVELS) 774011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ? 1 774111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : mem_barrier->subresourceRange.levelCount; 774211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((mem_barrier->subresourceRange.baseMipLevel + levelCount) > mipLevels) { 774311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 774411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_BARRIER, "DS", "%s: Subresource must have the sum of the baseMipLevel " 774511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "(%d) and levelCount (%d) be less than or equal to " 774611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "the total number of levels (%d).", 774711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcName, mem_barrier->subresourceRange.baseMipLevel, mem_barrier->subresourceRange.levelCount, 774811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert mipLevels); 774911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 775011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 775111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 775211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 775311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < bufferBarrierCount; ++i) { 775411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto mem_barrier = &pBufferMemBarriers[i]; 775511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->activeRenderPass) { 775611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 775711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 775811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_BARRIER, "DS", "%s: Buffer Barriers cannot be used during a render pass.", funcName); 775911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 776011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!mem_barrier) 776111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 776211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 776311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate buffer barrier queue family indices 776411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((mem_barrier->srcQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED && 776511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert mem_barrier->srcQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size()) || 776611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (mem_barrier->dstQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED && 776711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert mem_barrier->dstQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size())) { 776811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 776911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 777011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s: Buffer Barrier 0x%" PRIx64 " has QueueFamilyIndex greater " 777111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "than the number of QueueFamilies (" PRINTF_SIZE_T_SPECIFIER ") for this device.", 777211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 777311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->phys_dev_properties.queue_family_properties.size()); 777411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 777511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 777611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto buffer_data = dev_data->bufferMap.find(mem_barrier->buffer); 777711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (buffer_data != dev_data->bufferMap.end()) { 777811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceSize buffer_size = (buffer_data->second.createInfo.sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO) 777911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ? buffer_data->second.createInfo.size 778011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : 0; 778111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_barrier->offset >= buffer_size) { 778211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg( 778311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 778411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_BARRIER, "DS", 778511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " which is not less than total size 0x%" PRIx64 ".", 778611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 778711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(mem_barrier->offset), reinterpret_cast<const uint64_t &>(buffer_size)); 778811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (mem_barrier->size != VK_WHOLE_SIZE && (mem_barrier->offset + mem_barrier->size > buffer_size)) { 778911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg( 779011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 779111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_BARRIER, "DS", "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " and size 0x%" PRIx64 779211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " whose sum is greater than total size 0x%" PRIx64 ".", 779311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 779411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(mem_barrier->offset), reinterpret_cast<const uint64_t &>(mem_barrier->size), 779511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(buffer_size)); 779611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 779711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 779811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 779911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 780011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 780111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 780211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool validateEventStageMask(VkQueue queue, GLOBAL_CB_NODE *pCB, uint32_t eventCount, size_t firstEventIndex, VkPipelineStageFlags sourceStageMask) { 780311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 780411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkPipelineStageFlags stageMask = 0; 780511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map); 780611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < eventCount; ++i) { 780711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto event = pCB->events[firstEventIndex + i]; 780811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queue_data = dev_data->queueMap.find(queue); 780911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queue_data == dev_data->queueMap.end()) 781011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 781111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto event_data = queue_data->second.eventToStageMap.find(event); 781211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (event_data != queue_data->second.eventToStageMap.end()) { 781311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert stageMask |= event_data->second; 781411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 781511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto global_event_data = dev_data->eventMap.find(event); 781611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (global_event_data == dev_data->eventMap.end()) { 781711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, 781811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(event), __LINE__, DRAWSTATE_INVALID_EVENT, "DS", 781911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Event 0x%" PRIx64 " cannot be waited on if it has never been set.", 782011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(event)); 782111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 782211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert stageMask |= global_event_data->second.stageMask; 782311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 782411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 782511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 782611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Need to validate that host_bit is only set if set event is called 782711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // but set event can be called at any time. 782811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (sourceStageMask != stageMask && sourceStageMask != (stageMask | VK_PIPELINE_STAGE_HOST_BIT)) { 782911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 783011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_EVENT, "DS", "Submitting cmdbuffer with call to VkCmdWaitEvents " 783111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "using srcStageMask 0x%x which must be the bitwise " 783211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "OR of the stageMask parameters used in calls to " 783311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if " 783411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "used with vkSetEvent but instead is 0x%x.", 783511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sourceStageMask, stageMask); 783611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 783711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 783811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 783911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 784011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 784111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents, VkPipelineStageFlags sourceStageMask, 784211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 784311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 784411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 784511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 784611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 784711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 784811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 784911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 785011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto firstEventIndex = pCB->events.size(); 785111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < eventCount; ++i) { 785211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->waitedEvents.insert(pEvents[i]); 785311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->events.push_back(pEvents[i]); 785411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 785511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool(VkQueue)> eventUpdate = 785611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::bind(validateEventStageMask, std::placeholders::_1, pCB, eventCount, firstEventIndex, sourceStageMask); 785711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->eventUpdates.push_back(eventUpdate); 785811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->state == CB_RECORDING) { 785911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_WAITEVENTS, "vkCmdWaitEvents()"); 786011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 786111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdWaitEvents()"); 786211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 786311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= TransitionImageLayouts(commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 786411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 786511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ValidateBarriers("vkCmdWaitEvents", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 786611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 786711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 786811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 786911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 787011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdWaitEvents(commandBuffer, eventCount, pEvents, sourceStageMask, dstStageMask, 787111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 787211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 787311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 787411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 787511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 787611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, 787711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 787811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 787911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 788011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 788111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 788211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 788311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 788411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 788511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_PIPELINEBARRIER, "vkCmdPipelineBarrier()"); 788611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= TransitionImageLayouts(commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 788711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 788811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ValidateBarriers("vkCmdPipelineBarrier", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 788911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 789011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 789111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 789211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 789311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 789411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 789511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 789611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 789711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 789811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool setQueryState(VkQueue queue, VkCommandBuffer commandBuffer, QueryObject object, bool value) { 789911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 790011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 790111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 790211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->queryToStateMap[object] = value; 790311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 790411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queue_data = dev_data->queueMap.find(queue); 790511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queue_data != dev_data->queueMap.end()) { 790611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queue_data->second.queryToStateMap[object] = value; 790711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 790811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 790911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 791011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 791111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 791211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkFlags flags) { 791311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 791411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 791511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 791611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 791711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 791811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert QueryObject query = {queryPool, slot}; 791911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeQueries.insert(query); 792011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCB->startedQueries.count(query)) { 792111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->startedQueries.insert(query); 792211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 792311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_BEGINQUERY, "vkCmdBeginQuery()"); 792411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 792511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 792611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 792711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdBeginQuery(commandBuffer, queryPool, slot, flags); 792811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 792911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 793011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) { 793111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 793211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 793311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 793411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 793511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 793611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert QueryObject query = {queryPool, slot}; 793711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCB->activeQueries.count(query)) { 793811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 793911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 794011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_QUERY, "DS", "Ending a query before it was started: queryPool 0x%" PRIx64 ", index %d", 794111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(queryPool), slot); 794211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 794311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeQueries.erase(query); 794411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 794511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool(VkQueue)> queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true); 794611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->queryUpdates.push_back(queryUpdate); 794711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->state == CB_RECORDING) { 794811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_ENDQUERY, "VkCmdEndQuery()"); 794911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 795011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdEndQuery()"); 795111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 795211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 795311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 795411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 795511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdEndQuery(commandBuffer, queryPool, slot); 795611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 795711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 795811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 795911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) { 796011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 796111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 796211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 796311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 796411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 796511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < queryCount; i++) { 796611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert QueryObject query = {queryPool, firstQuery + i}; 796711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->waitedEventsBeforeQueryReset[query] = pCB->waitedEvents; 796811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool(VkQueue)> queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, false); 796911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->queryUpdates.push_back(queryUpdate); 797011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 797111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->state == CB_RECORDING) { 797211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_RESETQUERYPOOL, "VkCmdResetQueryPool()"); 797311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 797411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdResetQueryPool()"); 797511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 797611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, pCB, "vkCmdQueryPool"); 797711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 797811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 797911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 798011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount); 798111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 798211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 798311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t queryCount, uint32_t firstQuery) { 798411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 798511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(pCB->commandBuffer), layer_data_map); 798611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queue_data = dev_data->queueMap.find(queue); 798711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queue_data == dev_data->queueMap.end()) 798811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 798911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < queryCount; i++) { 799011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert QueryObject query = {queryPool, firstQuery + i}; 799111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto query_data = queue_data->second.queryToStateMap.find(query); 799211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool fail = false; 799311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (query_data != queue_data->second.queryToStateMap.end()) { 799411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!query_data->second) { 799511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fail = true; 799611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 799711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 799811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto global_query_data = dev_data->queryToStateMap.find(query); 799911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (global_query_data != dev_data->queryToStateMap.end()) { 800011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!global_query_data->second) { 800111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fail = true; 800211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 800311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 800411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fail = true; 800511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 800611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 800711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fail) { 800811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 800911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_QUERY, "DS", 801011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d", 801111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(queryPool), firstQuery + i); 801211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 801311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 801411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 801511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 801611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 801711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 801811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, 801911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) { 802011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 802111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 802211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 802311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 802411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if MTMERGESOURCE 802511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory mem; 802611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto cb_data = dev_data->commandBufferMap.find(commandBuffer); 802711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 802811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_mem_binding_from_object(dev_data, (uint64_t)dstBuffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, &mem); 802911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cb_data != dev_data->commandBufferMap.end()) { 803011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 803111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, mem, true); 803211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 803311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 803411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cb_data->second->validate_functions.push_back(function); 803511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 803611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= update_cmd_buf_and_mem_references(dev_data, commandBuffer, mem, "vkCmdCopyQueryPoolResults"); 803711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate that DST buffer has correct usage flags set 803811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validate_buffer_usage_flags(dev_data, dstBuffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, 803911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdCopyQueryPoolResults()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 804011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 804111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 804211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool(VkQueue)> queryUpdate = 804311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::bind(validateQuery, std::placeholders::_1, pCB, queryPool, queryCount, firstQuery); 804411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->queryUpdates.push_back(queryUpdate); 804511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->state == CB_RECORDING) { 804611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()"); 804711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 804811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdCopyQueryPoolResults()"); 804911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 805011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyQueryPoolResults"); 805111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 805211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 805311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 805411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, 805511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dstOffset, stride, flags); 805611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 805711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 805811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, 805911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, 806011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const void *pValues) { 806111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 806211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 806311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 806411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 806511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 806611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->state == CB_RECORDING) { 806711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_PUSHCONSTANTS, "vkCmdPushConstants()"); 806811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 806911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdPushConstants()"); 807011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 807111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 807211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validatePushConstantRange(dev_data, offset, size, "vkCmdPushConstants()"); 807311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (0 == stageFlags) { 807411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 807511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "vkCmdPushConstants() call has no stageFlags set."); 807611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 807711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 807811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Check if push constant update is within any of the ranges with the same stage flags specified in pipeline layout. 807911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pipeline_layout = getPipelineLayout(dev_data, layout); 808011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pipeline_layout) { 808111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 808211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "vkCmdPushConstants() Pipeline Layout 0x%" PRIx64 " not found.", 808311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)layout); 808411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 808511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Coalesce adjacent/overlapping pipeline ranges before checking to see if incoming range is 808611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // contained in the pipeline ranges. 808711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Build a {start, end} span list for ranges with matching stage flags. 808811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const auto &ranges = pipeline_layout->pushConstantRanges; 808911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct span { 809011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t start; 809111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t end; 809211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 809311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<span> spans; 809411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spans.reserve(ranges.size()); 809511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (const auto &iter : ranges) { 809611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (iter.stageFlags == stageFlags) { 809711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spans.push_back({iter.offset, iter.offset + iter.size}); 809811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 809911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 810011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (spans.size() == 0) { 810111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // There were no ranges that matched the stageFlags. 810211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 810311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", 810411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdPushConstants() stageFlags = 0x%" PRIx32 " do not match " 810511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "the stageFlags in any of the ranges in pipeline layout 0x%" PRIx64 ".", 810611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint32_t)stageFlags, (uint64_t)layout); 810711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 810811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Sort span list by start value. 810911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct comparer { 811011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool operator()(struct span i, struct span j) { return i.start < j.start; } 811111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } my_comparer; 811211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::sort(spans.begin(), spans.end(), my_comparer); 811311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 811411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Examine two spans at a time. 811511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<span>::iterator current = spans.begin(); 811611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<span>::iterator next = current + 1; 811711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (next != spans.end()) { 811811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (current->end < next->start) { 811911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // There is a gap; cannot coalesce. Move to the next two spans. 812011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++current; 812111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++next; 812211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 812311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Coalesce the two spans. The start of the next span 812411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // is within the current span, so pick the larger of 812511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // the end values to extend the current span. 812611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Then delete the next span and set next to the span after it. 812711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert current->end = max(current->end, next->end); 812811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert next = spans.erase(next); 812911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 813011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 813111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 813211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Now we can check if the incoming range is within any of the spans. 813311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool contained_in_a_range = false; 813411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < spans.size(); ++i) { 813511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((offset >= spans[i].start) && ((uint64_t)offset + (uint64_t)size <= (uint64_t)spans[i].end)) { 813611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert contained_in_a_range = true; 813711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 813811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 813911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 814011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!contained_in_a_range) { 814111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 814211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", 814311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdPushConstants() Push constant range [%d, %d) " 814411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "with stageFlags = 0x%" PRIx32 " " 814511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "not within flag-matching ranges in pipeline layout 0x%" PRIx64 ".", 814611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert offset, offset + size, (uint32_t)stageFlags, (uint64_t)layout); 814711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 814811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 814911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 815011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 815111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 815211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues); 815311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 815411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 815511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 815611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t slot) { 815711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 815811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 815911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 816011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 816111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 816211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert QueryObject query = {queryPool, slot}; 816311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool(VkQueue)> queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true); 816411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->queryUpdates.push_back(queryUpdate); 816511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->state == CB_RECORDING) { 816611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()"); 816711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 816811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdWriteTimestamp()"); 816911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 817011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 817111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 817211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 817311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot); 817411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 817511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 817611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo, 817711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, 817811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkFramebuffer *pFramebuffer) { 817911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 818011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer); 818111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 818211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Shadow create info and store in map 818311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 818411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 818511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto & fbNode = dev_data->frameBufferMap[*pFramebuffer]; 818611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fbNode.createInfo = *pCreateInfo; 818711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCreateInfo->pAttachments) { 818811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto attachments = new VkImageView[pCreateInfo->attachmentCount]; 818911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy(attachments, 819011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCreateInfo->pAttachments, 819111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCreateInfo->attachmentCount * sizeof(VkImageView)); 819211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fbNode.createInfo.pAttachments = attachments; 819311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 819411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 819511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageView view = pCreateInfo->pAttachments[i]; 819611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto view_data = dev_data->imageViewMap.find(view); 819711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (view_data == dev_data->imageViewMap.end()) { 819811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 819911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 820011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MT_FB_ATTACHMENT_INFO fb_info; 820111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_mem_binding_from_object(dev_data, (uint64_t)(view_data->second.image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 820211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert &fb_info.mem); 820311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fb_info.image = view_data->second.image; 820411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fbNode.attachments.push_back(fb_info); 820511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 820611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 820711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 820811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 820911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 821011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool FindDependency(const int index, const int dependent, const std::vector<DAGNode> &subpass_to_node, 821111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_set<uint32_t> &processed_nodes) { 821211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If we have already checked this node we have not found a dependency path so return false. 821311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (processed_nodes.count(index)) 821411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 821511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert processed_nodes.insert(index); 821611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const DAGNode &node = subpass_to_node[index]; 821711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Look for a dependency path. If one exists return true else recurse on the previous nodes. 821811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (std::find(node.prev.begin(), node.prev.end(), dependent) == node.prev.end()) { 821911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto elem : node.prev) { 822011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (FindDependency(elem, dependent, subpass_to_node, processed_nodes)) 822111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 822211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 822311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 822411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 822511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 822611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 822711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 822811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 822911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool CheckDependencyExists(const layer_data *my_data, const int subpass, const std::vector<uint32_t> &dependent_subpasses, 823011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const std::vector<DAGNode> &subpass_to_node, bool &skip_call) { 823111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool result = true; 823211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Loop through all subpasses that share the same attachment and make sure a dependency exists 823311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t k = 0; k < dependent_subpasses.size(); ++k) { 823411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (static_cast<uint32_t>(subpass) == dependent_subpasses[k]) 823511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 823611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const DAGNode &node = subpass_to_node[subpass]; 823711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Check for a specified dependency between the two nodes. If one exists we are done. 823811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto prev_elem = std::find(node.prev.begin(), node.prev.end(), dependent_subpasses[k]); 823911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto next_elem = std::find(node.next.begin(), node.next.end(), dependent_subpasses[k]); 824011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (prev_elem == node.prev.end() && next_elem == node.next.end()) { 824111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If no dependency exits an implicit dependency still might. If so, warn and if not throw an error. 824211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_set<uint32_t> processed_nodes; 824311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) || 824411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes)) { 824511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 824611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 824711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "A dependency between subpasses %d and %d must exist but only an implicit one is specified.", 824811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass, dependent_subpasses[k]); 824911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 825011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 825111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 825211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "A dependency between subpasses %d and %d must exist but one is not specified.", subpass, 825311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dependent_subpasses[k]); 825411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = false; 825511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 825611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 825711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 825811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 825911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 826011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 826111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool CheckPreserved(const layer_data *my_data, const VkRenderPassCreateInfo *pCreateInfo, const int index, 826211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t attachment, const std::vector<DAGNode> &subpass_to_node, int depth, bool &skip_call) { 826311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const DAGNode &node = subpass_to_node[index]; 826411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If this node writes to the attachment return true as next nodes need to preserve the attachment. 826511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[index]; 826611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 826711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachment == subpass.pColorAttachments[j].attachment) 826811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 826911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 827011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 827111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachment == subpass.pDepthStencilAttachment->attachment) 827211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 827311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 827411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool result = false; 827511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Loop through previous nodes and see if any of them write to the attachment. 827611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto elem : node.prev) { 827711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result |= CheckPreserved(my_data, pCreateInfo, elem, attachment, subpass_to_node, depth + 1, skip_call); 827811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 827911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If the attachment was written to by a previous node than this node needs to preserve it. 828011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result && depth > 0) { 828111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[index]; 828211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool has_preserved = false; 828311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) { 828411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass.pPreserveAttachments[j] == attachment) { 828511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert has_preserved = true; 828611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 828711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 828811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 828911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!has_preserved) { 829011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 829111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 829211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_RENDERPASS, "DS", 829311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Attachment %d is used by a later subpass and must be preserved in subpass %d.", attachment, index); 829411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 829511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 829611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 829711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 829811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 829911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class T> bool isRangeOverlapping(T offset1, T size1, T offset2, T size2) { 830011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return (((offset1 + size1) > offset2) && ((offset1 + size1) < (offset2 + size2))) || 830111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ((offset1 > offset2) && (offset1 < (offset2 + size2))); 830211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 830311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 830411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool isRegionOverlapping(VkImageSubresourceRange range1, VkImageSubresourceRange range2) { 830511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return (isRangeOverlapping(range1.baseMipLevel, range1.levelCount, range2.baseMipLevel, range2.levelCount) && 830611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert isRangeOverlapping(range1.baseArrayLayer, range1.layerCount, range2.baseArrayLayer, range2.layerCount)); 830711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 830811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 830911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool ValidateDependencies(const layer_data *my_data, FRAMEBUFFER_NODE const * framebuffer, 831011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert RENDER_PASS_NODE const * renderPass) { 831111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 831211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkFramebufferCreateInfo *pFramebufferInfo = &framebuffer->createInfo; 831311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkRenderPassCreateInfo *pCreateInfo = renderPass->pCreateInfo; 831411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto const & subpass_to_node = renderPass->subpassToNode; 831511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<std::vector<uint32_t>> output_attachment_to_subpass(pCreateInfo->attachmentCount); 831611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<std::vector<uint32_t>> input_attachment_to_subpass(pCreateInfo->attachmentCount); 831711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<std::vector<uint32_t>> overlapping_attachments(pCreateInfo->attachmentCount); 831811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Find overlapping attachments 831911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 832011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = i + 1; j < pCreateInfo->attachmentCount; ++j) { 832111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageView viewi = pFramebufferInfo->pAttachments[i]; 832211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageView viewj = pFramebufferInfo->pAttachments[j]; 832311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (viewi == viewj) { 832411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert overlapping_attachments[i].push_back(j); 832511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert overlapping_attachments[j].push_back(i); 832611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 832711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 832811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto view_data_i = my_data->imageViewMap.find(viewi); 832911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto view_data_j = my_data->imageViewMap.find(viewj); 833011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (view_data_i == my_data->imageViewMap.end() || view_data_j == my_data->imageViewMap.end()) { 833111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 833211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 833311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (view_data_i->second.image == view_data_j->second.image && 833411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert isRegionOverlapping(view_data_i->second.subresourceRange, view_data_j->second.subresourceRange)) { 833511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert overlapping_attachments[i].push_back(j); 833611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert overlapping_attachments[j].push_back(i); 833711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 833811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 833911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto image_data_i = my_data->imageMap.find(view_data_i->second.image); 834011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto image_data_j = my_data->imageMap.find(view_data_j->second.image); 834111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_data_i == my_data->imageMap.end() || image_data_j == my_data->imageMap.end()) { 834211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 834311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 834411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_data_i->second.mem == image_data_j->second.mem && 834511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert isRangeOverlapping(image_data_i->second.memOffset, image_data_i->second.memSize, image_data_j->second.memOffset, 834611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_data_j->second.memSize)) { 834711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert overlapping_attachments[i].push_back(j); 834811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert overlapping_attachments[j].push_back(i); 834911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 835011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 835111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 835211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < overlapping_attachments.size(); ++i) { 835311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t attachment = i; 835411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto other_attachment : overlapping_attachments[i]) { 835511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(pCreateInfo->pAttachments[attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) { 835611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 835711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 835811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_RENDERPASS, "DS", "Attachment %d aliases attachment %d but doesn't " 835911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT.", 836011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment, other_attachment); 836111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 836211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(pCreateInfo->pAttachments[other_attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) { 836311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 836411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 836511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_RENDERPASS, "DS", "Attachment %d aliases attachment %d but doesn't " 836611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT.", 836711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert other_attachment, attachment); 836811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 836911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 837011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 837111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Find for each attachment the subpasses that use them. 837211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_set<uint32_t> attachmentIndices; 837311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 837411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 837511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachmentIndices.clear(); 837611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 837711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t attachment = subpass.pInputAttachments[j].attachment; 837811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert input_attachment_to_subpass[attachment].push_back(i); 837911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto overlapping_attachment : overlapping_attachments[attachment]) { 838011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert input_attachment_to_subpass[overlapping_attachment].push_back(i); 838111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 838211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 838311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 838411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t attachment = subpass.pColorAttachments[j].attachment; 838511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert output_attachment_to_subpass[attachment].push_back(i); 838611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto overlapping_attachment : overlapping_attachments[attachment]) { 838711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert output_attachment_to_subpass[overlapping_attachment].push_back(i); 838811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 838911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachmentIndices.insert(attachment); 839011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 839111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 839211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 839311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert output_attachment_to_subpass[attachment].push_back(i); 839411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto overlapping_attachment : overlapping_attachments[attachment]) { 839511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert output_attachment_to_subpass[overlapping_attachment].push_back(i); 839611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 839711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 839811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachmentIndices.count(attachment)) { 839911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 840011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 840111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 0, __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 840211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot use same attachment (%u) as both color and depth output in same subpass (%u).", 840311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment, i); 840411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 840511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 840611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 840711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If there is a dependency needed make sure one exists 840811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 840911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 841011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If the attachment is an input then all subpasses that output must have a dependency relationship 841111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 841211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t &attachment = subpass.pInputAttachments[j].attachment; 841311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert CheckDependencyExists(my_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call); 841411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 841511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If the attachment is an output then all subpasses that use the attachment must have a dependency relationship 841611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 841711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t &attachment = subpass.pColorAttachments[j].attachment; 841811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert CheckDependencyExists(my_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call); 841911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert CheckDependencyExists(my_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip_call); 842011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 842111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 842211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t &attachment = subpass.pDepthStencilAttachment->attachment; 842311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert CheckDependencyExists(my_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call); 842411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert CheckDependencyExists(my_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip_call); 842511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 842611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 842711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Loop through implicit dependencies, if this pass reads make sure the attachment is preserved for all passes after it was 842811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // written. 842911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 843011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 843111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 843211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert CheckPreserved(my_data, pCreateInfo, i, subpass.pInputAttachments[j].attachment, subpass_to_node, 0, skip_call); 843311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 843411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 843511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 843611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 843711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// ValidateLayoutVsAttachmentDescription is a general function where we can validate various state associated with the 843811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// VkAttachmentDescription structs that are used by the sub-passes of a renderpass. Initial check is to make sure that 843911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// READ_ONLY layout attachments don't have CLEAR as their loadOp. 844011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool ValidateLayoutVsAttachmentDescription(debug_report_data *report_data, const VkImageLayout first_layout, 844111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t attachment, 844211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAttachmentDescription &attachment_description) { 844311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 844411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Verify that initial loadOp on READ_ONLY attachments is not CLEAR 844511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachment_description.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) { 844611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((first_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) || 844711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (first_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)) { 844811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 844911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 845011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDebugReportObjectTypeEXT(0), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 845111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot clear attachment %d with invalid first layout %s.", attachment, string_VkImageLayout(first_layout)); 845211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 845311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 845411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 845511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 845611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 845711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool ValidateLayouts(const layer_data *my_data, VkDevice device, const VkRenderPassCreateInfo *pCreateInfo) { 845811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip = false; 845911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 846011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 846111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 846211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 846311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass.pInputAttachments[j].layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL && 846411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass.pInputAttachments[j].layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { 846511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass.pInputAttachments[j].layout == VK_IMAGE_LAYOUT_GENERAL) { 846611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Verify Valid Use in spec. I believe this is allowed (valid) but may not be optimal performance 846711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip |= log_msg(my_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 846811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 846911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Layout for input attachment is GENERAL but should be READ_ONLY_OPTIMAL."); 847011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 847111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 847211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 847311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Layout for input attachment is %s but can only be READ_ONLY_OPTIMAL or GENERAL.", 847411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkImageLayout(subpass.pInputAttachments[j].layout)); 847511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 847611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 847711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto attach_index = subpass.pInputAttachments[j].attachment; 847811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip |= ValidateLayoutVsAttachmentDescription(my_data->report_data, subpass.pInputAttachments[j].layout, attach_index, 847911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCreateInfo->pAttachments[attach_index]); 848011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 848111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 848211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass.pColorAttachments[j].layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { 848311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass.pColorAttachments[j].layout == VK_IMAGE_LAYOUT_GENERAL) { 848411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Verify Valid Use in spec. I believe this is allowed (valid) but may not be optimal performance 848511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip |= log_msg(my_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 848611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 848711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Layout for color attachment is GENERAL but should be COLOR_ATTACHMENT_OPTIMAL."); 848811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 848911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 849011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 849111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Layout for color attachment is %s but can only be COLOR_ATTACHMENT_OPTIMAL or GENERAL.", 849211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkImageLayout(subpass.pColorAttachments[j].layout)); 849311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 849411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 849511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto attach_index = subpass.pColorAttachments[j].attachment; 849611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip |= ValidateLayoutVsAttachmentDescription(my_data->report_data, subpass.pColorAttachments[j].layout, attach_index, 849711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCreateInfo->pAttachments[attach_index]); 849811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 849911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((subpass.pDepthStencilAttachment != NULL) && (subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)) { 850011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass.pDepthStencilAttachment->layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { 850111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass.pDepthStencilAttachment->layout == VK_IMAGE_LAYOUT_GENERAL) { 850211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Verify Valid Use in spec. I believe this is allowed (valid) but may not be optimal performance 850311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip |= log_msg(my_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 850411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 850511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Layout for depth attachment is GENERAL but should be DEPTH_STENCIL_ATTACHMENT_OPTIMAL."); 850611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 850711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip |= 850811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 850911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 851011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Layout for depth attachment is %s but can only be DEPTH_STENCIL_ATTACHMENT_OPTIMAL or GENERAL.", 851111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkImageLayout(subpass.pDepthStencilAttachment->layout)); 851211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 851311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 851411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto attach_index = subpass.pDepthStencilAttachment->attachment; 851511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip |= ValidateLayoutVsAttachmentDescription(my_data->report_data, subpass.pDepthStencilAttachment->layout, 851611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attach_index, pCreateInfo->pAttachments[attach_index]); 851711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 851811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 851911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip; 852011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 852111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 852211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool CreatePassDAG(const layer_data *my_data, VkDevice device, const VkRenderPassCreateInfo *pCreateInfo, 852311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<DAGNode> &subpass_to_node, std::vector<bool> &has_self_dependency) { 852411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 852511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 852611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DAGNode &subpass_node = subpass_to_node[i]; 852711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass_node.pass = i; 852811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 852911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) { 853011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubpassDependency &dependency = pCreateInfo->pDependencies[i]; 853111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dependency.srcSubpass > dependency.dstSubpass && dependency.srcSubpass != VK_SUBPASS_EXTERNAL && 853211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dependency.dstSubpass != VK_SUBPASS_EXTERNAL) { 853311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 853411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_RENDERPASS, "DS", 853511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Depedency graph must be specified such that an earlier pass cannot depend on a later pass."); 853611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (dependency.srcSubpass == VK_SUBPASS_EXTERNAL && dependency.dstSubpass == VK_SUBPASS_EXTERNAL) { 853711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 853811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_RENDERPASS, "DS", "The src and dest subpasses cannot both be external."); 853911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (dependency.srcSubpass == dependency.dstSubpass) { 854011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert has_self_dependency[dependency.srcSubpass] = true; 854111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 854211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dependency.dstSubpass != VK_SUBPASS_EXTERNAL) { 854311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass_to_node[dependency.dstSubpass].prev.push_back(dependency.srcSubpass); 854411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 854511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dependency.srcSubpass != VK_SUBPASS_EXTERNAL) { 854611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass_to_node[dependency.srcSubpass].next.push_back(dependency.dstSubpass); 854711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 854811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 854911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 855011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 855111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 855211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 855311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo, 855411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, 855511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkShaderModule *pShaderModule) { 855611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 855711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 855811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 855911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /* Use SPIRV-Tools validator to try and catch any issues with the module itself */ 856011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spv_context ctx = spvContextCreate(SPV_ENV_VULKAN_1_0); 856111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spv_const_binary_t binary { pCreateInfo->pCode, pCreateInfo->codeSize / sizeof(uint32_t) }; 856211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spv_diagnostic diag = nullptr; 856311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 856411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto result = spvValidate(ctx, &binary, &diag); 856511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result != SPV_SUCCESS) { 856611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, 856711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result == SPV_WARNING ? VK_DEBUG_REPORT_WARNING_BIT_EXT : VK_DEBUG_REPORT_ERROR_BIT_EXT, 856811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDebugReportObjectTypeEXT(0), 0, 856911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, SHADER_CHECKER_INCONSISTENT_SPIRV, "SC", "SPIR-V module not valid: %s", 857011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert diag && diag->error ? diag->error : "(no error text)"); 857111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 857211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 857311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spvDiagnosticDestroy(diag); 857411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert spvContextDestroy(ctx); 857511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 857611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skip_call) 857711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 857811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 857911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult res = my_data->device_dispatch_table->CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule); 858011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 858111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (res == VK_SUCCESS) { 858211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 858311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->shaderModuleMap[*pShaderModule] = unique_ptr<shader_module>(new shader_module(pCreateInfo)); 858411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 858511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return res; 858611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 858711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 858811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo, 858911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, 859011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkRenderPass *pRenderPass) { 859111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 859211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 859311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Create DAG 859411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<bool> has_self_dependency(pCreateInfo->subpassCount); 859511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<DAGNode> subpass_to_node(pCreateInfo->subpassCount); 859611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 859711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 859811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= CreatePassDAG(dev_data, device, pCreateInfo, subpass_to_node, has_self_dependency); 859911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Validate 860011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= ValidateLayouts(dev_data, device, pCreateInfo); 860111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (skip_call) { 860211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return VK_ERROR_VALIDATION_FAILED_EXT; 860311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 860411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 860511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass); 860611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 860711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODOSC : Merge in tracking of renderpass from shader_checker 860811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Shadow create info and store in map 860911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkRenderPassCreateInfo *localRPCI = new VkRenderPassCreateInfo(*pCreateInfo); 861011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCreateInfo->pAttachments) { 861111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert localRPCI->pAttachments = new VkAttachmentDescription[localRPCI->attachmentCount]; 861211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy((void *)localRPCI->pAttachments, pCreateInfo->pAttachments, 861311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert localRPCI->attachmentCount * sizeof(VkAttachmentDescription)); 861411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 861511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCreateInfo->pSubpasses) { 861611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert localRPCI->pSubpasses = new VkSubpassDescription[localRPCI->subpassCount]; 861711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy((void *)localRPCI->pSubpasses, pCreateInfo->pSubpasses, localRPCI->subpassCount * sizeof(VkSubpassDescription)); 861811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 861911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < localRPCI->subpassCount; i++) { 862011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkSubpassDescription *subpass = (VkSubpassDescription *)&localRPCI->pSubpasses[i]; 862111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t attachmentCount = subpass->inputAttachmentCount + 862211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass->colorAttachmentCount * (1 + (subpass->pResolveAttachments ? 1 : 0)) + 862311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ((subpass->pDepthStencilAttachment) ? 1 : 0) + subpass->preserveAttachmentCount; 862411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkAttachmentReference *attachments = new VkAttachmentReference[attachmentCount]; 862511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 862611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy(attachments, subpass->pInputAttachments, sizeof(attachments[0]) * subpass->inputAttachmentCount); 862711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass->pInputAttachments = attachments; 862811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachments += subpass->inputAttachmentCount; 862911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 863011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy(attachments, subpass->pColorAttachments, sizeof(attachments[0]) * subpass->colorAttachmentCount); 863111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass->pColorAttachments = attachments; 863211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachments += subpass->colorAttachmentCount; 863311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 863411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass->pResolveAttachments) { 863511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy(attachments, subpass->pResolveAttachments, sizeof(attachments[0]) * subpass->colorAttachmentCount); 863611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass->pResolveAttachments = attachments; 863711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachments += subpass->colorAttachmentCount; 863811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 863911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 864011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass->pDepthStencilAttachment) { 864111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy(attachments, subpass->pDepthStencilAttachment, sizeof(attachments[0]) * 1); 864211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass->pDepthStencilAttachment = attachments; 864311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachments += 1; 864411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 864511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 864611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy(attachments, subpass->pPreserveAttachments, sizeof(attachments[0]) * subpass->preserveAttachmentCount); 864711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert subpass->pPreserveAttachments = &attachments->attachment; 864811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 864911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 865011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCreateInfo->pDependencies) { 865111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert localRPCI->pDependencies = new VkSubpassDependency[localRPCI->dependencyCount]; 865211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy((void *)localRPCI->pDependencies, pCreateInfo->pDependencies, 865311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert localRPCI->dependencyCount * sizeof(VkSubpassDependency)); 865411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 865511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 865611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto render_pass = new RENDER_PASS_NODE(localRPCI); 865711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert render_pass->renderPass = *pRenderPass; 865811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert render_pass->hasSelfDependency = has_self_dependency; 865911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert render_pass->subpassToNode = subpass_to_node; 866011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if MTMERGESOURCE 866111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // MTMTODO : Merge with code from above to eliminate duplication 866211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 866311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkAttachmentDescription desc = pCreateInfo->pAttachments[i]; 866411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MT_PASS_ATTACHMENT_INFO pass_info; 866511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass_info.load_op = desc.loadOp; 866611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass_info.store_op = desc.storeOp; 866711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pass_info.attachment = i; 866811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert render_pass->attachments.push_back(pass_info); 866911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 867011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Maybe fill list and then copy instead of locking 867111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<uint32_t, bool> &attachment_first_read = render_pass->attachment_first_read; 867211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unordered_map<uint32_t, VkImageLayout> &attachment_first_layout = 867311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert render_pass->attachment_first_layout; 867411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 867511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 867611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass.pipelineBindPoint != VK_PIPELINE_BIND_POINT_GRAPHICS) { 867711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 867811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 867911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Pipeline bind point for subpass %d must be VK_PIPELINE_BIND_POINT_GRAPHICS.", i); 868011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 868111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) { 868211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t attachment = subpass.pPreserveAttachments[j]; 868311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachment >= pCreateInfo->attachmentCount) { 868411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 868511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 868611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Preserve attachment %d cannot be greater than the total number of attachments %d.", 868711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment, pCreateInfo->attachmentCount); 868811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 868911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 869011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 869111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t attachment; 869211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass.pResolveAttachments) { 869311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment = subpass.pResolveAttachments[j].attachment; 869411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachment >= pCreateInfo->attachmentCount && attachment != VK_ATTACHMENT_UNUSED) { 869511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 869611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 869711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Color attachment %d cannot be greater than the total number of attachments %d.", 869811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment, pCreateInfo->attachmentCount); 869911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 870011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 870111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 870211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment = subpass.pColorAttachments[j].attachment; 870311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachment >= pCreateInfo->attachmentCount) { 870411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 870511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 870611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Color attachment %d cannot be greater than the total number of attachments %d.", 870711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment, pCreateInfo->attachmentCount); 870811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 870911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 871011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachment_first_read.count(attachment)) 871111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 871211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment_first_read.insert(std::make_pair(attachment, false)); 871311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment_first_layout.insert(std::make_pair(attachment, subpass.pColorAttachments[j].layout)); 871411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 871511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 871611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 871711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachment >= pCreateInfo->attachmentCount) { 871811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 871911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 872011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Depth stencil attachment %d cannot be greater than the total number of attachments %d.", 872111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment, pCreateInfo->attachmentCount); 872211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 872311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 872411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachment_first_read.count(attachment)) 872511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 872611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment_first_read.insert(std::make_pair(attachment, false)); 872711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment_first_layout.insert(std::make_pair(attachment, subpass.pDepthStencilAttachment->layout)); 872811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 872911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 873011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t attachment = subpass.pInputAttachments[j].attachment; 873111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachment >= pCreateInfo->attachmentCount) { 873211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 873311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 873411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Input attachment %d cannot be greater than the total number of attachments %d.", 873511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment, pCreateInfo->attachmentCount); 873611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 873711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 873811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (attachment_first_read.count(attachment)) 873911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 874011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment_first_read.insert(std::make_pair(attachment, true)); 874111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert attachment_first_layout.insert(std::make_pair(attachment, subpass.pInputAttachments[j].layout)); 874211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 874311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 874411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 874511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 874611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 874711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->renderPassMap[*pRenderPass] = render_pass; 874811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 874911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 875011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 875111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 875211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Free the renderpass shadow 875311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void deleteRenderPasses(layer_data *my_data) { 875411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (my_data->renderPassMap.size() <= 0) 875511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 875611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto ii = my_data->renderPassMap.begin(); ii != my_data->renderPassMap.end(); ++ii) { 875711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkRenderPassCreateInfo *pRenderPassInfo = (*ii).second->pCreateInfo; 875811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete[] pRenderPassInfo->pAttachments; 875911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pRenderPassInfo->pSubpasses) { 876011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pRenderPassInfo->subpassCount; ++i) { 876111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Attachements are all allocated in a block, so just need to 876211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // find the first non-null one to delete 876311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pRenderPassInfo->pSubpasses[i].pInputAttachments) { 876411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete[] pRenderPassInfo->pSubpasses[i].pInputAttachments; 876511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (pRenderPassInfo->pSubpasses[i].pColorAttachments) { 876611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete[] pRenderPassInfo->pSubpasses[i].pColorAttachments; 876711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (pRenderPassInfo->pSubpasses[i].pResolveAttachments) { 876811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete[] pRenderPassInfo->pSubpasses[i].pResolveAttachments; 876911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (pRenderPassInfo->pSubpasses[i].pPreserveAttachments) { 877011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete[] pRenderPassInfo->pSubpasses[i].pPreserveAttachments; 877111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 877211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 877311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete[] pRenderPassInfo->pSubpasses; 877411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 877511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete[] pRenderPassInfo->pDependencies; 877611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete pRenderPassInfo; 877711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete (*ii).second; 877811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 877911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->renderPassMap.clear(); 878011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 878111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 878211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool VerifyFramebufferAndRenderPassLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin) { 878311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 878411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkRenderPassCreateInfo *pRenderPassInfo = dev_data->renderPassMap[pRenderPassBegin->renderPass]->pCreateInfo; 878511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkFramebufferCreateInfo framebufferInfo = dev_data->frameBufferMap[pRenderPassBegin->framebuffer].createInfo; 878611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pRenderPassInfo->attachmentCount != framebufferInfo.attachmentCount) { 878711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 878811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_RENDERPASS, "DS", "You cannot start a render pass using a framebuffer " 878911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "with a different number of attachments."); 879011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 879111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) { 879211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImageView &image_view = framebufferInfo.pAttachments[i]; 879311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto image_data = dev_data->imageViewMap.find(image_view); 879411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(image_data != dev_data->imageViewMap.end()); 879511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImage &image = image_data->second.image; 879611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImageSubresourceRange &subRange = image_data->second.subresourceRange; 879711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert IMAGE_CMD_BUF_LAYOUT_NODE newNode = {pRenderPassInfo->pAttachments[i].initialLayout, 879811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pRenderPassInfo->pAttachments[i].initialLayout}; 879911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Do not iterate over every possibility - consolidate where possible 880011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subRange.levelCount; j++) { 880111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t level = subRange.baseMipLevel + j; 880211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t k = 0; k < subRange.layerCount; k++) { 880311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t layer = subRange.baseArrayLayer + k; 880411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImageSubresource sub = {subRange.aspectMask, level, layer}; 880511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert IMAGE_CMD_BUF_LAYOUT_NODE node; 880611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!FindLayout(pCB, image, sub, node)) { 880711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(pCB, image, sub, newNode); 880811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert continue; 880911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 881011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (newNode.layout != node.layout) { 881111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 881211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 881311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_RENDERPASS, "DS", "You cannot start a render pass using attachment %i " 881411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "where the " 881511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "initial layout is %s and the layout of the attachment at the " 881611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "start of the render pass is %s. The layouts must match.", 881711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert i, string_VkImageLayout(newNode.layout), string_VkImageLayout(node.layout)); 881811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 881911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 882011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 882111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 882211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 882311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 882411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 882511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void TransitionSubpassLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin, 882611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const int subpass_index) { 882711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto renderPass = getRenderPass(dev_data, pRenderPassBegin->renderPass); 882811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!renderPass) 882911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 883011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 883111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto framebuffer = getFramebuffer(dev_data, pRenderPassBegin->framebuffer); 883211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!framebuffer) 883311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 883411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 883511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkFramebufferCreateInfo &framebufferInfo = framebuffer->createInfo; 883611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubpassDescription &subpass = renderPass->pCreateInfo->pSubpasses[subpass_index]; 883711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 883811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImageView &image_view = framebufferInfo.pAttachments[subpass.pInputAttachments[j].attachment]; 883911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(dev_data, pCB, image_view, subpass.pInputAttachments[j].layout); 884011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 884111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 884211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImageView &image_view = framebufferInfo.pAttachments[subpass.pColorAttachments[j].attachment]; 884311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(dev_data, pCB, image_view, subpass.pColorAttachments[j].layout); 884411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 884511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((subpass.pDepthStencilAttachment != NULL) && (subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)) { 884611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImageView &image_view = framebufferInfo.pAttachments[subpass.pDepthStencilAttachment->attachment]; 884711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(dev_data, pCB, image_view, subpass.pDepthStencilAttachment->layout); 884811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 884911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 885011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 885111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validatePrimaryCommandBuffer(const layer_data *my_data, const GLOBAL_CB_NODE *pCB, const std::string &cmd_name) { 885211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 885311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 885411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 885511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", "Cannot execute command %s on a secondary command buffer.", 885611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cmd_name.c_str()); 885711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 885811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 885911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 886011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 886111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void TransitionFinalSubpassLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin) { 886211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto renderPass = getRenderPass(dev_data, pRenderPassBegin->renderPass); 886311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!renderPass) 886411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 886511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 886611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkRenderPassCreateInfo *pRenderPassInfo = renderPass->pCreateInfo; 886711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto framebuffer = getFramebuffer(dev_data, pRenderPassBegin->framebuffer); 886811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!framebuffer) 886911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 887011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 887111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) { 887211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkImageView &image_view = framebuffer->createInfo.pAttachments[i]; 887311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SetLayout(dev_data, pCB, image_view, pRenderPassInfo->pAttachments[i].finalLayout); 887411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 887511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 887611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 887711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool VerifyRenderAreaBounds(const layer_data *my_data, const VkRenderPassBeginInfo *pRenderPassBegin) { 887811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 887911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkFramebufferCreateInfo *pFramebufferInfo = &my_data->frameBufferMap.at(pRenderPassBegin->framebuffer).createInfo; 888011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pRenderPassBegin->renderArea.offset.x < 0 || 888111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pRenderPassBegin->renderArea.offset.x + pRenderPassBegin->renderArea.extent.width) > pFramebufferInfo->width || 888211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pRenderPassBegin->renderArea.offset.y < 0 || 888311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pRenderPassBegin->renderArea.offset.y + pRenderPassBegin->renderArea.extent.height) > pFramebufferInfo->height) { 888411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= static_cast<bool>(log_msg( 888511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 888611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_RENDER_AREA, "CORE", 888711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot execute a render pass with renderArea not within the bound of the " 888811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "framebuffer. RenderArea: x %d, y %d, width %d, height %d. Framebuffer: width %d, " 888911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "height %d.", 889011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pRenderPassBegin->renderArea.offset.x, pRenderPassBegin->renderArea.offset.y, pRenderPassBegin->renderArea.extent.width, 889111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pRenderPassBegin->renderArea.extent.height, pFramebufferInfo->width, pFramebufferInfo->height)); 889211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 889311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 889411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 889511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 889611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 889711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, VkSubpassContents contents) { 889811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 889911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 890011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 890111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 890211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto renderPass = pRenderPassBegin ? getRenderPass(dev_data, pRenderPassBegin->renderPass) : nullptr; 890311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto framebuffer = pRenderPassBegin ? getFramebuffer(dev_data, pRenderPassBegin->framebuffer) : nullptr; 890411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 890511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (renderPass) { 890611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if MTMERGE 890711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeFramebuffer = pRenderPassBegin->framebuffer; 890811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (size_t i = 0; i < renderPass->attachments.size(); ++i) { 890911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; 891011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (renderPass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { 891111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 891211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, fb_info.mem, true, fb_info.image); 891311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 891411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 891511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->validate_functions.push_back(function); 891611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (renderPass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_DONT_CARE) { 891711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 891811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, fb_info.mem, false, fb_info.image); 891911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 892011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 892111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->validate_functions.push_back(function); 892211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (renderPass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_LOAD) { 892311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 892411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image); 892511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 892611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->validate_functions.push_back(function); 892711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 892811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (renderPass->attachment_first_read[renderPass->attachments[i].attachment]) { 892911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 893011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image); 893111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 893211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->validate_functions.push_back(function); 893311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 893411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 893511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 893611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin); 893711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= VerifyFramebufferAndRenderPassLayouts(dev_data, pCB, pRenderPassBegin); 893811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= insideRenderPass(dev_data, pCB, "vkCmdBeginRenderPass"); 893911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (renderPass) { 894011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= ValidateDependencies(dev_data, framebuffer, renderPass); 894111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 894211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeRenderPass = renderPass; 894311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdBeginRenderPass"); 894411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_BEGINRENDERPASS, "vkCmdBeginRenderPass()"); 894511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // This is a shallow copy as that is all that is needed for now 894611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeRenderPassBeginInfo = *pRenderPassBegin; 894711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeSubpass = 0; 894811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeSubpassContents = contents; 894911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->framebuffers.insert(pRenderPassBegin->framebuffer); 895011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Connect this framebuffer to this cmdBuffer 895111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert framebuffer->referencingCmdBuffers.insert(pCB->commandBuffer); 895211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 895311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 895411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 895511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_RENDERPASS, "DS", "You cannot use a NULL RenderPass object in vkCmdBeginRenderPass()"); 895611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 895711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 895811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 895911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 896011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents); 896111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 896211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 896311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 896411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) { 896511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 896611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 896711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 896811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 896911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 897011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdNextSubpass"); 897111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_NEXTSUBPASS, "vkCmdNextSubpass()"); 897211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeSubpass++; 897311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeSubpassContents = contents; 897411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert TransitionSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, pCB->activeSubpass); 897511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdNextSubpass"); 897611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 897711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 897811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 897911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdNextSubpass(commandBuffer, contents); 898011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 898111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 898211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) { 898311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 898411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 898511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 898611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto pCB = getCBNode(dev_data, commandBuffer); 898711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 898811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert RENDER_PASS_NODE* pRPNode = pCB->activeRenderPass; 898911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto framebuffer = getFramebuffer(dev_data, pCB->activeFramebuffer); 899011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pRPNode) { 899111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (size_t i = 0; i < pRPNode->attachments.size(); ++i) { 899211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; 899311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pRPNode->attachments[i].store_op == VK_ATTACHMENT_STORE_OP_STORE) { 899411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 899511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, fb_info.mem, true, fb_info.image); 899611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 899711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 899811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->validate_functions.push_back(function); 899911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (pRPNode->attachments[i].store_op == VK_ATTACHMENT_STORE_OP_DONT_CARE) { 900011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::function<bool()> function = [=]() { 900111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_memory_valid(dev_data, fb_info.mem, false, fb_info.image); 900211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 900311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 900411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->validate_functions.push_back(function); 900511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 900611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 900711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 900811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass"); 900911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass"); 901011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()"); 901111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert TransitionFinalSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo); 901211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeRenderPass = nullptr; 901311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeSubpass = 0; 901411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->activeFramebuffer = VK_NULL_HANDLE; 901511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 901611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 901711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 901811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdEndRenderPass(commandBuffer); 901911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 902011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 902111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool logInvalidAttachmentMessage(layer_data *dev_data, VkCommandBuffer secondaryBuffer, RENDER_PASS_NODE const *secondaryPass, 902211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert RENDER_PASS_NODE const *primaryPass, uint32_t primaryAttach, uint32_t secondaryAttach, 902311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char *msg) { 902411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 902511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 902611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p which has a render pass 0x%" PRIx64 902711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " that is not compatible with the current render pass 0x%" PRIx64 "." 902811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Attachment %" PRIu32 " is not compatible with %" PRIu32 ". %s", 902911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)secondaryBuffer, (uint64_t)(secondaryPass->renderPass), (uint64_t)(primaryPass->renderPass), primaryAttach, secondaryAttach, 903011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert msg); 903111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 903211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 903311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateAttachmentCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, RENDER_PASS_NODE const *primaryPass, 903411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t primaryAttach, VkCommandBuffer secondaryBuffer, RENDER_PASS_NODE const *secondaryPass, 903511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t secondaryAttach, bool is_multi) { 903611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 903711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (primaryPass->pCreateInfo->attachmentCount <= primaryAttach) { 903811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert primaryAttach = VK_ATTACHMENT_UNUSED; 903911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 904011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (secondaryPass->pCreateInfo->attachmentCount <= secondaryAttach) { 904111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryAttach = VK_ATTACHMENT_UNUSED; 904211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 904311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (primaryAttach == VK_ATTACHMENT_UNUSED && secondaryAttach == VK_ATTACHMENT_UNUSED) { 904411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 904511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 904611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (primaryAttach == VK_ATTACHMENT_UNUSED) { 904711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, secondaryPass, primaryPass, primaryAttach, 904811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryAttach, "The first is unused while the second is not."); 904911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 905011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 905111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (secondaryAttach == VK_ATTACHMENT_UNUSED) { 905211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, secondaryPass, primaryPass, primaryAttach, 905311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryAttach, "The second is unused while the first is not."); 905411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 905511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 905611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (primaryPass->pCreateInfo->pAttachments[primaryAttach].format != 905711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryPass->pCreateInfo->pAttachments[secondaryAttach].format) { 905811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, secondaryPass, primaryPass, primaryAttach, 905911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryAttach, "They have different formats."); 906011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 906111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (primaryPass->pCreateInfo->pAttachments[primaryAttach].samples != 906211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryPass->pCreateInfo->pAttachments[secondaryAttach].samples) { 906311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, secondaryPass, primaryPass, primaryAttach, 906411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryAttach, "They have different samples."); 906511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 906611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (is_multi && 906711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert primaryPass->pCreateInfo->pAttachments[primaryAttach].flags != 906811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryPass->pCreateInfo->pAttachments[secondaryAttach].flags) { 906911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, secondaryPass, primaryPass, primaryAttach, 907011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryAttach, "They have different flags."); 907111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 907211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 907311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 907411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 907511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateSubpassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, RENDER_PASS_NODE const *primaryPass, 907611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkCommandBuffer secondaryBuffer, RENDER_PASS_NODE const *secondaryPass, const int subpass, 907711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool is_multi) { 907811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 907911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubpassDescription &primary_desc = primaryPass->pCreateInfo->pSubpasses[subpass]; 908011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSubpassDescription &secondary_desc = secondaryPass->pCreateInfo->pSubpasses[subpass]; 908111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t maxInputAttachmentCount = std::max(primary_desc.inputAttachmentCount, secondary_desc.inputAttachmentCount); 908211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < maxInputAttachmentCount; ++i) { 908311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t primary_input_attach = VK_ATTACHMENT_UNUSED, secondary_input_attach = VK_ATTACHMENT_UNUSED; 908411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (i < primary_desc.inputAttachmentCount) { 908511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert primary_input_attach = primary_desc.pInputAttachments[i].attachment; 908611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 908711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (i < secondary_desc.inputAttachmentCount) { 908811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondary_input_attach = secondary_desc.pInputAttachments[i].attachment; 908911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 909011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPass, primary_input_attach, secondaryBuffer, 909111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryPass, secondary_input_attach, is_multi); 909211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 909311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t maxColorAttachmentCount = std::max(primary_desc.colorAttachmentCount, secondary_desc.colorAttachmentCount); 909411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < maxColorAttachmentCount; ++i) { 909511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t primary_color_attach = VK_ATTACHMENT_UNUSED, secondary_color_attach = VK_ATTACHMENT_UNUSED; 909611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (i < primary_desc.colorAttachmentCount) { 909711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert primary_color_attach = primary_desc.pColorAttachments[i].attachment; 909811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 909911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (i < secondary_desc.colorAttachmentCount) { 910011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondary_color_attach = secondary_desc.pColorAttachments[i].attachment; 910111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 910211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPass, primary_color_attach, secondaryBuffer, 910311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryPass, secondary_color_attach, is_multi); 910411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t primary_resolve_attach = VK_ATTACHMENT_UNUSED, secondary_resolve_attach = VK_ATTACHMENT_UNUSED; 910511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (i < primary_desc.colorAttachmentCount && primary_desc.pResolveAttachments) { 910611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert primary_resolve_attach = primary_desc.pResolveAttachments[i].attachment; 910711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 910811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (i < secondary_desc.colorAttachmentCount && secondary_desc.pResolveAttachments) { 910911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondary_resolve_attach = secondary_desc.pResolveAttachments[i].attachment; 911011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 911111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPass, primary_resolve_attach, secondaryBuffer, 911211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryPass, secondary_resolve_attach, is_multi); 911311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 911411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t primary_depthstencil_attach = VK_ATTACHMENT_UNUSED, secondary_depthstencil_attach = VK_ATTACHMENT_UNUSED; 911511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (primary_desc.pDepthStencilAttachment) { 911611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert primary_depthstencil_attach = primary_desc.pDepthStencilAttachment[0].attachment; 911711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 911811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (secondary_desc.pDepthStencilAttachment) { 911911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondary_depthstencil_attach = secondary_desc.pDepthStencilAttachment[0].attachment; 912011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 912111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPass, primary_depthstencil_attach, secondaryBuffer, 912211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryPass, secondary_depthstencil_attach, is_multi); 912311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 912411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 912511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 912611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, VkRenderPass primaryPass, 912711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkCommandBuffer secondaryBuffer, VkRenderPass secondaryPass) { 912811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 912911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Early exit if renderPass objects are identical (and therefore compatible) 913011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (primaryPass == secondaryPass) 913111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 913211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto primary_render_pass = getRenderPass(dev_data, primaryPass); 913311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto secondary_render_pass = getRenderPass(dev_data, secondaryPass); 913411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!primary_render_pass) { 913511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 913611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 913711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 913811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands() called w/ invalid current Cmd Buffer 0x%p which has invalid render pass 0x%" PRIx64 ".", 913911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)primaryBuffer, (uint64_t)(primaryPass)); 914011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 914111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 914211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!secondary_render_pass) { 914311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 914411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 914511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 914611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands() called w/ invalid secondary Cmd Buffer 0x%p which has invalid render pass 0x%" PRIx64 ".", 914711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)secondaryBuffer, (uint64_t)(secondaryPass)); 914811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 914911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 915011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (primary_render_pass->pCreateInfo->subpassCount != secondary_render_pass->pCreateInfo->subpassCount) { 915111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 915211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 915311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p which has a render pass 0x%" PRIx64 915411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " that is not compatible with the current render pass 0x%" PRIx64 "." 915511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "They have a different number of subpasses.", 915611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)secondaryBuffer, (uint64_t)(secondaryPass), (uint64_t)(primaryPass)); 915711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 915811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 915911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto subpassCount = primary_render_pass->pCreateInfo->subpassCount; 916011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < subpassCount; ++i) { 916111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= validateSubpassCompatibility(dev_data, primaryBuffer, primary_render_pass, secondaryBuffer, 916211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondary_render_pass, i, subpassCount > 1); 916311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 916411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 916511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 916611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 916711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateFramebuffer(layer_data *dev_data, VkCommandBuffer primaryBuffer, const GLOBAL_CB_NODE *pCB, 916811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkCommandBuffer secondaryBuffer, const GLOBAL_CB_NODE *pSubCB) { 916911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 917011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pSubCB->beginInfo.pInheritanceInfo) { 917111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 917211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 917311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkFramebuffer primary_fb = pCB->activeFramebuffer; 917411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkFramebuffer secondary_fb = pSubCB->beginInfo.pInheritanceInfo->framebuffer; 917511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (secondary_fb != VK_NULL_HANDLE) { 917611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (primary_fb != secondary_fb) { 917711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 917811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 917911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p which has a framebuffer 0x%" PRIx64 918011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " that is not compatible with the current framebuffer 0x%" PRIx64 ".", 918111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)secondaryBuffer, (uint64_t)(secondary_fb), (uint64_t)(primary_fb)); 918211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 918311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto fb = getFramebuffer(dev_data, secondary_fb); 918411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!fb) { 918511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 918611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 918711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 918811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "which has invalid framebuffer 0x%" PRIx64 ".", 918911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)secondaryBuffer, (uint64_t)(secondary_fb)); 919011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 919111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 919211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= validateRenderPassCompatibility(dev_data, secondaryBuffer, fb->createInfo.renderPass, 919311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondaryBuffer, pSubCB->beginInfo.pInheritanceInfo->renderPass); 919411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 919511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 919611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 919711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 919811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateSecondaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, GLOBAL_CB_NODE *pSubCB) { 919911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 920011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unordered_set<int> activeTypes; 920111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto queryObject : pCB->activeQueries) { 920211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool); 920311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queryPoolData != dev_data->queryPoolMap.end()) { 920411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queryPoolData->second.createInfo.queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS && 920511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pSubCB->beginInfo.pInheritanceInfo) { 920611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkQueryPipelineStatisticFlags cmdBufStatistics = pSubCB->beginInfo.pInheritanceInfo->pipelineStatistics; 920711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((cmdBufStatistics & queryPoolData->second.createInfo.pipelineStatistics) != cmdBufStatistics) { 920811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 920911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 921011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 921111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 921211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "which has invalid active query pool 0x%" PRIx64 ". Pipeline statistics is being queried so the command " 921311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "buffer must have all bits set on the queryPool.", 921411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<void *>(pCB->commandBuffer), reinterpret_cast<const uint64_t &>(queryPoolData->first)); 921511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 921611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 921711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert activeTypes.insert(queryPoolData->second.createInfo.queryType); 921811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 921911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 922011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto queryObject : pSubCB->startedQueries) { 922111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool); 922211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (queryPoolData != dev_data->queryPoolMap.end() && activeTypes.count(queryPoolData->second.createInfo.queryType)) { 922311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 922411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 922511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 922611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 922711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "which has invalid active query pool 0x%" PRIx64 "of type %d but a query of that type has been started on " 922811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "secondary Cmd Buffer 0x%p.", 922911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<void *>(pCB->commandBuffer), reinterpret_cast<const uint64_t &>(queryPoolData->first), 923011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert queryPoolData->second.createInfo.queryType, reinterpret_cast<void *>(pSubCB->commandBuffer)); 923111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 923211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 923311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 923411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 923511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 923611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 923711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount, const VkCommandBuffer *pCommandBuffers) { 923811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 923911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); 924011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 924111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); 924211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB) { 924311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert GLOBAL_CB_NODE *pSubCB = NULL; 924411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < commandBuffersCount; i++) { 924511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pSubCB = getCBNode(dev_data, pCommandBuffers[i]); 924611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pSubCB) { 924711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 924811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 924911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 925011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p in element %u of pCommandBuffers array.", 925111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)pCommandBuffers[i], i); 925211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (VK_COMMAND_BUFFER_LEVEL_PRIMARY == pSubCB->createInfo.level) { 925311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 925411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 925511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands() called w/ Primary Cmd Buffer 0x%p in element %u of pCommandBuffers " 925611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "array. All cmd buffers in pCommandBuffers array must be secondary.", 925711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)pCommandBuffers[i], i); 925811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (pCB->activeRenderPass) { // Secondary CB w/i RenderPass must have *CONTINUE_BIT set 925911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 926011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 926111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 926211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pCommandBuffers[i], __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS", 926311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) executed within render pass (0x%" PRIxLEAST64 926411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") must have had vkBeginCommandBuffer() called w/ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT set.", 926511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)pCommandBuffers[i], (uint64_t)pCB->activeRenderPass->renderPass); 926611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 926711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Make sure render pass is compatible with parent command buffer pass if has continue 926811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validateRenderPassCompatibility(dev_data, commandBuffer, pCB->activeRenderPass->renderPass, pCommandBuffers[i], 926911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pSubCB->beginInfo.pInheritanceInfo->renderPass); 927011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validateFramebuffer(dev_data, commandBuffer, pCB, pCommandBuffers[i], pSubCB); 927111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 927211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string errorString = ""; 927311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->renderPass, 927411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pSubCB->beginInfo.pInheritanceInfo->renderPass, errorString)) { 927511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 927611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 927711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pCommandBuffers[i], __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 927811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 927911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") is incompatible w/ primary command buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 ") due to: %s", 928011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)pCommandBuffers[i], (uint64_t)pSubCB->beginInfo.pInheritanceInfo->renderPass, (void *)commandBuffer, 928111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pCB->activeRenderPass->renderPass, errorString.c_str()); 928211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 928311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If framebuffer for secondary CB is not NULL, then it must match FB from vkCmdBeginRenderPass() 928411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // that this CB will be executed in AND framebuffer must have been created w/ RP compatible w/ renderpass 928511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pSubCB->beginInfo.pInheritanceInfo->framebuffer) { 928611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pSubCB->beginInfo.pInheritanceInfo->framebuffer != pCB->activeRenderPassBeginInfo.framebuffer) { 928711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 928811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 928911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pCommandBuffers[i], __LINE__, DRAWSTATE_FRAMEBUFFER_INCOMPATIBLE, "DS", 929011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) references framebuffer (0x%" PRIxLEAST64 929111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") that does not match framebuffer (0x%" PRIxLEAST64 ") in active renderpass (0x%" PRIxLEAST64 ").", 929211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (void *)pCommandBuffers[i], (uint64_t)pSubCB->beginInfo.pInheritanceInfo->framebuffer, 929311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pCB->activeRenderPassBeginInfo.framebuffer, (uint64_t)pCB->activeRenderPass->renderPass); 929411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 929511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 929611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 929711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO(mlentine): Move more logic into this method 929811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validateSecondaryCommandBufferState(dev_data, pCB, pSubCB); 929911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validateCommandBufferState(dev_data, pSubCB); 930011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Secondary cmdBuffers are considered pending execution starting w/ 930111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // being recorded 930211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 930311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->globalInFlightCmdBuffers.find(pSubCB->commandBuffer) != dev_data->globalInFlightCmdBuffers.end()) { 930411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 930511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 930611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS", 930711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Attempt to simultaneously execute CB 0x%" PRIxLEAST64 " w/o VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT " 930811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "set!", 930911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(pCB->commandBuffer)); 931011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 931111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) { 931211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Warn that non-simultaneous secondary cmd buffer renders primary non-simultaneous 931311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 931411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 931511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(pCommandBuffers[i]), __LINE__, DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS", 931611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands(): Secondary Command Buffer (0x%" PRIxLEAST64 931711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set and will cause primary command buffer " 931811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "(0x%" PRIxLEAST64 ") to be treated as if it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT " 931911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "set, even though it does.", 932011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(pCommandBuffers[i]), (uint64_t)(pCB->commandBuffer)); 932111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->beginInfo.flags &= ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; 932211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 932311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 932411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCB->activeQueries.empty() && !dev_data->phys_dev_properties.features.inheritedQueries) { 932511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 932611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 932711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 932811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkCmdExecuteCommands(): Secondary Command Buffer " 932911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "(0x%" PRIxLEAST64 ") cannot be submitted with a query in " 933011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "flight and inherited queries not " 933111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "supported on this device.", 933211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t>(pCommandBuffers[i])); 933311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 933411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pSubCB->primaryCommandBuffer = pCB->commandBuffer; 933511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pCB->secondaryCommandBuffers.insert(pSubCB->commandBuffer); 933611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->globalInFlightCmdBuffers.insert(pSubCB->commandBuffer); 933711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 933811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdExecuteComands"); 933911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= addCmd(dev_data, pCB, CMD_EXECUTECOMMANDS, "vkCmdExecuteComands()"); 934011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 934111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 934211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 934311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->CmdExecuteCommands(commandBuffer, commandBuffersCount, pCommandBuffers); 934411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 934511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 934611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool ValidateMapImageLayouts(VkDevice device, VkDeviceMemory mem) { 934711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 934811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 934911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto mem_data = dev_data->memObjMap.find(mem); 935011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((mem_data != dev_data->memObjMap.end()) && (mem_data->second.image != VK_NULL_HANDLE)) { 935111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::vector<VkImageLayout> layouts; 935211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (FindLayouts(dev_data, mem_data->second.image, layouts)) { 935311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto layout : layouts) { 935411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (layout != VK_IMAGE_LAYOUT_PREINITIALIZED && layout != VK_IMAGE_LAYOUT_GENERAL) { 935511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 935611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Cannot map an image with layout %s. Only " 935711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "GENERAL or PREINITIALIZED are supported.", 935811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkImageLayout(layout)); 935911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 936011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 936111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 936211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 936311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skip_call; 936411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 936511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 936611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 936711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertMapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkFlags flags, void **ppData) { 936811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 936911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 937011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 937111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 937211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 937311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if MTMERGESOURCE 937411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DEVICE_MEM_INFO *pMemObj = get_mem_obj_info(dev_data, mem); 937511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pMemObj) { 937611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pMemObj->valid = true; 937711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((dev_data->phys_dev_mem_props.memoryTypes[pMemObj->allocInfo.memoryTypeIndex].propertyFlags & 937811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) { 937911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call = 938011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 938111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)mem, __LINE__, MEMTRACK_INVALID_STATE, "MEM", 938211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Mapping Memory without VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set: mem obj 0x%" PRIxLEAST64, (uint64_t)mem); 938311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 938411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 938511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= validateMemRange(dev_data, mem, offset, size); 938611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 938711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= ValidateMapImageLayouts(device, mem); 938811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 938911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 939011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skip_call) { 939111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = dev_data->device_dispatch_table->MapMemory(device, mem, offset, size, flags, ppData); 939211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 939311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if MTMERGESOURCE 939411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 939511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert storeMemRanges(dev_data, mem, offset, size); 939611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert initializeAndTrackMemory(dev_data, mem, size, ppData); 939711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 939811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 939911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 940011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 940111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 940211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 940311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 940411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL UnmapMemory(VkDevice device, VkDeviceMemory mem) { 940511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 940611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 940711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 940811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 940911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= deleteMemRanges(my_data, mem); 941011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 941111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 941211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->device_dispatch_table->UnmapMemory(device, mem); 941311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 941411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 941511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 941611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateMemoryIsMapped(layer_data *my_data, const char *funcName, uint32_t memRangeCount, 941711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkMappedMemoryRange *pMemRanges) { 941811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 941911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < memRangeCount; ++i) { 942011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto mem_element = my_data->memObjMap.find(pMemRanges[i].memory); 942111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_element != my_data->memObjMap.end()) { 942211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_element->second.memRange.offset > pMemRanges[i].offset) { 942311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg( 942411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 942511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pMemRanges[i].memory, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 942611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "%s: Flush/Invalidate offset (" PRINTF_SIZE_T_SPECIFIER ") is less than Memory Object's offset " 942711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "(" PRINTF_SIZE_T_SPECIFIER ").", 942811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcName, static_cast<size_t>(pMemRanges[i].offset), static_cast<size_t>(mem_element->second.memRange.offset)); 942911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 943011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((mem_element->second.memRange.size != VK_WHOLE_SIZE) && 943111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ((mem_element->second.memRange.offset + mem_element->second.memRange.size) < 943211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pMemRanges[i].offset + pMemRanges[i].size))) { 943311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 943411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)pMemRanges[i].memory, __LINE__, 943511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MEMTRACK_INVALID_MAP, "MEM", "%s: Flush/Invalidate upper-bound (" PRINTF_SIZE_T_SPECIFIER 943611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ") exceeds the Memory Object's upper-bound " 943711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "(" PRINTF_SIZE_T_SPECIFIER ").", 943811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcName, static_cast<size_t>(pMemRanges[i].offset + pMemRanges[i].size), 943911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static_cast<size_t>(mem_element->second.memRange.offset + mem_element->second.memRange.size)); 944011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 944111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 944211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 944311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 944411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 944511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 944611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateAndCopyNoncoherentMemoryToDriver(layer_data *my_data, uint32_t memRangeCount, 944711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkMappedMemoryRange *pMemRanges) { 944811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 944911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < memRangeCount; ++i) { 945011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto mem_element = my_data->memObjMap.find(pMemRanges[i].memory); 945111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_element != my_data->memObjMap.end()) { 945211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mem_element->second.pData) { 945311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceSize size = mem_element->second.memRange.size; 945411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceSize half_size = (size / 2); 945511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char *data = static_cast<char *>(mem_element->second.pData); 945611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto j = 0; j < half_size; ++j) { 945711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (data[j] != NoncoherentMemoryFillValue) { 945811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 945911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)pMemRanges[i].memory, __LINE__, 946011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MEMTRACK_INVALID_MAP, "MEM", "Memory overflow was detected on mem obj 0x%" PRIxLEAST64, 946111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pMemRanges[i].memory); 946211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 946311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 946411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto j = size + half_size; j < 2 * size; ++j) { 946511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (data[j] != NoncoherentMemoryFillValue) { 946611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 946711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)pMemRanges[i].memory, __LINE__, 946811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert MEMTRACK_INVALID_MAP, "MEM", "Memory overflow was detected on mem obj 0x%" PRIxLEAST64, 946911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pMemRanges[i].memory); 947011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 947111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 947211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy(mem_element->second.pDriverData, static_cast<void *>(data + (size_t)(half_size)), (size_t)(size)); 947311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 947411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 947511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 947611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return skipCall; 947711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 947811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 947911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVkResult VKAPI_CALL 948011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertFlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange *pMemRanges) { 948111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 948211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 948311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 948411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 948511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 948611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validateAndCopyNoncoherentMemoryToDriver(my_data, memRangeCount, pMemRanges); 948711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validateMemoryIsMapped(my_data, "vkFlushMappedMemoryRanges", memRangeCount, pMemRanges); 948811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 948911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 949011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = my_data->device_dispatch_table->FlushMappedMemoryRanges(device, memRangeCount, pMemRanges); 949111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 949211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 949311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 949411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 949511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVkResult VKAPI_CALL 949611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertInvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange *pMemRanges) { 949711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 949811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 949911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 950011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 950111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 950211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= validateMemoryIsMapped(my_data, "vkInvalidateMappedMemoryRanges", memRangeCount, pMemRanges); 950311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 950411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 950511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = my_data->device_dispatch_table->InvalidateMappedMemoryRanges(device, memRangeCount, pMemRanges); 950611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 950711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 950811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 950911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 951011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 951111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 951211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 951311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 951411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 951511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto image_node = dev_data->imageMap.find(image); 951611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_node != dev_data->imageMap.end()) { 951711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Track objects tied to memory 951811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint64_t image_handle = reinterpret_cast<uint64_t &>(image); 951911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = set_mem_binding(dev_data, mem, image_handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "vkBindImageMemory"); 952011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkMemoryRequirements memRequirements; 952111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 952211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->GetImageMemoryRequirements(device, image, &memRequirements); 952311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 952411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 952511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Track and validate bound memory range information 952611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const auto &memEntry = dev_data->memObjMap.find(mem); 952711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (memEntry != dev_data->memObjMap.end()) { 952811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const MEMORY_RANGE range = 952911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert insert_memory_ranges(image_handle, mem, memoryOffset, memRequirements, memEntry->second.imageRanges); 953011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall |= 953111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert validate_memory_range(dev_data, memEntry->second.bufferRanges, range, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT); 953211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 953311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 953411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert print_mem_list(dev_data); 953511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 953611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 953711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = dev_data->device_dispatch_table->BindImageMemory(device, image, mem, memoryOffset); 953811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.lock(); 953911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->memObjMap[mem].image = image; 954011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node->second.mem = mem; 954111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node->second.memOffset = memoryOffset; 954211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node->second.memSize = memRequirements.size; 954311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 954411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 954511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 954611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 954711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(image), __LINE__, MEMTRACK_INVALID_OBJECT, "MT", 954811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkBindImageMemory: Cannot find invalid image 0x%" PRIx64 ", has it already been deleted?", 954911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(image)); 955011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 955111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 955211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 955311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 955411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL SetEvent(VkDevice device, VkEvent event) { 955511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 955611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 955711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 955811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 955911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto event_node = dev_data->eventMap.find(event); 956011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (event_node != dev_data->eventMap.end()) { 956111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert event_node->second.needsSignaled = false; 956211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert event_node->second.stageMask = VK_PIPELINE_STAGE_HOST_BIT; 956311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (event_node->second.write_in_use) { 956411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, 956511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(event), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 956611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Cannot call vkSetEvent() on event 0x%" PRIxLEAST64 " that is already in use by a command buffer.", 956711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(event)); 956811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 956911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 957011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 957111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Host setting event is visible to all queues immediately so update stageMask for any queue that's seen this event 957211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : For correctness this needs separate fix to verify that app doesn't make incorrect assumptions about the 957311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // ordering of this command in relation to vkCmd[Set|Reset]Events (see GH297) 957411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto queue_data : dev_data->queueMap) { 957511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto event_entry = queue_data.second.eventToStageMap.find(event); 957611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (event_entry != queue_data.second.eventToStageMap.end()) { 957711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert event_entry->second |= VK_PIPELINE_STAGE_HOST_BIT; 957811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 957911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 958011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skip_call) 958111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = dev_data->device_dispatch_table->SetEvent(device, event); 958211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 958311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 958411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 958511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 958611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, VkFence fence) { 958711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map); 958811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 958911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 959011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 959111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // First verify that fence is not in use 959211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence != VK_NULL_HANDLE) { 959311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto fence_data = dev_data->fenceMap.find(fence); 959411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((bindInfoCount != 0) && fence_data->second.in_use.load()) { 959511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 959611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 959711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", 959811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Fence 0x%" PRIx64 " is already in use by another submission.", reinterpret_cast<uint64_t &>(fence)); 959911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 960011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!fence_data->second.needsSignaled) { 960111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 960211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 960311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 960411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted", 960511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(fence)); 960611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 960711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert trackCommandBuffers(dev_data, queue, 0, nullptr, fence); 960811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 960911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) { 961011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx]; 961111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Track objects tied to memory 961211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < bindInfo.bufferBindCount; j++) { 961311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t k = 0; k < bindInfo.pBufferBinds[j].bindCount; k++) { 961411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (set_sparse_mem_binding(dev_data, bindInfo.pBufferBinds[j].pBinds[k].memory, 961511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)bindInfo.pBufferBinds[j].buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 961611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkQueueBindSparse")) 961711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call = true; 961811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 961911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 962011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < bindInfo.imageOpaqueBindCount; j++) { 962111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t k = 0; k < bindInfo.pImageOpaqueBinds[j].bindCount; k++) { 962211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (set_sparse_mem_binding(dev_data, bindInfo.pImageOpaqueBinds[j].pBinds[k].memory, 962311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)bindInfo.pImageOpaqueBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 962411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkQueueBindSparse")) 962511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call = true; 962611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 962711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 962811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t j = 0; j < bindInfo.imageBindCount; j++) { 962911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t k = 0; k < bindInfo.pImageBinds[j].bindCount; k++) { 963011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (set_sparse_mem_binding(dev_data, bindInfo.pImageBinds[j].pBinds[k].memory, 963111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)bindInfo.pImageBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 963211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkQueueBindSparse")) 963311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call = true; 963411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 963511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 963611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < bindInfo.waitSemaphoreCount; ++i) { 963711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSemaphore &semaphore = bindInfo.pWaitSemaphores[i]; 963811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->semaphoreMap.find(semaphore) != dev_data->semaphoreMap.end()) { 963911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->semaphoreMap[semaphore].signaled) { 964011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->semaphoreMap[semaphore].signaled = false; 964111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 964211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 964311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 964411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 964511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkQueueBindSparse: Queue 0x%" PRIx64 " is waiting on semaphore 0x%" PRIx64 964611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert " that has no way to be signaled.", 964711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(queue), reinterpret_cast<const uint64_t &>(semaphore)); 964811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 964911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 965011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 965111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < bindInfo.signalSemaphoreCount; ++i) { 965211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSemaphore &semaphore = bindInfo.pSignalSemaphores[i]; 965311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->semaphoreMap.find(semaphore) != dev_data->semaphoreMap.end()) { 965411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->semaphoreMap[semaphore].signaled) { 965511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call = 965611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 965711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 965811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkQueueBindSparse: Queue 0x%" PRIx64 " is signaling semaphore 0x%" PRIx64 965911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ", but that semaphore is already signaled.", 966011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(queue), reinterpret_cast<const uint64_t &>(semaphore)); 966111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 966211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->semaphoreMap[semaphore].signaled = true; 966311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 966411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 966511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 966611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert print_mem_list(dev_data); 966711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 966811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 966911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skip_call) 967011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return dev_data->device_dispatch_table->QueueBindSparse(queue, bindInfoCount, pBindInfo, fence); 967111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 967211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 967311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 967411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 967511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, 967611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) { 967711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 967811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore); 967911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result == VK_SUCCESS) { 968011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 968111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SEMAPHORE_NODE* sNode = &dev_data->semaphoreMap[*pSemaphore]; 968211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sNode->signaled = false; 968311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sNode->queue = VK_NULL_HANDLE; 968411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sNode->in_use.store(0); 968511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 968611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 968711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 968811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 968911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 969011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) { 969111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 969211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateEvent(device, pCreateInfo, pAllocator, pEvent); 969311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result == VK_SUCCESS) { 969411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 969511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->eventMap[*pEvent].needsSignaled = false; 969611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->eventMap[*pEvent].in_use.store(0); 969711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->eventMap[*pEvent].stageMask = VkPipelineStageFlags(0); 969811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 969911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 970011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 970111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 970211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, 970311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, 970411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkSwapchainKHR *pSwapchain) { 970511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 970611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); 970711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 970811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == result) { 970911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert SWAPCHAIN_NODE *psc_node = new SWAPCHAIN_NODE(pCreateInfo); 971011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 971111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_extensions.swapchainMap[*pSwapchain] = psc_node; 971211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 971311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 971411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 971511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 971611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 971711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 971811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) { 971911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 972011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 972111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 972211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 972311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto swapchain_data = dev_data->device_extensions.swapchainMap.find(swapchain); 972411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (swapchain_data != dev_data->device_extensions.swapchainMap.end()) { 972511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (swapchain_data->second->images.size() > 0) { 972611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto swapchain_image : swapchain_data->second->images) { 972711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto image_sub = dev_data->imageSubresourceMap.find(swapchain_image); 972811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_sub != dev_data->imageSubresourceMap.end()) { 972911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto imgsubpair : image_sub->second) { 973011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto image_item = dev_data->imageLayoutMap.find(imgsubpair); 973111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (image_item != dev_data->imageLayoutMap.end()) { 973211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageLayoutMap.erase(image_item); 973311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 973411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 973511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageSubresourceMap.erase(image_sub); 973611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 973711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = clear_object_binding(dev_data, (uint64_t)swapchain_image, 973811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT); 973911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageMap.erase(swapchain_image); 974011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 974111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 974211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert delete swapchain_data->second; 974311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_extensions.swapchainMap.erase(swapchain); 974411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 974511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 974611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) 974711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator); 974811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 974911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 975011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 975111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pCount, VkImage *pSwapchainImages) { 975211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 975311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = dev_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pCount, pSwapchainImages); 975411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 975511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result == VK_SUCCESS && pSwapchainImages != NULL) { 975611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // This should never happen and is checked by param checker. 975711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!pCount) 975811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 975911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 976011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const size_t count = *pCount; 976111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto swapchain_node = dev_data->device_extensions.swapchainMap[swapchain]; 976211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!swapchain_node->images.empty()) { 976311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO : Not sure I like the memcmp here, but it works 976411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const bool mismatch = (swapchain_node->images.size() != count || 976511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcmp(&swapchain_node->images[0], pSwapchainImages, sizeof(swapchain_node->images[0]) * count)); 976611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mismatch) { 976711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO: Verify against Valid Usage section of extension 976811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 976911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)swapchain, __LINE__, MEMTRACK_NONE, "SWAP_CHAIN", 977011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkGetSwapchainInfoKHR(0x%" PRIx64 977111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ", VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_KHR) returned mismatching data", 977211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)(swapchain)); 977311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 977411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 977511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < *pCount; ++i) { 977611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert IMAGE_LAYOUT_NODE image_layout_node; 977711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_layout_node.layout = VK_IMAGE_LAYOUT_UNDEFINED; 977811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_layout_node.format = swapchain_node->createInfo.imageFormat; 977911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto &image_node = dev_data->imageMap[pSwapchainImages[i]]; 978011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node.createInfo.mipLevels = 1; 978111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node.createInfo.arrayLayers = swapchain_node->createInfo.imageArrayLayers; 978211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node.createInfo.usage = swapchain_node->createInfo.imageUsage; 978311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node.createInfo.format = swapchain_node->createInfo.imageFormat; 978411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node.createInfo.extent.width = swapchain_node->createInfo.imageExtent.width; 978511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node.createInfo.extent.height = swapchain_node->createInfo.imageExtent.height; 978611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node.createInfo.sharingMode = swapchain_node->createInfo.imageSharingMode; 978711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node.valid = false; 978811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert image_node.mem = MEMTRACKER_SWAP_CHAIN_IMAGE_KEY; 978911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert swapchain_node->images.push_back(pSwapchainImages[i]); 979011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ImageSubresourcePair subpair = {pSwapchainImages[i], false, VkImageSubresource()}; 979111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageSubresourceMap[pSwapchainImages[i]].push_back(subpair); 979211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->imageLayoutMap[subpair] = image_layout_node; 979311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_extensions.imageToSwapchainMap[pSwapchainImages[i]] = swapchain; 979411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 979511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 979611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 979711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 979811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 979911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) { 980011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map); 980111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 980211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skip_call = false; 980311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 980411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pPresentInfo) { 980511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 980611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) { 980711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkSemaphore &semaphore = pPresentInfo->pWaitSemaphores[i]; 980811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->semaphoreMap.find(semaphore) != dev_data->semaphoreMap.end()) { 980911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->semaphoreMap[semaphore].signaled) { 981011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->semaphoreMap[semaphore].signaled = false; 981111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 981211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 981311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 981411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 981511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Queue 0x%" PRIx64 " is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", 981611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(queue), reinterpret_cast<const uint64_t &>(semaphore)); 981711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 981811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 981911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 982011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDeviceMemory mem; 982111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { 982211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto swapchain_data = dev_data->device_extensions.swapchainMap.find(pPresentInfo->pSwapchains[i]); 982311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (swapchain_data != dev_data->device_extensions.swapchainMap.end() && 982411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pPresentInfo->pImageIndices[i] < swapchain_data->second->images.size()) { 982511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkImage image = swapchain_data->second->images[pPresentInfo->pImageIndices[i]]; 982611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if MTMERGESOURCE 982711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 982811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_mem_binding_from_object(dev_data, (uint64_t)(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &mem); 982911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= validate_memory_is_valid(dev_data, mem, "vkQueuePresentKHR()", image); 983011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 983111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert vector<VkImageLayout> layouts; 983211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (FindLayouts(dev_data, image, layouts)) { 983311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (auto layout : layouts) { 983411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { 983511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skip_call |= 983611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, 983711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<uint64_t &>(queue), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", 983811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "Images passed to present must be in layout " 983911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "PRESENT_SOURCE_KHR but is in %s", 984011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert string_VkImageLayout(layout)); 984111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 984211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 984311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 984411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 984511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 984611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 984711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 984811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skip_call) 984911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = dev_data->device_dispatch_table->QueuePresentKHR(queue, pPresentInfo); 985011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 985111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 985211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 985311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 985411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, 985511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) { 985611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); 985711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 985811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool skipCall = false; 985911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 986011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::unique_lock<std::mutex> lock(global_lock); 986111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (semaphore != VK_NULL_HANDLE && 986211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->semaphoreMap.find(semaphore) != dev_data->semaphoreMap.end()) { 986311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev_data->semaphoreMap[semaphore].signaled) { 986411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert skipCall = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 986511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 986611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "vkAcquireNextImageKHR: Semaphore must not be currently signaled or in a wait state"); 986711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 986811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->semaphoreMap[semaphore].signaled = true; 986911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 987011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto fence_data = dev_data->fenceMap.find(fence); 987111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fence_data != dev_data->fenceMap.end()) { 987211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fence_data->second.swapchain = swapchain; 987311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 987411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lock.unlock(); 987511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 987611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!skipCall) { 987711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = 987811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data->device_dispatch_table->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex); 987911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 988011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 988111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 988211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 988311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 988411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 988511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 988611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) { 988711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 988811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table; 988911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkResult res = pTable->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); 989011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (VK_SUCCESS == res) { 989111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 989211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert res = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback); 989311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 989411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return res; 989511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 989611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 989711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, 989811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDebugReportCallbackEXT msgCallback, 989911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator) { 990011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 990111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table; 990211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pTable->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); 990311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::lock_guard<std::mutex> lock(global_lock); 990411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator); 990511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 990611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 990711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 990811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object, 990911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { 991011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 991111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, 991211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pMsg); 991311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 991411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 991511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 991611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char *pLayerName, uint32_t *pCount, 991711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkExtensionProperties *pProperties) { 991811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) 991911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return util_GetExtensionProperties(0, NULL, pCount, pProperties); 992011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 992111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(physicalDevice); 992211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 992311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dispatch_key key = get_dispatch_key(physicalDevice); 992411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data = get_my_data_ptr(key, layer_data_map); 992511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties); 992611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 992711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 992811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction 992911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_core_instance_command(const char *name); 993011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 993111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction 993211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_core_device_command(const char *name); 993311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 993411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction 993511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_khr_swapchain_command(const char *name, VkDevice dev); 993611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 993711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice dev, const char *funcName) { 993811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PFN_vkVoidFunction proc = intercept_core_device_command(funcName); 993911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (proc) 994011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return proc; 994111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 994211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(dev); 994311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 994411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert proc = intercept_khr_swapchain_command(funcName, dev); 994511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (proc) 994611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return proc; 994711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 994811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data; 994911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert dev_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map); 995011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 995111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkLayerDispatchTable *pTable = dev_data->device_dispatch_table; 995211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 995311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pTable->GetDeviceProcAddr == NULL) 995411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return NULL; 995511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pTable->GetDeviceProcAddr(dev, funcName); 995611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 995711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 995811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 995911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) { 996011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PFN_vkVoidFunction proc = intercept_core_instance_command(funcName); 996111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!proc) 996211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert proc = intercept_core_device_command(funcName); 996311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!proc) 996411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE); 996511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (proc) 996611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return proc; 996711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 996811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(instance); 996911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 997011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *my_data; 997111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); 997211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName); 997311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (proc) 997411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return proc; 997511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 997611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table; 997711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pTable->GetInstanceProcAddr == NULL) 997811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return NULL; 997911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return pTable->GetInstanceProcAddr(instance, funcName); 998011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 998111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 998211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction 998311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_core_instance_command(const char *name) { 998411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static const struct { 998511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char *name; 998611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PFN_vkVoidFunction proc; 998711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } core_instance_commands[] = { 998811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) }, 998911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) }, 999011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) }, 999111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) }, 999211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) }, 999311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) }, 999411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 999511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 999611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // we should never be queried for these commands 999711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(strcmp(name, "vkEnumerateInstanceLayerProperties") && 999811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert strcmp(name, "vkEnumerateInstanceExtensionProperties") && 999911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert strcmp(name, "vkEnumerateDeviceLayerProperties")); 1000011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1000111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) { 1000211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!strcmp(core_instance_commands[i].name, name)) 1000311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return core_instance_commands[i].proc; 1000411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 1000511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1000611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return nullptr; 1000711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 1000811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1000911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction 1001011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_core_device_command(const char *name) { 1001111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static const struct { 1001211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char *name; 1001311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PFN_vkVoidFunction proc; 1001411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } core_device_commands[] = { 1001511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr)}, 1001611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkQueueSubmit", reinterpret_cast<PFN_vkVoidFunction>(QueueSubmit)}, 1001711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(WaitForFences)}, 1001811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(GetFenceStatus)}, 1001911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkQueueWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(QueueWaitIdle)}, 1002011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(DeviceWaitIdle)}, 1002111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue)}, 1002211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance)}, 1002311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice)}, 1002411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(DestroyFence)}, 1002511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(ResetFences)}, 1002611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(DestroySemaphore)}, 1002711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(DestroyEvent)}, 1002811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyQueryPool)}, 1002911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyBuffer)}, 1003011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(DestroyBufferView)}, 1003111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(DestroyImage)}, 1003211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyImageView", reinterpret_cast<PFN_vkVoidFunction>(DestroyImageView)}, 1003311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(DestroyShaderModule)}, 1003411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyPipeline", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipeline)}, 1003511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyPipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineLayout)}, 1003611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(DestroySampler)}, 1003711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorSetLayout)}, 1003811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorPool)}, 1003911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyFramebuffer)}, 1004011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(DestroyRenderPass)}, 1004111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateBuffer)}, 1004211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(CreateBufferView)}, 1004311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(CreateImage)}, 1004411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(CreateImageView)}, 1004511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(CreateFence)}, 1004611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreatePipelineCache", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineCache)}, 1004711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyPipelineCache", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineCache)}, 1004811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(GetPipelineCacheData)}, 1004911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(MergePipelineCaches)}, 1005011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateGraphicsPipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateGraphicsPipelines)}, 1005111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateComputePipelines)}, 1005211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(CreateSampler)}, 1005311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorSetLayout)}, 1005411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreatePipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineLayout)}, 1005511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorPool)}, 1005611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkResetDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(ResetDescriptorPool)}, 1005711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkAllocateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(AllocateDescriptorSets)}, 1005811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(FreeDescriptorSets)}, 1005911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets)}, 1006011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(CreateCommandPool)}, 1006111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyCommandPool)}, 1006211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandPool)}, 1006311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CreateQueryPool)}, 1006411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers)}, 1006511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(FreeCommandBuffers)}, 1006611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(BeginCommandBuffer)}, 1006711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkEndCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(EndCommandBuffer)}, 1006811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkResetCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandBuffer)}, 1006911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(CmdBindPipeline)}, 1007011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(CmdSetViewport)}, 1007111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissor)}, 1007211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(CmdSetLineWidth)}, 1007311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBias)}, 1007411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdSetBlendConstants)}, 1007511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBounds)}, 1007611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdSetStencilCompareMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilCompareMask)}, 1007711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdSetStencilWriteMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilWriteMask)}, 1007811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdSetStencilReference", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilReference)}, 1007911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDescriptorSets)}, 1008011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(CmdBindVertexBuffers)}, 1008111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdBindIndexBuffer)}, 1008211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(CmdDraw)}, 1008311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexed)}, 1008411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdDrawIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndirect)}, 1008511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdDrawIndexedIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexedIndirect)}, 1008611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatch)}, 1008711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatchIndirect)}, 1008811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdCopyBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBuffer)}, 1008911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImage)}, 1009011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(CmdBlitImage)}, 1009111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBufferToImage)}, 1009211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImageToBuffer)}, 1009311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdUpdateBuffer)}, 1009411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdFillBuffer)}, 1009511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearColorImage)}, 1009611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearDepthStencilImage)}, 1009711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdClearAttachments", reinterpret_cast<PFN_vkVoidFunction>(CmdClearAttachments)}, 1009811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(CmdResolveImage)}, 1009911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdSetEvent)}, 1010011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdResetEvent)}, 1010111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdWaitEvents", reinterpret_cast<PFN_vkVoidFunction>(CmdWaitEvents)}, 1010211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(CmdPipelineBarrier)}, 1010311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginQuery)}, 1010411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdEndQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdEndQuery)}, 1010511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CmdResetQueryPool)}, 1010611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyQueryPoolResults)}, 1010711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdPushConstants)}, 1010811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(CmdWriteTimestamp)}, 1010911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateFramebuffer)}, 1011011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(CreateShaderModule)}, 1011111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass)}, 1011211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginRenderPass)}, 1011311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdNextSubpass", reinterpret_cast<PFN_vkVoidFunction>(CmdNextSubpass)}, 1011411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdEndRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdEndRenderPass)}, 1011511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCmdExecuteCommands", reinterpret_cast<PFN_vkVoidFunction>(CmdExecuteCommands)}, 1011611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(SetEvent)}, 1011711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(MapMemory)}, 1011811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(UnmapMemory)}, 1011911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(FlushMappedMemoryRanges)}, 1012011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(InvalidateMappedMemoryRanges)}, 1012111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(AllocateMemory)}, 1012211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(FreeMemory)}, 1012311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(BindBufferMemory)}, 1012411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetBufferMemoryRequirements)}, 1012511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetImageMemoryRequirements)}, 1012611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(GetQueryPoolResults)}, 1012711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory)}, 1012811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkQueueBindSparse", reinterpret_cast<PFN_vkVoidFunction>(QueueBindSparse)}, 1012911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(CreateSemaphore)}, 1013011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert {"vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(CreateEvent)}, 1013111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 1013211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1013311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) { 1013411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!strcmp(core_device_commands[i].name, name)) 1013511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return core_device_commands[i].proc; 1013611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 1013711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1013811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return nullptr; 1013911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 1014011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1014111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction 1014211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_khr_swapchain_command(const char *name, VkDevice dev) { 1014311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static const struct { 1014411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char *name; 1014511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert PFN_vkVoidFunction proc; 1014611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } khr_swapchain_commands[] = { 1014711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR) }, 1014811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR) }, 1014911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { "vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR) }, 1015011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR) }, 1015111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { "vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR) }, 1015211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 1015311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1015411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (dev) { 1015511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert layer_data *dev_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map); 1015611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!dev_data->device_extensions.wsi_enabled) 1015711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return nullptr; 1015811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 1015911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1016011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) { 1016111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!strcmp(khr_swapchain_commands[i].name, name)) 1016211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return khr_swapchain_commands[i].proc; 1016311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 1016411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1016511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return nullptr; 1016611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 1016711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1016811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} // namespace core_validation 1016911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1017011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// vk_layer_logging.h expects these to be defined 1017111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1017211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL 1017311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 1017411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) { 1017511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return core_validation::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); 1017611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 1017711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1017811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 1017911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkDestroyDebugReportCallbackEXT(VkInstance instance, 1018011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkDebugReportCallbackEXT msgCallback, 1018111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const VkAllocationCallbacks *pAllocator) { 1018211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert core_validation::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); 1018311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 1018411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1018511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL 1018611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object, 1018711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { 1018811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert core_validation::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); 1018911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 1019011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1019111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// loader-layer interface v0 1019211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1019311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 1019411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { 1019511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return util_GetExtensionProperties(1, core_validation::instance_extensions, pCount, pProperties); 1019611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 1019711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1019811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 1019911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { 1020011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return util_GetLayerProperties(1, &core_validation::global_layer, pCount, pProperties); 1020111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 1020211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1020311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 1020411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { 1020511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return util_GetLayerProperties(1, &core_validation::global_layer, pCount, pProperties); 1020611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 1020711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1020811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 1020911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char *pLayerName, uint32_t *pCount, 1021011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert VkExtensionProperties *pProperties) { 1021111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // the layer command handles VK_NULL_HANDLE just fine 1021211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return core_validation::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties); 1021311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 1021411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1021511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) { 1021611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return core_validation::GetDeviceProcAddr(dev, funcName); 1021711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 1021811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1021911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { 1022011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties")) 1022111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceLayerProperties); 1022211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties")) 1022311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateDeviceLayerProperties); 1022411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties")) 1022511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceExtensionProperties); 1022611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!strcmp(funcName, "vkGetInstanceProcAddr")) 1022711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return reinterpret_cast<PFN_vkVoidFunction>(vkGetInstanceProcAddr); 1022811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1022911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return core_validation::GetInstanceProcAddr(instance, funcName); 1023011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 10231