blob: e569b5d1874b7981a797b12283e37647026a82de [file] [log] [blame]
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -07001/* Copyright (c) 2015-2016 The Khronos Group Inc.
2 * Copyright (c) 2015-2016 Valve Corporation
3 * Copyright (c) 2015-2016 LunarG, Inc.
4 * Copyright (C) 2015-2016 Google Inc.
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005 *
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -07006 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and/or associated documentation files (the "Materials"), to
8 * deal in the Materials without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Materials, and to permit persons to whom the Materials
11 * are furnished to do so, subject to the following conditions:
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060012 *
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -070013 * The above copyright notice(s) and this permission notice shall be included
14 * in all copies or substantial portions of the Materials.
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060015 *
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -070016 * The Materials are Confidential Information as defined by the Khronos
17 * Membership Agreement until designated non-confidential by Khronos, at which
18 * point this condition clause shall be removed.
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060019 *
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -070020 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060021 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -070022 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 *
24 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
25 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
26 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
27 * USE OR OTHER DEALINGS IN THE MATERIALS
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060028 *
Tobin Ehlis88452832015-12-03 09:40:56 -070029 * Author: Cody Northrop <cnorthrop@google.com>
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060030 * Author: Michael Lentine <mlentine@google.com>
Tobin Ehlis88452832015-12-03 09:40:56 -070031 * Author: Tobin Ehlis <tobine@google.com>
32 * Author: Chia-I Wu <olv@google.com>
Tobin Ehlis7e2ad752015-12-01 09:48:58 -070033 * Author: Chris Forbes <chrisf@ijw.co.nz>
Mark Lobodzinski78da8cb2015-12-28 15:51:07 -070034 * Author: Mark Lobodzinski <mark@lunarg.com>
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060035 */
36
Mark Lobodzinski78da8cb2015-12-28 15:51:07 -070037// Allow use of STL min and max functions in Windows
38#define NOMINMAX
39
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060040#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
Tobin Ehlis7e2ad752015-12-01 09:48:58 -070043#include <assert.h>
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060044#include <unordered_map>
Michael Lentineb6986752015-10-06 14:56:18 -070045#include <unordered_set>
Tobin Ehlis7e2ad752015-12-01 09:48:58 -070046#include <map>
47#include <string>
48#include <iostream>
49#include <algorithm>
Mark Lobodzinski39298632015-11-18 08:38:27 -070050#include <list>
Tobin Ehlis7e2ad752015-12-01 09:48:58 -070051#include <spirv.hpp>
Tobin Ehlis88452832015-12-03 09:40:56 -070052#include <set>
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060053
Tobin Ehlisb835d1b2015-07-03 10:34:49 -060054#include "vk_loader_platform.h"
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060055#include "vk_dispatch_table_helper.h"
56#include "vk_struct_string_helper_cpp.h"
Tony Barbour18f71552015-04-22 11:36:22 -060057#if defined(__GNUC__)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060058#pragma GCC diagnostic ignored "-Wwrite-strings"
Tony Barbour18f71552015-04-22 11:36:22 -060059#endif
Tony Barbour18f71552015-04-22 11:36:22 -060060#if defined(__GNUC__)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060061#pragma GCC diagnostic warning "-Wwrite-strings"
Tony Barbour18f71552015-04-22 11:36:22 -060062#endif
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060063#include "vk_struct_size_helper.h"
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060064#include "draw_state.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060065#include "vk_layer_config.h"
Michael Lentine97eb7462015-11-20 09:48:52 -080066#include "vulkan/vk_debug_marker_layer.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060067#include "vk_layer_table.h"
68#include "vk_layer_debug_marker_table.h"
69#include "vk_layer_data.h"
70#include "vk_layer_logging.h"
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -060071#include "vk_layer_extension_utils.h"
Tobin Ehlisa1c28562015-10-23 16:00:08 -060072#include "vk_layer_utils.h"
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060073
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -070074// This definition controls whether image layout transitions are
75// enabled/disabled.
Mark Lobodzinski31e5f282015-11-30 16:48:53 -070076// disable until corner cases are fixed
77#define DISABLE_IMAGE_LAYOUT_VALIDATION
78
Tobin Ehlis7e2ad752015-12-01 09:48:58 -070079using std::unordered_map;
80using std::unordered_set;
81
Tobin Ehlisac0ef842015-12-14 13:46:38 -070082// Track command pools and their command buffers
83struct CMD_POOL_INFO {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -070084 VkCommandPoolCreateFlags createFlags;
85 list<VkCommandBuffer> commandBuffers; // list container of cmd buffers
86 // allocated from this pool
Tobin Ehlisac0ef842015-12-14 13:46:38 -070087};
88
Tobin Ehlis0b632332015-10-07 09:38:40 -060089struct devExts {
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -070090 VkBool32 debug_marker_enabled;
Michael Lentineabc5e922015-10-12 11:30:14 -050091 VkBool32 wsi_enabled;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -070092 unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> swapchainMap;
Tobin Ehlis0b632332015-10-07 09:38:40 -060093};
94
Tobin Ehlis7e2ad752015-12-01 09:48:58 -070095// fwd decls
96struct shader_module;
97struct render_pass;
98
Cody Northrop55443ef2015-09-28 15:09:32 -060099struct layer_data {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700100 debug_report_data *report_data;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700101 std::vector<VkDebugReportCallbackEXT> logging_callback;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700102 VkLayerDispatchTable *device_dispatch_table;
103 VkLayerInstanceDispatchTable *instance_dispatch_table;
Tobin Ehlis0b632332015-10-07 09:38:40 -0600104 devExts device_extensions;
Tobin Ehlisae82e7f2016-01-20 16:23:37 -0700105 vector<VkQueue> queues; // all queues under given device
Tobin Ehlis74714d22016-01-25 15:24:34 -0800106 // Global set of all cmdBuffers that are inFlight on this device
107 unordered_set<VkCommandBuffer> globalInFlightCmdBuffers;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -0600108 // Layer specific data
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700109 unordered_map<VkSampler, unique_ptr<SAMPLER_NODE>> sampleMap;
110 unordered_map<VkImageView, unique_ptr<VkImageViewCreateInfo>> imageViewMap;
111 unordered_map<VkImage, unique_ptr<VkImageCreateInfo>> imageMap;
112 unordered_map<VkBufferView, unique_ptr<VkBufferViewCreateInfo>>
113 bufferViewMap;
114 unordered_map<VkBuffer, BUFFER_NODE> bufferMap;
115 unordered_map<VkPipeline, PIPELINE_NODE *> pipelineMap;
116 unordered_map<VkCommandPool, CMD_POOL_INFO> commandPoolMap;
117 unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_NODE *> descriptorPoolMap;
118 unordered_map<VkDescriptorSet, SET_NODE *> setMap;
119 unordered_map<VkDescriptorSetLayout, LAYOUT_NODE *> descriptorSetLayoutMap;
120 unordered_map<VkPipelineLayout, PIPELINE_LAYOUT_NODE> pipelineLayoutMap;
121 unordered_map<VkDeviceMemory, VkImage> memImageMap;
122 unordered_map<VkFence, FENCE_NODE> fenceMap;
123 unordered_map<VkQueue, QUEUE_NODE> queueMap;
124 unordered_map<VkEvent, EVENT_NODE> eventMap;
125 unordered_map<QueryObject, bool> queryToStateMap;
126 unordered_map<VkSemaphore, uint32_t> semaphoreSignaledMap;
127 unordered_map<void *, GLOBAL_CB_NODE *> commandBufferMap;
128 unordered_map<VkFramebuffer, VkFramebufferCreateInfo *> frameBufferMap;
129 unordered_map<VkImage, IMAGE_NODE *> imageLayoutMap;
130 unordered_map<VkRenderPass, RENDER_PASS_NODE *> renderPassMap;
131 unordered_map<VkShaderModule, shader_module *> shaderModuleMap;
Michael Lentineabc5e922015-10-12 11:30:14 -0500132 // Current render pass
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700133 VkRenderPassBeginInfo renderPassBeginInfo;
134 uint32_t currentSubpass;
135 unordered_map<VkDevice, VkPhysicalDeviceProperties> physDevPropertyMap;
Cody Northrop55443ef2015-09-28 15:09:32 -0600136
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700137 layer_data()
138 : report_data(nullptr), device_dispatch_table(nullptr),
139 instance_dispatch_table(nullptr), device_extensions(){};
Cody Northrop55443ef2015-09-28 15:09:32 -0600140};
Michael Lentine15a47882016-01-06 10:05:48 -0600141
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700142// Code imported from ShaderChecker
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700143static void build_def_index(shader_module *);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700144
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700145// A forward iterator over spirv instructions. Provides easy access to len,
146// opcode, and content words
147// without the caller needing to care too much about the physical SPIRV module
148// layout.
Chris Forbesc7e2e202016-01-18 08:56:40 +1300149struct spirv_inst_iter {
150 std::vector<uint32_t>::const_iterator zero;
151 std::vector<uint32_t>::const_iterator it;
152
153 uint32_t len() { return *it >> 16; }
154 uint32_t opcode() { return *it & 0x0ffffu; }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700155 uint32_t const &word(unsigned n) { return it[n]; }
Mark Youngd652d132016-01-25 13:37:06 -0700156 uint32_t offset() { return (uint32_t)(it - zero); }
Chris Forbesc7e2e202016-01-18 08:56:40 +1300157
158 spirv_inst_iter(std::vector<uint32_t>::const_iterator zero,
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700159 std::vector<uint32_t>::const_iterator it)
160 : zero(zero), it(it) {}
Chris Forbesc7e2e202016-01-18 08:56:40 +1300161
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700162 bool operator==(spirv_inst_iter const &other) { return it == other.it; }
Chris Forbesc7e2e202016-01-18 08:56:40 +1300163
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700164 bool operator!=(spirv_inst_iter const &other) { return it != other.it; }
Chris Forbesc7e2e202016-01-18 08:56:40 +1300165
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700166 spirv_inst_iter operator++(int) { /* x++ */
Chris Forbesc7e2e202016-01-18 08:56:40 +1300167 spirv_inst_iter ii = *this;
168 it += len();
169 return ii;
170 }
171
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700172 spirv_inst_iter operator++() { /* ++x; */
Chris Forbesc7e2e202016-01-18 08:56:40 +1300173 it += len();
174 return *this;
175 }
176
177 /* The iterator and the value are the same thing. */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700178 spirv_inst_iter &operator*() { return *this; }
179 spirv_inst_iter const &operator*() const { return *this; }
Chris Forbesc7e2e202016-01-18 08:56:40 +1300180};
181
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700182struct shader_module {
183 /* the spirv image itself */
184 vector<uint32_t> words;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700185 /* a mapping of <id> to the first word of its def. this is useful because
186 * walking type
187 * trees, constant expressions, etc requires jumping all over the
188 * instruction stream.
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700189 */
Chris Forbes21977d92016-01-26 13:41:39 +1300190 unordered_map<unsigned, unsigned> def_index;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700191
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700192 shader_module(VkShaderModuleCreateInfo const *pCreateInfo)
193 : words((uint32_t *)pCreateInfo->pCode,
194 (uint32_t *)pCreateInfo->pCode +
195 pCreateInfo->codeSize / sizeof(uint32_t)),
196 def_index() {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700197
Chris Forbes21977d92016-01-26 13:41:39 +1300198 build_def_index(this);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700199 }
Chris Forbesc7e2e202016-01-18 08:56:40 +1300200
201 /* expose begin() / end() to enable range-based for */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700202 spirv_inst_iter begin() const {
203 return spirv_inst_iter(words.begin(), words.begin() + 5);
204 } /* first insn */
205 spirv_inst_iter end() const {
206 return spirv_inst_iter(words.begin(), words.end());
207 } /* just past last insn */
Chris Forbesc7e2e202016-01-18 08:56:40 +1300208 /* given an offset into the module, produce an iterator there. */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700209 spirv_inst_iter at(unsigned offset) const {
210 return spirv_inst_iter(words.begin(), words.begin() + offset);
211 }
Chris Forbes1257f912016-01-18 12:07:01 +1300212
Chris Forbes21977d92016-01-26 13:41:39 +1300213 /* gets an iterator to the definition of an id */
214 spirv_inst_iter get_def(unsigned id) const {
215 auto it = def_index.find(id);
216 if (it == def_index.end()) {
Chris Forbes1257f912016-01-18 12:07:01 +1300217 return end();
218 }
219 return at(it->second);
220 }
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700221};
222
Tobin Ehlisb212dfc2015-10-07 15:40:22 -0600223// TODO : Do we need to guard access to layer_data_map w/ lock?
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700224static unordered_map<void *, layer_data *> layer_data_map;
Courtney Goeltzenleuchter3d0dfad2015-06-13 21:23:09 -0600225
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600226static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(g_initOnce);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700227// TODO : This can be much smarter, using separate locks for separate global
228// data
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600229static int globalLockInitialized = 0;
230static loader_platform_thread_mutex globalLock;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600231#define MAX_TID 513
232static loader_platform_thread_id g_tidMapping[MAX_TID] = {0};
233static uint32_t g_maxTID = 0;
Tobin Ehlisa16e8922015-06-16 15:50:44 -0600234
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700235template layer_data *
236get_my_data_ptr<layer_data>(void *data_key,
237 std::unordered_map<void *, layer_data *> &data_map);
Tobin Ehlisa16e8922015-06-16 15:50:44 -0600238
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600239// Map actual TID to an index value and return that index
240// This keeps TIDs in range from 0-MAX_TID and simplifies compares between runs
241static uint32_t getTIDIndex() {
242 loader_platform_thread_id tid = loader_platform_get_thread_id();
243 for (uint32_t i = 0; i < g_maxTID; i++) {
244 if (tid == g_tidMapping[i])
245 return i;
246 }
247 // Don't yet have mapping, set it and return newly set index
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700248 uint32_t retVal = (uint32_t)g_maxTID;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600249 g_tidMapping[g_maxTID++] = tid;
250 assert(g_maxTID < MAX_TID);
251 return retVal;
252}
Tobin Ehlis559c6382015-11-05 09:52:49 -0700253
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600254// Return a string representation of CMD_TYPE enum
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700255static string cmdTypeToString(CMD_TYPE cmd) {
256 switch (cmd) {
257 case CMD_BINDPIPELINE:
258 return "CMD_BINDPIPELINE";
259 case CMD_BINDPIPELINEDELTA:
260 return "CMD_BINDPIPELINEDELTA";
261 case CMD_SETVIEWPORTSTATE:
262 return "CMD_SETVIEWPORTSTATE";
263 case CMD_SETLINEWIDTHSTATE:
264 return "CMD_SETLINEWIDTHSTATE";
265 case CMD_SETDEPTHBIASSTATE:
266 return "CMD_SETDEPTHBIASSTATE";
267 case CMD_SETBLENDSTATE:
268 return "CMD_SETBLENDSTATE";
269 case CMD_SETDEPTHBOUNDSSTATE:
270 return "CMD_SETDEPTHBOUNDSSTATE";
271 case CMD_SETSTENCILREADMASKSTATE:
272 return "CMD_SETSTENCILREADMASKSTATE";
273 case CMD_SETSTENCILWRITEMASKSTATE:
274 return "CMD_SETSTENCILWRITEMASKSTATE";
275 case CMD_SETSTENCILREFERENCESTATE:
276 return "CMD_SETSTENCILREFERENCESTATE";
277 case CMD_BINDDESCRIPTORSETS:
278 return "CMD_BINDDESCRIPTORSETS";
279 case CMD_BINDINDEXBUFFER:
280 return "CMD_BINDINDEXBUFFER";
281 case CMD_BINDVERTEXBUFFER:
282 return "CMD_BINDVERTEXBUFFER";
283 case CMD_DRAW:
284 return "CMD_DRAW";
285 case CMD_DRAWINDEXED:
286 return "CMD_DRAWINDEXED";
287 case CMD_DRAWINDIRECT:
288 return "CMD_DRAWINDIRECT";
289 case CMD_DRAWINDEXEDINDIRECT:
290 return "CMD_DRAWINDEXEDINDIRECT";
291 case CMD_DISPATCH:
292 return "CMD_DISPATCH";
293 case CMD_DISPATCHINDIRECT:
294 return "CMD_DISPATCHINDIRECT";
295 case CMD_COPYBUFFER:
296 return "CMD_COPYBUFFER";
297 case CMD_COPYIMAGE:
298 return "CMD_COPYIMAGE";
299 case CMD_BLITIMAGE:
300 return "CMD_BLITIMAGE";
301 case CMD_COPYBUFFERTOIMAGE:
302 return "CMD_COPYBUFFERTOIMAGE";
303 case CMD_COPYIMAGETOBUFFER:
304 return "CMD_COPYIMAGETOBUFFER";
305 case CMD_CLONEIMAGEDATA:
306 return "CMD_CLONEIMAGEDATA";
307 case CMD_UPDATEBUFFER:
308 return "CMD_UPDATEBUFFER";
309 case CMD_FILLBUFFER:
310 return "CMD_FILLBUFFER";
311 case CMD_CLEARCOLORIMAGE:
312 return "CMD_CLEARCOLORIMAGE";
313 case CMD_CLEARATTACHMENTS:
314 return "CMD_CLEARCOLORATTACHMENT";
315 case CMD_CLEARDEPTHSTENCILIMAGE:
316 return "CMD_CLEARDEPTHSTENCILIMAGE";
317 case CMD_RESOLVEIMAGE:
318 return "CMD_RESOLVEIMAGE";
319 case CMD_SETEVENT:
320 return "CMD_SETEVENT";
321 case CMD_RESETEVENT:
322 return "CMD_RESETEVENT";
323 case CMD_WAITEVENTS:
324 return "CMD_WAITEVENTS";
325 case CMD_PIPELINEBARRIER:
326 return "CMD_PIPELINEBARRIER";
327 case CMD_BEGINQUERY:
328 return "CMD_BEGINQUERY";
329 case CMD_ENDQUERY:
330 return "CMD_ENDQUERY";
331 case CMD_RESETQUERYPOOL:
332 return "CMD_RESETQUERYPOOL";
333 case CMD_COPYQUERYPOOLRESULTS:
334 return "CMD_COPYQUERYPOOLRESULTS";
335 case CMD_WRITETIMESTAMP:
336 return "CMD_WRITETIMESTAMP";
337 case CMD_INITATOMICCOUNTERS:
338 return "CMD_INITATOMICCOUNTERS";
339 case CMD_LOADATOMICCOUNTERS:
340 return "CMD_LOADATOMICCOUNTERS";
341 case CMD_SAVEATOMICCOUNTERS:
342 return "CMD_SAVEATOMICCOUNTERS";
343 case CMD_BEGINRENDERPASS:
344 return "CMD_BEGINRENDERPASS";
345 case CMD_ENDRENDERPASS:
346 return "CMD_ENDRENDERPASS";
347 case CMD_DBGMARKERBEGIN:
348 return "CMD_DBGMARKERBEGIN";
349 case CMD_DBGMARKEREND:
350 return "CMD_DBGMARKEREND";
351 default:
352 return "UNKNOWN";
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600353 }
354}
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700355
356// SPIRV utility functions
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700357static void build_def_index(shader_module *module) {
Chris Forbesc7e2e202016-01-18 08:56:40 +1300358 for (auto insn : *module) {
359 switch (insn.opcode()) {
Chris Forbes92b9ab02016-01-26 13:49:27 +1300360 /* Types */
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700361 case spv::OpTypeVoid:
362 case spv::OpTypeBool:
363 case spv::OpTypeInt:
364 case spv::OpTypeFloat:
365 case spv::OpTypeVector:
366 case spv::OpTypeMatrix:
367 case spv::OpTypeImage:
368 case spv::OpTypeSampler:
369 case spv::OpTypeSampledImage:
370 case spv::OpTypeArray:
371 case spv::OpTypeRuntimeArray:
372 case spv::OpTypeStruct:
373 case spv::OpTypeOpaque:
374 case spv::OpTypePointer:
375 case spv::OpTypeFunction:
376 case spv::OpTypeEvent:
377 case spv::OpTypeDeviceEvent:
378 case spv::OpTypeReserveId:
379 case spv::OpTypeQueue:
380 case spv::OpTypePipe:
Chris Forbes21977d92016-01-26 13:41:39 +1300381 module->def_index[insn.word(1)] = insn.offset();
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700382 break;
383
Chris Forbes92b9ab02016-01-26 13:49:27 +1300384 /* Fixed constants */
385 case spv::OpConstantTrue:
386 case spv::OpConstantFalse:
387 case spv::OpConstant:
388 case spv::OpConstantComposite:
389 case spv::OpConstantSampler:
390 case spv::OpConstantNull:
391 module->def_index[insn.word(2)] = insn.offset();
392 break;
393
394 /* Specialization constants */
395 case spv::OpSpecConstantTrue:
396 case spv::OpSpecConstantFalse:
397 case spv::OpSpecConstant:
398 case spv::OpSpecConstantComposite:
399 case spv::OpSpecConstantOp:
400 module->def_index[insn.word(2)] = insn.offset();
401 break;
402
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700403 default:
Chris Forbes92b9ab02016-01-26 13:49:27 +1300404 /* We don't care about any other defs for now. */
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700405 break;
406 }
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700407 }
408}
409
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700410bool shader_is_spirv(VkShaderModuleCreateInfo const *pCreateInfo) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700411 uint32_t *words = (uint32_t *)pCreateInfo->pCode;
412 size_t sizeInWords = pCreateInfo->codeSize / sizeof(uint32_t);
413
414 /* Just validate that the header makes sense. */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700415 return sizeInWords >= 5 && words[0] == spv::MagicNumber &&
416 words[1] == spv::Version;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700417}
418
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700419static char const *storage_class_name(unsigned sc) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700420 switch (sc) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700421 case spv::StorageClassInput:
422 return "input";
423 case spv::StorageClassOutput:
424 return "output";
425 case spv::StorageClassUniformConstant:
426 return "const uniform";
427 case spv::StorageClassUniform:
428 return "uniform";
429 case spv::StorageClassWorkgroup:
430 return "workgroup local";
431 case spv::StorageClassCrossWorkgroup:
432 return "workgroup global";
433 case spv::StorageClassPrivate:
434 return "private global";
435 case spv::StorageClassFunction:
436 return "function";
437 case spv::StorageClassGeneric:
438 return "generic";
439 case spv::StorageClassAtomicCounter:
440 return "atomic counter";
441 case spv::StorageClassImage:
442 return "image";
443 default:
444 return "unknown";
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700445 }
446}
447
Chris Forbes204207a2016-01-26 14:07:16 +1300448/* get the value of an integral constant */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700449unsigned get_constant_value(shader_module const *src, unsigned id) {
Chris Forbes204207a2016-01-26 14:07:16 +1300450 auto value = src->get_def(id);
451 assert(value != src->end());
452
453 if (value.opcode() != spv::OpConstant) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700454 /* TODO: Either ensure that the specialization transform is already
455 performed on a module we're
Chris Forbes204207a2016-01-26 14:07:16 +1300456 considering here, OR -- specialize on the fly now.
457 */
458 return 1;
459 }
460
461 return value.word(3);
462}
463
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700464/* returns ptr to null terminator */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700465static char *describe_type(char *dst, shader_module const *src, unsigned type) {
Chris Forbes21977d92016-01-26 13:41:39 +1300466 auto insn = src->get_def(type);
Chris Forbes1257f912016-01-18 12:07:01 +1300467 assert(insn != src->end());
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700468
Chris Forbes1257f912016-01-18 12:07:01 +1300469 switch (insn.opcode()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700470 case spv::OpTypeBool:
471 return dst + sprintf(dst, "bool");
472 case spv::OpTypeInt:
473 return dst +
474 sprintf(dst, "%cint%d", insn.word(3) ? 's' : 'u', insn.word(2));
475 case spv::OpTypeFloat:
476 return dst + sprintf(dst, "float%d", insn.word(2));
477 case spv::OpTypeVector:
478 dst += sprintf(dst, "vec%d of ", insn.word(3));
479 return describe_type(dst, src, insn.word(2));
480 case spv::OpTypeMatrix:
481 dst += sprintf(dst, "mat%d of ", insn.word(3));
482 return describe_type(dst, src, insn.word(2));
483 case spv::OpTypeArray:
484 dst +=
485 sprintf(dst, "arr[%d] of ", get_constant_value(src, insn.word(3)));
486 return describe_type(dst, src, insn.word(2));
487 case spv::OpTypePointer:
488 dst += sprintf(dst, "ptr to %s ", storage_class_name(insn.word(2)));
489 return describe_type(dst, src, insn.word(3));
490 case spv::OpTypeStruct: {
491 dst += sprintf(dst, "struct of (");
492 for (unsigned i = 2; i < insn.len(); i++) {
493 dst = describe_type(dst, src, insn.word(i));
494 dst += sprintf(dst, i == insn.len() - 1 ? ")" : ", ");
495 }
496 return dst;
497 }
498 case spv::OpTypeSampler:
499 return dst + sprintf(dst, "sampler");
500 default:
501 return dst + sprintf(dst, "oddtype");
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700502 }
503}
504
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700505static bool types_match(shader_module const *a, shader_module const *b,
506 unsigned a_type, unsigned b_type, bool b_arrayed) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700507 /* walk two type trees together, and complain about differences */
Chris Forbes21977d92016-01-26 13:41:39 +1300508 auto a_insn = a->get_def(a_type);
509 auto b_insn = b->get_def(b_type);
Chris Forbes1257f912016-01-18 12:07:01 +1300510 assert(a_insn != a->end());
511 assert(b_insn != b->end());
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700512
Chris Forbes1257f912016-01-18 12:07:01 +1300513 if (b_arrayed && b_insn.opcode() == spv::OpTypeArray) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700514 /* we probably just found the extra level of arrayness in b_type:
515 * compare the type inside it to a_type */
Chris Forbes1257f912016-01-18 12:07:01 +1300516 return types_match(a, b, a_type, b_insn.word(2), false);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700517 }
518
Chris Forbes1257f912016-01-18 12:07:01 +1300519 if (a_insn.opcode() != b_insn.opcode()) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700520 return false;
521 }
522
Chris Forbes1257f912016-01-18 12:07:01 +1300523 switch (a_insn.opcode()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700524 /* if b_arrayed and we hit a leaf type, then we can't match -- there's
525 * nowhere for the extra OpTypeArray to be! */
526 case spv::OpTypeBool:
527 return true && !b_arrayed;
528 case spv::OpTypeInt:
529 /* match on width, signedness */
530 return a_insn.word(2) == b_insn.word(2) &&
531 a_insn.word(3) == b_insn.word(3) && !b_arrayed;
532 case spv::OpTypeFloat:
533 /* match on width */
534 return a_insn.word(2) == b_insn.word(2) && !b_arrayed;
535 case spv::OpTypeVector:
536 case spv::OpTypeMatrix:
537 /* match on element type, count. these all have the same layout. we
538 * don't get here if
539 * b_arrayed -- that is handled above. */
540 return !b_arrayed &&
541 types_match(a, b, a_insn.word(2), b_insn.word(2), b_arrayed) &&
542 a_insn.word(3) == b_insn.word(3);
543 case spv::OpTypeArray:
544 /* match on element type, count. these all have the same layout. we
545 * don't get here if
546 * b_arrayed. This differs from vector & matrix types in that the array
547 * size is the id of a constant instruction,
548 * not a literal within OpTypeArray */
549 return !b_arrayed &&
550 types_match(a, b, a_insn.word(2), b_insn.word(2), b_arrayed) &&
551 get_constant_value(a, a_insn.word(3)) ==
552 get_constant_value(b, b_insn.word(3));
553 case spv::OpTypeStruct:
554 /* match on all element types */
555 {
556 if (b_arrayed) {
557 /* for the purposes of matching different levels of arrayness,
558 * structs are leaves. */
559 return false;
560 }
561
562 if (a_insn.len() != b_insn.len()) {
563 return false; /* structs cannot match if member counts differ */
564 }
565
566 for (unsigned i = 2; i < a_insn.len(); i++) {
567 if (!types_match(a, b, a_insn.word(i), b_insn.word(i),
568 b_arrayed)) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700569 return false;
570 }
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700571 }
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700572
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700573 return true;
574 }
575 case spv::OpTypePointer:
576 /* match on pointee type. storage class is expected to differ */
577 return types_match(a, b, a_insn.word(3), b_insn.word(3), b_arrayed);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700578
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700579 default:
580 /* remaining types are CLisms, or may not appear in the interfaces we
581 * are interested in. Just claim no match.
582 */
583 return false;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700584 }
585}
586
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700587static int value_or_default(std::unordered_map<unsigned, unsigned> const &map,
588 unsigned id, int def) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700589 auto it = map.find(id);
590 if (it == map.end())
591 return def;
592 else
593 return it->second;
594}
595
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700596static unsigned get_locations_consumed_by_type(shader_module const *src,
597 unsigned type,
598 bool strip_array_level) {
Chris Forbes21977d92016-01-26 13:41:39 +1300599 auto insn = src->get_def(type);
Chris Forbes1257f912016-01-18 12:07:01 +1300600 assert(insn != src->end());
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700601
Chris Forbesc7e2e202016-01-18 08:56:40 +1300602 switch (insn.opcode()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700603 case spv::OpTypePointer:
604 /* see through the ptr -- this is only ever at the toplevel for graphics
605 * shaders;
606 * we're never actually passing pointers around. */
607 return get_locations_consumed_by_type(src, insn.word(3),
608 strip_array_level);
609 case spv::OpTypeArray:
610 if (strip_array_level) {
611 return get_locations_consumed_by_type(src, insn.word(2), false);
612 } else {
613 return get_constant_value(src, insn.word(3)) *
614 get_locations_consumed_by_type(src, insn.word(2), false);
615 }
616 case spv::OpTypeMatrix:
617 /* num locations is the dimension * element size */
618 return insn.word(3) *
619 get_locations_consumed_by_type(src, insn.word(2), false);
620 default:
621 /* everything else is just 1. */
622 return 1;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700623
624 /* TODO: extend to handle 64bit scalar types, whose vectors may need
625 * multiple locations. */
626 }
627}
628
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700629struct interface_var {
630 uint32_t id;
631 uint32_t type_id;
632 uint32_t offset;
633 /* TODO: collect the name, too? Isn't required to be present. */
634};
635
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700636static void collect_interface_block_members(
637 layer_data *my_data, VkDevice dev, shader_module const *src,
638 std::map<uint32_t, interface_var> &out,
639 std::map<uint32_t, interface_var> &builtins_out,
640 std::unordered_map<unsigned, unsigned> const &blocks,
641 bool is_array_of_verts, uint32_t id, uint32_t type_id) {
642 /* Walk down the type_id presented, trying to determine whether it's
643 * actually an interface block. */
Chris Forbes21977d92016-01-26 13:41:39 +1300644 auto type = src->get_def(type_id);
Chris Forbes1257f912016-01-18 12:07:01 +1300645
Chris Forbesa3e85f62016-01-15 14:53:11 +1300646 while (true) {
647
Chris Forbes1257f912016-01-18 12:07:01 +1300648 if (type.opcode() == spv::OpTypePointer) {
Chris Forbes21977d92016-01-26 13:41:39 +1300649 type = src->get_def(type.word(3));
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700650 } else if (type.opcode() == spv::OpTypeArray && is_array_of_verts) {
Chris Forbes21977d92016-01-26 13:41:39 +1300651 type = src->get_def(type.word(2));
Chris Forbesa3e85f62016-01-15 14:53:11 +1300652 is_array_of_verts = false;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700653 } else if (type.opcode() == spv::OpTypeStruct) {
Chris Forbes1257f912016-01-18 12:07:01 +1300654 if (blocks.find(type.word(1)) == blocks.end()) {
Chris Forbesa3e85f62016-01-15 14:53:11 +1300655 /* This isn't an interface block. */
656 return;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700657 } else {
Chris Forbesa3e85f62016-01-15 14:53:11 +1300658 /* We have found the correct type. Walk its members. */
659 break;
660 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700661 } else {
Chris Forbesa3e85f62016-01-15 14:53:11 +1300662 /* not an interface block */
663 return;
664 }
665 }
666
Chris Forbes1257f912016-01-18 12:07:01 +1300667 /* Walk all the OpMemberDecorate for type's result id. */
Chris Forbesc7e2e202016-01-18 08:56:40 +1300668 for (auto insn : *src) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700669 if (insn.opcode() == spv::OpMemberDecorate &&
670 insn.word(1) == type.word(1)) {
Chris Forbesc7e2e202016-01-18 08:56:40 +1300671 unsigned member_index = insn.word(2);
Chris Forbes1257f912016-01-18 12:07:01 +1300672 unsigned member_type_id = type.word(2 + member_index);
Chris Forbesa3e85f62016-01-15 14:53:11 +1300673
Chris Forbesc7e2e202016-01-18 08:56:40 +1300674 if (insn.word(3) == spv::DecorationLocation) {
675 unsigned location = insn.word(4);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700676 unsigned num_locations =
677 get_locations_consumed_by_type(src, member_type_id, false);
678 for (unsigned int offset = 0; offset < num_locations;
679 offset++) {
Chris Forbesa3e85f62016-01-15 14:53:11 +1300680 interface_var v;
681 v.id = id;
682 /* TODO: member index in interface_var too? */
683 v.type_id = member_type_id;
684 v.offset = offset;
685 out[location + offset] = v;
686 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700687 } else if (insn.word(3) == spv::DecorationBuiltIn) {
Chris Forbesc7e2e202016-01-18 08:56:40 +1300688 unsigned builtin = insn.word(4);
Chris Forbesa3e85f62016-01-15 14:53:11 +1300689 interface_var v;
690 v.id = id;
691 v.type_id = member_type_id;
692 v.offset = 0;
693 builtins_out[builtin] = v;
694 }
695 }
Chris Forbesa3e85f62016-01-15 14:53:11 +1300696 }
697}
698
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700699static void collect_interface_by_location(
700 layer_data *my_data, VkDevice dev, shader_module const *src,
701 spv::StorageClass sinterface, std::map<uint32_t, interface_var> &out,
702 std::map<uint32_t, interface_var> &builtins_out, bool is_array_of_verts) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700703 std::unordered_map<unsigned, unsigned> var_locations;
704 std::unordered_map<unsigned, unsigned> var_builtins;
Chris Forbesa3e85f62016-01-15 14:53:11 +1300705 std::unordered_map<unsigned, unsigned> blocks;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700706
Chris Forbesc7e2e202016-01-18 08:56:40 +1300707 for (auto insn : *src) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700708
709 /* We consider two interface models: SSO rendezvous-by-location, and
710 * builtins. Complain about anything that fits neither model.
711 */
Chris Forbesc7e2e202016-01-18 08:56:40 +1300712 if (insn.opcode() == spv::OpDecorate) {
713 if (insn.word(2) == spv::DecorationLocation) {
714 var_locations[insn.word(1)] = insn.word(3);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700715 }
716
Chris Forbesc7e2e202016-01-18 08:56:40 +1300717 if (insn.word(2) == spv::DecorationBuiltIn) {
718 var_builtins[insn.word(1)] = insn.word(3);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700719 }
Chris Forbesa3e85f62016-01-15 14:53:11 +1300720
Chris Forbesc7e2e202016-01-18 08:56:40 +1300721 if (insn.word(2) == spv::DecorationBlock) {
722 blocks[insn.word(1)] = 1;
Chris Forbesa3e85f62016-01-15 14:53:11 +1300723 }
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700724 }
725
726 /* TODO: handle grouped decorations */
727 /* TODO: handle index=1 dual source outputs from FS -- two vars will
728 * have the same location, and we DONT want to clobber. */
729
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700730 else if (insn.opcode() == spv::OpVariable &&
731 insn.word(3) == sinterface) {
Chris Forbesc7e2e202016-01-18 08:56:40 +1300732 unsigned id = insn.word(2);
733 unsigned type = insn.word(1);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700734
Chris Forbesc7e2e202016-01-18 08:56:40 +1300735 int location = value_or_default(var_locations, id, -1);
736 int builtin = value_or_default(var_builtins, id, -1);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700737
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700738 /* All variables and interface block members in the Input or Output
739 *storage classes
Chris Forbesf5020cf2016-01-13 09:29:31 +1300740 * must be decorated with either a builtin or an explicit location.
741 *
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700742 * TODO: integrate the interface block support here. For now, don't
743 *complain --
744 * a valid SPIRV module will only hit this path for the interface
745 *block case, as the
746 * individual members of the type are decorated, rather than
747 *variable declarations.
Chris Forbesf5020cf2016-01-13 09:29:31 +1300748 */
749
750 if (location != -1) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700751 /* A user-defined interface variable, with a location. Where a
752 * variable
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700753 * occupied multiple locations, emit one result for each. */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700754 unsigned num_locations = get_locations_consumed_by_type(
755 src, type, is_array_of_verts);
756 for (unsigned int offset = 0; offset < num_locations;
757 offset++) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700758 interface_var v;
759 v.id = id;
760 v.type_id = type;
761 v.offset = offset;
762 out[location + offset] = v;
763 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700764 } else if (builtin != -1) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700765 /* A builtin interface variable */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700766 /* Note that since builtin interface variables do not consume
767 * numbered
768 * locations, there is no larger-than-vec4 consideration as
769 * above
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700770 */
771 interface_var v;
772 v.id = id;
773 v.type_id = type;
774 v.offset = 0;
775 builtins_out[builtin] = v;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700776 } else {
Chris Forbesa3e85f62016-01-15 14:53:11 +1300777 /* An interface block instance */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700778 collect_interface_block_members(my_data, dev, src, out,
779 builtins_out, blocks,
780 is_array_of_verts, id, type);
Chris Forbesa3e85f62016-01-15 14:53:11 +1300781 }
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700782 }
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700783 }
784}
785
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700786static void collect_interface_by_descriptor_slot(
787 layer_data *my_data, VkDevice dev, shader_module const *src,
788 spv::StorageClass sinterface,
789 std::map<std::pair<unsigned, unsigned>, interface_var> &out) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700790
791 std::unordered_map<unsigned, unsigned> var_sets;
792 std::unordered_map<unsigned, unsigned> var_bindings;
793
Chris Forbesc7e2e202016-01-18 08:56:40 +1300794 for (auto insn : *src) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700795 /* All variables in the Uniform or UniformConstant storage classes are
796 * required to be decorated with both
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700797 * DecorationDescriptorSet and DecorationBinding.
798 */
Chris Forbesc7e2e202016-01-18 08:56:40 +1300799 if (insn.opcode() == spv::OpDecorate) {
800 if (insn.word(2) == spv::DecorationDescriptorSet) {
801 var_sets[insn.word(1)] = insn.word(3);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700802 }
803
Chris Forbesc7e2e202016-01-18 08:56:40 +1300804 if (insn.word(2) == spv::DecorationBinding) {
805 var_bindings[insn.word(1)] = insn.word(3);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700806 }
807 }
808
Chris Forbesc7e2e202016-01-18 08:56:40 +1300809 else if (insn.opcode() == spv::OpVariable &&
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700810 (insn.word(3) == spv::StorageClassUniform ||
811 insn.word(3) == spv::StorageClassUniformConstant)) {
Chris Forbesc7e2e202016-01-18 08:56:40 +1300812 unsigned set = value_or_default(var_sets, insn.word(2), 0);
813 unsigned binding = value_or_default(var_bindings, insn.word(2), 0);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700814
815 auto existing_it = out.find(std::make_pair(set, binding));
816 if (existing_it != out.end()) {
817 /* conflict within spv image */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700818 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
819 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0,
820 __LINE__, SHADER_CHECKER_INCONSISTENT_SPIRV, "SC",
821 "var %d (type %d) in %s interface in descriptor slot "
822 "(%u,%u) conflicts with existing definition",
823 insn.word(2), insn.word(1),
824 storage_class_name(sinterface),
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700825 existing_it->first.first, existing_it->first.second);
826 }
827
828 interface_var v;
Chris Forbesc7e2e202016-01-18 08:56:40 +1300829 v.id = insn.word(2);
830 v.type_id = insn.word(1);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700831 out[std::make_pair(set, binding)] = v;
832 }
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700833 }
834}
835
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700836static bool validate_interface_between_stages(layer_data *my_data, VkDevice dev,
837 shader_module const *producer,
838 char const *producer_name,
839 shader_module const *consumer,
840 char const *consumer_name,
841 bool consumer_arrayed_input) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700842 std::map<uint32_t, interface_var> outputs;
843 std::map<uint32_t, interface_var> inputs;
844
845 std::map<uint32_t, interface_var> builtin_outputs;
846 std::map<uint32_t, interface_var> builtin_inputs;
847
848 bool pass = true;
849
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700850 collect_interface_by_location(my_data, dev, producer,
851 spv::StorageClassOutput, outputs,
852 builtin_outputs, false);
853 collect_interface_by_location(my_data, dev, consumer,
854 spv::StorageClassInput, inputs,
855 builtin_inputs, consumer_arrayed_input);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700856
857 auto a_it = outputs.begin();
858 auto b_it = inputs.begin();
859
860 /* maps sorted by key (location); walk them together to find mismatches */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700861 while ((outputs.size() > 0 && a_it != outputs.end()) ||
862 (inputs.size() && b_it != inputs.end())) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700863 bool a_at_end = outputs.size() == 0 || a_it == outputs.end();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700864 bool b_at_end = inputs.size() == 0 || b_it == inputs.end();
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700865 auto a_first = a_at_end ? 0 : a_it->first;
866 auto b_first = b_at_end ? 0 : b_it->first;
867
868 if (b_at_end || ((!a_at_end) && (a_first < b_first))) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700869 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_PERF_WARN_BIT_EXT,
870 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0,
871 __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC",
872 "%s writes to output location %d which is not consumed "
873 "by %s",
874 producer_name, a_first, consumer_name)) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700875 pass = false;
876 }
877 a_it++;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700878 } else if (a_at_end || a_first > b_first) {
879 if (log_msg(
880 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
881 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0, __LINE__,
882 SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC",
883 "%s consumes input location %d which is not written by %s",
884 consumer_name, b_first, producer_name)) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700885 pass = false;
886 }
887 b_it++;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700888 } else {
889 if (types_match(producer, consumer, a_it->second.type_id,
890 b_it->second.type_id, consumer_arrayed_input)) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700891 /* OK! */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700892 } else {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700893 char producer_type[1024];
894 char consumer_type[1024];
895 describe_type(producer_type, producer, a_it->second.type_id);
896 describe_type(consumer_type, consumer, b_it->second.type_id);
897
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700898 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
899 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0,
900 __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH,
901 "SC", "Type mismatch on location %d: '%s' vs '%s'",
902 a_it->first, producer_type, consumer_type)) {
903 pass = false;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700904 }
905 }
906 a_it++;
907 b_it++;
908 }
909 }
910
911 return pass;
912}
913
914enum FORMAT_TYPE {
915 FORMAT_TYPE_UNDEFINED,
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700916 FORMAT_TYPE_FLOAT, /* UNORM, SNORM, FLOAT, USCALED, SSCALED, SRGB --
917 anything we consider float in the shader */
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700918 FORMAT_TYPE_SINT,
919 FORMAT_TYPE_UINT,
920};
921
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700922static unsigned get_format_type(VkFormat fmt) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700923 switch (fmt) {
924 case VK_FORMAT_UNDEFINED:
925 return FORMAT_TYPE_UNDEFINED;
926 case VK_FORMAT_R8_SINT:
927 case VK_FORMAT_R8G8_SINT:
928 case VK_FORMAT_R8G8B8_SINT:
929 case VK_FORMAT_R8G8B8A8_SINT:
930 case VK_FORMAT_R16_SINT:
931 case VK_FORMAT_R16G16_SINT:
932 case VK_FORMAT_R16G16B16_SINT:
933 case VK_FORMAT_R16G16B16A16_SINT:
934 case VK_FORMAT_R32_SINT:
935 case VK_FORMAT_R32G32_SINT:
936 case VK_FORMAT_R32G32B32_SINT:
937 case VK_FORMAT_R32G32B32A32_SINT:
938 case VK_FORMAT_B8G8R8_SINT:
939 case VK_FORMAT_B8G8R8A8_SINT:
940 case VK_FORMAT_A2B10G10R10_SINT_PACK32:
941 case VK_FORMAT_A2R10G10B10_SINT_PACK32:
942 return FORMAT_TYPE_SINT;
943 case VK_FORMAT_R8_UINT:
944 case VK_FORMAT_R8G8_UINT:
945 case VK_FORMAT_R8G8B8_UINT:
946 case VK_FORMAT_R8G8B8A8_UINT:
947 case VK_FORMAT_R16_UINT:
948 case VK_FORMAT_R16G16_UINT:
949 case VK_FORMAT_R16G16B16_UINT:
950 case VK_FORMAT_R16G16B16A16_UINT:
951 case VK_FORMAT_R32_UINT:
952 case VK_FORMAT_R32G32_UINT:
953 case VK_FORMAT_R32G32B32_UINT:
954 case VK_FORMAT_R32G32B32A32_UINT:
955 case VK_FORMAT_B8G8R8_UINT:
956 case VK_FORMAT_B8G8R8A8_UINT:
957 case VK_FORMAT_A2B10G10R10_UINT_PACK32:
958 case VK_FORMAT_A2R10G10B10_UINT_PACK32:
959 return FORMAT_TYPE_UINT;
960 default:
961 return FORMAT_TYPE_FLOAT;
962 }
963}
964
965/* characterizes a SPIR-V type appearing in an interface to a FF stage,
966 * for comparison to a VkFormat's characterization above. */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700967static unsigned get_fundamental_type(shader_module const *src, unsigned type) {
Chris Forbes21977d92016-01-26 13:41:39 +1300968 auto insn = src->get_def(type);
Chris Forbes1257f912016-01-18 12:07:01 +1300969 assert(insn != src->end());
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700970
Chris Forbes1257f912016-01-18 12:07:01 +1300971 switch (insn.opcode()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700972 case spv::OpTypeInt:
973 return insn.word(3) ? FORMAT_TYPE_SINT : FORMAT_TYPE_UINT;
974 case spv::OpTypeFloat:
975 return FORMAT_TYPE_FLOAT;
976 case spv::OpTypeVector:
977 return get_fundamental_type(src, insn.word(2));
978 case spv::OpTypeMatrix:
979 return get_fundamental_type(src, insn.word(2));
980 case spv::OpTypeArray:
981 return get_fundamental_type(src, insn.word(2));
982 case spv::OpTypePointer:
983 return get_fundamental_type(src, insn.word(3));
984 default:
985 return FORMAT_TYPE_UNDEFINED;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700986 }
987}
988
989static bool
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700990validate_vi_consistency(layer_data *my_data, VkDevice dev,
991 VkPipelineVertexInputStateCreateInfo const *vi) {
992 /* walk the binding descriptions, which describe the step rate and stride of
993 * each vertex buffer.
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700994 * each binding should be specified only once.
995 */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700996 std::unordered_map<uint32_t, VkVertexInputBindingDescription const *>
997 bindings;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700998 bool pass = true;
999
1000 for (unsigned i = 0; i < vi->vertexBindingDescriptionCount; i++) {
1001 auto desc = &vi->pVertexBindingDescriptions[i];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001002 auto &binding = bindings[desc->binding];
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001003 if (binding) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001004 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1005 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0,
1006 __LINE__, SHADER_CHECKER_INCONSISTENT_VI, "SC",
1007 "Duplicate vertex input binding descriptions for "
1008 "binding %d",
1009 desc->binding)) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001010 pass = false;
1011 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001012 } else {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001013 binding = desc;
1014 }
1015 }
1016
1017 return pass;
1018}
1019
1020static bool
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001021validate_vi_against_vs_inputs(layer_data *my_data, VkDevice dev,
1022 VkPipelineVertexInputStateCreateInfo const *vi,
1023 shader_module const *vs) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001024 std::map<uint32_t, interface_var> inputs;
1025 /* we collect builtin inputs, but they will never appear in the VI state --
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001026 * the vs builtin inputs are generated in the pipeline, not sourced from
1027 * buffers (VertexID, etc)
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001028 */
1029 std::map<uint32_t, interface_var> builtin_inputs;
1030 bool pass = true;
1031
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001032 collect_interface_by_location(my_data, dev, vs, spv::StorageClassInput,
1033 inputs, builtin_inputs, false);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001034
1035 /* Build index by location */
1036 std::map<uint32_t, VkVertexInputAttributeDescription const *> attribs;
1037 if (vi) {
1038 for (unsigned i = 0; i < vi->vertexAttributeDescriptionCount; i++)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001039 attribs[vi->pVertexAttributeDescriptions[i].location] =
1040 &vi->pVertexAttributeDescriptions[i];
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001041 }
1042
1043 auto it_a = attribs.begin();
1044 auto it_b = inputs.begin();
1045
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001046 while ((attribs.size() > 0 && it_a != attribs.end()) ||
1047 (inputs.size() > 0 && it_b != inputs.end())) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001048 bool a_at_end = attribs.size() == 0 || it_a == attribs.end();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001049 bool b_at_end = inputs.size() == 0 || it_b == inputs.end();
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001050 auto a_first = a_at_end ? 0 : it_a->first;
1051 auto b_first = b_at_end ? 0 : it_b->first;
Chris Forbes7d83cd52016-01-15 11:32:03 +13001052 if (!a_at_end && (b_at_end || a_first < b_first)) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001053 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_PERF_WARN_BIT_EXT,
1054 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0,
1055 __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC",
1056 "Vertex attribute at location %d not consumed by VS",
1057 a_first)) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001058 pass = false;
1059 }
1060 it_a++;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001061 } else if (!b_at_end && (a_at_end || b_first < a_first)) {
1062 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1063 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0,
1064 __LINE__, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC",
1065 "VS consumes input at location %d but not provided",
1066 b_first)) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001067 pass = false;
1068 }
1069 it_b++;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001070 } else {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001071 unsigned attrib_type = get_format_type(it_a->second->format);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001072 unsigned input_type =
1073 get_fundamental_type(vs, it_b->second.type_id);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001074
1075 /* type checking */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001076 if (attrib_type != FORMAT_TYPE_UNDEFINED &&
1077 input_type != FORMAT_TYPE_UNDEFINED &&
1078 attrib_type != input_type) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001079 char vs_type[1024];
1080 describe_type(vs_type, vs, it_b->second.type_id);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001081 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1082 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0,
1083 __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH,
1084 "SC", "Attribute type of `%s` at location %d does "
1085 "not match VS input type of `%s`",
1086 string_VkFormat(it_a->second->format), a_first,
1087 vs_type)) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001088 pass = false;
1089 }
1090 }
1091
1092 /* OK! */
1093 it_a++;
1094 it_b++;
1095 }
1096 }
1097
1098 return pass;
1099}
1100
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001101static bool validate_fs_outputs_against_render_pass(layer_data *my_data,
1102 VkDevice dev,
1103 shader_module const *fs,
1104 RENDER_PASS_NODE const *rp,
1105 uint32_t subpass) {
1106 const std::vector<VkFormat> &color_formats =
1107 rp->subpassColorFormats[subpass];
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001108 std::map<uint32_t, interface_var> outputs;
1109 std::map<uint32_t, interface_var> builtin_outputs;
1110 bool pass = true;
1111
1112 /* TODO: dual source blend index (spv::DecIndex, zero if not provided) */
1113
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001114 collect_interface_by_location(my_data, dev, fs, spv::StorageClassOutput,
1115 outputs, builtin_outputs, false);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001116
1117 auto it = outputs.begin();
1118 uint32_t attachment = 0;
1119
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001120 /* Walk attachment list and outputs together -- this is a little overpowered
1121 * since attachments
1122 * are currently dense, but the parallel with matching between shader stages
1123 * is nice.
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001124 */
1125
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001126 while ((outputs.size() > 0 && it != outputs.end()) ||
1127 attachment < color_formats.size()) {
1128 if (attachment == color_formats.size() ||
1129 (it != outputs.end() && it->first < attachment)) {
1130 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT,
1131 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0,
1132 __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC",
1133 "FS writes to output location %d with no matching "
1134 "attachment",
1135 it->first)) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001136 pass = false;
1137 }
1138 it++;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001139 } else if (it == outputs.end() || it->first > attachment) {
1140 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1141 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0,
1142 __LINE__, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC",
1143 "Attachment %d not written by FS", attachment)) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001144 pass = false;
1145 }
1146 attachment++;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001147 } else {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001148 unsigned output_type = get_fundamental_type(fs, it->second.type_id);
1149 unsigned att_type = get_format_type(color_formats[attachment]);
1150
1151 /* type checking */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001152 if (att_type != FORMAT_TYPE_UNDEFINED &&
1153 output_type != FORMAT_TYPE_UNDEFINED &&
1154 att_type != output_type) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001155 char fs_type[1024];
1156 describe_type(fs_type, fs, it->second.type_id);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001157 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1158 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0,
1159 __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH,
1160 "SC", "Attachment %d of type `%s` does not match "
1161 "FS output type of `%s`",
1162 attachment,
1163 string_VkFormat(color_formats[attachment]),
1164 fs_type)) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001165 pass = false;
1166 }
1167 }
1168
1169 /* OK! */
1170 it++;
1171 attachment++;
1172 }
1173 }
1174
1175 return pass;
1176}
1177
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001178struct shader_stage_attributes {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001179 char const *const name;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001180 bool arrayed_input;
1181};
1182
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001183static shader_stage_attributes shader_stage_attribs[] = {
1184 {"vertex shader", false},
1185 {"tessellation control shader", true},
1186 {"tessellation evaluation shader", false},
1187 {"geometry shader", true},
1188 {"fragment shader", false},
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001189};
1190
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001191// For given pipelineLayout verify that the setLayout at slot.first
1192// has the requested binding at slot.second
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001193static bool
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001194has_descriptor_binding(layer_data *my_data,
1195 vector<VkDescriptorSetLayout> *pipelineLayout,
1196 std::pair<unsigned, unsigned> slot) {
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001197 if (!pipelineLayout)
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001198 return false;
1199
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001200 if (slot.first >= pipelineLayout->size())
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001201 return false;
1202
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001203 auto set = my_data->descriptorSetLayoutMap[(*pipelineLayout)[slot.first]]
1204 ->bindings;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001205
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001206 return (set.find(slot.second) != set.end());
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001207}
1208
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001209static uint32_t get_shader_stage_id(VkShaderStageFlagBits stage) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001210 uint32_t bit_pos = u_ffs(stage);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001211 return bit_pos - 1;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001212}
1213
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001214// Block of code at start here for managing/tracking Pipeline state that this
1215// layer cares about
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001216
1217static uint64_t g_drawCount[NUM_DRAW_TYPES] = {0, 0, 0, 0};
1218
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001219// TODO : Should be tracking lastBound per commandBuffer and when draws occur,
1220// report based on that cmd buffer lastBound
1221// Then need to synchronize the accesses based on cmd buffer so that if I'm
1222// reading state on one cmd buffer, updates
1223// to that same cmd buffer by separate thread are not changing state from
1224// underneath us
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001225// Track the last cmd buffer touched by this thread
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001226
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06001227// prototype
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001228static GLOBAL_CB_NODE *getCBNode(layer_data *, const VkCommandBuffer);
Tobin Ehlis559c6382015-11-05 09:52:49 -07001229
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001230static VkBool32 hasDrawCmd(GLOBAL_CB_NODE *pCB) {
1231 for (uint32_t i = 0; i < NUM_DRAW_TYPES; i++) {
Tobin Ehlis53eddda2015-07-01 16:46:13 -06001232 if (pCB->drawCount[i])
1233 return VK_TRUE;
1234 }
1235 return VK_FALSE;
1236}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001237
Tobin Ehlise382c5a2015-06-10 12:57:07 -06001238// Check object status for selected flag state
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001239static VkBool32 validate_status(layer_data *my_data, GLOBAL_CB_NODE *pNode,
1240 CBStatusFlags enable_mask,
1241 CBStatusFlags status_mask,
1242 CBStatusFlags status_flag, VkFlags msg_flags,
1243 DRAW_STATE_ERROR error_code,
1244 const char *fail_msg) {
1245 // If non-zero enable mask is present, check it against status but if
1246 // enable_mask
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001247 // is 0 then no enable required so we should always just check status
1248 if ((!enable_mask) || (enable_mask & pNode->status)) {
1249 if ((pNode->status & status_mask) != status_flag) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001250 // TODO : How to pass dispatchable objects as srcObject? Here src
1251 // obj should be cmd buffer
1252 return log_msg(my_data->report_data, msg_flags,
1253 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
1254 __LINE__, error_code, "DS",
1255 "CB object %#" PRIxLEAST64 ": %s",
1256 (uint64_t)(pNode->commandBuffer), fail_msg);
Tobin Ehlise382c5a2015-06-10 12:57:07 -06001257 }
Tobin Ehlise382c5a2015-06-10 12:57:07 -06001258 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001259 return VK_FALSE;
Tobin Ehlise382c5a2015-06-10 12:57:07 -06001260}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001261
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001262// Retrieve pipeline node ptr for given pipeline object
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001263static PIPELINE_NODE *getPipeline(layer_data *my_data,
1264 const VkPipeline pipeline) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001265 loader_platform_thread_lock_mutex(&globalLock);
Chia-I Wue2fc5522015-10-26 20:04:44 +08001266 if (my_data->pipelineMap.find(pipeline) == my_data->pipelineMap.end()) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001267 loader_platform_thread_unlock_mutex(&globalLock);
1268 return NULL;
1269 }
1270 loader_platform_thread_unlock_mutex(&globalLock);
Chia-I Wue2fc5522015-10-26 20:04:44 +08001271 return my_data->pipelineMap[pipeline];
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001272}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001273
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001274// Return VK_TRUE if for a given PSO, the given state enum is dynamic, else
1275// return VK_FALSE
1276static VkBool32 isDynamic(const PIPELINE_NODE *pPipeline,
1277 const VkDynamicState state) {
Tobin Ehlisd332f282015-10-02 11:00:56 -06001278 if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001279 for (uint32_t i = 0;
1280 i < pPipeline->graphicsPipelineCI.pDynamicState->dynamicStateCount;
1281 i++) {
1282 if (state ==
1283 pPipeline->graphicsPipelineCI.pDynamicState->pDynamicStates[i])
Tobin Ehlisd332f282015-10-02 11:00:56 -06001284 return VK_TRUE;
1285 }
1286 }
1287 return VK_FALSE;
1288}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001289
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001290// Validate state stored as flags at time of draw call
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001291static VkBool32 validate_draw_state_flags(layer_data *my_data,
1292 GLOBAL_CB_NODE *pCB,
1293 VkBool32 indexedDraw) {
Courtney Goeltzenleuchtercd2a0992015-07-09 11:44:38 -06001294 VkBool32 result;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001295 result = validate_status(
1296 my_data, pCB, CBSTATUS_NONE, CBSTATUS_VIEWPORT_SET,
1297 CBSTATUS_VIEWPORT_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1298 DRAWSTATE_VIEWPORT_NOT_BOUND,
1299 "Dynamic viewport state not set for this command buffer");
1300 result |= validate_status(
1301 my_data, pCB, CBSTATUS_NONE, CBSTATUS_SCISSOR_SET, CBSTATUS_SCISSOR_SET,
1302 VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_SCISSOR_NOT_BOUND,
1303 "Dynamic scissor state not set for this command buffer");
1304 result |= validate_status(
1305 my_data, pCB, CBSTATUS_NONE, CBSTATUS_LINE_WIDTH_SET,
1306 CBSTATUS_LINE_WIDTH_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1307 DRAWSTATE_LINE_WIDTH_NOT_BOUND,
1308 "Dynamic line width state not set for this command buffer");
1309 result |= validate_status(
1310 my_data, pCB, CBSTATUS_NONE, CBSTATUS_DEPTH_BIAS_SET,
1311 CBSTATUS_DEPTH_BIAS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1312 DRAWSTATE_DEPTH_BIAS_NOT_BOUND,
1313 "Dynamic depth bias state not set for this command buffer");
1314 result |= validate_status(
1315 my_data, pCB, CBSTATUS_COLOR_BLEND_WRITE_ENABLE, CBSTATUS_BLEND_SET,
1316 CBSTATUS_BLEND_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1317 DRAWSTATE_BLEND_NOT_BOUND,
1318 "Dynamic blend object state not set for this command buffer");
1319 result |= validate_status(
1320 my_data, pCB, CBSTATUS_DEPTH_WRITE_ENABLE, CBSTATUS_DEPTH_BOUNDS_SET,
1321 CBSTATUS_DEPTH_BOUNDS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1322 DRAWSTATE_DEPTH_BOUNDS_NOT_BOUND,
1323 "Dynamic depth bounds state not set for this command buffer");
1324 result |= validate_status(
1325 my_data, pCB, CBSTATUS_STENCIL_TEST_ENABLE,
1326 CBSTATUS_STENCIL_READ_MASK_SET, CBSTATUS_STENCIL_READ_MASK_SET,
1327 VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_STENCIL_NOT_BOUND,
1328 "Dynamic stencil read mask state not set for this command buffer");
1329 result |= validate_status(
1330 my_data, pCB, CBSTATUS_STENCIL_TEST_ENABLE,
1331 CBSTATUS_STENCIL_WRITE_MASK_SET, CBSTATUS_STENCIL_WRITE_MASK_SET,
1332 VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_STENCIL_NOT_BOUND,
1333 "Dynamic stencil write mask state not set for this command buffer");
1334 result |= validate_status(
1335 my_data, pCB, CBSTATUS_STENCIL_TEST_ENABLE,
1336 CBSTATUS_STENCIL_REFERENCE_SET, CBSTATUS_STENCIL_REFERENCE_SET,
1337 VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_STENCIL_NOT_BOUND,
1338 "Dynamic stencil reference state not set for this command buffer");
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001339 if (indexedDraw)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001340 result |= validate_status(
1341 my_data, pCB, CBSTATUS_NONE, CBSTATUS_INDEX_BUFFER_BOUND,
1342 CBSTATUS_INDEX_BUFFER_BOUND, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1343 DRAWSTATE_INDEX_BUFFER_NOT_BOUND, "Index buffer object not bound "
1344 "to this command buffer when "
1345 "Indexed Draw attempted");
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001346 return result;
1347}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001348
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001349// Verify attachment reference compatibility according to spec
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001350// If one array is larger, treat missing elements of shorter array as
1351// VK_ATTACHMENT_UNUSED & other array much match this
1352// If both AttachmentReference arrays have requested index, check their
1353// corresponding AttachementDescriptions
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001354// to make sure that format and samples counts match.
1355// If not, they are not compatible.
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001356static bool attachment_references_compatible(
1357 const uint32_t index, const VkAttachmentReference *pPrimary,
1358 const uint32_t primaryCount,
1359 const VkAttachmentDescription *pPrimaryAttachments,
1360 const VkAttachmentReference *pSecondary, const uint32_t secondaryCount,
1361 const VkAttachmentDescription *pSecondaryAttachments) {
1362 if (index >=
1363 primaryCount) { // Check secondary as if primary is VK_ATTACHMENT_UNUSED
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001364 if (VK_ATTACHMENT_UNUSED != pSecondary[index].attachment)
1365 return false;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001366 } else if (index >= secondaryCount) { // Check primary as if secondary is
1367 // VK_ATTACHMENT_UNUSED
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001368 if (VK_ATTACHMENT_UNUSED != pPrimary[index].attachment)
1369 return false;
1370 } else { // format and sample count must match
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001371 if ((pPrimaryAttachments[pPrimary[index].attachment].format ==
1372 pSecondaryAttachments[pSecondary[index].attachment].format) &&
1373 (pPrimaryAttachments[pPrimary[index].attachment].samples ==
1374 pSecondaryAttachments[pSecondary[index].attachment].samples))
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001375 return true;
1376 }
1377 // Format and sample counts didn't match
1378 return false;
1379}
1380
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001381// For give primary and secondary RenderPass objects, verify that they're
1382// compatible
1383static bool verify_renderpass_compatibility(layer_data *my_data,
1384 const VkRenderPass primaryRP,
1385 const VkRenderPass secondaryRP,
1386 string &errorMsg) {
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001387 stringstream errorStr;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001388 if (my_data->renderPassMap.find(primaryRP) ==
1389 my_data->renderPassMap.end()) {
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001390 errorStr << "invalid VkRenderPass (" << primaryRP << ")";
1391 errorMsg = errorStr.str();
1392 return false;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001393 } else if (my_data->renderPassMap.find(secondaryRP) ==
1394 my_data->renderPassMap.end()) {
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001395 errorStr << "invalid VkRenderPass (" << secondaryRP << ")";
1396 errorMsg = errorStr.str();
1397 return false;
1398 }
1399 // Trivial pass case is exact same RP
1400 if (primaryRP == secondaryRP)
1401 return true;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001402 const VkRenderPassCreateInfo *primaryRPCI =
1403 my_data->renderPassMap[primaryRP]->pCreateInfo;
1404 const VkRenderPassCreateInfo *secondaryRPCI =
1405 my_data->renderPassMap[secondaryRP]->pCreateInfo;
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001406 if (primaryRPCI->subpassCount != secondaryRPCI->subpassCount) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001407 errorStr << "RenderPass for primary cmdBuffer has "
1408 << primaryRPCI->subpassCount
1409 << " subpasses but renderPass for secondary cmdBuffer has "
1410 << secondaryRPCI->subpassCount << " subpasses.";
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001411 errorMsg = errorStr.str();
1412 return false;
1413 }
1414 uint32_t spIndex = 0;
1415 for (spIndex = 0; spIndex < primaryRPCI->subpassCount; ++spIndex) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001416 // For each subpass, verify that corresponding color, input, resolve &
1417 // depth/stencil attachment references are compatible
1418 uint32_t primaryColorCount =
1419 primaryRPCI->pSubpasses[spIndex].colorAttachmentCount;
1420 uint32_t secondaryColorCount =
1421 secondaryRPCI->pSubpasses[spIndex].colorAttachmentCount;
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001422 uint32_t colorMax = std::max(primaryColorCount, secondaryColorCount);
1423 for (uint32_t cIdx = 0; cIdx < colorMax; ++cIdx) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001424 if (!attachment_references_compatible(
1425 cIdx, primaryRPCI->pSubpasses[spIndex].pColorAttachments,
1426 primaryColorCount, primaryRPCI->pAttachments,
1427 secondaryRPCI->pSubpasses[spIndex].pColorAttachments,
1428 secondaryColorCount, secondaryRPCI->pAttachments)) {
1429 errorStr << "color attachments at index " << cIdx
1430 << " of subpass index " << spIndex
1431 << " are not compatible.";
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001432 errorMsg = errorStr.str();
1433 return false;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001434 } else if (!attachment_references_compatible(
1435 cIdx,
1436 primaryRPCI->pSubpasses[spIndex].pResolveAttachments,
1437 primaryColorCount, primaryRPCI->pAttachments,
1438 secondaryRPCI->pSubpasses[spIndex]
1439 .pResolveAttachments,
1440 secondaryColorCount, secondaryRPCI->pAttachments)) {
1441 errorStr << "resolve attachments at index " << cIdx
1442 << " of subpass index " << spIndex
1443 << " are not compatible.";
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001444 errorMsg = errorStr.str();
1445 return false;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001446 } else if (!attachment_references_compatible(
1447 cIdx, primaryRPCI->pSubpasses[spIndex]
1448 .pDepthStencilAttachment,
1449 primaryColorCount, primaryRPCI->pAttachments,
1450 secondaryRPCI->pSubpasses[spIndex]
1451 .pDepthStencilAttachment,
1452 secondaryColorCount, secondaryRPCI->pAttachments)) {
1453 errorStr << "depth/stencil attachments at index " << cIdx
1454 << " of subpass index " << spIndex
1455 << " are not compatible.";
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001456 errorMsg = errorStr.str();
1457 return false;
1458 }
1459 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001460 uint32_t primaryInputCount =
1461 primaryRPCI->pSubpasses[spIndex].inputAttachmentCount;
1462 uint32_t secondaryInputCount =
1463 secondaryRPCI->pSubpasses[spIndex].inputAttachmentCount;
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001464 uint32_t inputMax = std::max(primaryInputCount, secondaryInputCount);
1465 for (uint32_t i = 0; i < inputMax; ++i) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001466 if (!attachment_references_compatible(
1467 i, primaryRPCI->pSubpasses[spIndex].pInputAttachments,
1468 primaryColorCount, primaryRPCI->pAttachments,
1469 secondaryRPCI->pSubpasses[spIndex].pInputAttachments,
1470 secondaryColorCount, secondaryRPCI->pAttachments)) {
1471 errorStr << "input attachments at index " << i
1472 << " of subpass index " << spIndex
1473 << " are not compatible.";
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001474 errorMsg = errorStr.str();
1475 return false;
1476 }
1477 }
1478 }
1479 return true;
1480}
1481
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001482// For give SET_NODE, verify that its Set is compatible w/ the setLayout
1483// corresponding to pipelineLayout[layoutIndex]
1484static bool verify_set_layout_compatibility(layer_data *my_data,
1485 const SET_NODE *pSet,
1486 const VkPipelineLayout layout,
1487 const uint32_t layoutIndex,
1488 string &errorMsg) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07001489 stringstream errorStr;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001490 if (my_data->pipelineLayoutMap.find(layout) ==
1491 my_data->pipelineLayoutMap.end()) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07001492 errorStr << "invalid VkPipelineLayout (" << layout << ")";
1493 errorMsg = errorStr.str();
Tobin Ehlis559c6382015-11-05 09:52:49 -07001494 return false;
1495 }
1496 PIPELINE_LAYOUT_NODE pl = my_data->pipelineLayoutMap[layout];
1497 if (layoutIndex >= pl.descriptorSetLayouts.size()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001498 errorStr << "VkPipelineLayout (" << layout << ") only contains "
1499 << pl.descriptorSetLayouts.size()
1500 << " setLayouts corresponding to sets 0-"
1501 << pl.descriptorSetLayouts.size() - 1
1502 << ", but you're attempting to bind set to index "
1503 << layoutIndex;
Tobin Ehlis8fab6562015-12-01 09:57:09 -07001504 errorMsg = errorStr.str();
Tobin Ehlis559c6382015-11-05 09:52:49 -07001505 return false;
1506 }
1507 // Get the specific setLayout from PipelineLayout that overlaps this set
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001508 LAYOUT_NODE *pLayoutNode =
1509 my_data->descriptorSetLayoutMap[pl.descriptorSetLayouts[layoutIndex]];
Tobin Ehlis559c6382015-11-05 09:52:49 -07001510 if (pLayoutNode->layout == pSet->pLayout->layout) { // trivial pass case
1511 return true;
1512 }
Courtney Goeltzenleuchter51239472015-12-16 16:06:06 -07001513 size_t descriptorCount = pLayoutNode->descriptorTypes.size();
Tobin Ehlis559c6382015-11-05 09:52:49 -07001514 if (descriptorCount != pSet->pLayout->descriptorTypes.size()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001515 errorStr << "setLayout " << layoutIndex << " from pipelineLayout "
1516 << layout << " has " << descriptorCount
1517 << " descriptors, but corresponding set being bound has "
1518 << pSet->pLayout->descriptorTypes.size() << " descriptors.";
Tobin Ehlis8fab6562015-12-01 09:57:09 -07001519 errorMsg = errorStr.str();
Tobin Ehlis559c6382015-11-05 09:52:49 -07001520 return false; // trivial fail case
1521 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001522 // Now need to check set against corresponding pipelineLayout to verify
1523 // compatibility
1524 for (size_t i = 0; i < descriptorCount; ++i) {
Tobin Ehlis559c6382015-11-05 09:52:49 -07001525 // Need to verify that layouts are identically defined
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001526 // TODO : Is below sufficient? Making sure that types & stageFlags
1527 // match per descriptor
Tobin Ehlis559c6382015-11-05 09:52:49 -07001528 // do we also need to check immutable samplers?
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001529 if (pLayoutNode->descriptorTypes[i] !=
1530 pSet->pLayout->descriptorTypes[i]) {
1531 errorStr << "descriptor " << i
1532 << " for descriptorSet being bound is type '"
1533 << string_VkDescriptorType(
1534 pSet->pLayout->descriptorTypes[i])
1535 << "' but corresponding descriptor from pipelineLayout is "
1536 "type '"
1537 << string_VkDescriptorType(pLayoutNode->descriptorTypes[i])
1538 << "'";
Tobin Ehlis8fab6562015-12-01 09:57:09 -07001539 errorMsg = errorStr.str();
Tobin Ehlis559c6382015-11-05 09:52:49 -07001540 return false;
1541 }
1542 if (pLayoutNode->stageFlags[i] != pSet->pLayout->stageFlags[i]) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001543 errorStr << "stageFlags " << i
1544 << " for descriptorSet being bound is "
1545 << pSet->pLayout->stageFlags[i]
1546 << "' but corresponding descriptor from pipelineLayout "
1547 "has stageFlags " << pLayoutNode->stageFlags[i];
Tobin Ehlis8fab6562015-12-01 09:57:09 -07001548 errorMsg = errorStr.str();
Tobin Ehlis559c6382015-11-05 09:52:49 -07001549 return false;
1550 }
1551 }
1552 return true;
1553}
1554
Tobin Ehlis88452832015-12-03 09:40:56 -07001555// Validate that the shaders used by the given pipeline
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001556// As a side effect this function also records the sets that are actually used
1557// by the pipeline
1558static VkBool32 validate_pipeline_shaders(layer_data *my_data, VkDevice dev,
1559 PIPELINE_NODE *pPipeline) {
1560 VkGraphicsPipelineCreateInfo const *pCreateInfo =
1561 &pPipeline->graphicsPipelineCI;
1562 /* We seem to allow pipeline stages to be specified out of order, so collect
1563 * and identify them
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001564 * before trying to do anything more: */
1565 int vertex_stage = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT);
1566 int geometry_stage = get_shader_stage_id(VK_SHADER_STAGE_GEOMETRY_BIT);
1567 int fragment_stage = get_shader_stage_id(VK_SHADER_STAGE_FRAGMENT_BIT);
1568
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001569 shader_module **shaders =
1570 new shader_module *[fragment_stage + 1]; /* exclude CS */
1571 memset(shaders, 0, sizeof(shader_module *) * (fragment_stage + 1));
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001572 RENDER_PASS_NODE const *rp = 0;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001573 VkPipelineVertexInputStateCreateInfo const *vi = 0;
Mark Youngb20a6a82016-01-07 15:41:43 -07001574 VkBool32 pass = VK_TRUE;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001575
1576 for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001577 VkPipelineShaderStageCreateInfo const *pStage =
1578 &pCreateInfo->pStages[i];
1579 if (pStage->sType ==
1580 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001581
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001582 if ((pStage->stage &
1583 (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT |
1584 VK_SHADER_STAGE_FRAGMENT_BIT |
1585 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
1586 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) == 0) {
1587 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT,
1588 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/ 0,
1589 __LINE__, SHADER_CHECKER_UNKNOWN_STAGE, "SC",
1590 "Unknown shader stage %d", pStage->stage)) {
Mark Youngb20a6a82016-01-07 15:41:43 -07001591 pass = VK_FALSE;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001592 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001593 } else {
1594 shader_module *module =
1595 my_data->shaderModuleMap[pStage->module];
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001596 shaders[get_shader_stage_id(pStage->stage)] = module;
1597
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001598 /* validate descriptor set layout against what the spirv module
1599 * actually uses */
1600 std::map<std::pair<unsigned, unsigned>, interface_var>
1601 descriptor_uses;
1602 collect_interface_by_descriptor_slot(my_data, dev, module,
1603 spv::StorageClassUniform,
1604 descriptor_uses);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001605
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001606 auto layouts =
1607 pCreateInfo->layout != VK_NULL_HANDLE
1608 ? &(my_data->pipelineLayoutMap[pCreateInfo->layout]
1609 .descriptorSetLayouts)
1610 : nullptr;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001611
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001612 for (auto it = descriptor_uses.begin();
1613 it != descriptor_uses.end(); it++) {
1614 // As a side-effect of this function, capture which sets are
1615 // used by the pipeline
Tobin Ehlis88452832015-12-03 09:40:56 -07001616 pPipeline->active_sets.insert(it->first.first);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001617
1618 /* find the matching binding */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001619 auto found =
1620 has_descriptor_binding(my_data, layouts, it->first);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001621
1622 if (!found) {
1623 char type_name[1024];
1624 describe_type(type_name, module, it->second.type_id);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001625 if (log_msg(my_data->report_data,
1626 VK_DEBUG_REPORT_ERROR_BIT_EXT,
1627 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1628 /*dev*/ 0, __LINE__,
1629 SHADER_CHECKER_MISSING_DESCRIPTOR, "SC",
1630 "Shader uses descriptor slot %u.%u (used "
1631 "as type `%s`) but not declared in "
1632 "pipeline layout",
1633 it->first.first, it->first.second,
1634 type_name)) {
Mark Youngb20a6a82016-01-07 15:41:43 -07001635 pass = VK_FALSE;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001636 }
1637 }
1638 }
1639 }
1640 }
1641 }
1642
1643 if (pCreateInfo->renderPass != VK_NULL_HANDLE)
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001644 rp = my_data->renderPassMap[pCreateInfo->renderPass];
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001645
1646 vi = pCreateInfo->pVertexInputState;
1647
1648 if (vi) {
1649 pass = validate_vi_consistency(my_data, dev, vi) && pass;
1650 }
1651
1652 if (shaders[vertex_stage]) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001653 pass = validate_vi_against_vs_inputs(my_data, dev, vi,
1654 shaders[vertex_stage]) &&
1655 pass;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001656 }
1657
1658 /* TODO: enforce rules about present combinations of shaders */
1659 int producer = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT);
1660 int consumer = get_shader_stage_id(VK_SHADER_STAGE_GEOMETRY_BIT);
1661
1662 while (!shaders[producer] && producer != fragment_stage) {
1663 producer++;
1664 consumer++;
1665 }
1666
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001667 for (; producer != fragment_stage && consumer <= fragment_stage;
1668 consumer++) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001669 assert(shaders[producer]);
1670 if (shaders[consumer]) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001671 pass = validate_interface_between_stages(
1672 my_data, dev, shaders[producer],
1673 shader_stage_attribs[producer].name, shaders[consumer],
1674 shader_stage_attribs[consumer].name,
1675 shader_stage_attribs[consumer].arrayed_input) &&
1676 pass;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001677
1678 producer = consumer;
1679 }
1680 }
1681
1682 if (shaders[fragment_stage] && rp) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001683 pass = validate_fs_outputs_against_render_pass(
1684 my_data, dev, shaders[fragment_stage], rp,
1685 pCreateInfo->subpass) &&
1686 pass;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001687 }
1688
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001689 delete[] shaders;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001690
1691 return pass;
1692}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001693
Tobin Ehlisf6585052015-12-17 11:48:42 -07001694// Return Set node ptr for specified set or else NULL
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001695static SET_NODE *getSetNode(layer_data *my_data, const VkDescriptorSet set) {
Tobin Ehlisf6585052015-12-17 11:48:42 -07001696 loader_platform_thread_lock_mutex(&globalLock);
1697 if (my_data->setMap.find(set) == my_data->setMap.end()) {
1698 loader_platform_thread_unlock_mutex(&globalLock);
1699 return NULL;
1700 }
1701 loader_platform_thread_unlock_mutex(&globalLock);
1702 return my_data->setMap[set];
1703}
Tobin Ehlisd2393772016-01-29 11:50:47 -07001704// For the given command buffer, verify that for each set set in activeSetNodes
1705// that any dynamic descriptor in that set has a valid dynamic offset bound.
1706// To be valid, the dynamic offset combined with the offet and range from its
1707// descriptor update must not overflow the size of its buffer being updated
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001708static VkBool32
1709validate_dynamic_offsets(layer_data *my_data, const GLOBAL_CB_NODE *pCB,
1710 const vector<SET_NODE *> activeSetNodes) {
Tobin Ehlisf6585052015-12-17 11:48:42 -07001711 VkBool32 result = VK_FALSE;
Tobin Ehlisf6585052015-12-17 11:48:42 -07001712
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001713 VkWriteDescriptorSet *pWDS = NULL;
Tobin Ehlisf6585052015-12-17 11:48:42 -07001714 uint32_t dynOffsetIndex = 0;
1715 VkDeviceSize bufferSize = 0;
Tobin Ehlisd2393772016-01-29 11:50:47 -07001716 for (auto set_node : activeSetNodes) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001717 for (uint32_t i = 0; i < set_node->descriptorCount; ++i) {
Tobin Ehlisd2393772016-01-29 11:50:47 -07001718 switch (set_node->ppDescriptors[i]->sType) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001719 case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
1720 pWDS = (VkWriteDescriptorSet *)set_node->ppDescriptors[i];
1721 if ((pWDS->descriptorType ==
1722 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
1723 (pWDS->descriptorType ==
1724 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
1725 for (uint32_t j = 0; j < pWDS->descriptorCount; ++j) {
1726 bufferSize =
1727 my_data->bufferMap[pWDS->pBufferInfo[j].buffer]
1728 .create_info->size;
1729 if ((pCB->dynamicOffsets[dynOffsetIndex] +
1730 pWDS->pBufferInfo[j].offset +
1731 pWDS->pBufferInfo[j].range) > bufferSize) {
1732 result |= log_msg(
1733 my_data->report_data,
1734 VK_DEBUG_REPORT_ERROR_BIT_EXT,
1735 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
1736 (uint64_t)set_node->set, __LINE__,
1737 DRAWSTATE_DYNAMIC_OFFSET_OVERFLOW, "DS",
1738 "VkDescriptorSet (%#" PRIxLEAST64
1739 ") bound as set #%u has dynamic offset %u. "
1740 "Combined with offet %#" PRIxLEAST64
1741 " and range %#" PRIxLEAST64
1742 " from its update, this oversteps its buffer "
1743 "(%#" PRIxLEAST64
1744 ") which has a size of %#" PRIxLEAST64 ".",
1745 (uint64_t)set_node->set, i,
1746 pCB->dynamicOffsets[dynOffsetIndex],
1747 pWDS->pBufferInfo[j].offset,
1748 pWDS->pBufferInfo[j].range,
1749 (uint64_t)pWDS->pBufferInfo[j].buffer,
1750 bufferSize);
Tobin Ehlisf6585052015-12-17 11:48:42 -07001751 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001752 dynOffsetIndex++;
1753 i += j; // Advance i to end of this set of descriptors
1754 // (++i at end of for loop will move 1 index
1755 // past last of these descriptors)
Tobin Ehlisf6585052015-12-17 11:48:42 -07001756 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001757 }
1758 break;
1759 default: // Currently only shadowing Write update nodes so shouldn't
1760 // get here
1761 assert(0);
1762 continue;
Tobin Ehlisd2393772016-01-29 11:50:47 -07001763 }
Tobin Ehlisf6585052015-12-17 11:48:42 -07001764 }
1765 }
1766 return result;
1767}
1768
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001769// Validate overall state at the time of a draw call
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001770static VkBool32 validate_draw_state(layer_data *my_data, GLOBAL_CB_NODE *pCB,
1771 VkBool32 indexedDraw) {
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001772 // First check flag states
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06001773 VkBool32 result = validate_draw_state_flags(my_data, pCB, indexedDraw);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001774 PIPELINE_NODE *pPipe = getPipeline(my_data, pCB->lastBoundPipeline);
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001775 // Now complete other state checks
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001776 // TODO : Currently only performing next check if *something* was bound
1777 // (non-zero last bound)
1778 // There is probably a better way to gate when this check happens, and to
1779 // know if something *should* have been bound
1780 // We should have that check separately and then gate this check based on
1781 // that check
Mark Lobodzinski74635932015-12-18 15:35:38 -07001782 if (pPipe) {
Tobin Ehlisd2393772016-01-29 11:50:47 -07001783 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski74635932015-12-18 15:35:38 -07001784 if (pCB->lastBoundPipelineLayout) {
1785 string errorString;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001786 // Need a vector (vs. std::set) of active Sets for dynamicOffset
1787 // validation in case same set bound w/ different offsets
1788 vector<SET_NODE *> activeSetNodes;
Mark Lobodzinski74635932015-12-18 15:35:38 -07001789 for (auto setIndex : pPipe->active_sets) {
1790 // If valid set is not bound throw an error
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001791 if ((pCB->boundDescriptorSets.size() <= setIndex) ||
1792 (!pCB->boundDescriptorSets[setIndex])) {
1793 result |= log_msg(
1794 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1795 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
1796 DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS",
1797 "VkPipeline %#" PRIxLEAST64
1798 " uses set #%u but that set is not bound.",
1799 (uint64_t)pPipe->pipeline, setIndex);
1800 } else if (!verify_set_layout_compatibility(
1801 my_data,
1802 my_data
1803 ->setMap[pCB->boundDescriptorSets[setIndex]],
1804 pPipe->graphicsPipelineCI.layout, setIndex,
1805 errorString)) {
1806 // Set is bound but not compatible w/ overlapping
1807 // pipelineLayout from PSO
1808 VkDescriptorSet setHandle =
1809 my_data->setMap[pCB->boundDescriptorSets[setIndex]]
1810 ->set;
1811 result |= log_msg(
1812 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1813 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
1814 (uint64_t)setHandle, __LINE__,
1815 DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS",
1816 "VkDescriptorSet (%#" PRIxLEAST64
1817 ") bound as set #%u is not compatible with overlapping "
1818 "VkPipelineLayout %#" PRIxLEAST64 " due to: %s",
1819 (uint64_t)setHandle, setIndex,
1820 (uint64_t)pPipe->graphicsPipelineCI.layout,
1821 errorString.c_str());
1822 } else { // Valid set is bound and layout compatible, validate
1823 // that it's updated and verify any dynamic offsets
Tobin Ehlis43c39c02016-01-11 13:18:40 -07001824 // Pull the set node
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001825 SET_NODE *pSet =
1826 my_data->setMap[pCB->boundDescriptorSets[setIndex]];
1827 // Save vector of all active sets to verify dynamicOffsets
1828 // below
Tobin Ehlisd2393772016-01-29 11:50:47 -07001829 activeSetNodes.push_back(pSet);
Tobin Ehlis43c39c02016-01-11 13:18:40 -07001830 // Make sure set has been updated
1831 if (!pSet->pUpdateStructs) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001832 result |= log_msg(
1833 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1834 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
1835 (uint64_t)pSet->set, __LINE__,
1836 DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS",
1837 "DS %#" PRIxLEAST64 " bound but it was never "
1838 "updated. It is now being used "
1839 "to draw so this will result "
1840 "in undefined behavior.",
1841 (uint64_t)pSet->set);
Tobin Ehlis43c39c02016-01-11 13:18:40 -07001842 }
Mark Lobodzinski74635932015-12-18 15:35:38 -07001843 }
Tobin Ehlis88452832015-12-03 09:40:56 -07001844 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001845 // For each dynamic descriptor, make sure dynamic offset doesn't
1846 // overstep buffer
Tobin Ehlisd2393772016-01-29 11:50:47 -07001847 if (!pCB->dynamicOffsets.empty())
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001848 result |=
1849 validate_dynamic_offsets(my_data, pCB, activeSetNodes);
Tobin Ehlis88452832015-12-03 09:40:56 -07001850 }
Mark Lobodzinski74635932015-12-18 15:35:38 -07001851 // Verify Vtx binding
1852 if (pPipe->vtxBindingCount > 0) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001853 VkPipelineVertexInputStateCreateInfo *vtxInCI =
1854 &pPipe->vertexInputCI;
1855 for (uint32_t i = 0; i < vtxInCI->vertexBindingDescriptionCount;
1856 i++) {
1857 if ((pCB->currentDrawData.buffers.size() < (i + 1)) ||
1858 (pCB->currentDrawData.buffers[i] == VK_NULL_HANDLE)) {
1859 result |= log_msg(
1860 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1861 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
1862 DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
1863 "The Pipeline State Object (%#" PRIxLEAST64
1864 ") expects that this Command Buffer's vertex binding "
1865 "Index %d should be set via vkCmdBindVertexBuffers.",
Mark Lobodzinski74635932015-12-18 15:35:38 -07001866 (uint64_t)pCB->lastBoundPipeline, i);
Mark Lobodzinski74635932015-12-18 15:35:38 -07001867 }
1868 }
1869 } else {
Michael Lentine700b0aa2015-10-30 17:57:32 -07001870 if (!pCB->currentDrawData.buffers.empty()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001871 result |= log_msg(
1872 my_data->report_data, VK_DEBUG_REPORT_PERF_WARN_BIT_EXT,
1873 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
1874 DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
1875 "Vertex buffers are bound to command buffer (%#" PRIxLEAST64
1876 ") but no vertex buffers are attached to this Pipeline "
1877 "State Object (%#" PRIxLEAST64 ").",
1878 (uint64_t)pCB->commandBuffer,
1879 (uint64_t)pCB->lastBoundPipeline);
Tobin Ehlisf7bf4502015-09-09 15:12:35 -06001880 }
1881 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001882 // If Viewport or scissors are dynamic, verify that dynamic count
1883 // matches PSO count
Mark Lobodzinski74635932015-12-18 15:35:38 -07001884 VkBool32 dynViewport = isDynamic(pPipe, VK_DYNAMIC_STATE_VIEWPORT);
1885 VkBool32 dynScissor = isDynamic(pPipe, VK_DYNAMIC_STATE_SCISSOR);
1886 if (dynViewport) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001887 if (pCB->viewports.size() !=
1888 pPipe->graphicsPipelineCI.pViewportState->viewportCount) {
1889 result |= log_msg(
1890 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1891 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
1892 DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
1893 "Dynamic viewportCount from vkCmdSetViewport() "
1894 "is " PRINTF_SIZE_T_SPECIFIER
1895 ", but PSO viewportCount is %u. These counts must match.",
1896 pCB->viewports.size(),
1897 pPipe->graphicsPipelineCI.pViewportState->viewportCount);
Mark Lobodzinski74635932015-12-18 15:35:38 -07001898 }
Tobin Ehlisd332f282015-10-02 11:00:56 -06001899 }
Mark Lobodzinski74635932015-12-18 15:35:38 -07001900 if (dynScissor) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001901 if (pCB->scissors.size() !=
1902 pPipe->graphicsPipelineCI.pViewportState->scissorCount) {
1903 result |= log_msg(
1904 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1905 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
1906 DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
1907 "Dynamic scissorCount from vkCmdSetScissor() "
1908 "is " PRINTF_SIZE_T_SPECIFIER
1909 ", but PSO scissorCount is %u. These counts must match.",
1910 pCB->scissors.size(),
1911 pPipe->graphicsPipelineCI.pViewportState->scissorCount);
Mark Lobodzinski74635932015-12-18 15:35:38 -07001912 }
Tobin Ehlisd332f282015-10-02 11:00:56 -06001913 }
Tobin Ehlisd2393772016-01-29 11:50:47 -07001914 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlisd332f282015-10-02 11:00:56 -06001915 }
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001916 return result;
1917}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001918
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001919// Verify that create state for a pipeline is valid
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001920static VkBool32 verifyPipelineCreateState(layer_data *my_data,
1921 const VkDevice device,
1922 PIPELINE_NODE *pPipeline) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001923 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinski2fd2d032015-12-16 14:25:22 -07001924
Tobin Ehlis88452832015-12-03 09:40:56 -07001925 if (!validate_pipeline_shaders(my_data, device, pPipeline)) {
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001926 skipCall = VK_TRUE;
1927 }
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001928 // VS is required
1929 if (!(pPipeline->active_shaders & VK_SHADER_STAGE_VERTEX_BIT)) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001930 skipCall |=
1931 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1932 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
1933 DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
1934 "Invalid Pipeline CreateInfo State: Vtx Shader required");
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001935 }
1936 // Either both or neither TC/TE shaders should be defined
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001937 if (((pPipeline->active_shaders &
1938 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) == 0) !=
1939 ((pPipeline->active_shaders &
1940 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) == 0)) {
1941 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1942 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
1943 DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
1944 "Invalid Pipeline CreateInfo State: TE and TC "
1945 "shaders must be included or excluded as a pair");
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001946 }
1947 // Compute shaders should be specified independent of Gfx shaders
1948 if ((pPipeline->active_shaders & VK_SHADER_STAGE_COMPUTE_BIT) &&
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001949 (pPipeline->active_shaders &
1950 (VK_SHADER_STAGE_VERTEX_BIT |
1951 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
1952 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT |
1953 VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_FRAGMENT_BIT))) {
1954 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1955 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
1956 DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
1957 "Invalid Pipeline CreateInfo State: Do not specify "
1958 "Compute Shader for Gfx Pipeline");
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001959 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001960 // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology is only valid for
1961 // tessellation pipelines.
1962 // Mismatching primitive topology and tessellation fails graphics pipeline
1963 // creation.
1964 if (pPipeline->active_shaders &
1965 (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
1966 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) &&
Chia-I Wu515eb8f2015-10-31 00:31:16 +08001967 (pPipeline->iaStateCI.topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001968 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1969 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
1970 DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
1971 "Invalid Pipeline CreateInfo State: "
1972 "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST must be set as "
1973 "IA topology for tessellation pipelines");
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001974 }
Chia-I Wu515eb8f2015-10-31 00:31:16 +08001975 if (pPipeline->iaStateCI.topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001976 if (~pPipeline->active_shaders &
1977 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {
1978 skipCall |=
1979 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1980 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
1981 DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
1982 "Invalid Pipeline CreateInfo State: "
1983 "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology "
1984 "is only valid for tessellation pipelines");
Tobin Ehlis912df022015-09-17 08:46:18 -06001985 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001986 if (!pPipeline->tessStateCI.patchControlPoints ||
1987 (pPipeline->tessStateCI.patchControlPoints > 32)) {
1988 skipCall |=
1989 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1990 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
1991 DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
1992 "Invalid Pipeline CreateInfo State: "
1993 "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology "
1994 "used with patchControlPoints value %u."
1995 " patchControlPoints should be >0 and <=32.",
1996 pPipeline->tessStateCI.patchControlPoints);
Tobin Ehlis912df022015-09-17 08:46:18 -06001997 }
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001998 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001999 // Viewport state must be included and viewport and scissor counts should
2000 // always match
2001 // NOTE : Even if these are flagged as dynamic, counts need to be set
2002 // correctly for shader compiler
Tobin Ehlisd332f282015-10-02 11:00:56 -06002003 if (!pPipeline->graphicsPipelineCI.pViewportState) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002004 skipCall |=
2005 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2006 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
2007 DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
2008 "Gfx Pipeline pViewportState is null. Even if viewport and "
2009 "scissors are dynamic PSO must include viewportCount and "
2010 "scissorCount in pViewportState.");
2011 } else if (pPipeline->graphicsPipelineCI.pViewportState->scissorCount !=
2012 pPipeline->graphicsPipelineCI.pViewportState->viewportCount) {
2013 skipCall |= log_msg(
2014 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2015 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
2016 DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
2017 "Gfx Pipeline viewport count (%u) must match scissor count (%u).",
2018 pPipeline->vpStateCI.viewportCount,
2019 pPipeline->vpStateCI.scissorCount);
Tobin Ehlisd332f282015-10-02 11:00:56 -06002020 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002021 // If viewport or scissor are not dynamic, then verify that data is
2022 // appropriate for count
Tobin Ehlisd332f282015-10-02 11:00:56 -06002023 VkBool32 dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT);
2024 VkBool32 dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR);
2025 if (!dynViewport) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002026 if (pPipeline->graphicsPipelineCI.pViewportState->viewportCount &&
2027 !pPipeline->graphicsPipelineCI.pViewportState->pViewports) {
2028 skipCall |= log_msg(
2029 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2030 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
2031 DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
2032 "Gfx Pipeline viewportCount is %u, but pViewports is NULL. "
2033 "For non-zero viewportCount, you must either include "
2034 "pViewports data, or include viewport in pDynamicState and "
2035 "set it with vkCmdSetViewport().",
2036 pPipeline->graphicsPipelineCI.pViewportState
2037 ->viewportCount);
Tobin Ehlise68360f2015-10-01 11:15:13 -06002038 }
2039 }
Tobin Ehlisd332f282015-10-02 11:00:56 -06002040 if (!dynScissor) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002041 if (pPipeline->graphicsPipelineCI.pViewportState->scissorCount &&
2042 !pPipeline->graphicsPipelineCI.pViewportState->pScissors) {
2043 skipCall |= log_msg(
2044 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2045 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
2046 DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
2047 "Gfx Pipeline scissorCount is %u, but pScissors is NULL. "
2048 "For non-zero scissorCount, you must either include "
2049 "pScissors data, or include scissor in pDynamicState and "
2050 "set it with vkCmdSetScissor().",
2051 pPipeline->graphicsPipelineCI.pViewportState->scissorCount);
Tobin Ehlisd332f282015-10-02 11:00:56 -06002052 }
Tobin Ehlise68360f2015-10-01 11:15:13 -06002053 }
2054 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002055 return skipCall;
Tobin Ehlis75283bf2015-06-18 15:59:33 -06002056}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002057
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002058// Init the pipeline mapping info based on pipeline create info LL tree
2059// Threading note : Calls to this function should wrapped in mutex
Tobin Ehlis88452832015-12-03 09:40:56 -07002060// TODO : this should really just be in the constructor for PIPELINE_NODE
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002061static PIPELINE_NODE *
2062initGraphicsPipeline(layer_data *dev_data,
2063 const VkGraphicsPipelineCreateInfo *pCreateInfo,
2064 PIPELINE_NODE *pBasePipeline) {
2065 PIPELINE_NODE *pPipeline = new PIPELINE_NODE;
Mark Lobodzinskic44baa52015-12-11 11:56:07 -07002066
Tobin Ehlis75283bf2015-06-18 15:59:33 -06002067 if (pBasePipeline) {
Mark Lobodzinskic44baa52015-12-11 11:56:07 -07002068 *pPipeline = *pBasePipeline;
Tobin Ehlis75283bf2015-06-18 15:59:33 -06002069 }
Mark Lobodzinskic44baa52015-12-11 11:56:07 -07002070
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002071 // First init create info
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002072 memcpy(&pPipeline->graphicsPipelineCI, pCreateInfo,
2073 sizeof(VkGraphicsPipelineCreateInfo));
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002074
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002075 size_t bufferSize = 0;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002076 const VkPipelineVertexInputStateCreateInfo *pVICI = NULL;
2077 const VkPipelineColorBlendStateCreateInfo *pCBCI = NULL;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002078
2079 for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002080 const VkPipelineShaderStageCreateInfo *pPSSCI =
2081 &pCreateInfo->pStages[i];
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002082
Chia-I Wu28e06912015-10-31 00:31:16 +08002083 switch (pPSSCI->stage) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002084 case VK_SHADER_STAGE_VERTEX_BIT:
2085 memcpy(&pPipeline->vsCI, pPSSCI,
2086 sizeof(VkPipelineShaderStageCreateInfo));
2087 pPipeline->active_shaders |= VK_SHADER_STAGE_VERTEX_BIT;
2088 break;
2089 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
2090 memcpy(&pPipeline->tcsCI, pPSSCI,
2091 sizeof(VkPipelineShaderStageCreateInfo));
2092 pPipeline->active_shaders |=
2093 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
2094 break;
2095 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
2096 memcpy(&pPipeline->tesCI, pPSSCI,
2097 sizeof(VkPipelineShaderStageCreateInfo));
2098 pPipeline->active_shaders |=
2099 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
2100 break;
2101 case VK_SHADER_STAGE_GEOMETRY_BIT:
2102 memcpy(&pPipeline->gsCI, pPSSCI,
2103 sizeof(VkPipelineShaderStageCreateInfo));
2104 pPipeline->active_shaders |= VK_SHADER_STAGE_GEOMETRY_BIT;
2105 break;
2106 case VK_SHADER_STAGE_FRAGMENT_BIT:
2107 memcpy(&pPipeline->fsCI, pPSSCI,
2108 sizeof(VkPipelineShaderStageCreateInfo));
2109 pPipeline->active_shaders |= VK_SHADER_STAGE_FRAGMENT_BIT;
2110 break;
2111 case VK_SHADER_STAGE_COMPUTE_BIT:
2112 // TODO : Flag error, CS is specified through
2113 // VkComputePipelineCreateInfo
2114 pPipeline->active_shaders |= VK_SHADER_STAGE_COMPUTE_BIT;
2115 break;
2116 default:
2117 // TODO : Flag error
2118 break;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002119 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002120 }
Tobin Ehlis963a4042015-09-29 08:18:34 -06002121 // Copy over GraphicsPipelineCreateInfo structure embedded pointers
2122 if (pCreateInfo->stageCount != 0) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002123 pPipeline->graphicsPipelineCI.pStages =
2124 new VkPipelineShaderStageCreateInfo[pCreateInfo->stageCount];
2125 bufferSize =
2126 pCreateInfo->stageCount * sizeof(VkPipelineShaderStageCreateInfo);
2127 memcpy((void *)pPipeline->graphicsPipelineCI.pStages,
2128 pCreateInfo->pStages, bufferSize);
Tobin Ehlis963a4042015-09-29 08:18:34 -06002129 }
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002130 if (pCreateInfo->pVertexInputState != NULL) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002131 memcpy((void *)&pPipeline->vertexInputCI,
2132 pCreateInfo->pVertexInputState,
2133 sizeof(VkPipelineVertexInputStateCreateInfo));
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002134 // Copy embedded ptrs
2135 pVICI = pCreateInfo->pVertexInputState;
Chia-I Wud50a7d72015-10-26 20:48:51 +08002136 pPipeline->vtxBindingCount = pVICI->vertexBindingDescriptionCount;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002137 if (pPipeline->vtxBindingCount) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002138 pPipeline->pVertexBindingDescriptions =
2139 new VkVertexInputBindingDescription[pPipeline->vtxBindingCount];
2140 bufferSize = pPipeline->vtxBindingCount *
2141 sizeof(VkVertexInputBindingDescription);
2142 memcpy((void *)pPipeline->pVertexBindingDescriptions,
2143 pVICI->pVertexBindingDescriptions, bufferSize);
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002144 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08002145 pPipeline->vtxAttributeCount = pVICI->vertexAttributeDescriptionCount;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002146 if (pPipeline->vtxAttributeCount) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002147 pPipeline->pVertexAttributeDescriptions =
2148 new VkVertexInputAttributeDescription[pPipeline
2149 ->vtxAttributeCount];
2150 bufferSize = pPipeline->vtxAttributeCount *
2151 sizeof(VkVertexInputAttributeDescription);
2152 memcpy((void *)pPipeline->pVertexAttributeDescriptions,
2153 pVICI->pVertexAttributeDescriptions, bufferSize);
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002154 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002155 pPipeline->graphicsPipelineCI.pVertexInputState =
2156 &pPipeline->vertexInputCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002157 }
Tony Barbourdd6e32e2015-07-10 15:29:03 -06002158 if (pCreateInfo->pInputAssemblyState != NULL) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002159 memcpy((void *)&pPipeline->iaStateCI, pCreateInfo->pInputAssemblyState,
2160 sizeof(VkPipelineInputAssemblyStateCreateInfo));
2161 pPipeline->graphicsPipelineCI.pInputAssemblyState =
2162 &pPipeline->iaStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002163 }
Tony Barbourdd6e32e2015-07-10 15:29:03 -06002164 if (pCreateInfo->pTessellationState != NULL) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002165 memcpy((void *)&pPipeline->tessStateCI, pCreateInfo->pTessellationState,
2166 sizeof(VkPipelineTessellationStateCreateInfo));
2167 pPipeline->graphicsPipelineCI.pTessellationState =
2168 &pPipeline->tessStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002169 }
Tony Barbourdd6e32e2015-07-10 15:29:03 -06002170 if (pCreateInfo->pViewportState != NULL) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002171 memcpy((void *)&pPipeline->vpStateCI, pCreateInfo->pViewportState,
2172 sizeof(VkPipelineViewportStateCreateInfo));
Tony Barbourdd6e32e2015-07-10 15:29:03 -06002173 pPipeline->graphicsPipelineCI.pViewportState = &pPipeline->vpStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002174 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002175 if (pCreateInfo->pRasterizationState != NULL) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002176 memcpy((void *)&pPipeline->rsStateCI, pCreateInfo->pRasterizationState,
2177 sizeof(VkPipelineRasterizationStateCreateInfo));
2178 pPipeline->graphicsPipelineCI.pRasterizationState =
2179 &pPipeline->rsStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002180 }
Tony Barbourdd6e32e2015-07-10 15:29:03 -06002181 if (pCreateInfo->pMultisampleState != NULL) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002182 memcpy((void *)&pPipeline->msStateCI, pCreateInfo->pMultisampleState,
2183 sizeof(VkPipelineMultisampleStateCreateInfo));
Tony Barbourdd6e32e2015-07-10 15:29:03 -06002184 pPipeline->graphicsPipelineCI.pMultisampleState = &pPipeline->msStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002185 }
Tobin Ehlis963a4042015-09-29 08:18:34 -06002186 if (pCreateInfo->pDepthStencilState != NULL) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002187 memcpy((void *)&pPipeline->dsStateCI, pCreateInfo->pDepthStencilState,
2188 sizeof(VkPipelineDepthStencilStateCreateInfo));
2189 pPipeline->graphicsPipelineCI.pDepthStencilState =
2190 &pPipeline->dsStateCI;
Tobin Ehlis963a4042015-09-29 08:18:34 -06002191 }
Tony Barbourdd6e32e2015-07-10 15:29:03 -06002192 if (pCreateInfo->pColorBlendState != NULL) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002193 memcpy((void *)&pPipeline->cbStateCI, pCreateInfo->pColorBlendState,
2194 sizeof(VkPipelineColorBlendStateCreateInfo));
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002195 // Copy embedded ptrs
Tony Barbourdd6e32e2015-07-10 15:29:03 -06002196 pCBCI = pCreateInfo->pColorBlendState;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002197 pPipeline->attachmentCount = pCBCI->attachmentCount;
2198 if (pPipeline->attachmentCount) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002199 pPipeline->pAttachments =
2200 new VkPipelineColorBlendAttachmentState[pPipeline
2201 ->attachmentCount];
2202 bufferSize = pPipeline->attachmentCount *
2203 sizeof(VkPipelineColorBlendAttachmentState);
2204 memcpy((void *)pPipeline->pAttachments, pCBCI->pAttachments,
2205 bufferSize);
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002206 }
Tony Barbourdd6e32e2015-07-10 15:29:03 -06002207 pPipeline->graphicsPipelineCI.pColorBlendState = &pPipeline->cbStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002208 }
Tobin Ehlis963a4042015-09-29 08:18:34 -06002209 if (pCreateInfo->pDynamicState != NULL) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002210 memcpy((void *)&pPipeline->dynStateCI, pCreateInfo->pDynamicState,
2211 sizeof(VkPipelineDynamicStateCreateInfo));
Tobin Ehlis963a4042015-09-29 08:18:34 -06002212 if (pPipeline->dynStateCI.dynamicStateCount) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002213 pPipeline->dynStateCI.pDynamicStates =
2214 new VkDynamicState[pPipeline->dynStateCI.dynamicStateCount];
2215 bufferSize = pPipeline->dynStateCI.dynamicStateCount *
2216 sizeof(VkDynamicState);
2217 memcpy((void *)pPipeline->dynStateCI.pDynamicStates,
2218 pCreateInfo->pDynamicState->pDynamicStates, bufferSize);
Tobin Ehlis963a4042015-09-29 08:18:34 -06002219 }
2220 pPipeline->graphicsPipelineCI.pDynamicState = &pPipeline->dynStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002221 }
Tobin Ehlis88452832015-12-03 09:40:56 -07002222 pPipeline->active_sets.clear();
Tobin Ehlis75283bf2015-06-18 15:59:33 -06002223 return pPipeline;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002224}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002225
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002226// Free the Pipeline nodes
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002227static void deletePipelines(layer_data *my_data) {
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002228 if (my_data->pipelineMap.size() <= 0)
David Pinedod8f83d82015-04-27 16:36:17 -06002229 return;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002230 for (auto ii = my_data->pipelineMap.begin();
2231 ii != my_data->pipelineMap.end(); ++ii) {
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002232 if ((*ii).second->graphicsPipelineCI.stageCount != 0) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002233 delete[](*ii).second->graphicsPipelineCI.pStages;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06002234 }
Tobin Ehlisf313c8b2015-04-01 11:59:08 -06002235 if ((*ii).second->pVertexBindingDescriptions) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002236 delete[](*ii).second->pVertexBindingDescriptions;
Tobin Ehlisf313c8b2015-04-01 11:59:08 -06002237 }
2238 if ((*ii).second->pVertexAttributeDescriptions) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002239 delete[](*ii).second->pVertexAttributeDescriptions;
Tobin Ehlisf313c8b2015-04-01 11:59:08 -06002240 }
2241 if ((*ii).second->pAttachments) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002242 delete[](*ii).second->pAttachments;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002243 }
Tobin Ehlis963a4042015-09-29 08:18:34 -06002244 if ((*ii).second->dynStateCI.dynamicStateCount != 0) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002245 delete[](*ii).second->dynStateCI.pDynamicStates;
Tobin Ehlis963a4042015-09-29 08:18:34 -06002246 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002247 delete (*ii).second;
2248 }
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002249 my_data->pipelineMap.clear();
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002250}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002251
Tobin Ehliseba312c2015-04-01 08:40:34 -06002252// For given pipeline, return number of MSAA samples, or one if MSAA disabled
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002253static VkSampleCountFlagBits getNumSamples(layer_data *my_data,
2254 const VkPipeline pipeline) {
2255 PIPELINE_NODE *pPipe = my_data->pipelineMap[pipeline];
2256 if (VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO ==
2257 pPipe->msStateCI.sType) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002258 return pPipe->msStateCI.rasterizationSamples;
Tobin Ehlis577188e2015-07-13 14:51:15 -06002259 }
Chia-I Wu5c17c962015-10-31 00:31:16 +08002260 return VK_SAMPLE_COUNT_1_BIT;
Tobin Ehliseba312c2015-04-01 08:40:34 -06002261}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002262
Tobin Ehliseba312c2015-04-01 08:40:34 -06002263// Validate state related to the PSO
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002264static VkBool32
2265validatePipelineState(layer_data *my_data, const GLOBAL_CB_NODE *pCB,
2266 const VkPipelineBindPoint pipelineBindPoint,
2267 const VkPipeline pipeline) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002268 if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) {
Tobin Ehliseba312c2015-04-01 08:40:34 -06002269 // Verify that any MSAA request in PSO matches sample# in bound FB
Chia-I Wu5c17c962015-10-31 00:31:16 +08002270 VkSampleCountFlagBits psoNumSamples = getNumSamples(my_data, pipeline);
Tobin Ehliseba312c2015-04-01 08:40:34 -06002271 if (pCB->activeRenderPass) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002272 const VkRenderPassCreateInfo *pRPCI =
2273 my_data->renderPassMap[pCB->activeRenderPass]->pCreateInfo;
2274 const VkSubpassDescription *pSD =
2275 &pRPCI->pSubpasses[pCB->activeSubpass];
2276 VkSampleCountFlagBits subpassNumSamples = (VkSampleCountFlagBits)0;
Chia-I Wu08accc62015-07-07 11:50:03 +08002277 uint32_t i;
2278
Chia-I Wud50a7d72015-10-26 20:48:51 +08002279 for (i = 0; i < pSD->colorAttachmentCount; i++) {
Chia-I Wu5c17c962015-10-31 00:31:16 +08002280 VkSampleCountFlagBits samples;
Chia-I Wu08accc62015-07-07 11:50:03 +08002281
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002282 if (pSD->pColorAttachments[i].attachment ==
2283 VK_ATTACHMENT_UNUSED)
Chia-I Wu08accc62015-07-07 11:50:03 +08002284 continue;
2285
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002286 samples =
2287 pRPCI->pAttachments[pSD->pColorAttachments[i].attachment]
2288 .samples;
2289 if (subpassNumSamples == (VkSampleCountFlagBits)0) {
Chia-I Wu08accc62015-07-07 11:50:03 +08002290 subpassNumSamples = samples;
2291 } else if (subpassNumSamples != samples) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002292 subpassNumSamples = (VkSampleCountFlagBits)-1;
Chia-I Wu08accc62015-07-07 11:50:03 +08002293 break;
2294 }
2295 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002296 if (pSD->pDepthStencilAttachment &&
2297 pSD->pDepthStencilAttachment->attachment !=
2298 VK_ATTACHMENT_UNUSED) {
2299 const VkSampleCountFlagBits samples =
2300 pRPCI
2301 ->pAttachments[pSD->pDepthStencilAttachment->attachment]
2302 .samples;
2303 if (subpassNumSamples == (VkSampleCountFlagBits)0)
Chia-I Wu08accc62015-07-07 11:50:03 +08002304 subpassNumSamples = samples;
2305 else if (subpassNumSamples != samples)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002306 subpassNumSamples = (VkSampleCountFlagBits)-1;
Chia-I Wu08accc62015-07-07 11:50:03 +08002307 }
2308
2309 if (psoNumSamples != subpassNumSamples) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002310 return log_msg(
2311 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2312 VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
2313 (uint64_t)pipeline, __LINE__,
2314 DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS",
2315 "Num samples mismatch! Binding PSO (%#" PRIxLEAST64
2316 ") with %u samples while current RenderPass (%#" PRIxLEAST64
2317 ") w/ %u samples!",
2318 (uint64_t)pipeline, psoNumSamples,
2319 (uint64_t)pCB->activeRenderPass, subpassNumSamples);
Tobin Ehliseba312c2015-04-01 08:40:34 -06002320 }
2321 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002322 // TODO : I believe it's an error if we reach this point and don't
2323 // have an activeRenderPass
Tobin Ehliseba312c2015-04-01 08:40:34 -06002324 // Verify and flag error as appropriate
2325 }
2326 // TODO : Add more checks here
2327 } else {
2328 // TODO : Validate non-gfx pipeline updates
2329 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002330 return VK_FALSE;
Tobin Ehliseba312c2015-04-01 08:40:34 -06002331}
2332
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002333// Block of code at start here specifically for managing/tracking DSs
2334
Tobin Ehlis793ad302015-04-03 12:01:11 -06002335// Return Pool node ptr for specified pool or else NULL
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002336static DESCRIPTOR_POOL_NODE *getPoolNode(layer_data *my_data,
2337 const VkDescriptorPool pool) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002338 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002339 if (my_data->descriptorPoolMap.find(pool) ==
2340 my_data->descriptorPoolMap.end()) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002341 loader_platform_thread_unlock_mutex(&globalLock);
2342 return NULL;
2343 }
2344 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07002345 return my_data->descriptorPoolMap[pool];
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002346}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002347
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002348static LAYOUT_NODE *getLayoutNode(layer_data *my_data,
2349 const VkDescriptorSetLayout layout) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002350 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002351 if (my_data->descriptorSetLayoutMap.find(layout) ==
2352 my_data->descriptorSetLayoutMap.end()) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002353 loader_platform_thread_unlock_mutex(&globalLock);
2354 return NULL;
2355 }
2356 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07002357 return my_data->descriptorSetLayoutMap[layout];
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002358}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002359
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002360// Return VK_FALSE if update struct is of valid type, otherwise flag error and
2361// return code from callback
2362static VkBool32 validUpdateStruct(layer_data *my_data, const VkDevice device,
2363 const GENERIC_HEADER *pUpdateStruct) {
2364 switch (pUpdateStruct->sType) {
2365 case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
2366 case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
2367 return VK_FALSE;
2368 default:
2369 return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2370 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
2371 DRAWSTATE_INVALID_UPDATE_STRUCT, "DS",
2372 "Unexpected UPDATE struct of type %s (value %u) in "
2373 "vkUpdateDescriptors() struct tree",
2374 string_VkStructureType(pUpdateStruct->sType),
2375 pUpdateStruct->sType);
Tobin Ehlis0174fed2015-05-28 12:10:17 -06002376 }
2377}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002378
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002379// Set count for given update struct in the last parameter
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002380// Return value of skipCall, which is only VK_TRUE if error occurs and callback
2381// signals execution to cease
2382static uint32_t getUpdateCount(layer_data *my_data, const VkDevice device,
2383 const GENERIC_HEADER *pUpdateStruct) {
2384 switch (pUpdateStruct->sType) {
2385 case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
2386 return ((VkWriteDescriptorSet *)pUpdateStruct)->descriptorCount;
2387 case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
2388 // TODO : Need to understand this case better and make sure code is
2389 // correct
2390 return ((VkCopyDescriptorSet *)pUpdateStruct)->descriptorCount;
Tobin Ehlis793ad302015-04-03 12:01:11 -06002391 }
Courtney Goeltzenleuchter7f47bca2015-12-16 16:08:08 -07002392
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002393 return 0;
Tobin Ehlis793ad302015-04-03 12:01:11 -06002394}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002395
Tobin Ehlis793ad302015-04-03 12:01:11 -06002396// For given Layout Node and binding, return index where that binding begins
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002397static uint32_t getBindingStartIndex(const LAYOUT_NODE *pLayout,
2398 const uint32_t binding) {
Tobin Ehlis793ad302015-04-03 12:01:11 -06002399 uint32_t offsetIndex = 0;
Chia-I Wud46e6ae2015-10-31 00:31:16 +08002400 for (uint32_t i = 0; i < pLayout->createInfo.bindingCount; i++) {
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07002401 if (pLayout->createInfo.pBindings[i].binding == binding)
Chia-I Wud46e6ae2015-10-31 00:31:16 +08002402 break;
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07002403 offsetIndex += pLayout->createInfo.pBindings[i].descriptorCount;
Tobin Ehlis793ad302015-04-03 12:01:11 -06002404 }
2405 return offsetIndex;
2406}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002407
Tobin Ehlis793ad302015-04-03 12:01:11 -06002408// For given layout node and binding, return last index that is updated
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002409static uint32_t getBindingEndIndex(const LAYOUT_NODE *pLayout,
2410 const uint32_t binding) {
Tobin Ehlis793ad302015-04-03 12:01:11 -06002411 uint32_t offsetIndex = 0;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002412 for (uint32_t i = 0; i < pLayout->createInfo.bindingCount; i++) {
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07002413 offsetIndex += pLayout->createInfo.pBindings[i].descriptorCount;
2414 if (pLayout->createInfo.pBindings[i].binding == binding)
Chia-I Wud46e6ae2015-10-31 00:31:16 +08002415 break;
Tobin Ehlis793ad302015-04-03 12:01:11 -06002416 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002417 return offsetIndex - 1;
Tobin Ehlis793ad302015-04-03 12:01:11 -06002418}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002419
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002420// For given layout and update, return the first overall index of the layout
2421// that is updated
2422static uint32_t getUpdateStartIndex(layer_data *my_data, const VkDevice device,
2423 const LAYOUT_NODE *pLayout,
2424 const uint32_t binding,
2425 const uint32_t arrayIndex,
2426 const GENERIC_HEADER *pUpdateStruct) {
2427 return getBindingStartIndex(pLayout, binding) + arrayIndex;
Tobin Ehlis793ad302015-04-03 12:01:11 -06002428}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002429
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002430// For given layout and update, return the last overall index of the layout that
2431// is updated
2432static uint32_t getUpdateEndIndex(layer_data *my_data, const VkDevice device,
2433 const LAYOUT_NODE *pLayout,
2434 const uint32_t binding,
2435 const uint32_t arrayIndex,
2436 const GENERIC_HEADER *pUpdateStruct) {
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002437 uint32_t count = getUpdateCount(my_data, device, pUpdateStruct);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002438 return getBindingStartIndex(pLayout, binding) + arrayIndex + count - 1;
Tobin Ehlis793ad302015-04-03 12:01:11 -06002439}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002440
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002441// Verify that the descriptor type in the update struct matches what's expected
2442// by the layout
2443static VkBool32 validateUpdateConsistency(layer_data *my_data,
2444 const VkDevice device,
2445 const LAYOUT_NODE *pLayout,
2446 const GENERIC_HEADER *pUpdateStruct,
2447 uint32_t startIndex,
2448 uint32_t endIndex) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002449 // First get actual type of update
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002450 VkBool32 skipCall = VK_FALSE;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06002451 VkDescriptorType actualType;
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002452 uint32_t i = 0;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002453 switch (pUpdateStruct->sType) {
2454 case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
2455 actualType = ((VkWriteDescriptorSet *)pUpdateStruct)->descriptorType;
2456 break;
2457 case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
2458 /* no need to validate */
2459 return VK_FALSE;
2460 break;
2461 default:
2462 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2463 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
2464 DRAWSTATE_INVALID_UPDATE_STRUCT, "DS",
2465 "Unexpected UPDATE struct of type %s (value %u) in "
2466 "vkUpdateDescriptors() struct tree",
2467 string_VkStructureType(pUpdateStruct->sType),
2468 pUpdateStruct->sType);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002469 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002470 if (VK_FALSE == skipCall) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002471 // Set first stageFlags as reference and verify that all other updates
2472 // match it
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002473 VkShaderStageFlags refStageFlags = pLayout->stageFlags[startIndex];
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002474 for (i = startIndex; i <= endIndex; i++) {
Tobin Ehlis644ff042015-10-20 10:11:55 -06002475 if (pLayout->descriptorTypes[i] != actualType) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002476 skipCall |= log_msg(
2477 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2478 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
2479 DRAWSTATE_DESCRIPTOR_TYPE_MISMATCH, "DS",
2480 "Write descriptor update has descriptor type %s that does "
2481 "not match overlapping binding descriptor type of %s!",
2482 string_VkDescriptorType(actualType),
2483 string_VkDescriptorType(pLayout->descriptorTypes[i]));
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002484 }
2485 if (pLayout->stageFlags[i] != refStageFlags) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002486 skipCall |= log_msg(
2487 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2488 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
2489 DRAWSTATE_DESCRIPTOR_STAGEFLAGS_MISMATCH, "DS",
2490 "Write descriptor update has stageFlags %x that do not "
2491 "match overlapping binding descriptor stageFlags of %x!",
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002492 refStageFlags, pLayout->stageFlags[i]);
Tobin Ehlis483cc352015-09-30 08:30:20 -06002493 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002494 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002495 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002496 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002497}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002498
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002499// Determine the update type, allocate a new struct of that type, shadow the
2500// given pUpdate
2501// struct into the pNewNode param. Return VK_TRUE if error condition
2502// encountered and callback signals early exit.
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002503// NOTE : Calls to this function should be wrapped in mutex
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002504static VkBool32 shadowUpdateNode(layer_data *my_data, const VkDevice device,
2505 GENERIC_HEADER *pUpdate,
2506 GENERIC_HEADER **pNewNode) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002507 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002508 VkWriteDescriptorSet *pWDS = NULL;
2509 VkCopyDescriptorSet *pCDS = NULL;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002510 size_t array_size = 0;
2511 size_t base_array_size = 0;
2512 size_t total_array_size = 0;
2513 size_t baseBuffAddr = 0;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002514 switch (pUpdate->sType) {
2515 case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
2516 pWDS = new VkWriteDescriptorSet;
2517 *pNewNode = (GENERIC_HEADER *)pWDS;
2518 memcpy(pWDS, pUpdate, sizeof(VkWriteDescriptorSet));
Courtney Goeltzenleuchter4cb6d922015-10-23 13:38:14 -06002519
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002520 switch (pWDS->descriptorType) {
2521 case VK_DESCRIPTOR_TYPE_SAMPLER:
2522 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2523 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2524 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
2525 VkDescriptorImageInfo *info =
2526 new VkDescriptorImageInfo[pWDS->descriptorCount];
2527 memcpy(info, pWDS->pImageInfo,
2528 pWDS->descriptorCount * sizeof(VkDescriptorImageInfo));
2529 pWDS->pImageInfo = info;
2530 } break;
2531 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2532 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
2533 VkBufferView *info = new VkBufferView[pWDS->descriptorCount];
2534 memcpy(info, pWDS->pTexelBufferView,
2535 pWDS->descriptorCount * sizeof(VkBufferView));
2536 pWDS->pTexelBufferView = info;
2537 } break;
2538 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2539 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2540 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2541 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
2542 VkDescriptorBufferInfo *info =
2543 new VkDescriptorBufferInfo[pWDS->descriptorCount];
2544 memcpy(info, pWDS->pBufferInfo,
2545 pWDS->descriptorCount * sizeof(VkDescriptorBufferInfo));
2546 pWDS->pBufferInfo = info;
2547 } break;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002548 default:
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002549 return VK_ERROR_VALIDATION_FAILED_EXT;
2550 break;
2551 }
2552 break;
2553 case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
2554 pCDS = new VkCopyDescriptorSet;
2555 *pNewNode = (GENERIC_HEADER *)pCDS;
2556 memcpy(pCDS, pUpdate, sizeof(VkCopyDescriptorSet));
2557 break;
2558 default:
2559 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2560 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
2561 DRAWSTATE_INVALID_UPDATE_STRUCT, "DS",
2562 "Unexpected UPDATE struct of type %s (value %u) in "
2563 "vkUpdateDescriptors() struct tree",
2564 string_VkStructureType(pUpdate->sType), pUpdate->sType))
2565 return VK_TRUE;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002566 }
2567 // Make sure that pNext for the end of shadow copy is NULL
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002568 (*pNewNode)->pNext = NULL;
2569 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002570}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002571
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002572// Verify that given sampler is valid
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002573static VkBool32 validateSampler(const layer_data *my_data,
2574 const VkSampler *pSampler,
2575 const VkBool32 immutable) {
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002576 VkBool32 skipCall = VK_FALSE;
Chia-I Wue2fc5522015-10-26 20:04:44 +08002577 auto sampIt = my_data->sampleMap.find(*pSampler);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002578 if (sampIt == my_data->sampleMap.end()) {
2579 if (!immutable) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002580 skipCall |= log_msg(
2581 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2582 VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, (uint64_t)*pSampler,
2583 __LINE__, DRAWSTATE_SAMPLER_DESCRIPTOR_ERROR, "DS",
2584 "vkUpdateDescriptorSets: Attempt to update descriptor with "
2585 "invalid sampler %#" PRIxLEAST64,
2586 (uint64_t)*pSampler);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002587 } else { // immutable
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002588 skipCall |= log_msg(
2589 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2590 VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, (uint64_t)*pSampler,
2591 __LINE__, DRAWSTATE_SAMPLER_DESCRIPTOR_ERROR, "DS",
2592 "vkUpdateDescriptorSets: Attempt to update descriptor whose "
2593 "binding has an invalid immutable sampler %#" PRIxLEAST64,
2594 (uint64_t)*pSampler);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002595 }
2596 } else {
2597 // TODO : Any further checks we want to do on the sampler?
2598 }
2599 return skipCall;
2600}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002601
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002602// Verify that given imageView is valid
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002603static VkBool32 validateImageView(const layer_data *my_data,
2604 const VkImageView *pImageView,
2605 const VkImageLayout imageLayout) {
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002606 VkBool32 skipCall = VK_FALSE;
Chia-I Wue2fc5522015-10-26 20:04:44 +08002607 auto ivIt = my_data->imageViewMap.find(*pImageView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002608 if (ivIt == my_data->imageViewMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002609 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2610 VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT,
2611 (uint64_t)*pImageView, __LINE__,
2612 DRAWSTATE_IMAGEVIEW_DESCRIPTOR_ERROR, "DS",
2613 "vkUpdateDescriptorSets: Attempt to update "
2614 "descriptor with invalid imageView %#" PRIxLEAST64,
2615 (uint64_t)*pImageView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002616 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002617 // Validate that imageLayout is compatible with aspectMask and image
2618 // format
2619 VkImageAspectFlags aspectMask =
2620 ivIt->second->subresourceRange.aspectMask;
Chia-I Wue2fc5522015-10-26 20:04:44 +08002621 VkImage image = ivIt->second->image;
Michael Lentine7b236262015-10-23 12:41:44 -07002622 // TODO : Check here in case we have a bad image
Tobin Ehlis75cd1c52016-01-21 10:21:04 -07002623 auto imgIt = my_data->imageLayoutMap.find(image);
2624 if (imgIt == my_data->imageLayoutMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002625 skipCall |= log_msg(
2626 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2627 VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)image,
2628 __LINE__, DRAWSTATE_IMAGEVIEW_DESCRIPTOR_ERROR, "DS",
2629 "vkUpdateDescriptorSets: Attempt to update descriptor with "
2630 "invalid image %#" PRIxLEAST64 " in imageView %#" PRIxLEAST64,
2631 (uint64_t)image, (uint64_t)*pImageView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002632 } else {
2633 VkFormat format = (*imgIt).second->format;
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -07002634 VkBool32 ds = vk_format_is_depth_or_stencil(format);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002635 switch (imageLayout) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002636 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
2637 // Only Color bit must be set
2638 if ((aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) !=
2639 VK_IMAGE_ASPECT_COLOR_BIT) {
2640 skipCall |= log_msg(
2641 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2642 VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT,
2643 (uint64_t)*pImageView, __LINE__,
2644 DRAWSTATE_INVALID_IMAGE_ASPECT, "DS",
2645 "vkUpdateDescriptorSets: Updating descriptor with "
2646 "layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL and "
2647 "imageView %#" PRIxLEAST64 ""
2648 " that does not have VK_IMAGE_ASPECT_COLOR_BIT set.",
2649 (uint64_t)*pImageView);
2650 }
2651 // format must NOT be DS
2652 if (ds) {
2653 skipCall |= log_msg(
2654 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2655 VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT,
2656 (uint64_t)*pImageView, __LINE__,
2657 DRAWSTATE_IMAGEVIEW_DESCRIPTOR_ERROR, "DS",
2658 "vkUpdateDescriptorSets: Updating descriptor with "
2659 "layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL and "
2660 "imageView %#" PRIxLEAST64 ""
2661 " but the image format is %s which is not a color "
2662 "format.",
2663 (uint64_t)*pImageView, string_VkFormat(format));
2664 }
2665 break;
2666 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
2667 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
2668 // Depth or stencil bit must be set, but both must NOT be set
2669 if (aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) {
2670 if (aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) {
2671 // both must NOT be set
2672 skipCall |= log_msg(
2673 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2674 VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT,
2675 (uint64_t)*pImageView, __LINE__,
2676 DRAWSTATE_INVALID_IMAGE_ASPECT, "DS",
2677 "vkUpdateDescriptorSets: Updating descriptor with "
2678 "imageView %#" PRIxLEAST64 ""
2679 " that has both STENCIL and DEPTH aspects set",
2680 (uint64_t)*pImageView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002681 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002682 } else if (!(aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
2683 // Neither were set
2684 skipCall |= log_msg(
2685 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2686 VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT,
2687 (uint64_t)*pImageView, __LINE__,
2688 DRAWSTATE_INVALID_IMAGE_ASPECT, "DS",
2689 "vkUpdateDescriptorSets: Updating descriptor with "
2690 "layout %s and imageView %#" PRIxLEAST64 ""
2691 " that does not have STENCIL or DEPTH aspect set.",
2692 string_VkImageLayout(imageLayout),
2693 (uint64_t)*pImageView);
2694 }
2695 // format must be DS
2696 if (!ds) {
2697 skipCall |= log_msg(
2698 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2699 VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT,
2700 (uint64_t)*pImageView, __LINE__,
2701 DRAWSTATE_IMAGEVIEW_DESCRIPTOR_ERROR, "DS",
2702 "vkUpdateDescriptorSets: Updating descriptor with "
2703 "layout %s and imageView %#" PRIxLEAST64 ""
2704 " but the image format is %s which is not a "
2705 "depth/stencil format.",
2706 string_VkImageLayout(imageLayout),
2707 (uint64_t)*pImageView, string_VkFormat(format));
2708 }
2709 break;
2710 default:
2711 // anything to check for other layouts?
2712 break;
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002713 }
2714 }
2715 }
2716 return skipCall;
2717}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002718
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002719// Verify that given bufferView is valid
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002720static VkBool32 validateBufferView(const layer_data *my_data,
2721 const VkBufferView *pBufferView) {
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002722 VkBool32 skipCall = VK_FALSE;
Chia-I Wue2fc5522015-10-26 20:04:44 +08002723 auto sampIt = my_data->bufferViewMap.find(*pBufferView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002724 if (sampIt == my_data->bufferViewMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002725 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2726 VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT,
2727 (uint64_t)*pBufferView, __LINE__,
2728 DRAWSTATE_BUFFERVIEW_DESCRIPTOR_ERROR, "DS",
2729 "vkUpdateDescriptorSets: Attempt to update "
2730 "descriptor with invalid bufferView %#" PRIxLEAST64,
2731 (uint64_t)*pBufferView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002732 } else {
2733 // TODO : Any further checks we want to do on the bufferView?
2734 }
2735 return skipCall;
2736}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002737
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002738// Verify that given bufferInfo is valid
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002739static VkBool32 validateBufferInfo(const layer_data *my_data,
2740 const VkDescriptorBufferInfo *pBufferInfo) {
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002741 VkBool32 skipCall = VK_FALSE;
Chia-I Wue2fc5522015-10-26 20:04:44 +08002742 auto sampIt = my_data->bufferMap.find(pBufferInfo->buffer);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002743 if (sampIt == my_data->bufferMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002744 skipCall |=
2745 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2746 VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
2747 (uint64_t)pBufferInfo->buffer, __LINE__,
2748 DRAWSTATE_BUFFERINFO_DESCRIPTOR_ERROR, "DS",
2749 "vkUpdateDescriptorSets: Attempt to update descriptor "
2750 "where bufferInfo has invalid buffer %#" PRIxLEAST64,
2751 (uint64_t)pBufferInfo->buffer);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002752 } else {
2753 // TODO : Any further checks we want to do on the bufferView?
2754 }
2755 return skipCall;
2756}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002757
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002758static VkBool32
2759validateUpdateContents(const layer_data *my_data,
2760 const VkWriteDescriptorSet *pWDS,
2761 const VkDescriptorSetLayoutBinding *pLayoutBinding) {
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002762 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002763 // First verify that for the given Descriptor type, the correct
2764 // DescriptorInfo data is supplied
2765 VkBufferView *pBufferView = NULL;
2766 const VkSampler *pSampler = NULL;
2767 VkImageView *pImageView = NULL;
2768 VkImageLayout *pImageLayout = NULL;
2769 VkDescriptorBufferInfo *pBufferInfo = NULL;
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002770 VkBool32 immutable = VK_FALSE;
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002771 uint32_t i = 0;
2772 // For given update type, verify that update contents are correct
2773 switch (pWDS->descriptorType) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002774 case VK_DESCRIPTOR_TYPE_SAMPLER:
2775 for (i = 0; i < pWDS->descriptorCount; ++i) {
2776 skipCall |= validateSampler(my_data, &(pWDS->pImageInfo[i].sampler),
2777 immutable);
2778 }
2779 break;
2780 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2781 for (i = 0; i < pWDS->descriptorCount; ++i) {
2782 if (NULL == pLayoutBinding->pImmutableSamplers) {
2783 pSampler = &(pWDS->pImageInfo[i].sampler);
2784 if (immutable) {
2785 skipCall |= log_msg(
2786 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2787 VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT,
2788 (uint64_t)*pSampler, __LINE__,
2789 DRAWSTATE_INCONSISTENT_IMMUTABLE_SAMPLER_UPDATE, "DS",
2790 "vkUpdateDescriptorSets: Update #%u is not an "
2791 "immutable sampler %#" PRIxLEAST64
2792 ", but previous update(s) from this "
2793 "VkWriteDescriptorSet struct used an immutable "
2794 "sampler. All updates from a single struct must either "
2795 "use immutable or non-immutable samplers.",
2796 i, (uint64_t)*pSampler);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002797 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002798 } else {
2799 if (i > 0 && !immutable) {
2800 skipCall |= log_msg(
2801 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2802 VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT,
2803 (uint64_t)*pSampler, __LINE__,
2804 DRAWSTATE_INCONSISTENT_IMMUTABLE_SAMPLER_UPDATE, "DS",
2805 "vkUpdateDescriptorSets: Update #%u is an immutable "
2806 "sampler, but previous update(s) from this "
2807 "VkWriteDescriptorSet struct used a non-immutable "
2808 "sampler. All updates from a single struct must either "
2809 "use immutable or non-immutable samplers.",
2810 i);
2811 }
2812 immutable = VK_TRUE;
2813 pSampler = &(pLayoutBinding->pImmutableSamplers[i]);
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002814 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002815 skipCall |= validateSampler(my_data, pSampler, immutable);
2816 }
2817 // Intentionally fall through here to also validate image stuff
2818 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2819 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2820 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2821 for (i = 0; i < pWDS->descriptorCount; ++i) {
2822 skipCall |=
2823 validateImageView(my_data, &(pWDS->pImageInfo[i].imageView),
2824 pWDS->pImageInfo[i].imageLayout);
2825 }
2826 break;
2827 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2828 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2829 for (i = 0; i < pWDS->descriptorCount; ++i) {
2830 skipCall |=
2831 validateBufferView(my_data, &(pWDS->pTexelBufferView[i]));
2832 }
2833 break;
2834 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2835 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2836 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2837 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2838 for (i = 0; i < pWDS->descriptorCount; ++i) {
2839 skipCall |= validateBufferInfo(my_data, &(pWDS->pBufferInfo[i]));
2840 }
2841 break;
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002842 }
2843 return skipCall;
2844}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002845// Validate that given set is valid and that it's not being used by an in-flight
2846// CmdBuffer
Tobin Ehlis9c4f38d2016-01-14 12:47:19 -07002847// func_str is the name of the calling function
2848// Return VK_FALSE if no errors occur
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002849// Return VK_TRUE if validation error occurs and callback returns VK_TRUE (to
2850// skip upcoming API call down the chain)
2851VkBool32 validateIdleDescriptorSet(const layer_data *my_data,
2852 VkDescriptorSet set, std::string func_str) {
Tobin Ehlis9c4f38d2016-01-14 12:47:19 -07002853 VkBool32 skip_call = VK_FALSE;
2854 auto set_node = my_data->setMap.find(set);
2855 if (set_node == my_data->setMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002856 skip_call |=
2857 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2858 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
2859 (uint64_t)(set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS",
2860 "Cannot call %s() on descriptor set %" PRIxLEAST64
2861 " that has not been allocated.",
2862 func_str.c_str(), (uint64_t)(set));
Tobin Ehlis9c4f38d2016-01-14 12:47:19 -07002863 } else {
2864 if (set_node->second->in_use.load()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002865 skip_call |=
2866 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2867 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
2868 (uint64_t)(set), __LINE__, DRAWSTATE_OBJECT_INUSE, "DS",
2869 "Cannot call %s() on descriptor set %" PRIxLEAST64
2870 " that is in use by a command buffer.",
2871 func_str.c_str(), (uint64_t)(set));
Tobin Ehlis9c4f38d2016-01-14 12:47:19 -07002872 }
2873 }
2874 return skip_call;
2875}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002876static void invalidateBoundCmdBuffers(layer_data *dev_data,
2877 const SET_NODE *pSet) {
Tobin Ehlise6e574b2016-01-24 23:25:31 -07002878 // Flag any CBs this set is bound to as INVALID
2879 for (auto cb : pSet->boundCmdBuffers) {
2880 auto cb_node = dev_data->commandBufferMap.find(cb);
2881 if (cb_node != dev_data->commandBufferMap.end()) {
2882 cb_node->second->state = CB_INVALID;
2883 }
2884 }
2885}
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002886// update DS mappings based on write and copy update arrays
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002887static VkBool32 dsUpdate(layer_data *my_data, VkDevice device,
2888 uint32_t descriptorWriteCount,
2889 const VkWriteDescriptorSet *pWDS,
2890 uint32_t descriptorCopyCount,
2891 const VkCopyDescriptorSet *pCDS) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002892 VkBool32 skipCall = VK_FALSE;
Chia-I Wu9d00ed72015-05-25 16:27:55 +08002893
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002894 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002895 LAYOUT_NODE *pLayout = NULL;
2896 VkDescriptorSetLayoutCreateInfo *pLayoutCI = NULL;
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002897 // Validate Write updates
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002898 uint32_t i = 0;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002899 for (i = 0; i < descriptorWriteCount; i++) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002900 VkDescriptorSet ds = pWDS[i].dstSet;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002901 SET_NODE *pSet = my_data->setMap[ds];
Tobin Ehlis9c4f38d2016-01-14 12:47:19 -07002902 // Set being updated cannot be in-flight
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002903 if ((skipCall = validateIdleDescriptorSet(
2904 my_data, ds, "VkUpdateDescriptorSets")) == VK_TRUE)
Tobin Ehlis9c4f38d2016-01-14 12:47:19 -07002905 return skipCall;
Tobin Ehlise6e574b2016-01-24 23:25:31 -07002906 // If set is bound to any cmdBuffers, mark them invalid
2907 invalidateBoundCmdBuffers(my_data, pSet);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002908 GENERIC_HEADER *pUpdate = (GENERIC_HEADER *)&pWDS[i];
Tobin Ehlis793ad302015-04-03 12:01:11 -06002909 pLayout = pSet->pLayout;
Tobin Ehlis0174fed2015-05-28 12:10:17 -06002910 // First verify valid update struct
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002911 if ((skipCall = validUpdateStruct(my_data, device, pUpdate)) ==
2912 VK_TRUE) {
Tobin Ehlis0174fed2015-05-28 12:10:17 -06002913 break;
2914 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002915 uint32_t binding = 0, endIndex = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002916 binding = pWDS[i].dstBinding;
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002917 // Make sure that layout being updated has the binding being updated
Chia-I Wud46e6ae2015-10-31 00:31:16 +08002918 if (pLayout->bindings.find(binding) == pLayout->bindings.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002919 skipCall |= log_msg(
2920 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2921 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)(ds),
2922 __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS",
2923 "Descriptor Set %" PRIu64 " does not have binding to match "
2924 "update binding %u for update type "
2925 "%s!",
2926 (uint64_t)(ds), binding,
2927 string_VkStructureType(pUpdate->sType));
Tobin Ehlis9c536442015-06-19 13:00:59 -06002928 } else {
Tobin Ehlis793ad302015-04-03 12:01:11 -06002929 // Next verify that update falls within size of given binding
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002930 endIndex = getUpdateEndIndex(my_data, device, pLayout, binding,
2931 pWDS[i].dstArrayElement, pUpdate);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002932 if (getBindingEndIndex(pLayout, binding) < endIndex) {
Tobin Ehlis793ad302015-04-03 12:01:11 -06002933 pLayoutCI = &pLayout->createInfo;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002934 string DSstr = vk_print_vkdescriptorsetlayoutcreateinfo(
2935 pLayoutCI, "{DS} ");
2936 skipCall |=
2937 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2938 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
2939 (uint64_t)(ds), __LINE__,
2940 DRAWSTATE_DESCRIPTOR_UPDATE_OUT_OF_BOUNDS, "DS",
2941 "Descriptor update type of %s is out of bounds for "
2942 "matching binding %u in Layout w/ CI:\n%s!",
2943 string_VkStructureType(pUpdate->sType), binding,
2944 DSstr.c_str());
2945 } else { // TODO : should we skip update on a type mismatch or force
2946 // it?
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002947 uint32_t startIndex;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002948 startIndex =
2949 getUpdateStartIndex(my_data, device, pLayout, binding,
2950 pWDS[i].dstArrayElement, pUpdate);
2951 // Layout bindings match w/ update, now verify that update type
2952 // & stageFlags are the same for entire update
2953 if ((skipCall = validateUpdateConsistency(
2954 my_data, device, pLayout, pUpdate, startIndex,
2955 endIndex)) == VK_FALSE) {
2956 // The update is within bounds and consistent, but need to
2957 // make sure contents make sense as well
2958 if ((skipCall = validateUpdateContents(
2959 my_data, &pWDS[i],
2960 &pLayout->createInfo.pBindings[binding])) ==
2961 VK_FALSE) {
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002962 // Update is good. Save the update info
2963 // Create new update struct for this set's shadow copy
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002964 GENERIC_HEADER *pNewNode = NULL;
2965 skipCall |= shadowUpdateNode(my_data, device, pUpdate,
2966 &pNewNode);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002967 if (NULL == pNewNode) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002968 skipCall |= log_msg(
2969 my_data->report_data,
2970 VK_DEBUG_REPORT_ERROR_BIT_EXT,
2971 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
2972 (uint64_t)(ds), __LINE__,
2973 DRAWSTATE_OUT_OF_MEMORY, "DS",
2974 "Out of memory while attempting to allocate "
2975 "UPDATE struct in vkUpdateDescriptors()");
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002976 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002977 // Insert shadow node into LL of updates for this
2978 // set
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002979 pNewNode->pNext = pSet->pUpdateStructs;
2980 pSet->pUpdateStructs = pNewNode;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002981 // Now update appropriate descriptor(s) to point to
2982 // new Update node
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002983 for (uint32_t j = startIndex; j <= endIndex; j++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002984 assert(j < pSet->descriptorCount);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002985 pSet->ppDescriptors[j] = pNewNode;
2986 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002987 }
2988 }
2989 }
2990 }
2991 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002992 }
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002993 // Now validate copy updates
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002994 for (i = 0; i < descriptorCopyCount; ++i) {
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002995 SET_NODE *pSrcSet = NULL, *pDstSet = NULL;
2996 LAYOUT_NODE *pSrcLayout = NULL, *pDstLayout = NULL;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07002997 uint32_t srcStartIndex = 0, srcEndIndex = 0, dstStartIndex = 0,
2998 dstEndIndex = 0;
2999 // For each copy make sure that update falls within given layout and
3000 // that types match
Chia-I Wue2fc5522015-10-26 20:04:44 +08003001 pSrcSet = my_data->setMap[pCDS[i].srcSet];
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003002 pDstSet = my_data->setMap[pCDS[i].dstSet];
Tobin Ehlis9c4f38d2016-01-14 12:47:19 -07003003 // Set being updated cannot be in-flight
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003004 if ((skipCall = validateIdleDescriptorSet(
3005 my_data, pDstSet->set, "VkUpdateDescriptorSets")) == VK_TRUE)
Tobin Ehlis9c4f38d2016-01-14 12:47:19 -07003006 return skipCall;
Tobin Ehlise6e574b2016-01-24 23:25:31 -07003007 invalidateBoundCmdBuffers(my_data, pDstSet);
Tobin Ehlis8a62e632015-10-27 15:43:38 -06003008 pSrcLayout = pSrcSet->pLayout;
3009 pDstLayout = pDstSet->pLayout;
3010 // Validate that src binding is valid for src set layout
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003011 if (pSrcLayout->bindings.find(pCDS[i].srcBinding) ==
3012 pSrcLayout->bindings.end()) {
3013 skipCall |=
3014 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3015 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
3016 (uint64_t)pSrcSet->set, __LINE__,
3017 DRAWSTATE_INVALID_UPDATE_INDEX,
3018 "DS", "Copy descriptor update %u has srcBinding %u "
3019 "which is out of bounds for underlying SetLayout "
3020 "%#" PRIxLEAST64 " which only has bindings 0-%u.",
3021 i, pCDS[i].srcBinding, (uint64_t)pSrcLayout->layout,
3022 pSrcLayout->createInfo.bindingCount - 1);
3023 } else if (pDstLayout->bindings.find(pCDS[i].dstBinding) ==
3024 pDstLayout->bindings.end()) {
3025 skipCall |=
3026 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3027 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
3028 (uint64_t)pDstSet->set, __LINE__,
3029 DRAWSTATE_INVALID_UPDATE_INDEX,
3030 "DS", "Copy descriptor update %u has dstBinding %u "
3031 "which is out of bounds for underlying SetLayout "
3032 "%#" PRIxLEAST64 " which only has bindings 0-%u.",
3033 i, pCDS[i].dstBinding, (uint64_t)pDstLayout->layout,
3034 pDstLayout->createInfo.bindingCount - 1);
Tobin Ehlis8a62e632015-10-27 15:43:38 -06003035 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003036 // Proceed with validation. Bindings are ok, but make sure update is
3037 // within bounds of given layout
3038 srcEndIndex = getUpdateEndIndex(
3039 my_data, device, pSrcLayout, pCDS[i].srcBinding,
3040 pCDS[i].srcArrayElement, (const GENERIC_HEADER *)&(pCDS[i]));
3041 dstEndIndex = getUpdateEndIndex(
3042 my_data, device, pDstLayout, pCDS[i].dstBinding,
3043 pCDS[i].dstArrayElement, (const GENERIC_HEADER *)&(pCDS[i]));
3044 if (getBindingEndIndex(pSrcLayout, pCDS[i].srcBinding) <
3045 srcEndIndex) {
Tobin Ehlis8a62e632015-10-27 15:43:38 -06003046 pLayoutCI = &pSrcLayout->createInfo;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003047 string DSstr = vk_print_vkdescriptorsetlayoutcreateinfo(
3048 pLayoutCI, "{DS} ");
3049 skipCall |=
3050 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3051 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
3052 (uint64_t)pSrcSet->set, __LINE__,
3053 DRAWSTATE_DESCRIPTOR_UPDATE_OUT_OF_BOUNDS, "DS",
3054 "Copy descriptor src update is out of bounds for "
3055 "matching binding %u in Layout w/ CI:\n%s!",
3056 pCDS[i].srcBinding, DSstr.c_str());
3057 } else if (getBindingEndIndex(pDstLayout, pCDS[i].dstBinding) <
3058 dstEndIndex) {
Tobin Ehlis8a62e632015-10-27 15:43:38 -06003059 pLayoutCI = &pDstLayout->createInfo;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003060 string DSstr = vk_print_vkdescriptorsetlayoutcreateinfo(
3061 pLayoutCI, "{DS} ");
3062 skipCall |=
3063 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3064 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
3065 (uint64_t)pDstSet->set, __LINE__,
3066 DRAWSTATE_DESCRIPTOR_UPDATE_OUT_OF_BOUNDS, "DS",
3067 "Copy descriptor dest update is out of bounds for "
3068 "matching binding %u in Layout w/ CI:\n%s!",
3069 pCDS[i].dstBinding, DSstr.c_str());
Tobin Ehlis8a62e632015-10-27 15:43:38 -06003070 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003071 srcStartIndex = getUpdateStartIndex(
3072 my_data, device, pSrcLayout, pCDS[i].srcBinding,
3073 pCDS[i].srcArrayElement,
3074 (const GENERIC_HEADER *)&(pCDS[i]));
3075 dstStartIndex = getUpdateStartIndex(
3076 my_data, device, pDstLayout, pCDS[i].dstBinding,
3077 pCDS[i].dstArrayElement,
3078 (const GENERIC_HEADER *)&(pCDS[i]));
3079 for (uint32_t j = 0; j < pCDS[i].descriptorCount; ++j) {
3080 // For copy just make sure that the types match and then
3081 // perform the update
3082 if (pSrcLayout->descriptorTypes[srcStartIndex + j] !=
3083 pDstLayout->descriptorTypes[dstStartIndex + j]) {
3084 skipCall |= log_msg(
3085 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3086 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
3087 DRAWSTATE_DESCRIPTOR_TYPE_MISMATCH, "DS",
3088 "Copy descriptor update index %u, update count "
3089 "#%u, has src update descriptor type %s that does "
3090 "not match overlapping dest descriptor type of %s!",
3091 i, j + 1,
3092 string_VkDescriptorType(
3093 pSrcLayout->descriptorTypes[srcStartIndex + j]),
3094 string_VkDescriptorType(
3095 pDstLayout
3096 ->descriptorTypes[dstStartIndex + j]));
Tobin Ehlis8a62e632015-10-27 15:43:38 -06003097 } else {
3098 // point dst descriptor at corresponding src descriptor
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003099 // TODO : This may be a hole. I believe copy should be
3100 // its own copy,
3101 // otherwise a subsequent write update to src will
3102 // incorrectly affect the copy
3103 pDstSet->ppDescriptors[j + dstStartIndex] =
3104 pSrcSet->ppDescriptors[j + srcStartIndex];
Tobin Ehlis8a62e632015-10-27 15:43:38 -06003105 }
3106 }
3107 }
3108 }
3109 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003110 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003111 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003112}
Tobin Ehlis559c6382015-11-05 09:52:49 -07003113
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003114// Verify that given pool has descriptors that are being requested for
3115// allocation
3116static VkBool32 validate_descriptor_availability_in_pool(
3117 layer_data *dev_data, DESCRIPTOR_POOL_NODE *pPoolNode, uint32_t count,
3118 const VkDescriptorSetLayout *pSetLayouts) {
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003119 VkBool32 skipCall = VK_FALSE;
3120 uint32_t i = 0, j = 0;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003121 for (i = 0; i < count; ++i) {
3122 LAYOUT_NODE *pLayout = getLayoutNode(dev_data, pSetLayouts[i]);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003123 if (NULL == pLayout) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003124 skipCall |= log_msg(
3125 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3126 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
3127 (uint64_t)pSetLayouts[i], __LINE__, DRAWSTATE_INVALID_LAYOUT,
3128 "DS", "Unable to find set layout node for layout %#" PRIxLEAST64
3129 " specified in vkAllocateDescriptorSets() call",
3130 (uint64_t)pSetLayouts[i]);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003131 } else {
Chia-I Wu1b99bb22015-10-27 19:25:11 +08003132 uint32_t typeIndex = 0, poolSizeCount = 0;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003133 for (j = 0; j < pLayout->createInfo.bindingCount; ++j) {
3134 typeIndex = static_cast<uint32_t>(
3135 pLayout->createInfo.pBindings[j].descriptorType);
3136 poolSizeCount =
3137 pLayout->createInfo.pBindings[j].descriptorCount;
3138 if (poolSizeCount >
3139 pPoolNode->availableDescriptorTypeCount[typeIndex]) {
3140 skipCall |= log_msg(
3141 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3142 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
3143 (uint64_t)pLayout->layout, __LINE__,
3144 DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS",
3145 "Unable to allocate %u descriptors of type %s from "
3146 "pool %#" PRIxLEAST64 ". This pool only has %u "
3147 "descriptors of this type "
3148 "remaining.",
3149 poolSizeCount,
3150 string_VkDescriptorType(
3151 pLayout->createInfo.pBindings[j].descriptorType),
3152 (uint64_t)pPoolNode->pool,
3153 pPoolNode->availableDescriptorTypeCount[typeIndex]);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003154 } else { // Decrement available descriptors of this type
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003155 pPoolNode->availableDescriptorTypeCount[typeIndex] -=
3156 poolSizeCount;
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003157 }
3158 }
3159 }
3160 }
3161 return skipCall;
3162}
Tobin Ehlis559c6382015-11-05 09:52:49 -07003163
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003164// Free the shadowed update node for this Set
3165// NOTE : Calls to this function should be wrapped in mutex
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003166static void freeShadowUpdateTree(SET_NODE *pSet) {
3167 GENERIC_HEADER *pShadowUpdate = pSet->pUpdateStructs;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003168 pSet->pUpdateStructs = NULL;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003169 GENERIC_HEADER *pFreeUpdate = pShadowUpdate;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003170 // Clear the descriptor mappings as they will now be invalid
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003171 memset(pSet->ppDescriptors, 0,
3172 pSet->descriptorCount * sizeof(GENERIC_HEADER *));
3173 while (pShadowUpdate) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003174 pFreeUpdate = pShadowUpdate;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003175 pShadowUpdate = (GENERIC_HEADER *)pShadowUpdate->pNext;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003176 uint32_t index = 0;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003177 VkWriteDescriptorSet *pWDS = NULL;
3178 VkCopyDescriptorSet *pCDS = NULL;
3179 void **ppToFree = NULL;
3180 switch (pFreeUpdate->sType) {
3181 case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
3182 pWDS = (VkWriteDescriptorSet *)pFreeUpdate;
3183 switch (pWDS->descriptorType) {
3184 case VK_DESCRIPTOR_TYPE_SAMPLER:
3185 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
3186 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
3187 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
3188 delete[] pWDS -> pImageInfo;
3189 } break;
3190 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
3191 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
3192 delete[] pWDS -> pTexelBufferView;
3193 } break;
3194 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
3195 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
3196 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
3197 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
3198 delete[] pWDS -> pBufferInfo;
3199 } break;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003200 default:
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003201 break;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003202 }
3203 break;
3204 case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
3205 break;
3206 default:
3207 assert(0);
3208 break;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003209 }
Tobin Ehlisecc6bd02015-04-08 10:58:37 -06003210 delete pFreeUpdate;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003211 }
3212}
Tobin Ehlis559c6382015-11-05 09:52:49 -07003213
Tobin Ehlis793ad302015-04-03 12:01:11 -06003214// Free all DS Pools including their Sets & related sub-structs
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003215// NOTE : Calls to this function should be wrapped in mutex
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003216static void deletePools(layer_data *my_data) {
Mark Lobodzinski39298632015-11-18 08:38:27 -07003217 if (my_data->descriptorPoolMap.size() <= 0)
David Pinedod8f83d82015-04-27 16:36:17 -06003218 return;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003219 for (auto ii = my_data->descriptorPoolMap.begin();
3220 ii != my_data->descriptorPoolMap.end(); ++ii) {
3221 SET_NODE *pSet = (*ii).second->pSets;
3222 SET_NODE *pFreeSet = pSet;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003223 while (pSet) {
3224 pFreeSet = pSet;
3225 pSet = pSet->pNext;
Tobin Ehlisecc6bd02015-04-08 10:58:37 -06003226 // Freeing layouts handled in deleteLayouts() function
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003227 // Free Update shadow struct tree
3228 freeShadowUpdateTree(pFreeSet);
3229 if (pFreeSet->ppDescriptors) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003230 delete[] pFreeSet -> ppDescriptors;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003231 }
3232 delete pFreeSet;
3233 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003234 delete (*ii).second;
3235 }
Mark Lobodzinski39298632015-11-18 08:38:27 -07003236 my_data->descriptorPoolMap.clear();
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003237}
Tobin Ehlis559c6382015-11-05 09:52:49 -07003238
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003239// WARN : Once deleteLayouts() called, any layout ptrs in Pool/Set data
3240// structure will be invalid
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003241// NOTE : Calls to this function should be wrapped in mutex
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003242static void deleteLayouts(layer_data *my_data) {
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07003243 if (my_data->descriptorSetLayoutMap.size() <= 0)
David Pinedod8f83d82015-04-27 16:36:17 -06003244 return;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003245 for (auto ii = my_data->descriptorSetLayoutMap.begin();
3246 ii != my_data->descriptorSetLayoutMap.end(); ++ii) {
3247 LAYOUT_NODE *pLayout = (*ii).second;
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07003248 if (pLayout->createInfo.pBindings) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003249 for (uint32_t i = 0; i < pLayout->createInfo.bindingCount; i++) {
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07003250 if (pLayout->createInfo.pBindings[i].pImmutableSamplers)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003251 delete[] pLayout -> createInfo.pBindings[i]
3252 .pImmutableSamplers;
Tobin Ehlisecc6bd02015-04-08 10:58:37 -06003253 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003254 delete[] pLayout -> createInfo.pBindings;
Tobin Ehlisecc6bd02015-04-08 10:58:37 -06003255 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003256 delete pLayout;
3257 }
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07003258 my_data->descriptorSetLayoutMap.clear();
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003259}
Tobin Ehlis559c6382015-11-05 09:52:49 -07003260
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003261// Currently clearing a set is removing all previous updates to that set
3262// TODO : Validate if this is correct clearing behavior
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003263static void clearDescriptorSet(layer_data *my_data, VkDescriptorSet set) {
3264 SET_NODE *pSet = getSetNode(my_data, set);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003265 if (!pSet) {
3266 // TODO : Return error
Tobin Ehlisce132d82015-06-19 15:07:05 -06003267 } else {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003268 loader_platform_thread_lock_mutex(&globalLock);
3269 freeShadowUpdateTree(pSet);
3270 loader_platform_thread_unlock_mutex(&globalLock);
3271 }
3272}
3273
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003274static void clearDescriptorPool(layer_data *my_data, const VkDevice device,
3275 const VkDescriptorPool pool,
3276 VkDescriptorPoolResetFlags flags) {
3277 DESCRIPTOR_POOL_NODE *pPool = getPoolNode(my_data, pool);
Tobin Ehlis793ad302015-04-03 12:01:11 -06003278 if (!pPool) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003279 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3280 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, (uint64_t)pool,
3281 __LINE__, DRAWSTATE_INVALID_POOL, "DS",
3282 "Unable to find pool node for pool %#" PRIxLEAST64
3283 " specified in vkResetDescriptorPool() call",
3284 (uint64_t)pool);
Tobin Ehlisce132d82015-06-19 15:07:05 -06003285 } else {
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06003286 // TODO: validate flags
Tobin Ehlis793ad302015-04-03 12:01:11 -06003287 // For every set off of this pool, clear it
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003288 SET_NODE *pSet = pPool->pSets;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003289 while (pSet) {
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06003290 clearDescriptorSet(my_data, pSet->set);
Mark Lobodzinskidcce0792016-01-04 09:40:19 -07003291 pSet = pSet->pNext;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003292 }
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003293 // Reset available count to max count for this pool
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003294 for (uint32_t i = 0; i < pPool->availableDescriptorTypeCount.size();
3295 ++i) {
3296 pPool->availableDescriptorTypeCount[i] =
3297 pPool->maxDescriptorTypeCount[i];
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003298 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003299 }
3300}
Tobin Ehlis559c6382015-11-05 09:52:49 -07003301
Tobin Ehlisa16e8922015-06-16 15:50:44 -06003302// For given CB object, fetch associated CB Node from map
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003303static GLOBAL_CB_NODE *getCBNode(layer_data *my_data,
3304 const VkCommandBuffer cb) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003305 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07003306 if (my_data->commandBufferMap.count(cb) == 0) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003307 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003308 // TODO : How to pass cb as srcObj here?
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003309 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3310 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
3311 DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
3312 "Attempt to use CommandBuffer %#" PRIxLEAST64
3313 " that doesn't exist!",
3314 (uint64_t)(cb));
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003315 return NULL;
3316 }
3317 loader_platform_thread_unlock_mutex(&globalLock);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003318 return my_data->commandBufferMap[cb];
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003319}
Tobin Ehlis559c6382015-11-05 09:52:49 -07003320
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003321// Free all CB Nodes
3322// NOTE : Calls to this function should be wrapped in mutex
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003323static void deleteCommandBuffers(layer_data *my_data) {
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07003324 if (my_data->commandBufferMap.size() <= 0) {
David Pinedod8f83d82015-04-27 16:36:17 -06003325 return;
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07003326 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003327 for (auto ii = my_data->commandBufferMap.begin();
3328 ii != my_data->commandBufferMap.end(); ++ii) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003329 delete (*ii).second;
3330 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003331 my_data->commandBufferMap.clear();
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003332}
Tobin Ehlis559c6382015-11-05 09:52:49 -07003333
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003334static VkBool32 report_error_no_cb_begin(const layer_data *dev_data,
3335 const VkCommandBuffer cb,
3336 const char *caller_name) {
3337 return log_msg(
3338 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3339 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)cb, __LINE__,
3340 DRAWSTATE_NO_BEGIN_COMMAND_BUFFER, "DS",
3341 "You must call vkBeginCommandBuffer() before this call to %s",
3342 caller_name);
Tobin Ehlis9c536442015-06-19 13:00:59 -06003343}
Michael Lentine3dea6512015-10-28 15:55:18 -07003344
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003345VkBool32 validateCmdsInCmdBuffer(const layer_data *dev_data,
3346 const GLOBAL_CB_NODE *pCB,
3347 const CMD_TYPE cmd_type) {
3348 if (!pCB->activeRenderPass)
3349 return VK_FALSE;
Mark Youngb20a6a82016-01-07 15:41:43 -07003350 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003351 if (pCB->activeSubpassContents ==
3352 VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS &&
3353 cmd_type != CMD_EXECUTECOMMANDS) {
3354 skip_call |=
3355 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3356 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
3357 DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
3358 "Commands cannot be called in a subpass using secondary "
3359 "command buffers.");
3360 } else if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_INLINE &&
3361 cmd_type == CMD_EXECUTECOMMANDS) {
3362 skip_call |=
3363 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3364 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
3365 DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
3366 "vkCmdExecuteCommands() cannot be called in a subpass "
3367 "using inline commands.");
Michael Lentine2e068b22015-12-29 16:05:27 -06003368 }
Michael Lentine3dea6512015-10-28 15:55:18 -07003369 return skip_call;
3370}
3371
Tobin Ehlis61b36f32015-12-16 08:19:42 -07003372// Add specified CMD to the CmdBuffer in given pCB, flagging errors if CB is not
3373// in the recording state or if there's an issue with the Cmd ordering
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003374static VkBool32 addCmd(const layer_data *my_data, GLOBAL_CB_NODE *pCB,
3375 const CMD_TYPE cmd, const char *caller_name) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07003376 VkBool32 skipCall = VK_FALSE;
3377 if (pCB->state != CB_RECORDING) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003378 skipCall |=
3379 report_error_no_cb_begin(my_data, pCB->commandBuffer, caller_name);
Tobin Ehlis61b36f32015-12-16 08:19:42 -07003380 skipCall |= validateCmdsInCmdBuffer(my_data, pCB, cmd);
Tobin Ehlis9a874302016-01-20 10:25:29 -07003381 CMD_NODE cmdNode = {};
3382 // init cmd node and append to end of cmd LL
3383 cmdNode.cmdNumber = ++pCB->numCmds;
3384 cmdNode.type = cmd;
3385 pCB->cmds.push_back(cmdNode);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003386 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003387 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003388}
Tobin Ehlisef694652016-01-19 12:03:34 -07003389// Reset the command buffer state
3390// Maintain the createInfo and set state to CB_NEW, but clear all other state
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003391static void resetCB(layer_data *my_data, const VkCommandBuffer cb) {
3392 GLOBAL_CB_NODE *pCB = my_data->commandBufferMap[cb];
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003393 if (pCB) {
Tobin Ehlis9a874302016-01-20 10:25:29 -07003394 pCB->cmds.clear();
Tobin Ehlisef694652016-01-19 12:03:34 -07003395 // Reset CB state (note that createInfo is not cleared)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003396 pCB->commandBuffer = cb;
Michael Lentineabc5e922015-10-12 11:30:14 -05003397 memset(&pCB->beginInfo, 0, sizeof(VkCommandBufferBeginInfo));
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003398 memset(&pCB->inheritanceInfo, 0,
3399 sizeof(VkCommandBufferInheritanceInfo));
Michael Lentineabc5e922015-10-12 11:30:14 -05003400 pCB->fence = 0;
3401 pCB->numCmds = 0;
3402 memset(pCB->drawCount, 0, NUM_DRAW_TYPES * sizeof(uint64_t));
3403 pCB->state = CB_NEW;
3404 pCB->submitCount = 0;
3405 pCB->status = 0;
Michael Lentineabc5e922015-10-12 11:30:14 -05003406 pCB->lastBoundPipeline = 0;
3407 pCB->viewports.clear();
3408 pCB->scissors.clear();
3409 pCB->lineWidth = 0;
3410 pCB->depthBiasConstantFactor = 0;
3411 pCB->depthBiasClamp = 0;
3412 pCB->depthBiasSlopeFactor = 0;
3413 memset(pCB->blendConstants, 0, 4 * sizeof(float));
3414 pCB->minDepthBounds = 0;
3415 pCB->maxDepthBounds = 0;
3416 memset(&pCB->front, 0, sizeof(stencil_data));
3417 memset(&pCB->back, 0, sizeof(stencil_data));
3418 pCB->lastBoundDescriptorSet = 0;
3419 pCB->lastBoundPipelineLayout = 0;
3420 pCB->activeRenderPass = 0;
3421 pCB->activeSubpass = 0;
Tobin Ehlise6e574b2016-01-24 23:25:31 -07003422 // Before clearing uniqueBoundSets, remove this CB off of its boundCBs
3423 for (auto set : pCB->uniqueBoundSets) {
3424 auto set_node = my_data->setMap.find(set);
3425 if (set_node != my_data->setMap.end()) {
3426 set_node->second->boundCmdBuffers.erase(pCB->commandBuffer);
3427 }
3428 }
3429 pCB->uniqueBoundSets.clear();
Michael Lentineabc5e922015-10-12 11:30:14 -05003430 pCB->framebuffer = 0;
Michael Lentineabc5e922015-10-12 11:30:14 -05003431 pCB->boundDescriptorSets.clear();
Michael Lentine700b0aa2015-10-30 17:57:32 -07003432 pCB->drawData.clear();
3433 pCB->currentDrawData.buffers.clear();
Michael Lentineabc5e922015-10-12 11:30:14 -05003434 pCB->imageLayoutMap.clear();
Michael Lentineb887b0a2015-12-29 14:12:11 -06003435 pCB->waitedEvents.clear();
3436 pCB->waitedEventsBeforeQueryReset.clear();
3437 pCB->queryToStateMap.clear();
Tobin Ehlisf4aafc02016-01-15 13:34:44 -07003438 pCB->secondaryCommandBuffers.clear();
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003439 }
3440}
Tobin Ehlis559c6382015-11-05 09:52:49 -07003441
Tobin Ehlis963a4042015-09-29 08:18:34 -06003442// Set PSO-related status bits for CB, including dynamic state set via PSO
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003443static void set_cb_pso_status(GLOBAL_CB_NODE *pCB, const PIPELINE_NODE *pPipe) {
Tobin Ehlise382c5a2015-06-10 12:57:07 -06003444 for (uint32_t i = 0; i < pPipe->cbStateCI.attachmentCount; i++) {
Chia-I Wu1b99bb22015-10-27 19:25:11 +08003445 if (0 != pPipe->pAttachments[i].colorWriteMask) {
Tobin Ehlise382c5a2015-06-10 12:57:07 -06003446 pCB->status |= CBSTATUS_COLOR_BLEND_WRITE_ENABLE;
3447 }
3448 }
3449 if (pPipe->dsStateCI.depthWriteEnable) {
Cody Northrop82485a82015-08-18 15:21:16 -06003450 pCB->status |= CBSTATUS_DEPTH_WRITE_ENABLE;
3451 }
Cody Northrop82485a82015-08-18 15:21:16 -06003452 if (pPipe->dsStateCI.stencilTestEnable) {
3453 pCB->status |= CBSTATUS_STENCIL_TEST_ENABLE;
Tobin Ehlise382c5a2015-06-10 12:57:07 -06003454 }
Tobin Ehlisd332f282015-10-02 11:00:56 -06003455 // Account for any dynamic state not set via this PSO
3456 if (!pPipe->dynStateCI.dynamicStateCount) { // All state is static
3457 pCB->status = CBSTATUS_ALL;
3458 } else {
Tobin Ehlis5e5a1e92015-10-01 09:24:40 -06003459 // First consider all state on
3460 // Then unset any state that's noted as dynamic in PSO
3461 // Finally OR that into CB statemask
3462 CBStatusFlags psoDynStateMask = CBSTATUS_ALL;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003463 for (uint32_t i = 0; i < pPipe->dynStateCI.dynamicStateCount; i++) {
Tobin Ehlis963a4042015-09-29 08:18:34 -06003464 switch (pPipe->dynStateCI.pDynamicStates[i]) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003465 case VK_DYNAMIC_STATE_VIEWPORT:
3466 psoDynStateMask &= ~CBSTATUS_VIEWPORT_SET;
3467 break;
3468 case VK_DYNAMIC_STATE_SCISSOR:
3469 psoDynStateMask &= ~CBSTATUS_SCISSOR_SET;
3470 break;
3471 case VK_DYNAMIC_STATE_LINE_WIDTH:
3472 psoDynStateMask &= ~CBSTATUS_LINE_WIDTH_SET;
3473 break;
3474 case VK_DYNAMIC_STATE_DEPTH_BIAS:
3475 psoDynStateMask &= ~CBSTATUS_DEPTH_BIAS_SET;
3476 break;
3477 case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
3478 psoDynStateMask &= ~CBSTATUS_BLEND_SET;
3479 break;
3480 case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
3481 psoDynStateMask &= ~CBSTATUS_DEPTH_BOUNDS_SET;
3482 break;
3483 case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
3484 psoDynStateMask &= ~CBSTATUS_STENCIL_READ_MASK_SET;
3485 break;
3486 case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
3487 psoDynStateMask &= ~CBSTATUS_STENCIL_WRITE_MASK_SET;
3488 break;
3489 case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
3490 psoDynStateMask &= ~CBSTATUS_STENCIL_REFERENCE_SET;
3491 break;
3492 default:
3493 // TODO : Flag error here
3494 break;
Tobin Ehlis963a4042015-09-29 08:18:34 -06003495 }
3496 }
Tobin Ehlis5e5a1e92015-10-01 09:24:40 -06003497 pCB->status |= psoDynStateMask;
Tobin Ehlis963a4042015-09-29 08:18:34 -06003498 }
Tobin Ehlise382c5a2015-06-10 12:57:07 -06003499}
Tobin Ehlis559c6382015-11-05 09:52:49 -07003500
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003501// Print the last bound Gfx Pipeline
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003502static VkBool32 printPipeline(layer_data *my_data, const VkCommandBuffer cb) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003503 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003504 GLOBAL_CB_NODE *pCB = getCBNode(my_data, cb);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003505 if (pCB) {
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06003506 PIPELINE_NODE *pPipeTrav = getPipeline(my_data, pCB->lastBoundPipeline);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003507 if (!pPipeTrav) {
3508 // nothing to print
Tobin Ehlisce132d82015-06-19 15:07:05 -06003509 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003510 skipCall |=
3511 log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
3512 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
3513 DRAWSTATE_NONE, "DS", "%s",
3514 vk_print_vkgraphicspipelinecreateinfo(
3515 &pPipeTrav->graphicsPipelineCI, "{DS}").c_str());
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003516 }
3517 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003518 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003519}
Tobin Ehlis559c6382015-11-05 09:52:49 -07003520
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003521// Print details of DS config to stdout
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003522static VkBool32 printDSConfig(layer_data *my_data, const VkCommandBuffer cb) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003523 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003524 char ds_config_str[1024 * 256] = {0}; // TODO : Currently making this buffer
3525 // HUGE w/o overrun protection. Need
3526 // to be smarter, start smaller, and
3527 // grow as needed.
3528 GLOBAL_CB_NODE *pCB = getCBNode(my_data, cb);
Tobin Ehlis93f89e82015-06-09 08:39:32 -06003529 if (pCB && pCB->lastBoundDescriptorSet) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003530 SET_NODE *pSet = getSetNode(my_data, pCB->lastBoundDescriptorSet);
3531 DESCRIPTOR_POOL_NODE *pPool = getPoolNode(my_data, pSet->pool);
Tobin Ehlis793ad302015-04-03 12:01:11 -06003532 // Print out pool details
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003533 skipCall |= log_msg(
3534 my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
3535 (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_NONE, "DS",
3536 "Details for pool %#" PRIxLEAST64 ".", (uint64_t)pPool->pool);
3537 string poolStr =
3538 vk_print_vkdescriptorpoolcreateinfo(&pPool->createInfo, " ");
3539 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
3540 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
3541 DRAWSTATE_NONE, "DS", "%s", poolStr.c_str());
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003542 // Print out set details
3543 char prefix[10];
3544 uint32_t index = 0;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003545 skipCall |=
3546 log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
3547 (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_NONE,
3548 "DS", "Details for descriptor set %#" PRIxLEAST64 ".",
3549 (uint64_t)pSet->set);
3550 LAYOUT_NODE *pLayout = pSet->pLayout;
Tobin Ehlis793ad302015-04-03 12:01:11 -06003551 // Print layout details
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003552 skipCall |= log_msg(
3553 my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
3554 (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_NONE, "DS",
3555 "Layout #%u, (object %#" PRIxLEAST64 ") for DS %#" PRIxLEAST64 ".",
3556 index + 1, (uint64_t)(pLayout->layout), (uint64_t)(pSet->set));
Tobin Ehlis793ad302015-04-03 12:01:11 -06003557 sprintf(prefix, " [L%u] ", index);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003558 string DSLstr = vk_print_vkdescriptorsetlayoutcreateinfo(
3559 &pLayout->createInfo, prefix).c_str();
3560 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
3561 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
3562 DRAWSTATE_NONE, "DS", "%s", DSLstr.c_str());
Tobin Ehlis793ad302015-04-03 12:01:11 -06003563 index++;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003564 GENERIC_HEADER *pUpdate = pSet->pUpdateStructs;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003565 if (pUpdate) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003566 skipCall |= log_msg(
3567 my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
3568 (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_NONE,
3569 "DS", "Update Chain [UC] for descriptor set %#" PRIxLEAST64 ":",
3570 (uint64_t)pSet->set);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003571 sprintf(prefix, " [UC] ");
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003572 skipCall |= log_msg(
3573 my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
3574 (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_NONE,
3575 "DS", "%s", dynamic_display(pUpdate, prefix).c_str());
3576 // TODO : If there is a "view" associated with this update, print CI
3577 // for that view
Tobin Ehlisce132d82015-06-19 15:07:05 -06003578 } else {
Tobin Ehlisbf081f32015-06-15 08:41:17 -06003579 if (0 != pSet->descriptorCount) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003580 skipCall |= log_msg(
3581 my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
3582 (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_NONE,
3583 "DS", "No Update Chain for descriptor set %#" PRIxLEAST64
3584 " which has %u descriptors (vkUpdateDescriptors has "
3585 "not been called)",
3586 (uint64_t)pSet->set, pSet->descriptorCount);
Tobin Ehlisce132d82015-06-19 15:07:05 -06003587 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003588 skipCall |= log_msg(
3589 my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
3590 (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_NONE,
3591 "DS",
3592 "FYI: No descriptors in descriptor set %#" PRIxLEAST64 ".",
3593 (uint64_t)pSet->set);
Tobin Ehlisbf081f32015-06-15 08:41:17 -06003594 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003595 }
3596 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003597 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003598}
3599
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003600static void printCB(layer_data *my_data, const VkCommandBuffer cb) {
3601 GLOBAL_CB_NODE *pCB = getCBNode(my_data, cb);
Tobin Ehlis9a874302016-01-20 10:25:29 -07003602 if (pCB && pCB->cmds.size() > 0) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003603 log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
3604 (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_NONE,
3605 "DS", "Cmds in CB %p", (void *)cb);
Tobin Ehlis9a874302016-01-20 10:25:29 -07003606 vector<CMD_NODE> cmds = pCB->cmds;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003607 for (auto ii = cmds.begin(); ii != cmds.end(); ++ii) {
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003608 // TODO : Need to pass cb as srcObj here
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003609 log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
3610 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
3611 DRAWSTATE_NONE, "DS", " CMD#%" PRIu64 ": %s",
3612 (*ii).cmdNumber, cmdTypeToString((*ii).type).c_str());
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003613 }
Tobin Ehlisce132d82015-06-19 15:07:05 -06003614 } else {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003615 // Nothing to print
3616 }
3617}
3618
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003619static VkBool32 synchAndPrintDSConfig(layer_data *my_data,
3620 const VkCommandBuffer cb) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003621 VkBool32 skipCall = VK_FALSE;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003622 if (!(my_data->report_data->active_flags & VK_DEBUG_REPORT_INFO_BIT_EXT)) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003623 return skipCall;
Mike Stroyanba35e352015-08-12 17:11:28 -06003624 }
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06003625 skipCall |= printDSConfig(my_data, cb);
3626 skipCall |= printPipeline(my_data, cb);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003627 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003628}
3629
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003630// Flags validation error if the associated call is made inside a render pass.
3631// The apiName
Mark Lobodzinski5495d132015-09-30 16:19:16 -06003632// routine should ONLY be called outside a render pass.
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003633static VkBool32 insideRenderPass(const layer_data *my_data, GLOBAL_CB_NODE *pCB,
3634 const char *apiName) {
Mark Lobodzinski5495d132015-09-30 16:19:16 -06003635 VkBool32 inside = VK_FALSE;
3636 if (pCB->activeRenderPass) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003637 inside = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3638 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3639 (uint64_t)pCB->commandBuffer, __LINE__,
3640 DRAWSTATE_INVALID_RENDERPASS_CMD, "DS",
3641 "%s: It is invalid to issue this call inside an "
3642 "active render pass (%#" PRIxLEAST64 ")",
3643 apiName, (uint64_t)pCB->activeRenderPass);
Mark Lobodzinski5495d132015-09-30 16:19:16 -06003644 }
3645 return inside;
3646}
3647
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003648// Flags validation error if the associated call is made outside a render pass.
3649// The apiName
Mark Lobodzinski5495d132015-09-30 16:19:16 -06003650// routine should ONLY be called inside a render pass.
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003651static VkBool32 outsideRenderPass(const layer_data *my_data,
3652 GLOBAL_CB_NODE *pCB, const char *apiName) {
Mark Lobodzinski5495d132015-09-30 16:19:16 -06003653 VkBool32 outside = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003654 if (((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) &&
3655 (!pCB->activeRenderPass)) ||
Mark Lobodzinski74635932015-12-18 15:35:38 -07003656 ((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) &&
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003657 (!pCB->activeRenderPass) &&
3658 !(pCB->beginInfo.flags &
3659 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))) {
3660 outside = log_msg(
3661 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3662 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3663 (uint64_t)pCB->commandBuffer, __LINE__,
3664 DRAWSTATE_NO_ACTIVE_RENDERPASS, "DS",
3665 "%s: This call must be issued inside an active render pass.",
3666 apiName);
Mark Lobodzinski5495d132015-09-30 16:19:16 -06003667 }
3668 return outside;
3669}
3670
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003671static void init_draw_state(layer_data *my_data,
3672 const VkAllocationCallbacks *pAllocator) {
Tobin Ehlisa16e8922015-06-16 15:50:44 -06003673 uint32_t report_flags = 0;
3674 uint32_t debug_action = 0;
3675 FILE *log_output = NULL;
3676 const char *option_str;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003677 VkDebugReportCallbackEXT callback;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003678 // initialize DrawState options
Tobin Ehlisa16e8922015-06-16 15:50:44 -06003679 report_flags = getLayerOptionFlags("DrawStateReportFlags", 0);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003680 getLayerOptionEnum("DrawStateDebugAction", (uint32_t *)&debug_action);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003681
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003682 if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG) {
Tobin Ehlisa16e8922015-06-16 15:50:44 -06003683 option_str = getLayerOption("DrawStateLogFilename");
Tobin Ehlisb1df55e2015-09-15 09:55:54 -06003684 log_output = getLayerLogOutput(option_str, "DrawState");
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003685 VkDebugReportCallbackCreateInfoEXT dbgInfo;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07003686 memset(&dbgInfo, 0, sizeof(dbgInfo));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003687 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07003688 dbgInfo.pfnCallback = log_callback;
3689 dbgInfo.pUserData = log_output;
3690 dbgInfo.flags = report_flags;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003691 layer_create_msg_callback(my_data->report_data, &dbgInfo, pAllocator,
3692 &callback);
Courtney Goeltzenleuchter62d945a2015-10-05 15:58:38 -06003693 my_data->logging_callback.push_back(callback);
3694 }
3695
3696 if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003697 VkDebugReportCallbackCreateInfoEXT dbgInfo;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07003698 memset(&dbgInfo, 0, sizeof(dbgInfo));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003699 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07003700 dbgInfo.pfnCallback = win32_debug_output_msg;
3701 dbgInfo.pUserData = log_output;
3702 dbgInfo.flags = report_flags;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003703 layer_create_msg_callback(my_data->report_data, &dbgInfo, pAllocator,
3704 &callback);
Courtney Goeltzenleuchter62d945a2015-10-05 15:58:38 -06003705 my_data->logging_callback.push_back(callback);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003706 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003707
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003708 if (!globalLockInitialized) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003709 loader_platform_thread_create_mutex(&globalLock);
3710 globalLockInitialized = 1;
3711 }
3712}
3713
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003714VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
3715 vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo,
3716 const VkAllocationCallbacks *pAllocator,
3717 VkInstance *pInstance) {
3718 VkLayerInstanceCreateInfo *chain_info =
3719 get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Courtney Goeltzenleuchterabc035e2015-06-01 14:29:58 -06003720
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003721 assert(chain_info->u.pLayerInfo);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003722 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr =
3723 chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
3724 PFN_vkCreateInstance fpCreateInstance =
3725 (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003726 if (fpCreateInstance == NULL) {
3727 return VK_ERROR_INITIALIZATION_FAILED;
Courtney Goeltzenleuchterabc035e2015-06-01 14:29:58 -06003728 }
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003729
3730 // Advance the link info for the next element on the chain
3731 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
3732
3733 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
3734 if (result != VK_SUCCESS)
3735 return result;
3736
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003737 layer_data *my_data =
3738 get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003739 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003740 layer_init_instance_dispatch_table(
3741 *pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003742
3743 my_data->report_data = debug_report_create_instance(
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003744 my_data->instance_dispatch_table, *pInstance,
3745 pCreateInfo->enabledExtensionCount,
3746 pCreateInfo->ppEnabledExtensionNames);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003747
3748 init_draw_state(my_data, pAllocator);
3749
Courtney Goeltzenleuchterabc035e2015-06-01 14:29:58 -06003750 return result;
3751}
3752
Jon Ashburn3950e1b2015-05-20 09:00:28 -06003753/* hook DestroyInstance to remove tableInstanceMap entry */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003754VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
3755 vkDestroyInstance(VkInstance instance,
3756 const VkAllocationCallbacks *pAllocator) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07003757 // TODOSC : Shouldn't need any customization here
Tobin Ehlisa16e8922015-06-16 15:50:44 -06003758 dispatch_key key = get_dispatch_key(instance);
Tobin Ehlis0b632332015-10-07 09:38:40 -06003759 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
3760 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Chia-I Wuf7458c52015-10-26 21:10:41 +08003761 pTable->DestroyInstance(instance, pAllocator);
Tobin Ehlisa16e8922015-06-16 15:50:44 -06003762
3763 // Clean up logging callback, if any
Courtney Goeltzenleuchter62d945a2015-10-05 15:58:38 -06003764 while (my_data->logging_callback.size() > 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003765 VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07003766 layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
Courtney Goeltzenleuchter62d945a2015-10-05 15:58:38 -06003767 my_data->logging_callback.pop_back();
Tobin Ehlisa16e8922015-06-16 15:50:44 -06003768 }
3769
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -06003770 layer_debug_report_destroy_instance(my_data->report_data);
Tobin Ehlis0b632332015-10-07 09:38:40 -06003771 delete my_data->instance_dispatch_table;
3772 layer_data_map.erase(key);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003773 // TODO : Potential race here with separate threads creating/destroying
3774 // instance
Tobin Ehlis0b632332015-10-07 09:38:40 -06003775 if (layer_data_map.empty()) {
Mike Stroyanfcb4ba62015-08-18 15:56:18 -06003776 // Release mutex when destroying last instance.
3777 loader_platform_thread_delete_mutex(&globalLock);
3778 globalLockInitialized = 0;
3779 }
Jon Ashburn3950e1b2015-05-20 09:00:28 -06003780}
3781
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003782static void
3783createDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo,
3784 VkDevice device) {
Tony Barbour3b4732f2015-07-13 13:37:24 -06003785 uint32_t i;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003786 layer_data *dev_data =
3787 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Tobin Ehlis0b632332015-10-07 09:38:40 -06003788 dev_data->device_extensions.debug_marker_enabled = false;
Michael Lentineabc5e922015-10-12 11:30:14 -05003789 dev_data->device_extensions.wsi_enabled = false;
3790
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003791 VkLayerDispatchTable *pDisp = dev_data->device_dispatch_table;
3792 PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
Michael Lentineabc5e922015-10-12 11:30:14 -05003793
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003794 pDisp->CreateSwapchainKHR =
3795 (PFN_vkCreateSwapchainKHR)gpa(device, "vkCreateSwapchainKHR");
3796 pDisp->DestroySwapchainKHR =
3797 (PFN_vkDestroySwapchainKHR)gpa(device, "vkDestroySwapchainKHR");
3798 pDisp->GetSwapchainImagesKHR =
3799 (PFN_vkGetSwapchainImagesKHR)gpa(device, "vkGetSwapchainImagesKHR");
3800 pDisp->AcquireNextImageKHR =
3801 (PFN_vkAcquireNextImageKHR)gpa(device, "vkAcquireNextImageKHR");
3802 pDisp->QueuePresentKHR =
3803 (PFN_vkQueuePresentKHR)gpa(device, "vkQueuePresentKHR");
Jon Ashburne68a9ff2015-05-25 14:11:37 -06003804
Jon Ashburnf19916e2016-01-11 13:12:43 -07003805 for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003806 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
3807 VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
Michael Lentineabc5e922015-10-12 11:30:14 -05003808 dev_data->device_extensions.wsi_enabled = true;
3809 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003810 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
3811 DEBUG_MARKER_EXTENSION_NAME) == 0) {
3812 /* Found a matching extension name, mark it enabled and init
3813 * dispatch table*/
Tobin Ehlis0b632332015-10-07 09:38:40 -06003814 dev_data->device_extensions.debug_marker_enabled = true;
Jon Ashburn1d4b1282015-12-10 19:12:21 -07003815 initDebugMarkerTable(device);
Jon Ashburne68a9ff2015-05-25 14:11:37 -06003816 }
Jon Ashburne68a9ff2015-05-25 14:11:37 -06003817 }
3818}
3819
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003820VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
3821 vkCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
3822 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
3823 VkLayerDeviceCreateInfo *chain_info =
3824 get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski941aea92016-01-13 10:23:15 -07003825
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003826 assert(chain_info->u.pLayerInfo);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003827 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr =
3828 chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
3829 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr =
3830 chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
3831 PFN_vkCreateDevice fpCreateDevice =
3832 (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003833 if (fpCreateDevice == NULL) {
3834 return VK_ERROR_INITIALIZATION_FAILED;
Tobin Ehlisa16e8922015-06-16 15:50:44 -06003835 }
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003836
3837 // Advance the link info for the next element on the chain
3838 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
3839
3840 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
3841 if (result != VK_SUCCESS) {
3842 return result;
3843 }
3844
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003845 layer_data *my_instance_data =
3846 get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
3847 layer_data *my_device_data =
3848 get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003849
3850 // Setup device dispatch table
3851 my_device_data->device_dispatch_table = new VkLayerDispatchTable;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003852 layer_init_device_dispatch_table(
3853 *pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003854
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003855 my_device_data->report_data = layer_debug_report_create_device(
3856 my_instance_data->report_data, *pDevice);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003857 createDeviceRegisterExtensions(pCreateInfo, *pDevice);
3858 // Get physical device limits for this device
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003859 my_instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(
3860 gpu, &(my_instance_data->physDevPropertyMap[*pDevice]));
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003861 return result;
3862}
Tobin Ehlis559c6382015-11-05 09:52:49 -07003863
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06003864// prototype
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003865static void deleteRenderPasses(layer_data *);
3866VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
3867 vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07003868 // TODOSC : Shouldn't need any customization here
Jeremy Hayes5d29ce32015-06-19 11:37:38 -06003869 dispatch_key key = get_dispatch_key(device);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003870 layer_data *dev_data = get_my_data_ptr(key, layer_data_map);
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06003871 // Free all the memory
3872 loader_platform_thread_lock_mutex(&globalLock);
3873 deletePipelines(dev_data);
3874 deleteRenderPasses(dev_data);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003875 deleteCommandBuffers(dev_data);
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06003876 deletePools(dev_data);
3877 deleteLayouts(dev_data);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06003878 dev_data->imageViewMap.clear();
3879 dev_data->imageMap.clear();
3880 dev_data->bufferViewMap.clear();
3881 dev_data->bufferMap.clear();
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06003882 loader_platform_thread_unlock_mutex(&globalLock);
3883
Chia-I Wuf7458c52015-10-26 21:10:41 +08003884 dev_data->device_dispatch_table->DestroyDevice(device, pAllocator);
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06003885 tableDebugMarkerMap.erase(key);
Tobin Ehlis0b632332015-10-07 09:38:40 -06003886 delete dev_data->device_dispatch_table;
3887 layer_data_map.erase(key);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003888}
3889
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07003890static const VkExtensionProperties instance_extensions[] = {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003891 {VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06003892
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003893VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
3894 vkEnumerateInstanceExtensionProperties(const char *pLayerName,
3895 uint32_t *pCount,
3896 VkExtensionProperties *pProperties) {
3897 return util_GetExtensionProperties(1, instance_extensions, pCount,
3898 pProperties);
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06003899}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06003900
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003901static const VkLayerProperties ds_global_layers[] = {{
3902 "VK_LAYER_LUNARG_draw_state", VK_API_VERSION, VK_MAKE_VERSION(0, 1, 0),
3903 "Validation layer: draw_state",
3904}};
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07003905
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003906VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
3907 vkEnumerateInstanceLayerProperties(uint32_t *pCount,
3908 VkLayerProperties *pProperties) {
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06003909 return util_GetLayerProperties(ARRAY_SIZE(ds_global_layers),
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003910 ds_global_layers, pCount, pProperties);
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06003911}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06003912
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003913static const VkExtensionProperties ds_device_extensions[] = {{
3914 DEBUG_MARKER_EXTENSION_NAME, VK_MAKE_VERSION(0, 1, 0),
3915}};
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06003916
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003917static const VkLayerProperties ds_device_layers[] = {{
3918 "VK_LAYER_LUNARG_draw_state", VK_API_VERSION, VK_MAKE_VERSION(0, 1, 0),
3919 "Validation layer: draw_state",
3920}};
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06003921
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003922VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
3923 vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
3924 const char *pLayerName,
3925 uint32_t *pCount,
3926 VkExtensionProperties *pProperties) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07003927 // DrawState does not have any physical device extensions
Jon Ashburn751c4842015-11-02 17:37:20 -07003928 if (pLayerName == NULL) {
3929 dispatch_key key = get_dispatch_key(physicalDevice);
3930 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003931 return my_data->instance_dispatch_table
3932 ->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount,
3933 pProperties);
Jon Ashburn751c4842015-11-02 17:37:20 -07003934 } else {
3935 return util_GetExtensionProperties(ARRAY_SIZE(ds_device_extensions),
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003936 ds_device_extensions, pCount,
3937 pProperties);
Jon Ashburn751c4842015-11-02 17:37:20 -07003938 }
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06003939}
3940
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003941VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
3942 vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
3943 uint32_t *pCount,
3944 VkLayerProperties *pProperties) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07003945 /* DrawState physical device layers are the same as global */
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003946 return util_GetLayerProperties(ARRAY_SIZE(ds_device_layers),
3947 ds_device_layers, pCount, pProperties);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06003948}
3949
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07003950VkBool32 ValidateCmdBufImageLayouts(VkCommandBuffer cmdBuffer) {
Mark Youngb20a6a82016-01-07 15:41:43 -07003951 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003952 layer_data *dev_data =
3953 get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
3954 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
Michael Lentineabc5e922015-10-12 11:30:14 -05003955 for (auto cb_image_data : pCB->imageLayoutMap) {
3956 auto image_data = dev_data->imageLayoutMap.find(cb_image_data.first);
3957 if (image_data == dev_data->imageLayoutMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003958 skip_call |= log_msg(
3959 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3960 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
3961 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
3962 "Cannot submit cmd buffer using deleted image %" PRIu64 ".",
3963 (uint64_t)(cb_image_data.first));
Michael Lentineabc5e922015-10-12 11:30:14 -05003964 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003965 if (dev_data->imageLayoutMap[cb_image_data.first]->layout !=
3966 cb_image_data.second.initialLayout) {
3967 skip_call |= log_msg(
3968 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3969 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
3970 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
3971 "Cannot submit cmd buffer using image with layout %d when "
3972 "first use is %d.",
3973 dev_data->imageLayoutMap[cb_image_data.first]->layout,
3974 cb_image_data.second.initialLayout);
Michael Lentineabc5e922015-10-12 11:30:14 -05003975 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003976 dev_data->imageLayoutMap[cb_image_data.first]->layout =
3977 cb_image_data.second.layout;
Michael Lentineabc5e922015-10-12 11:30:14 -05003978 }
3979 }
3980 return skip_call;
3981}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003982// Track which resources are in-flight by atomically incrementing their "in_use"
3983// count
3984VkBool32 validateAndIncrementResources(layer_data *my_data,
3985 GLOBAL_CB_NODE *pCB) {
Mark Youngb20a6a82016-01-07 15:41:43 -07003986 VkBool32 skip_call = VK_FALSE;
Michael Lentine700b0aa2015-10-30 17:57:32 -07003987 for (auto drawDataElement : pCB->drawData) {
3988 for (auto buffer : drawDataElement.buffers) {
3989 auto buffer_data = my_data->bufferMap.find(buffer);
3990 if (buffer_data == my_data->bufferMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07003991 skip_call |= log_msg(
3992 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3993 VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, (uint64_t)(buffer),
3994 __LINE__, DRAWSTATE_INVALID_BUFFER, "DS",
3995 "Cannot submit cmd buffer using deleted buffer %" PRIu64
3996 ".",
3997 (uint64_t)(buffer));
Michael Lentine700b0aa2015-10-30 17:57:32 -07003998 } else {
3999 buffer_data->second.in_use.fetch_add(1);
4000 }
4001 }
4002 }
Tobin Ehlise6e574b2016-01-24 23:25:31 -07004003 for (auto set : pCB->uniqueBoundSets) {
4004 auto setNode = my_data->setMap.find(set);
4005 if (setNode == my_data->setMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004006 skip_call |= log_msg(
4007 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4008 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)(set),
4009 __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS",
4010 "Cannot submit cmd buffer using deleted descriptor set %" PRIu64
4011 ".",
4012 (uint64_t)(set));
Tobin Ehlise6e574b2016-01-24 23:25:31 -07004013 } else {
4014 setNode->second->in_use.fetch_add(1);
4015 }
4016 }
Michael Lentine2e068b22015-12-29 16:05:27 -06004017 return skip_call;
Michael Lentine700b0aa2015-10-30 17:57:32 -07004018}
4019
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004020void decrementResources(layer_data *my_data, VkCommandBuffer cmdBuffer) {
4021 GLOBAL_CB_NODE *pCB = getCBNode(my_data, cmdBuffer);
Michael Lentine700b0aa2015-10-30 17:57:32 -07004022 for (auto drawDataElement : pCB->drawData) {
4023 for (auto buffer : drawDataElement.buffers) {
4024 auto buffer_data = my_data->bufferMap.find(buffer);
4025 if (buffer_data != my_data->bufferMap.end()) {
4026 buffer_data->second.in_use.fetch_sub(1);
4027 }
4028 }
4029 }
Tobin Ehlise6e574b2016-01-24 23:25:31 -07004030 for (auto set : pCB->uniqueBoundSets) {
Tobin Ehlis9c4f38d2016-01-14 12:47:19 -07004031 auto setNode = my_data->setMap.find(set);
4032 if (setNode != my_data->setMap.end()) {
4033 setNode->second->in_use.fetch_sub(1);
4034 }
4035 }
Michael Lentineb887b0a2015-12-29 14:12:11 -06004036 for (auto queryStatePair : pCB->queryToStateMap) {
4037 my_data->queryToStateMap[queryStatePair.first] = queryStatePair.second;
4038 }
Michael Lentine700b0aa2015-10-30 17:57:32 -07004039}
4040
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004041void decrementResources(layer_data *my_data, uint32_t fenceCount,
4042 const VkFence *pFences) {
Michael Lentine700b0aa2015-10-30 17:57:32 -07004043 for (uint32_t i = 0; i < fenceCount; ++i) {
4044 auto fence_data = my_data->fenceMap.find(pFences[i]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004045 if (fence_data == my_data->fenceMap.end() ||
4046 !fence_data->second.needsSignaled)
4047 return;
Michael Lentine700b0aa2015-10-30 17:57:32 -07004048 fence_data->second.needsSignaled = false;
4049 if (fence_data->second.priorFence != VK_NULL_HANDLE) {
4050 decrementResources(my_data, 1, &fence_data->second.priorFence);
4051 }
4052 for (auto cmdBuffer : fence_data->second.cmdBuffers) {
4053 decrementResources(my_data, cmdBuffer);
4054 }
4055 }
4056}
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07004057
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004058void decrementResources(layer_data *my_data, VkQueue queue) {
Michael Lentine700b0aa2015-10-30 17:57:32 -07004059 auto queue_data = my_data->queueMap.find(queue);
4060 if (queue_data != my_data->queueMap.end()) {
4061 for (auto cmdBuffer : queue_data->second.untrackedCmdBuffers) {
4062 decrementResources(my_data, cmdBuffer);
4063 }
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07004064 queue_data->second.untrackedCmdBuffers.clear();
Michael Lentine700b0aa2015-10-30 17:57:32 -07004065 decrementResources(my_data, 1, &queue_data->second.priorFence);
4066 }
4067}
4068
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004069void trackCommandBuffers(layer_data *my_data, VkQueue queue,
4070 uint32_t cmdBufferCount,
4071 const VkCommandBuffer *pCmdBuffers, VkFence fence) {
Michael Lentine700b0aa2015-10-30 17:57:32 -07004072 auto queue_data = my_data->queueMap.find(queue);
4073 if (fence != VK_NULL_HANDLE) {
4074 VkFence priorFence = VK_NULL_HANDLE;
4075 if (queue_data != my_data->queueMap.end()) {
4076 priorFence = queue_data->second.priorFence;
4077 queue_data->second.priorFence = fence;
4078 for (auto cmdBuffer : queue_data->second.untrackedCmdBuffers) {
4079 my_data->fenceMap[fence].cmdBuffers.push_back(cmdBuffer);
4080 }
4081 queue_data->second.untrackedCmdBuffers.clear();
4082 }
4083 my_data->fenceMap[fence].cmdBuffers.clear();
4084 my_data->fenceMap[fence].priorFence = priorFence;
4085 my_data->fenceMap[fence].needsSignaled = true;
Tobin Ehlis74714d22016-01-25 15:24:34 -08004086 my_data->fenceMap[fence].queue = queue;
Michael Lentine700b0aa2015-10-30 17:57:32 -07004087 for (uint32_t i = 0; i < cmdBufferCount; ++i) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004088 for (auto secondaryCmdBuffer :
4089 my_data->commandBufferMap[pCmdBuffers[i]]
4090 ->secondaryCommandBuffers) {
4091 my_data->fenceMap[fence].cmdBuffers.push_back(
4092 secondaryCmdBuffer);
Tobin Ehlisf4aafc02016-01-15 13:34:44 -07004093 }
Michael Lentine700b0aa2015-10-30 17:57:32 -07004094 my_data->fenceMap[fence].cmdBuffers.push_back(pCmdBuffers[i]);
4095 }
4096 } else {
4097 if (queue_data != my_data->queueMap.end()) {
4098 for (uint32_t i = 0; i < cmdBufferCount; ++i) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004099 for (auto secondaryCmdBuffer :
4100 my_data->commandBufferMap[pCmdBuffers[i]]
4101 ->secondaryCommandBuffers) {
4102 queue_data->second.untrackedCmdBuffers.push_back(
4103 secondaryCmdBuffer);
Tobin Ehlisf4aafc02016-01-15 13:34:44 -07004104 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004105 queue_data->second.untrackedCmdBuffers.push_back(
4106 pCmdBuffers[i]);
Michael Lentine700b0aa2015-10-30 17:57:32 -07004107 }
4108 }
4109 }
Michael Lentineb887b0a2015-12-29 14:12:11 -06004110 if (queue_data != my_data->queueMap.end()) {
4111 for (uint32_t i = 0; i < cmdBufferCount; ++i) {
Tobin Ehlisae82e7f2016-01-20 16:23:37 -07004112 // Add cmdBuffers to both the global set and queue set
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004113 for (auto secondaryCmdBuffer :
4114 my_data->commandBufferMap[pCmdBuffers[i]]
4115 ->secondaryCommandBuffers) {
Tobin Ehlis74714d22016-01-25 15:24:34 -08004116 my_data->globalInFlightCmdBuffers.insert(secondaryCmdBuffer);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004117 queue_data->second.inFlightCmdBuffers.insert(
4118 secondaryCmdBuffer);
Tobin Ehlisf4aafc02016-01-15 13:34:44 -07004119 }
Tobin Ehlis74714d22016-01-25 15:24:34 -08004120 my_data->globalInFlightCmdBuffers.insert(pCmdBuffers[i]);
4121 queue_data->second.inFlightCmdBuffers.insert(pCmdBuffers[i]);
4122 }
4123 }
4124}
4125
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004126static VkBool32 validateCommandBufferState(layer_data *dev_data,
4127 GLOBAL_CB_NODE *pCB) {
Tobin Ehlis74714d22016-01-25 15:24:34 -08004128 // Track in-use for resources off of primary and any secondary CBs
4129 VkBool32 skipCall = validateAndIncrementResources(dev_data, pCB);
4130 if (!pCB->secondaryCommandBuffers.empty()) {
4131 for (auto secondaryCmdBuffer : pCB->secondaryCommandBuffers) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004132 skipCall |= validateAndIncrementResources(
4133 dev_data, dev_data->commandBufferMap[secondaryCmdBuffer]);
Tobin Ehlis74714d22016-01-25 15:24:34 -08004134 }
4135 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004136 if ((pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) &&
4137 (pCB->submitCount > 1)) {
4138 skipCall |=
4139 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4140 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
4141 DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS",
4142 "CB %#" PRIxLEAST64
4143 " was begun w/ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT "
4144 "set, but has been submitted %#" PRIxLEAST64 " times.",
4145 (uint64_t)(pCB->commandBuffer), pCB->submitCount);
Tobin Ehlis74714d22016-01-25 15:24:34 -08004146 }
4147 // Validate that cmd buffers have been updated
4148 if (CB_RECORDED != pCB->state) {
4149 if (CB_INVALID == pCB->state) {
4150 // Inform app of reason CB invalid
4151 if (!pCB->destroyedSets.empty()) {
4152 std::stringstream set_string;
4153 for (auto set : pCB->destroyedSets) {
4154 set_string << " " << set;
4155 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004156 skipCall |= log_msg(
4157 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4158 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
4159 (uint64_t)(pCB->commandBuffer), __LINE__,
4160 DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
4161 "You are submitting command buffer %#" PRIxLEAST64
4162 " that is invalid because it had the following bound "
4163 "descriptor set(s) destroyed: %s",
4164 (uint64_t)(pCB->commandBuffer), set_string.str().c_str());
Tobin Ehlis74714d22016-01-25 15:24:34 -08004165 }
4166 if (!pCB->updatedSets.empty()) {
4167 std::stringstream set_string;
4168 for (auto set : pCB->updatedSets) {
4169 set_string << " " << set;
4170 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004171 skipCall |= log_msg(
4172 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4173 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
4174 (uint64_t)(pCB->commandBuffer), __LINE__,
4175 DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
4176 "You are submitting command buffer %#" PRIxLEAST64
4177 " that is invalid because it had the following bound "
4178 "descriptor set(s) updated: %s",
4179 (uint64_t)(pCB->commandBuffer), set_string.str().c_str());
Tobin Ehlis74714d22016-01-25 15:24:34 -08004180 }
4181 } else { // Flag error for using CB w/o vkEndCommandBuffer() called
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004182 skipCall |= log_msg(
4183 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4184 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
4185 (uint64_t)(pCB->commandBuffer), __LINE__,
4186 DRAWSTATE_NO_END_COMMAND_BUFFER, "DS",
4187 "You must call vkEndCommandBuffer() on CB %#" PRIxLEAST64
4188 " before this call to vkQueueSubmit()!",
4189 (uint64_t)(pCB->commandBuffer));
Tobin Ehlis74714d22016-01-25 15:24:34 -08004190 loader_platform_thread_unlock_mutex(&globalLock);
4191 return VK_ERROR_VALIDATION_FAILED_EXT;
4192 }
4193 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004194 // If USAGE_SIMULTANEOUS_USE_BIT not set then CB cannot already be executing
4195 // on device
4196 if (!(pCB->beginInfo.flags &
4197 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
4198 if (dev_data->globalInFlightCmdBuffers.find(pCB->commandBuffer) !=
4199 dev_data->globalInFlightCmdBuffers.end()) {
4200 skipCall |= log_msg(
4201 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4202 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
4203 (uint64_t)(pCB->commandBuffer), __LINE__,
4204 DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS",
4205 "Attempt to simultaneously execute CB %#" PRIxLEAST64
4206 " w/o VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set!",
4207 (uint64_t)(pCB->commandBuffer));
Michael Lentineb887b0a2015-12-29 14:12:11 -06004208 }
4209 }
Michael Lentine700b0aa2015-10-30 17:57:32 -07004210}
4211
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004212VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4213 vkQueueSubmit(VkQueue queue, uint32_t submitCount,
4214 const VkSubmitInfo *pSubmits, VkFence fence) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004215 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004216 GLOBAL_CB_NODE *pCB = NULL;
4217 layer_data *dev_data =
4218 get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06004219 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
Chia-I Wu40cf0ae2015-10-26 17:20:32 +08004220 const VkSubmitInfo *submit = &pSubmits[submit_idx];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004221 for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) {
Michael Lentine15a47882016-01-06 10:05:48 -06004222 if (dev_data->semaphoreSignaledMap[submit->pWaitSemaphores[i]]) {
4223 dev_data->semaphoreSignaledMap[submit->pWaitSemaphores[i]] = 0;
4224 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004225 skipCall |= log_msg(
4226 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4227 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
4228 DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
4229 "Queue %#" PRIx64 " is waiting on semaphore %#" PRIx64
4230 " that has no way to be signaled.",
4231 (uint64_t)(queue), (uint64_t)(submit->pWaitSemaphores[i]));
Michael Lentine15a47882016-01-06 10:05:48 -06004232 }
4233 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004234 for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) {
Michael Lentine15a47882016-01-06 10:05:48 -06004235 dev_data->semaphoreSignaledMap[submit->pSignalSemaphores[i]] = 1;
4236 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004237 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07004238
4239#ifndef DISABLE_IMAGE_LAYOUT_VALIDATION
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004240 skipCall |= ValidateCmdBufImageLayouts(submit->pCommandBuffers[i]);
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07004241#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
4242
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06004243 pCB = getCBNode(dev_data, submit->pCommandBuffers[i]);
4244 loader_platform_thread_lock_mutex(&globalLock);
4245 pCB->submitCount++; // increment submit count
Tobin Ehlise6e574b2016-01-24 23:25:31 -07004246 skipCall |= validateCommandBufferState(dev_data, pCB);
Tobin Ehlisc4bdde12015-05-27 14:30:06 -06004247 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlisa9f3d762015-05-22 12:38:16 -06004248 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004249 trackCommandBuffers(dev_data, queue, submit->commandBufferCount,
4250 submit->pCommandBuffers, fence);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004251 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004252 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004253 return dev_data->device_dispatch_table->QueueSubmit(queue, submitCount,
4254 pSubmits, fence);
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07004255 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004256}
4257
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004258VkBool32 cleanInFlightCmdBuffer(layer_data *my_data,
4259 VkCommandBuffer cmdBuffer) {
Mark Youngb20a6a82016-01-07 15:41:43 -07004260 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004261 GLOBAL_CB_NODE *pCB = getCBNode(my_data, cmdBuffer);
Mark Lobodzinskia9e7c042016-01-25 14:27:49 -07004262 if (pCB) {
4263 for (auto queryEventsPair : pCB->waitedEventsBeforeQueryReset) {
4264 for (auto event : queryEventsPair.second) {
4265 if (my_data->eventMap[event].needsSignaled) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004266 skip_call |= log_msg(
4267 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4268 VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 0,
4269 DRAWSTATE_INVALID_QUERY, "DS",
4270 "Cannot get query results on queryPool %" PRIu64
4271 " with index %d which was guarded by unsignaled event "
4272 "%" PRIu64 ".",
4273 (uint64_t)(queryEventsPair.first.pool),
4274 queryEventsPair.first.index, (uint64_t)(event));
Mark Lobodzinskia9e7c042016-01-25 14:27:49 -07004275 }
Michael Lentineb887b0a2015-12-29 14:12:11 -06004276 }
4277 }
4278 }
4279 return skip_call;
4280}
Tobin Ehlis74714d22016-01-25 15:24:34 -08004281// Remove given cmd_buffer from the global inFlight set.
4282// Also, if given queue is valid, then remove the cmd_buffer from that queues
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004283// inFlightCmdBuffer set. Finally, check all other queues and if given
4284// cmd_buffer
Tobin Ehlis74714d22016-01-25 15:24:34 -08004285// is still in flight on another queue, add it back into the global set.
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004286static inline void removeInFlightCmdBuffer(layer_data *dev_data,
4287 VkCommandBuffer cmd_buffer,
4288 VkQueue queue) {
4289 // Pull it off of global list initially, but if we find it in any other
4290 // queue list, add it back in
Tobin Ehlis74714d22016-01-25 15:24:34 -08004291 dev_data->globalInFlightCmdBuffers.erase(cmd_buffer);
4292 if (dev_data->queueMap.find(queue) != dev_data->queueMap.end()) {
4293 dev_data->queueMap[queue].inFlightCmdBuffers.erase(cmd_buffer);
4294 for (auto q : dev_data->queues) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004295 if ((q != queue) &&
4296 (dev_data->queueMap[q].inFlightCmdBuffers.find(cmd_buffer) !=
4297 dev_data->queueMap[q].inFlightCmdBuffers.end())) {
Tobin Ehlis74714d22016-01-25 15:24:34 -08004298 dev_data->globalInFlightCmdBuffers.insert(cmd_buffer);
4299 break;
4300 }
Tobin Ehlisae82e7f2016-01-20 16:23:37 -07004301 }
4302 }
4303}
Michael Lentineb887b0a2015-12-29 14:12:11 -06004304
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004305VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4306 vkWaitForFences(VkDevice device, uint32_t fenceCount,
4307 const VkFence *pFences, VkBool32 waitAll,
4308 uint64_t timeout) {
4309 layer_data *dev_data =
4310 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4311 VkResult result = dev_data->device_dispatch_table->WaitForFences(
4312 device, fenceCount, pFences, waitAll, timeout);
Mark Youngb20a6a82016-01-07 15:41:43 -07004313 VkBool32 skip_call = VK_FALSE;
Tobin Ehlis74714d22016-01-25 15:24:34 -08004314 if (result == VK_SUCCESS) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004315 // When we know that all fences are complete we can clean/remove their
4316 // CBs
Tobin Ehlis74714d22016-01-25 15:24:34 -08004317 if (waitAll || fenceCount == 1) {
4318 for (uint32_t i = 0; i < fenceCount; ++i) {
4319 VkQueue fence_queue = dev_data->fenceMap[pFences[i]].queue;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004320 for (auto cmdBuffer :
4321 dev_data->fenceMap[pFences[i]].cmdBuffers) {
Tobin Ehlis74714d22016-01-25 15:24:34 -08004322 skip_call |= cleanInFlightCmdBuffer(dev_data, cmdBuffer);
4323 removeInFlightCmdBuffer(dev_data, cmdBuffer, fence_queue);
4324 }
4325 }
4326 decrementResources(dev_data, fenceCount, pFences);
Michael Lentineb887b0a2015-12-29 14:12:11 -06004327 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004328 // NOTE : Alternate case not handled here is when some fences have
4329 // completed. In
4330 // this case for app to guarantee which fences completed it will have
4331 // to call
4332 // vkGetFenceStatus() at which point we'll clean/remove their CBs if
4333 // complete.
Michael Lentine700b0aa2015-10-30 17:57:32 -07004334 }
Mark Youngb20a6a82016-01-07 15:41:43 -07004335 if (VK_FALSE != skip_call)
Mark Lobodzinskice738852016-01-07 10:04:02 -07004336 return VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentine700b0aa2015-10-30 17:57:32 -07004337 return result;
4338}
4339
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004340VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4341 vkGetFenceStatus(VkDevice device, VkFence fence) {
4342 layer_data *dev_data =
4343 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4344 VkResult result =
4345 dev_data->device_dispatch_table->GetFenceStatus(device, fence);
Tobin Ehlisae82e7f2016-01-20 16:23:37 -07004346 VkBool32 skip_call = VK_FALSE;
Michael Lentine700b0aa2015-10-30 17:57:32 -07004347 if (result == VK_SUCCESS) {
Tobin Ehlisae82e7f2016-01-20 16:23:37 -07004348 auto fence_queue = dev_data->fenceMap[fence].queue;
Michael Lentineb887b0a2015-12-29 14:12:11 -06004349 for (auto cmdBuffer : dev_data->fenceMap[fence].cmdBuffers) {
Tobin Ehlisae82e7f2016-01-20 16:23:37 -07004350 skip_call |= cleanInFlightCmdBuffer(dev_data, cmdBuffer);
Tobin Ehlis74714d22016-01-25 15:24:34 -08004351 removeInFlightCmdBuffer(dev_data, cmdBuffer, fence_queue);
Michael Lentineb887b0a2015-12-29 14:12:11 -06004352 }
Michael Lentine700b0aa2015-10-30 17:57:32 -07004353 decrementResources(dev_data, 1, &fence);
4354 }
Tobin Ehlisae82e7f2016-01-20 16:23:37 -07004355 if (VK_FALSE != skip_call)
4356 return VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentine700b0aa2015-10-30 17:57:32 -07004357 return result;
4358}
4359
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004360VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4361 vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex,
4362 uint32_t queueIndex, VkQueue *pQueue) {
4363 layer_data *dev_data =
4364 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4365 dev_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex,
4366 queueIndex, pQueue);
Tobin Ehlisae82e7f2016-01-20 16:23:37 -07004367 dev_data->queues.push_back(*pQueue);
Michael Lentine700b0aa2015-10-30 17:57:32 -07004368 dev_data->queueMap[*pQueue].device = device;
4369}
4370
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004371VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle(VkQueue queue) {
4372 layer_data *dev_data =
4373 get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Michael Lentine700b0aa2015-10-30 17:57:32 -07004374 decrementResources(dev_data, queue);
Tobin Ehlisae82e7f2016-01-20 16:23:37 -07004375 VkBool32 skip_call = VK_FALSE;
4376 // Iterate over local set since we erase set members as we go in for loop
4377 auto local_cb_set = dev_data->queueMap[queue].inFlightCmdBuffers;
4378 for (auto cmdBuffer : local_cb_set) {
4379 skip_call |= cleanInFlightCmdBuffer(dev_data, cmdBuffer);
Tobin Ehlis74714d22016-01-25 15:24:34 -08004380 removeInFlightCmdBuffer(dev_data, cmdBuffer, queue);
Michael Lentineb887b0a2015-12-29 14:12:11 -06004381 }
Tobin Ehlisae82e7f2016-01-20 16:23:37 -07004382 dev_data->queueMap[queue].inFlightCmdBuffers.clear();
4383 if (VK_FALSE != skip_call)
4384 return VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentine700b0aa2015-10-30 17:57:32 -07004385 return dev_data->device_dispatch_table->QueueWaitIdle(queue);
4386}
4387
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004388VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4389 vkDeviceWaitIdle(VkDevice device) {
Tobin Ehlis74714d22016-01-25 15:24:34 -08004390 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004391 layer_data *dev_data =
4392 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Tobin Ehlisae82e7f2016-01-20 16:23:37 -07004393 for (auto queue : dev_data->queues) {
4394 decrementResources(dev_data, queue);
Tobin Ehlis74714d22016-01-25 15:24:34 -08004395 if (dev_data->queueMap.find(queue) != dev_data->queueMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004396 // Clear all of the queue inFlightCmdBuffers (global set cleared
4397 // below)
Tobin Ehlis74714d22016-01-25 15:24:34 -08004398 dev_data->queueMap[queue].inFlightCmdBuffers.clear();
4399 }
Michael Lentine700b0aa2015-10-30 17:57:32 -07004400 }
Tobin Ehlis74714d22016-01-25 15:24:34 -08004401 for (auto cmdBuffer : dev_data->globalInFlightCmdBuffers) {
4402 skip_call |= cleanInFlightCmdBuffer(dev_data, cmdBuffer);
Michael Lentineb887b0a2015-12-29 14:12:11 -06004403 }
Tobin Ehlis74714d22016-01-25 15:24:34 -08004404 dev_data->globalInFlightCmdBuffers.clear();
4405 if (VK_FALSE != skip_call)
4406 return VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentine700b0aa2015-10-30 17:57:32 -07004407 return dev_data->device_dispatch_table->DeviceWaitIdle(device);
4408}
4409
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004410VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4411 vkDestroyFence(VkDevice device, VkFence fence,
4412 const VkAllocationCallbacks *pAllocator) {
4413 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
4414 ->device_dispatch_table->DestroyFence(device, fence, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004415 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004416}
4417
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004418VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4419 vkDestroySemaphore(VkDevice device, VkSemaphore semaphore,
4420 const VkAllocationCallbacks *pAllocator) {
4421 layer_data *dev_data =
4422 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4423 dev_data->device_dispatch_table->DestroySemaphore(device, semaphore,
4424 pAllocator);
Michael Lentine15a47882016-01-06 10:05:48 -06004425 dev_data->semaphoreSignaledMap.erase(semaphore);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004426 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004427}
4428
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004429VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4430 vkDestroyEvent(VkDevice device, VkEvent event,
4431 const VkAllocationCallbacks *pAllocator) {
4432 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
4433 ->device_dispatch_table->DestroyEvent(device, event, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004434 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004435}
4436
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004437VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4438 vkDestroyQueryPool(VkDevice device, VkQueryPool queryPool,
4439 const VkAllocationCallbacks *pAllocator) {
4440 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
4441 ->device_dispatch_table->DestroyQueryPool(device, queryPool,
4442 pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004443 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004444}
4445
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004446VKAPI_ATTR VkResult VKAPI_CALL
4447 vkGetQueryPoolResults(VkDevice device, VkQueryPool queryPool,
4448 uint32_t firstQuery, uint32_t queryCount,
4449 size_t dataSize, void *pData, VkDeviceSize stride,
4450 VkQueryResultFlags flags) {
4451 layer_data *dev_data =
4452 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Michael Lentineb887b0a2015-12-29 14:12:11 -06004453 unordered_map<QueryObject, vector<VkCommandBuffer>> queriesInFlight;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004454 GLOBAL_CB_NODE *pCB = nullptr;
Tobin Ehlis74714d22016-01-25 15:24:34 -08004455 for (auto cmdBuffer : dev_data->globalInFlightCmdBuffers) {
Michael Lentineb887b0a2015-12-29 14:12:11 -06004456 pCB = getCBNode(dev_data, cmdBuffer);
4457 for (auto queryStatePair : pCB->queryToStateMap) {
4458 queriesInFlight[queryStatePair.first].push_back(cmdBuffer);
4459 }
4460 }
Mark Youngb20a6a82016-01-07 15:41:43 -07004461 VkBool32 skip_call = VK_FALSE;
Michael Lentineb887b0a2015-12-29 14:12:11 -06004462 for (uint32_t i = 0; i < queryCount; ++i) {
Mark Lobodzinskice738852016-01-07 10:04:02 -07004463 QueryObject query = {queryPool, firstQuery + i};
Michael Lentineb887b0a2015-12-29 14:12:11 -06004464 auto queryElement = queriesInFlight.find(query);
4465 auto queryToStateElement = dev_data->queryToStateMap.find(query);
4466 if (queryToStateElement != dev_data->queryToStateMap.end()) {
4467 }
4468 // Available and in flight
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004469 if (queryElement != queriesInFlight.end() &&
4470 queryToStateElement != dev_data->queryToStateMap.end() &&
4471 queryToStateElement->second) {
Michael Lentineb887b0a2015-12-29 14:12:11 -06004472 for (auto cmdBuffer : queryElement->second) {
4473 pCB = getCBNode(dev_data, cmdBuffer);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004474 auto queryEventElement =
4475 pCB->waitedEventsBeforeQueryReset.find(query);
4476 if (queryEventElement ==
4477 pCB->waitedEventsBeforeQueryReset.end()) {
4478 skip_call |= log_msg(
4479 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4480 VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__,
4481 DRAWSTATE_INVALID_QUERY, "DS",
4482 "Cannot get query results on queryPool %" PRIu64
4483 " with index %d which is in flight.",
4484 (uint64_t)(queryPool), firstQuery + i);
Michael Lentineb887b0a2015-12-29 14:12:11 -06004485 } else {
4486 for (auto event : queryEventElement->second) {
4487 dev_data->eventMap[event].needsSignaled = true;
4488 }
4489 }
4490 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004491 // Unavailable and in flight
4492 } else if (queryElement != queriesInFlight.end() &&
4493 queryToStateElement != dev_data->queryToStateMap.end() &&
4494 !queryToStateElement->second) {
4495 // TODO : Can there be the same query in use by multiple command
4496 // buffers in flight?
Michael Lentineb887b0a2015-12-29 14:12:11 -06004497 bool make_available = false;
4498 for (auto cmdBuffer : queryElement->second) {
4499 pCB = getCBNode(dev_data, cmdBuffer);
4500 make_available |= pCB->queryToStateMap[query];
4501 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004502 if (!(((flags & VK_QUERY_RESULT_PARTIAL_BIT) ||
4503 (flags & VK_QUERY_RESULT_WAIT_BIT)) &&
4504 make_available)) {
4505 skip_call |= log_msg(
4506 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4507 VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__,
4508 DRAWSTATE_INVALID_QUERY, "DS",
4509 "Cannot get query results on queryPool %" PRIu64
4510 " with index %d which is unavailable.",
4511 (uint64_t)(queryPool), firstQuery + i);
Michael Lentineb887b0a2015-12-29 14:12:11 -06004512 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004513 // Unavailable
4514 } else if (queryToStateElement != dev_data->queryToStateMap.end() &&
4515 !queryToStateElement->second) {
4516 skip_call |=
4517 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4518 VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__,
4519 DRAWSTATE_INVALID_QUERY, "DS",
4520 "Cannot get query results on queryPool %" PRIu64
4521 " with index %d which is unavailable.",
4522 (uint64_t)(queryPool), firstQuery + i);
4523 // Unitialized
Michael Lentineb887b0a2015-12-29 14:12:11 -06004524 } else if (queryToStateElement == dev_data->queryToStateMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004525 skip_call |=
4526 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4527 VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__,
4528 DRAWSTATE_INVALID_QUERY, "DS",
4529 "Cannot get query results on queryPool %" PRIu64
4530 " with index %d which is uninitialized.",
4531 (uint64_t)(queryPool), firstQuery + i);
Michael Lentineb887b0a2015-12-29 14:12:11 -06004532 }
4533 }
4534 if (skip_call)
Mark Lobodzinskice738852016-01-07 10:04:02 -07004535 return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004536 return dev_data->device_dispatch_table->GetQueryPoolResults(
4537 device, queryPool, firstQuery, queryCount, dataSize, pData, stride,
4538 flags);
Michael Lentineb887b0a2015-12-29 14:12:11 -06004539}
4540
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004541VkBool32 validateIdleBuffer(const layer_data *my_data, VkBuffer buffer) {
Mark Youngb20a6a82016-01-07 15:41:43 -07004542 VkBool32 skip_call = VK_FALSE;
Michael Lentine700b0aa2015-10-30 17:57:32 -07004543 auto buffer_data = my_data->bufferMap.find(buffer);
4544 if (buffer_data == my_data->bufferMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004545 skip_call |= log_msg(
4546 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4547 VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, (uint64_t)(buffer),
4548 __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS",
4549 "Cannot free buffer %" PRIxLEAST64 " that has not been allocated.",
4550 (uint64_t)(buffer));
Michael Lentine700b0aa2015-10-30 17:57:32 -07004551 } else {
4552 if (buffer_data->second.in_use.load()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004553 skip_call |=
4554 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4555 VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
4556 (uint64_t)(buffer), __LINE__, DRAWSTATE_OBJECT_INUSE,
4557 "DS", "Cannot free buffer %" PRIxLEAST64
4558 " that is in use by a command buffer.",
4559 (uint64_t)(buffer));
Michael Lentine700b0aa2015-10-30 17:57:32 -07004560 }
4561 }
4562 return skip_call;
4563}
4564
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004565VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4566 vkDestroyBuffer(VkDevice device, VkBuffer buffer,
4567 const VkAllocationCallbacks *pAllocator) {
4568 layer_data *dev_data =
4569 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Mark Youngb20a6a82016-01-07 15:41:43 -07004570 VkBool32 skip_call = VK_FALSE;
Michael Lentine700b0aa2015-10-30 17:57:32 -07004571 if (!validateIdleBuffer(dev_data, buffer)) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004572 dev_data->device_dispatch_table->DestroyBuffer(device, buffer,
4573 pAllocator);
Michael Lentine700b0aa2015-10-30 17:57:32 -07004574 }
Chia-I Wue2fc5522015-10-26 20:04:44 +08004575 dev_data->bufferMap.erase(buffer);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004576}
4577
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004578VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4579 vkDestroyBufferView(VkDevice device, VkBufferView bufferView,
4580 const VkAllocationCallbacks *pAllocator) {
4581 layer_data *dev_data =
4582 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4583 dev_data->device_dispatch_table->DestroyBufferView(device, bufferView,
4584 pAllocator);
Chia-I Wue2fc5522015-10-26 20:04:44 +08004585 dev_data->bufferViewMap.erase(bufferView);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004586}
4587
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004588VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4589 vkDestroyImage(VkDevice device, VkImage image,
4590 const VkAllocationCallbacks *pAllocator) {
4591 layer_data *dev_data =
4592 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08004593 dev_data->device_dispatch_table->DestroyImage(device, image, pAllocator);
Chia-I Wue2fc5522015-10-26 20:04:44 +08004594 dev_data->imageMap.erase(image);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004595}
4596
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004597VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4598 vkDestroyImageView(VkDevice device, VkImageView imageView,
4599 const VkAllocationCallbacks *pAllocator) {
4600 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
4601 ->device_dispatch_table->DestroyImageView(device, imageView,
4602 pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004603 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004604}
4605
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004606VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4607 vkDestroyShaderModule(VkDevice device, VkShaderModule shaderModule,
4608 const VkAllocationCallbacks *pAllocator) {
4609 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
4610 ->device_dispatch_table->DestroyShaderModule(device, shaderModule,
4611 pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004612 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004613}
4614
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004615VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4616 vkDestroyPipeline(VkDevice device, VkPipeline pipeline,
4617 const VkAllocationCallbacks *pAllocator) {
4618 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
4619 ->device_dispatch_table->DestroyPipeline(device, pipeline, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004620 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004621}
4622
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004623VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4624 vkDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout,
4625 const VkAllocationCallbacks *pAllocator) {
4626 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
4627 ->device_dispatch_table->DestroyPipelineLayout(device, pipelineLayout,
4628 pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004629 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004630}
4631
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004632VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4633 vkDestroySampler(VkDevice device, VkSampler sampler,
4634 const VkAllocationCallbacks *pAllocator) {
4635 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
4636 ->device_dispatch_table->DestroySampler(device, sampler, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004637 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004638}
4639
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004640VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4641 vkDestroyDescriptorSetLayout(VkDevice device,
4642 VkDescriptorSetLayout descriptorSetLayout,
4643 const VkAllocationCallbacks *pAllocator) {
4644 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
4645 ->device_dispatch_table->DestroyDescriptorSetLayout(
4646 device, descriptorSetLayout, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004647 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004648}
4649
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004650VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4651 vkDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
4652 const VkAllocationCallbacks *pAllocator) {
4653 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
4654 ->device_dispatch_table->DestroyDescriptorPool(device, descriptorPool,
4655 pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004656 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004657}
4658
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004659VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4660 vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool,
4661 uint32_t count,
4662 const VkCommandBuffer *pCommandBuffers) {
4663 layer_data *dev_data =
4664 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski39298632015-11-18 08:38:27 -07004665
Courtney Goeltzenleuchter51239472015-12-16 16:06:06 -07004666 for (uint32_t i = 0; i < count; i++) {
Tobin Ehlis74714d22016-01-25 15:24:34 -08004667 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07004668 // Delete CB information structure, and remove from commandBufferMap
4669 auto cb = dev_data->commandBufferMap.find(pCommandBuffers[i]);
4670 if (cb != dev_data->commandBufferMap.end()) {
Tobin Ehlise6e574b2016-01-24 23:25:31 -07004671 // reset prior to delete for data clean-up
4672 resetCB(dev_data, (*cb).second->commandBuffer);
Mark Lobodzinski39298632015-11-18 08:38:27 -07004673 delete (*cb).second;
4674 dev_data->commandBufferMap.erase(cb);
4675 }
4676
4677 // Remove commandBuffer reference from commandPoolMap
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004678 dev_data->commandPoolMap[commandPool].commandBuffers.remove(
4679 pCommandBuffers[i]);
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07004680 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07004681 }
4682
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004683 dev_data->device_dispatch_table->FreeCommandBuffers(device, commandPool,
4684 count, pCommandBuffers);
Mark Lobodzinski39298632015-11-18 08:38:27 -07004685}
4686
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004687VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4688 vkCreateCommandPool(VkDevice device,
4689 const VkCommandPoolCreateInfo *pCreateInfo,
4690 const VkAllocationCallbacks *pAllocator,
4691 VkCommandPool *pCommandPool) {
4692 layer_data *dev_data =
4693 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski39298632015-11-18 08:38:27 -07004694
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004695 VkResult result = dev_data->device_dispatch_table->CreateCommandPool(
4696 device, pCreateInfo, pAllocator, pCommandPool);
Mark Lobodzinski39298632015-11-18 08:38:27 -07004697
4698 if (VK_SUCCESS == result) {
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07004699 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004700 dev_data->commandPoolMap[*pCommandPool].createFlags =
4701 pCreateInfo->flags;
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07004702 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07004703 }
4704 return result;
4705}
Michael Lentinee063fe42016-01-27 17:52:20 -06004706
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004707VkBool32 validateCommandBuffersNotInUse(const layer_data *dev_data,
4708 VkCommandPool commandPool) {
Mark Youngbaa677f2016-01-28 09:36:15 -07004709 VkBool32 skipCall = VK_FALSE;
Michael Lentinee063fe42016-01-27 17:52:20 -06004710 loader_platform_thread_lock_mutex(&globalLock);
4711 auto pool_data = dev_data->commandPoolMap.find(commandPool);
4712 if (pool_data != dev_data->commandPoolMap.end()) {
4713 for (auto cmdBuffer : pool_data->second.commandBuffers) {
Tobin Ehlis74714d22016-01-25 15:24:34 -08004714 if (dev_data->globalInFlightCmdBuffers.count(cmdBuffer)) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004715 skipCall |= log_msg(
4716 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4717 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT,
4718 (uint64_t)(commandPool), __LINE__, DRAWSTATE_OBJECT_INUSE,
4719 "DS",
4720 "Cannot reset command pool %" PRIx64
4721 " when allocated command buffer %" PRIx64 " is in use.",
4722 (uint64_t)(commandPool), (uint64_t)(cmdBuffer));
Michael Lentinee063fe42016-01-27 17:52:20 -06004723 }
4724 }
4725 }
4726 loader_platform_thread_unlock_mutex(&globalLock);
Mark Youngbaa677f2016-01-28 09:36:15 -07004727 return skipCall;
Michael Lentinee063fe42016-01-27 17:52:20 -06004728}
4729
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004730// Destroy commandPool along with all of the commandBuffers allocated from that
4731// pool
4732VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4733 vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool,
4734 const VkAllocationCallbacks *pAllocator) {
4735 layer_data *dev_data =
4736 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07004737 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07004738
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004739 // Must remove cmdpool from cmdpoolmap, after removing all cmdbuffers in its
4740 // list from the commandPoolMap
4741 if (dev_data->commandPoolMap.find(commandPool) !=
4742 dev_data->commandPoolMap.end()) {
4743 for (auto poolCb =
4744 dev_data->commandPoolMap[commandPool].commandBuffers.begin();
4745 poolCb !=
4746 dev_data->commandPoolMap[commandPool].commandBuffers.end();) {
Mark Lobodzinski39298632015-11-18 08:38:27 -07004747 auto del_cb = dev_data->commandBufferMap.find(*poolCb);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004748 delete (*del_cb).second; // delete CB info structure
4749 dev_data->commandBufferMap.erase(
4750 del_cb); // Remove this command buffer from cbMap
4751 poolCb = dev_data->commandPoolMap[commandPool].commandBuffers.erase(
4752 poolCb); // Remove CB reference from commandPoolMap's list
Mark Lobodzinski39298632015-11-18 08:38:27 -07004753 }
4754 }
4755 dev_data->commandPoolMap.erase(commandPool);
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07004756
4757 loader_platform_thread_unlock_mutex(&globalLock);
Michael Lentinee063fe42016-01-27 17:52:20 -06004758
Mark Youngbaa677f2016-01-28 09:36:15 -07004759 if (VK_TRUE == validateCommandBuffersNotInUse(dev_data, commandPool))
Michael Lentinee063fe42016-01-27 17:52:20 -06004760 return;
4761
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004762 dev_data->device_dispatch_table->DestroyCommandPool(device, commandPool,
4763 pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004764}
4765
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004766VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4767 vkResetCommandPool(VkDevice device, VkCommandPool commandPool,
4768 VkCommandPoolResetFlags flags) {
4769 layer_data *dev_data =
4770 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4771 VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlisac0ef842015-12-14 13:46:38 -07004772
Mark Youngbaa677f2016-01-28 09:36:15 -07004773 if (VK_TRUE == validateCommandBuffersNotInUse(dev_data, commandPool))
Michael Lentined2a7d632016-01-27 17:02:39 -06004774 return VK_ERROR_VALIDATION_FAILED_EXT;
4775
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004776 result = dev_data->device_dispatch_table->ResetCommandPool(
4777 device, commandPool, flags);
Tobin Ehlisac0ef842015-12-14 13:46:38 -07004778 // Reset all of the CBs allocated from this pool
4779 if (VK_SUCCESS == result) {
Tobin Ehlis74714d22016-01-25 15:24:34 -08004780 loader_platform_thread_lock_mutex(&globalLock);
Tobin Ehlisac0ef842015-12-14 13:46:38 -07004781 auto it = dev_data->commandPoolMap[commandPool].commandBuffers.begin();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004782 while (it !=
4783 dev_data->commandPoolMap[commandPool].commandBuffers.end()) {
Tobin Ehlisac0ef842015-12-14 13:46:38 -07004784 resetCB(dev_data, (*it));
4785 ++it;
4786 }
Tobin Ehlis74714d22016-01-25 15:24:34 -08004787 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlisac0ef842015-12-14 13:46:38 -07004788 }
4789 return result;
4790}
4791
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004792VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4793 vkDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer,
4794 const VkAllocationCallbacks *pAllocator) {
4795 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
4796 ->device_dispatch_table->DestroyFramebuffer(device, framebuffer,
4797 pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004798 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004799}
4800
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004801VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4802 vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass,
4803 const VkAllocationCallbacks *pAllocator) {
4804 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
4805 ->device_dispatch_table->DestroyRenderPass(device, renderPass,
4806 pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004807 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004808}
4809
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004810VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4811 vkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
4812 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
4813 layer_data *dev_data =
4814 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4815 VkResult result = dev_data->device_dispatch_table->CreateBuffer(
4816 device, pCreateInfo, pAllocator, pBuffer);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06004817 if (VK_SUCCESS == result) {
4818 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004819 // TODO : This doesn't create deep copy of pQueueFamilyIndices so need
4820 // to fix that if/when we want that data to be valid
4821 dev_data->bufferMap[*pBuffer].create_info =
4822 unique_ptr<VkBufferCreateInfo>(
4823 new VkBufferCreateInfo(*pCreateInfo));
Michael Lentine700b0aa2015-10-30 17:57:32 -07004824 dev_data->bufferMap[*pBuffer].in_use.store(0);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06004825 loader_platform_thread_unlock_mutex(&globalLock);
4826 }
4827 return result;
4828}
4829
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004830VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4831 vkCreateBufferView(VkDevice device,
4832 const VkBufferViewCreateInfo *pCreateInfo,
4833 const VkAllocationCallbacks *pAllocator,
4834 VkBufferView *pView) {
4835 layer_data *dev_data =
4836 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4837 VkResult result = dev_data->device_dispatch_table->CreateBufferView(
4838 device, pCreateInfo, pAllocator, pView);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06004839 if (VK_SUCCESS == result) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004840 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004841 dev_data->bufferViewMap[*pView] = unique_ptr<VkBufferViewCreateInfo>(
4842 new VkBufferViewCreateInfo(*pCreateInfo));
Tobin Ehlisa1c28562015-10-23 16:00:08 -06004843 loader_platform_thread_unlock_mutex(&globalLock);
4844 }
4845 return result;
4846}
4847
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004848VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4849 vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
4850 const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
4851 layer_data *dev_data =
4852 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4853 VkResult result = dev_data->device_dispatch_table->CreateImage(
4854 device, pCreateInfo, pAllocator, pImage);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06004855 if (VK_SUCCESS == result) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004856 IMAGE_NODE *image_node = new IMAGE_NODE;
Michael Lentineabc5e922015-10-12 11:30:14 -05004857 image_node->layout = pCreateInfo->initialLayout;
Tobin Ehlis75cd1c52016-01-21 10:21:04 -07004858 image_node->format = pCreateInfo->format;
Tobin Ehlisa1c28562015-10-23 16:00:08 -06004859 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004860 dev_data->imageMap[*pImage] =
4861 unique_ptr<VkImageCreateInfo>(new VkImageCreateInfo(*pCreateInfo));
Michael Lentineabc5e922015-10-12 11:30:14 -05004862 dev_data->imageLayoutMap[*pImage] = image_node;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004863 loader_platform_thread_unlock_mutex(&globalLock);
4864 }
4865 return result;
4866}
4867
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004868VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4869 vkCreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
4870 const VkAllocationCallbacks *pAllocator,
4871 VkImageView *pView) {
4872 layer_data *dev_data =
4873 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4874 VkResult result = dev_data->device_dispatch_table->CreateImageView(
4875 device, pCreateInfo, pAllocator, pView);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06004876 if (VK_SUCCESS == result) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004877 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004878 dev_data->imageViewMap[*pView] = unique_ptr<VkImageViewCreateInfo>(
4879 new VkImageViewCreateInfo(*pCreateInfo));
Tobin Ehlis53eddda2015-07-01 16:46:13 -06004880 loader_platform_thread_unlock_mutex(&globalLock);
4881 }
4882 return result;
4883}
4884
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004885// TODO handle pipeline caches
4886VKAPI_ATTR VkResult VKAPI_CALL
4887 vkCreatePipelineCache(VkDevice device,
4888 const VkPipelineCacheCreateInfo *pCreateInfo,
4889 const VkAllocationCallbacks *pAllocator,
4890 VkPipelineCache *pPipelineCache) {
4891 layer_data *dev_data =
4892 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4893 VkResult result = dev_data->device_dispatch_table->CreatePipelineCache(
4894 device, pCreateInfo, pAllocator, pPipelineCache);
Jon Ashburnc669cc62015-07-09 15:02:25 -06004895 return result;
4896}
4897
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004898VKAPI_ATTR void VKAPI_CALL
4899 vkDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache,
4900 const VkAllocationCallbacks *pAllocator) {
4901 layer_data *dev_data =
4902 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4903 dev_data->device_dispatch_table->DestroyPipelineCache(device, pipelineCache,
4904 pAllocator);
Jon Ashburnc669cc62015-07-09 15:02:25 -06004905}
4906
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004907VKAPI_ATTR VkResult VKAPI_CALL
4908 vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache,
4909 size_t *pDataSize, void *pData) {
4910 layer_data *dev_data =
4911 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4912 VkResult result = dev_data->device_dispatch_table->GetPipelineCacheData(
4913 device, pipelineCache, pDataSize, pData);
Jon Ashburnc669cc62015-07-09 15:02:25 -06004914 return result;
4915}
4916
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004917VKAPI_ATTR VkResult VKAPI_CALL
4918 vkMergePipelineCaches(VkDevice device, VkPipelineCache dstCache,
4919 uint32_t srcCacheCount,
4920 const VkPipelineCache *pSrcCaches) {
4921 layer_data *dev_data =
4922 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4923 VkResult result = dev_data->device_dispatch_table->MergePipelineCaches(
4924 device, dstCache, srcCacheCount, pSrcCaches);
Jon Ashburnc669cc62015-07-09 15:02:25 -06004925 return result;
4926}
4927
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004928VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4929 vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache,
4930 uint32_t count,
4931 const VkGraphicsPipelineCreateInfo *pCreateInfos,
4932 const VkAllocationCallbacks *pAllocator,
4933 VkPipeline *pPipelines) {
Courtney Goeltzenleuchtered894072015-09-04 13:39:59 -06004934 VkResult result = VK_SUCCESS;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004935 // TODO What to do with pipelineCache?
Tobin Ehlis75283bf2015-06-18 15:59:33 -06004936 // The order of operations here is a little convoluted but gets the job done
4937 // 1. Pipeline create state is first shadowed into PIPELINE_NODE struct
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004938 // 2. Create state is then validated (which uses flags setup during
4939 // shadowing)
4940 // 3. If everything looks good, we'll then create the pipeline and add NODE
4941 // to pipelineMap
Tobin Ehlis11efc302015-09-16 10:33:53 -06004942 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004943 // TODO : Improve this data struct w/ unique_ptrs so cleanup below is
4944 // automatic
4945 vector<PIPELINE_NODE *> pPipeNode(count);
4946 layer_data *dev_data =
4947 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski475a2182015-11-10 15:25:01 -07004948
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004949 uint32_t i = 0;
Tobin Ehlis75283bf2015-06-18 15:59:33 -06004950 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski475a2182015-11-10 15:25:01 -07004951
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004952 for (i = 0; i < count; i++) {
Mark Lobodzinski475a2182015-11-10 15:25:01 -07004953 pPipeNode[i] = initGraphicsPipeline(dev_data, &pCreateInfos[i], NULL);
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004954 skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode[i]);
Tobin Ehlis11efc302015-09-16 10:33:53 -06004955 }
Mark Lobodzinski475a2182015-11-10 15:25:01 -07004956
Tobin Ehlis75283bf2015-06-18 15:59:33 -06004957 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07004958
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07004959 if (VK_FALSE == skipCall) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004960 result = dev_data->device_dispatch_table->CreateGraphicsPipelines(
4961 device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
Tobin Ehlis75283bf2015-06-18 15:59:33 -06004962 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004963 for (i = 0; i < count; i++) {
Tobin Ehlis11efc302015-09-16 10:33:53 -06004964 pPipeNode[i]->pipeline = pPipelines[i];
Chia-I Wue2fc5522015-10-26 20:04:44 +08004965 dev_data->pipelineMap[pPipeNode[i]->pipeline] = pPipeNode[i];
Tobin Ehlis11efc302015-09-16 10:33:53 -06004966 }
Tobin Ehlis75283bf2015-06-18 15:59:33 -06004967 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlisce132d82015-06-19 15:07:05 -06004968 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004969 for (i = 0; i < count; i++) {
Tobin Ehlis11efc302015-09-16 10:33:53 -06004970 if (pPipeNode[i]) {
4971 // If we allocated a pipeNode, need to clean it up here
4972 delete[] pPipeNode[i]->pVertexBindingDescriptions;
4973 delete[] pPipeNode[i]->pVertexAttributeDescriptions;
4974 delete[] pPipeNode[i]->pAttachments;
4975 delete pPipeNode[i];
4976 }
Tobin Ehlis75283bf2015-06-18 15:59:33 -06004977 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07004978 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis75283bf2015-06-18 15:59:33 -06004979 }
Courtney Goeltzenleuchtere2aaad02015-04-13 16:16:04 -06004980 return result;
4981}
4982
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004983VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4984 vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache,
4985 uint32_t count,
4986 const VkComputePipelineCreateInfo *pCreateInfos,
4987 const VkAllocationCallbacks *pAllocator,
4988 VkPipeline *pPipelines) {
4989 VkResult result = VK_SUCCESS;
Mark Lobodzinski475a2182015-11-10 15:25:01 -07004990 VkBool32 skipCall = VK_FALSE;
4991
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004992 // TODO : Improve this data struct w/ unique_ptrs so cleanup below is
4993 // automatic
4994 vector<PIPELINE_NODE *> pPipeNode(count);
4995 layer_data *dev_data =
4996 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski475a2182015-11-10 15:25:01 -07004997
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07004998 uint32_t i = 0;
Mark Lobodzinski475a2182015-11-10 15:25:01 -07004999 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005000 for (i = 0; i < count; i++) {
Mark Lobodzinski475a2182015-11-10 15:25:01 -07005001 // TODO: Verify compute stage bits
5002
5003 // Create and initialize internal tracking data structure
5004 pPipeNode[i] = new PIPELINE_NODE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005005 memcpy(&pPipeNode[i]->computePipelineCI, (const void *)&pCreateInfos[i],
5006 sizeof(VkComputePipelineCreateInfo));
Mark Lobodzinski475a2182015-11-10 15:25:01 -07005007
5008 // TODO: Add Compute Pipeline Verification
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005009 // skipCall |= verifyPipelineCreateState(dev_data, device,
5010 // pPipeNode[i]);
Mark Lobodzinski475a2182015-11-10 15:25:01 -07005011 }
5012 loader_platform_thread_unlock_mutex(&globalLock);
5013
5014 if (VK_FALSE == skipCall) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005015 result = dev_data->device_dispatch_table->CreateComputePipelines(
5016 device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
Mark Lobodzinski475a2182015-11-10 15:25:01 -07005017 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005018 for (i = 0; i < count; i++) {
Mark Lobodzinski475a2182015-11-10 15:25:01 -07005019 pPipeNode[i]->pipeline = pPipelines[i];
5020 dev_data->pipelineMap[pPipeNode[i]->pipeline] = pPipeNode[i];
5021 }
5022 loader_platform_thread_unlock_mutex(&globalLock);
5023 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005024 for (i = 0; i < count; i++) {
Mark Lobodzinski475a2182015-11-10 15:25:01 -07005025 if (pPipeNode[i]) {
5026 // Clean up any locally allocated data structures
5027 delete pPipeNode[i];
5028 }
5029 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005030 return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski475a2182015-11-10 15:25:01 -07005031 }
5032 return result;
5033}
5034
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005035VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
5036 vkCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
5037 const VkAllocationCallbacks *pAllocator,
5038 VkSampler *pSampler) {
5039 layer_data *dev_data =
5040 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5041 VkResult result = dev_data->device_dispatch_table->CreateSampler(
5042 device, pCreateInfo, pAllocator, pSampler);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005043 if (VK_SUCCESS == result) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005044 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005045 dev_data->sampleMap[*pSampler] =
5046 unique_ptr<SAMPLER_NODE>(new SAMPLER_NODE(pSampler, pCreateInfo));
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005047 loader_platform_thread_unlock_mutex(&globalLock);
5048 }
5049 return result;
5050}
5051
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005052VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorSetLayout(
5053 VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
5054 const VkAllocationCallbacks *pAllocator,
5055 VkDescriptorSetLayout *pSetLayout) {
5056 layer_data *dev_data =
5057 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5058 VkResult result =
5059 dev_data->device_dispatch_table->CreateDescriptorSetLayout(
5060 device, pCreateInfo, pAllocator, pSetLayout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005061 if (VK_SUCCESS == result) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07005062 // TODOSC : Capture layout bindings set
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005063 LAYOUT_NODE *pNewNode = new LAYOUT_NODE;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005064 if (NULL == pNewNode) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005065 if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5066 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
5067 (uint64_t)*pSetLayout, __LINE__,
5068 DRAWSTATE_OUT_OF_MEMORY, "DS",
5069 "Out of memory while attempting to allocate "
5070 "LAYOUT_NODE in vkCreateDescriptorSetLayout()"))
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005071 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005072 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005073 memcpy((void *)&pNewNode->createInfo, pCreateInfo,
5074 sizeof(VkDescriptorSetLayoutCreateInfo));
5075 pNewNode->createInfo.pBindings =
5076 new VkDescriptorSetLayoutBinding[pCreateInfo->bindingCount];
5077 memcpy((void *)pNewNode->createInfo.pBindings, pCreateInfo->pBindings,
5078 sizeof(VkDescriptorSetLayoutBinding) *
5079 pCreateInfo->bindingCount);
Chia-I Wud46e6ae2015-10-31 00:31:16 +08005080 // g++ does not like reserve with size 0
5081 if (pCreateInfo->bindingCount)
5082 pNewNode->bindings.reserve(pCreateInfo->bindingCount);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005083 uint32_t totalCount = 0;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005084 for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
5085 if (!pNewNode->bindings.insert(pCreateInfo->pBindings[i].binding)
5086 .second) {
5087 if (log_msg(
5088 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5089 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
5090 (uint64_t)*pSetLayout, __LINE__,
5091 DRAWSTATE_INVALID_LAYOUT, "DS",
5092 "duplicated binding number in "
5093 "VkDescriptorSetLayoutBinding"))
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005094 return VK_ERROR_VALIDATION_FAILED_EXT;
Chia-I Wud46e6ae2015-10-31 00:31:16 +08005095 }
5096
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07005097 totalCount += pCreateInfo->pBindings[i].descriptorCount;
5098 if (pCreateInfo->pBindings[i].pImmutableSamplers) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005099 VkSampler **ppIS =
5100 (VkSampler **)&pNewNode->createInfo.pBindings[i]
5101 .pImmutableSamplers;
5102 *ppIS =
5103 new VkSampler[pCreateInfo->pBindings[i].descriptorCount];
5104 memcpy(*ppIS, pCreateInfo->pBindings[i].pImmutableSamplers,
5105 pCreateInfo->pBindings[i].descriptorCount *
5106 sizeof(VkSampler));
Tobin Ehlis793ad302015-04-03 12:01:11 -06005107 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005108 }
Tobin Ehlis43c39c02016-01-11 13:18:40 -07005109 pNewNode->layout = *pSetLayout;
5110 pNewNode->startIndex = 0;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005111 if (totalCount > 0) {
Cody Northrop43751cc2015-10-26 14:07:35 -06005112 pNewNode->descriptorTypes.resize(totalCount);
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06005113 pNewNode->stageFlags.resize(totalCount);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005114 uint32_t offset = 0;
Tobin Ehlis793ad302015-04-03 12:01:11 -06005115 uint32_t j = 0;
Tobin Ehlisda2f0d02015-11-04 12:28:28 -07005116 VkDescriptorType dType;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005117 for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07005118 dType = pCreateInfo->pBindings[i].descriptorType;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005119 for (j = 0; j < pCreateInfo->pBindings[i].descriptorCount;
5120 j++) {
Tobin Ehlisda2f0d02015-11-04 12:28:28 -07005121 pNewNode->descriptorTypes[offset + j] = dType;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005122 pNewNode->stageFlags[offset + j] =
5123 pCreateInfo->pBindings[i].stageFlags;
Tobin Ehlisda2f0d02015-11-04 12:28:28 -07005124 if ((dType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
5125 (dType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
5126 pNewNode->dynamicDescriptorCount++;
5127 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005128 }
Tobin Ehlis793ad302015-04-03 12:01:11 -06005129 offset += j;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005130 }
Tobin Ehlis43c39c02016-01-11 13:18:40 -07005131 pNewNode->endIndex = pNewNode->startIndex + totalCount - 1;
5132 } else { // no descriptors
5133 pNewNode->endIndex = 0;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005134 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005135 // Put new node at Head of global Layer list
5136 loader_platform_thread_lock_mutex(&globalLock);
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07005137 dev_data->descriptorSetLayoutMap[*pSetLayout] = pNewNode;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005138 loader_platform_thread_unlock_mutex(&globalLock);
5139 }
5140 return result;
5141}
5142
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005143VKAPI_ATTR VkResult VKAPI_CALL
5144 vkCreatePipelineLayout(VkDevice device,
5145 const VkPipelineLayoutCreateInfo *pCreateInfo,
5146 const VkAllocationCallbacks *pAllocator,
5147 VkPipelineLayout *pPipelineLayout) {
5148 layer_data *dev_data =
5149 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5150 VkResult result = dev_data->device_dispatch_table->CreatePipelineLayout(
5151 device, pCreateInfo, pAllocator, pPipelineLayout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005152 if (VK_SUCCESS == result) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07005153 // TODOSC : Merge capture of the setLayouts per pipeline
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005154 PIPELINE_LAYOUT_NODE &plNode =
5155 dev_data->pipelineLayoutMap[*pPipelineLayout];
Chia-I Wud50a7d72015-10-26 20:48:51 +08005156 plNode.descriptorSetLayouts.resize(pCreateInfo->setLayoutCount);
Tobin Ehlis644ff042015-10-20 10:11:55 -06005157 uint32_t i = 0;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005158 for (i = 0; i < pCreateInfo->setLayoutCount; ++i) {
Tobin Ehlis644ff042015-10-20 10:11:55 -06005159 plNode.descriptorSetLayouts[i] = pCreateInfo->pSetLayouts[i];
5160 }
Cody Northrop43751cc2015-10-26 14:07:35 -06005161 plNode.pushConstantRanges.resize(pCreateInfo->pushConstantRangeCount);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005162 for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
Tobin Ehlis644ff042015-10-20 10:11:55 -06005163 plNode.pushConstantRanges[i] = pCreateInfo->pPushConstantRanges[i];
5164 }
Tobin Ehlis793ad302015-04-03 12:01:11 -06005165 }
5166 return result;
5167}
5168
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005169VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
5170 vkCreateDescriptorPool(VkDevice device,
5171 const VkDescriptorPoolCreateInfo *pCreateInfo,
5172 const VkAllocationCallbacks *pAllocator,
5173 VkDescriptorPool *pDescriptorPool) {
5174 layer_data *dev_data =
5175 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5176 VkResult result = dev_data->device_dispatch_table->CreateDescriptorPool(
5177 device, pCreateInfo, pAllocator, pDescriptorPool);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005178 if (VK_SUCCESS == result) {
Tobin Ehlis793ad302015-04-03 12:01:11 -06005179 // Insert this pool into Global Pool LL at head
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005180 if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
5181 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
5182 (uint64_t)*pDescriptorPool, __LINE__,
5183 DRAWSTATE_OUT_OF_MEMORY, "DS",
5184 "Created Descriptor Pool %#" PRIxLEAST64,
5185 (uint64_t)*pDescriptorPool))
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005186 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005187 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005188 DESCRIPTOR_POOL_NODE *pNewNode =
5189 new DESCRIPTOR_POOL_NODE(*pDescriptorPool, pCreateInfo);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005190 if (NULL == pNewNode) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005191 if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5192 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
5193 (uint64_t)*pDescriptorPool, __LINE__,
5194 DRAWSTATE_OUT_OF_MEMORY, "DS",
5195 "Out of memory while attempting to allocate "
5196 "DESCRIPTOR_POOL_NODE in vkCreateDescriptorPool()"))
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005197 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlisce132d82015-06-19 15:07:05 -06005198 } else {
Mark Lobodzinski39298632015-11-18 08:38:27 -07005199 dev_data->descriptorPoolMap[*pDescriptorPool] = pNewNode;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005200 }
5201 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlisce132d82015-06-19 15:07:05 -06005202 } else {
Tobin Ehlis793ad302015-04-03 12:01:11 -06005203 // Need to do anything if pool create fails?
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005204 }
5205 return result;
5206}
5207
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005208VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
5209 vkResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
5210 VkDescriptorPoolResetFlags flags) {
5211 layer_data *dev_data =
5212 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5213 VkResult result = dev_data->device_dispatch_table->ResetDescriptorPool(
5214 device, descriptorPool, flags);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005215 if (VK_SUCCESS == result) {
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06005216 clearDescriptorPool(dev_data, device, descriptorPool, flags);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005217 }
5218 return result;
5219}
5220
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005221VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
5222 vkAllocateDescriptorSets(VkDevice device,
5223 const VkDescriptorSetAllocateInfo *pAllocateInfo,
5224 VkDescriptorSet *pDescriptorSets) {
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06005225 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005226 layer_data *dev_data =
5227 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06005228 // Verify that requested descriptorSets are available in pool
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005229 DESCRIPTOR_POOL_NODE *pPoolNode =
5230 getPoolNode(dev_data, pAllocateInfo->descriptorPool);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06005231 if (!pPoolNode) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005232 skipCall |=
5233 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5234 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
5235 (uint64_t)pAllocateInfo->descriptorPool, __LINE__,
5236 DRAWSTATE_INVALID_POOL, "DS",
5237 "Unable to find pool node for pool %#" PRIxLEAST64
5238 " specified in vkAllocateDescriptorSets() call",
5239 (uint64_t)pAllocateInfo->descriptorPool);
5240 } else { // Make sure pool has all the available descriptors before calling
5241 // down chain
5242 skipCall |= validate_descriptor_availability_in_pool(
5243 dev_data, pPoolNode, pAllocateInfo->descriptorSetCount,
5244 pAllocateInfo->pSetLayouts);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06005245 }
5246 if (skipCall)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005247 return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005248 VkResult result = dev_data->device_dispatch_table->AllocateDescriptorSets(
5249 device, pAllocateInfo, pDescriptorSets);
Cody Northrop1e4f8022015-08-03 12:47:29 -06005250 if (VK_SUCCESS == result) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005251 DESCRIPTOR_POOL_NODE *pPoolNode =
5252 getPoolNode(dev_data, pAllocateInfo->descriptorPool);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06005253 if (pPoolNode) {
Jon Ashburnf19916e2016-01-11 13:12:43 -07005254 if (pAllocateInfo->descriptorSetCount == 0) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005255 log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
5256 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
5257 pAllocateInfo->descriptorSetCount, __LINE__,
5258 DRAWSTATE_NONE, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005259 "AllocateDescriptorSets called with 0 count");
Cody Northrop1e4f8022015-08-03 12:47:29 -06005260 }
Jon Ashburnf19916e2016-01-11 13:12:43 -07005261 for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005262 log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
5263 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
5264 (uint64_t)pDescriptorSets[i], __LINE__, DRAWSTATE_NONE,
5265 "DS", "Created Descriptor Set %#" PRIxLEAST64,
5266 (uint64_t)pDescriptorSets[i]);
Tobin Ehlis793ad302015-04-03 12:01:11 -06005267 // Create new set node and add to head of pool nodes
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005268 SET_NODE *pNewNode = new SET_NODE;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005269 if (NULL == pNewNode) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005270 if (log_msg(dev_data->report_data,
5271 VK_DEBUG_REPORT_ERROR_BIT_EXT,
5272 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
5273 (uint64_t)pDescriptorSets[i], __LINE__,
5274 DRAWSTATE_OUT_OF_MEMORY, "DS",
5275 "Out of memory while attempting to allocate "
5276 "SET_NODE in vkAllocateDescriptorSets()"))
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005277 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlisce132d82015-06-19 15:07:05 -06005278 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005279 // TODO : Pool should store a total count of each type of
5280 // Descriptor available
5281 // When descriptors are allocated, decrement the count and
5282 // validate here
5283 // that the count doesn't go below 0. One reset/free need
5284 // to bump count back up.
Tobin Ehlis793ad302015-04-03 12:01:11 -06005285 // Insert set at head of Set LL for this pool
5286 pNewNode->pNext = pPoolNode->pSets;
Tobin Ehlis9c4f38d2016-01-14 12:47:19 -07005287 pNewNode->in_use.store(0);
Tobin Ehlis793ad302015-04-03 12:01:11 -06005288 pPoolNode->pSets = pNewNode;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005289 LAYOUT_NODE *pLayout =
5290 getLayoutNode(dev_data, pAllocateInfo->pSetLayouts[i]);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005291 if (NULL == pLayout) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005292 if (log_msg(
5293 dev_data->report_data,
5294 VK_DEBUG_REPORT_ERROR_BIT_EXT,
5295 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
5296 (uint64_t)pAllocateInfo->pSetLayouts[i],
5297 __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
5298 "Unable to find set layout node for layout "
5299 "%#" PRIxLEAST64
5300 " specified in vkAllocateDescriptorSets() call",
5301 (uint64_t)pAllocateInfo->pSetLayouts[i]))
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005302 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005303 }
Tobin Ehlis793ad302015-04-03 12:01:11 -06005304 pNewNode->pLayout = pLayout;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005305 pNewNode->pool = pAllocateInfo->descriptorPool;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005306 pNewNode->set = pDescriptorSets[i];
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005307 pNewNode->descriptorCount = pLayout->endIndex + 1;
5308 if (pNewNode->descriptorCount) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005309 size_t descriptorArraySize = sizeof(GENERIC_HEADER *) *
5310 pNewNode->descriptorCount;
5311 pNewNode->ppDescriptors =
5312 new GENERIC_HEADER *[descriptorArraySize];
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005313 memset(pNewNode->ppDescriptors, 0, descriptorArraySize);
5314 }
Chia-I Wue2fc5522015-10-26 20:04:44 +08005315 dev_data->setMap[pDescriptorSets[i]] = pNewNode;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005316 }
5317 }
5318 }
5319 }
5320 return result;
5321}
5322
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005323VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
5324 vkFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool,
5325 uint32_t count,
5326 const VkDescriptorSet *pDescriptorSets) {
Tobin Ehlise735c692015-10-08 13:13:50 -06005327 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005328 layer_data *dev_data =
5329 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Tobin Ehlis9c4f38d2016-01-14 12:47:19 -07005330 // Make sure that no sets being destroyed are in-flight
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005331 for (uint32_t i = 0; i < count; ++i)
5332 skipCall |= validateIdleDescriptorSet(dev_data, pDescriptorSets[i],
5333 "vkFreeDesriptorSets");
Mark Lobodzinski39298632015-11-18 08:38:27 -07005334 DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, descriptorPool);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005335 if (pPoolNode &&
5336 !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT &
5337 pPoolNode->createInfo.flags)) {
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06005338 // Can't Free from a NON_FREE pool
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005339 skipCall |=
5340 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5341 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, (uint64_t)device,
5342 __LINE__, DRAWSTATE_CANT_FREE_FROM_NON_FREE_POOL, "DS",
5343 "It is invalid to call vkFreeDescriptorSets() with a pool "
5344 "created without setting "
5345 "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT.");
Tobin Ehlise735c692015-10-08 13:13:50 -06005346 }
Mark Youngb20a6a82016-01-07 15:41:43 -07005347 if (VK_FALSE != skipCall)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005348 return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005349 VkResult result = dev_data->device_dispatch_table->FreeDescriptorSets(
5350 device, descriptorPool, count, pDescriptorSets);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06005351 if (VK_SUCCESS == result) {
5352 // For each freed descriptor add it back into the pool as available
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005353 for (uint32_t i = 0; i < count; ++i) {
5354 SET_NODE *pSet =
5355 dev_data->setMap[pDescriptorSets[i]]; // getSetNode() without
5356 // locking
Tobin Ehlise6e574b2016-01-24 23:25:31 -07005357 invalidateBoundCmdBuffers(dev_data, pSet);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005358 LAYOUT_NODE *pLayout = pSet->pLayout;
Chia-I Wu1b99bb22015-10-27 19:25:11 +08005359 uint32_t typeIndex = 0, poolSizeCount = 0;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005360 for (uint32_t j = 0; j < pLayout->createInfo.bindingCount; ++j) {
5361 typeIndex = static_cast<uint32_t>(
5362 pLayout->createInfo.pBindings[j].descriptorType);
5363 poolSizeCount =
5364 pLayout->createInfo.pBindings[j].descriptorCount;
5365 pPoolNode->availableDescriptorTypeCount[typeIndex] +=
5366 poolSizeCount;
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06005367 }
5368 }
5369 }
5370 // TODO : Any other clean-up or book-keeping to do here?
Tony Barbour34ec6922015-07-10 10:50:45 -06005371 return result;
5372}
5373
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005374VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
5375 vkUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
5376 const VkWriteDescriptorSet *pDescriptorWrites,
5377 uint32_t descriptorCopyCount,
5378 const VkCopyDescriptorSet *pDescriptorCopies) {
5379 // dsUpdate will return VK_TRUE only if a bailout error occurs, so we want
5380 // to call down tree when update returns VK_FALSE
5381 layer_data *dev_data =
5382 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5383 if (!dsUpdate(dev_data, device, descriptorWriteCount, pDescriptorWrites,
5384 descriptorCopyCount, pDescriptorCopies)) {
5385 dev_data->device_dispatch_table->UpdateDescriptorSets(
5386 device, descriptorWriteCount, pDescriptorWrites,
5387 descriptorCopyCount, pDescriptorCopies);
Jon Ashburn3950e1b2015-05-20 09:00:28 -06005388 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005389}
5390
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005391VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
5392 vkAllocateCommandBuffers(VkDevice device,
5393 const VkCommandBufferAllocateInfo *pCreateInfo,
5394 VkCommandBuffer *pCommandBuffer) {
5395 layer_data *dev_data =
5396 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5397 VkResult result = dev_data->device_dispatch_table->AllocateCommandBuffers(
5398 device, pCreateInfo, pCommandBuffer);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005399 if (VK_SUCCESS == result) {
Jon Ashburnf19916e2016-01-11 13:12:43 -07005400 for (uint32_t i = 0; i < pCreateInfo->commandBufferCount; i++) {
Mark Lobodzinski39298632015-11-18 08:38:27 -07005401 // Validate command pool
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005402 if (dev_data->commandPoolMap.find(pCreateInfo->commandPool) !=
5403 dev_data->commandPoolMap.end()) {
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07005404 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07005405 // Add command buffer to its commandPool map
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005406 dev_data->commandPoolMap[pCreateInfo->commandPool]
5407 .commandBuffers.push_back(pCommandBuffer[i]);
5408 GLOBAL_CB_NODE *pCB = new GLOBAL_CB_NODE;
Mark Lobodzinski39298632015-11-18 08:38:27 -07005409 // Add command buffer to map
5410 dev_data->commandBufferMap[pCommandBuffer[i]] = pCB;
5411 resetCB(dev_data, pCommandBuffer[i]);
5412 pCB->commandBuffer = pCommandBuffer[i];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005413 pCB->createInfo = *pCreateInfo;
5414 pCB->device = device;
Tobin Ehlis74714d22016-01-25 15:24:34 -08005415 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07005416 }
5417 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005418 }
5419 return result;
5420}
5421
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005422VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
5423 vkBeginCommandBuffer(VkCommandBuffer commandBuffer,
5424 const VkCommandBufferBeginInfo *pBeginInfo) {
Mark Youngb20a6a82016-01-07 15:41:43 -07005425 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005426 layer_data *dev_data =
5427 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Mark Lobodzinskid9139a62015-08-04 16:24:20 -06005428 // Validate command buffer level
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005429 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Mark Lobodzinskid9139a62015-08-04 16:24:20 -06005430 if (pCB) {
Jon Ashburnf19916e2016-01-11 13:12:43 -07005431 if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
5432 // Secondary Command Buffer
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005433 // TODO : Add check here from spec "If commandBuffer is a secondary
5434 // command buffer and either the
5435 // occlusionQueryEnable member of pBeginInfo is VK_FALSE, or the
5436 // precise occlusion queries feature
5437 // is not enabled, the queryFlags member of pBeginInfo must not
5438 // contain VK_QUERY_CONTROL_PRECISE_BIT"
5439 const VkCommandBufferInheritanceInfo *pInfo =
5440 pBeginInfo->pInheritanceInfo;
5441 if (pBeginInfo->flags &
5442 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) {
5443 if (!pInfo->renderPass) { // renderpass should NOT be null for
5444 // an Secondary CB
5445 skipCall |= log_msg(
5446 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5447 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5448 (uint64_t)commandBuffer, __LINE__,
5449 DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
5450 "vkBeginCommandBuffer(): Secondary Command Buffers "
5451 "(%p) must specify a valid renderpass parameter.",
5452 (void *)commandBuffer);
Tobin Ehlis651d9b02015-12-16 05:01:22 -07005453 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005454 if (!pInfo->framebuffer) { // framebuffer may be null for an
5455 // Secondary CB, but this affects
5456 // perf
5457 skipCall |=
5458 log_msg(dev_data->report_data,
5459 VK_DEBUG_REPORT_PERF_WARN_BIT_EXT,
5460 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5461 (uint64_t)commandBuffer, __LINE__,
5462 DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
5463 "vkBeginCommandBuffer(): Secondary Command "
5464 "Buffers (%p) may perform better if a valid "
5465 "framebuffer parameter is specified.",
5466 (void *)commandBuffer);
Tobin Ehlis651d9b02015-12-16 05:01:22 -07005467 } else {
5468 string errorString = "";
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005469 VkRenderPass fbRP =
5470 dev_data->frameBufferMap[pInfo->framebuffer]
5471 ->renderPass;
5472 if (!verify_renderpass_compatibility(
5473 dev_data, fbRP, pInfo->renderPass, errorString)) {
5474 // renderPass that framebuffer was created with must be
5475 // compatible with local renderPass
5476 skipCall |= log_msg(
5477 dev_data->report_data,
5478 VK_DEBUG_REPORT_ERROR_BIT_EXT,
5479 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5480 (uint64_t)commandBuffer, __LINE__,
5481 DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
5482 "vkBeginCommandBuffer(): Secondary Command Buffer "
5483 "(%p) renderPass (%#" PRIxLEAST64
5484 ") is incompatible w/ framebuffer (%#" PRIxLEAST64
5485 ") w/ render pass (%#" PRIxLEAST64 ") due to: %s",
5486 (void *)commandBuffer, (uint64_t)pInfo->renderPass,
5487 (uint64_t)pInfo->framebuffer, (uint64_t)fbRP,
5488 errorString.c_str());
Tobin Ehlis651d9b02015-12-16 05:01:22 -07005489 }
5490 }
Mark Lobodzinskid9139a62015-08-04 16:24:20 -06005491 }
5492 }
Tobin Ehlisac0ef842015-12-14 13:46:38 -07005493 if (CB_RECORDING == pCB->state) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005494 skipCall |=
5495 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5496 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5497 (uint64_t)commandBuffer, __LINE__,
5498 DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
5499 "vkBeginCommandBuffer(): Cannot call Begin on CB "
5500 "(%#" PRIxLEAST64 ") in the RECORDING state. Must "
5501 "first call vkEndCommandBuffer().",
5502 (uint64_t)commandBuffer);
Tobin Ehlisac0ef842015-12-14 13:46:38 -07005503 } else if (CB_RECORDED == pCB->state) {
5504 VkCommandPool cmdPool = pCB->createInfo.commandPool;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005505 if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT &
5506 dev_data->commandPoolMap[cmdPool].createFlags)) {
5507 skipCall |= log_msg(
5508 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5509 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5510 (uint64_t)commandBuffer, __LINE__,
5511 DRAWSTATE_INVALID_COMMAND_BUFFER_RESET, "DS",
5512 "Call to vkBeginCommandBuffer() on command buffer "
5513 "(%#" PRIxLEAST64 ") attempts to implicitly reset "
5514 "cmdBuffer created from command pool "
5515 "(%#" PRIxLEAST64
5516 ") that does NOT have the "
5517 "VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set.",
5518 (uint64_t)commandBuffer, (uint64_t)cmdPool);
Tobin Ehlisac0ef842015-12-14 13:46:38 -07005519 }
Tobin Ehlis74714d22016-01-25 15:24:34 -08005520 loader_platform_thread_lock_mutex(&globalLock);
Tobin Ehlisef694652016-01-19 12:03:34 -07005521 resetCB(dev_data, commandBuffer);
Tobin Ehlis74714d22016-01-25 15:24:34 -08005522 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlisac0ef842015-12-14 13:46:38 -07005523 }
Tobin Ehlisef694652016-01-19 12:03:34 -07005524 // Set updated state here in case implicit reset occurs above
Tobin Ehlis74714d22016-01-25 15:24:34 -08005525 loader_platform_thread_lock_mutex(&globalLock);
Tobin Ehlisef694652016-01-19 12:03:34 -07005526 pCB->state = CB_RECORDING;
5527 pCB->beginInfo = *pBeginInfo;
Tobin Ehliscd5bfd82016-01-19 13:12:52 -07005528 if (pCB->beginInfo.pInheritanceInfo) {
5529 pCB->inheritanceInfo = *(pCB->beginInfo.pInheritanceInfo);
5530 pCB->beginInfo.pInheritanceInfo = &pCB->inheritanceInfo;
5531 }
Tobin Ehlis74714d22016-01-25 15:24:34 -08005532 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlis59278bf2015-08-18 07:10:58 -06005533 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005534 skipCall |= log_msg(
5535 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5536 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5537 (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER,
5538 "DS", "In vkBeginCommandBuffer() and unable to find CommandBuffer "
5539 "Node for CB %p!",
5540 (void *)commandBuffer);
Mark Lobodzinskid9139a62015-08-04 16:24:20 -06005541 }
Mark Youngb20a6a82016-01-07 15:41:43 -07005542 if (VK_FALSE != skipCall) {
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005543 return VK_ERROR_VALIDATION_FAILED_EXT;
Courtney Goeltzenleuchter5fe086f2015-09-04 15:03:52 -06005544 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005545 VkResult result = dev_data->device_dispatch_table->BeginCommandBuffer(
5546 commandBuffer, pBeginInfo);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005547 return result;
5548}
5549
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005550VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
5551 vkEndCommandBuffer(VkCommandBuffer commandBuffer) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005552 VkBool32 skipCall = VK_FALSE;
Courtney Goeltzenleuchtered894072015-09-04 13:39:59 -06005553 VkResult result = VK_SUCCESS;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005554 layer_data *dev_data =
5555 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5556 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis9c536442015-06-19 13:00:59 -06005557 if (pCB) {
Tobin Ehlisac0ef842015-12-14 13:46:38 -07005558 if (pCB->state != CB_RECORDING) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005559 skipCall |= report_error_no_cb_begin(dev_data, commandBuffer,
5560 "vkEndCommandBuffer()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005561 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005562 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005563 if (VK_FALSE == skipCall) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005564 result =
5565 dev_data->device_dispatch_table->EndCommandBuffer(commandBuffer);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005566 if (VK_SUCCESS == result) {
Tobin Ehlisac0ef842015-12-14 13:46:38 -07005567 pCB->state = CB_RECORDED;
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005568 // Reset CB status flags
5569 pCB->status = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005570 printCB(dev_data, commandBuffer);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005571 }
5572 } else {
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005573 result = VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005574 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005575 return result;
5576}
5577
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005578VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
5579 vkResetCommandBuffer(VkCommandBuffer commandBuffer,
5580 VkCommandBufferResetFlags flags) {
Tobin Ehlisac0ef842015-12-14 13:46:38 -07005581 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005582 layer_data *dev_data =
5583 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5584 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlisac0ef842015-12-14 13:46:38 -07005585 VkCommandPool cmdPool = pCB->createInfo.commandPool;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005586 if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT &
5587 dev_data->commandPoolMap[cmdPool].createFlags)) {
5588 skipCall |=
5589 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5590 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5591 (uint64_t)commandBuffer, __LINE__,
5592 DRAWSTATE_INVALID_COMMAND_BUFFER_RESET, "DS",
5593 "Attempt to reset command buffer (%#" PRIxLEAST64
5594 ") created from command pool (%#" PRIxLEAST64
5595 ") that does NOT have the "
5596 "VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set.",
5597 (uint64_t)commandBuffer, (uint64_t)cmdPool);
Tobin Ehlisac0ef842015-12-14 13:46:38 -07005598 }
Mark Youngb20a6a82016-01-07 15:41:43 -07005599 if (skipCall != VK_FALSE)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005600 return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005601 VkResult result = dev_data->device_dispatch_table->ResetCommandBuffer(
5602 commandBuffer, flags);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005603 if (VK_SUCCESS == result) {
Tobin Ehlis74714d22016-01-25 15:24:34 -08005604 loader_platform_thread_lock_mutex(&globalLock);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005605 resetCB(dev_data, commandBuffer);
Tobin Ehlis74714d22016-01-25 15:24:34 -08005606 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005607 }
5608 return result;
5609}
5610
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005611VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
5612 vkCmdBindPipeline(VkCommandBuffer commandBuffer,
5613 VkPipelineBindPoint pipelineBindPoint,
5614 VkPipeline pipeline) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005615 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005616 layer_data *dev_data =
5617 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5618 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005619 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005620 skipCall |=
5621 addCmd(dev_data, pCB, CMD_BINDPIPELINE, "vkCmdBindPipeline()");
5622 if ((VK_PIPELINE_BIND_POINT_COMPUTE == pipelineBindPoint) &&
5623 (pCB->activeRenderPass)) {
5624 skipCall |= log_msg(
5625 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5626 VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, (uint64_t)pipeline,
5627 __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS",
5628 "Incorrectly binding compute pipeline (%#" PRIxLEAST64
5629 ") during active RenderPass (%#" PRIxLEAST64 ")",
5630 (uint64_t)pipeline, (uint64_t)pCB->activeRenderPass);
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005631 } else if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005632 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdBindPipeline");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005633 }
5634
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005635 PIPELINE_NODE *pPN = getPipeline(dev_data, pipeline);
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005636 if (pPN) {
5637 pCB->lastBoundPipeline = pipeline;
5638 loader_platform_thread_lock_mutex(&globalLock);
5639 set_cb_pso_status(pCB, pPN);
5640 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005641 skipCall |= validatePipelineState(dev_data, pCB, pipelineBindPoint,
5642 pipeline);
Tobin Ehlisce132d82015-06-19 15:07:05 -06005643 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005644 skipCall |= log_msg(
5645 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5646 VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, (uint64_t)pipeline,
5647 __LINE__, DRAWSTATE_INVALID_PIPELINE, "DS",
5648 "Attempt to bind Pipeline %#" PRIxLEAST64
5649 " that doesn't exist!",
5650 (uint64_t)(pipeline));
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005651 }
5652 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005653 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005654 dev_data->device_dispatch_table->CmdBindPipeline(
5655 commandBuffer, pipelineBindPoint, pipeline);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005656}
5657
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005658VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
5659 vkCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport,
5660 uint32_t viewportCount, const VkViewport *pViewports) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005661 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005662 layer_data *dev_data =
5663 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5664 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis9c536442015-06-19 13:00:59 -06005665 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005666 skipCall |=
5667 addCmd(dev_data, pCB, CMD_SETVIEWPORTSTATE, "vkCmdSetViewport()");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005668 loader_platform_thread_lock_mutex(&globalLock);
5669 pCB->status |= CBSTATUS_VIEWPORT_SET;
5670 pCB->viewports.resize(viewportCount);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005671 memcpy(pCB->viewports.data(), pViewports,
5672 viewportCount * sizeof(VkViewport));
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005673 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlis9c536442015-06-19 13:00:59 -06005674 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005675 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005676 dev_data->device_dispatch_table->CmdSetViewport(
5677 commandBuffer, firstViewport, viewportCount, pViewports);
Courtney Goeltzenleuchter078f8172015-09-21 11:44:06 -06005678}
5679
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005680VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
5681 vkCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor,
5682 uint32_t scissorCount, const VkRect2D *pScissors) {
Courtney Goeltzenleuchter078f8172015-09-21 11:44:06 -06005683 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005684 layer_data *dev_data =
5685 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5686 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Courtney Goeltzenleuchter078f8172015-09-21 11:44:06 -06005687 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005688 skipCall |=
5689 addCmd(dev_data, pCB, CMD_SETSCISSORSTATE, "vkCmdSetScissor()");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005690 loader_platform_thread_lock_mutex(&globalLock);
5691 pCB->status |= CBSTATUS_SCISSOR_SET;
5692 pCB->scissors.resize(scissorCount);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005693 memcpy(pCB->scissors.data(), pScissors,
5694 scissorCount * sizeof(VkRect2D));
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005695 loader_platform_thread_unlock_mutex(&globalLock);
Courtney Goeltzenleuchter078f8172015-09-21 11:44:06 -06005696 }
5697 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005698 dev_data->device_dispatch_table->CmdSetScissor(
5699 commandBuffer, firstScissor, scissorCount, pScissors);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005700}
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005701
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005702VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
5703 vkCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005704 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005705 layer_data *dev_data =
5706 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5707 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005708 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005709 skipCall |=
5710 addCmd(dev_data, pCB, CMD_SETLINEWIDTHSTATE, "vkCmdSetLineWidth()");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005711 /* TODO: Do we still need this lock? */
5712 loader_platform_thread_lock_mutex(&globalLock);
5713 pCB->status |= CBSTATUS_LINE_WIDTH_SET;
5714 pCB->lineWidth = lineWidth;
5715 loader_platform_thread_unlock_mutex(&globalLock);
Cody Northrop12365112015-08-17 11:10:49 -06005716 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005717 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005718 dev_data->device_dispatch_table->CmdSetLineWidth(commandBuffer,
5719 lineWidth);
Cody Northrop12365112015-08-17 11:10:49 -06005720}
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005721
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005722VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
5723 vkCmdSetDepthBias(VkCommandBuffer commandBuffer,
5724 float depthBiasConstantFactor, float depthBiasClamp,
5725 float depthBiasSlopeFactor) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005726 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005727 layer_data *dev_data =
5728 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5729 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Cody Northrop12365112015-08-17 11:10:49 -06005730 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005731 skipCall |=
5732 addCmd(dev_data, pCB, CMD_SETDEPTHBIASSTATE, "vkCmdSetDepthBias()");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005733 pCB->status |= CBSTATUS_DEPTH_BIAS_SET;
5734 pCB->depthBiasConstantFactor = depthBiasConstantFactor;
5735 pCB->depthBiasClamp = depthBiasClamp;
5736 pCB->depthBiasSlopeFactor = depthBiasSlopeFactor;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005737 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005738 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005739 dev_data->device_dispatch_table->CmdSetDepthBias(
5740 commandBuffer, depthBiasConstantFactor, depthBiasClamp,
5741 depthBiasSlopeFactor);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005742}
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005743
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005744VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
5745 vkCmdSetBlendConstants(VkCommandBuffer commandBuffer,
5746 const float blendConstants[4]) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005747 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005748 layer_data *dev_data =
5749 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5750 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005751 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005752 skipCall |= addCmd(dev_data, pCB, CMD_SETBLENDSTATE,
5753 "vkCmdSetBlendConstants()");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005754 pCB->status |= CBSTATUS_BLEND_SET;
5755 memcpy(pCB->blendConstants, blendConstants, 4 * sizeof(float));
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005756 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005757 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005758 dev_data->device_dispatch_table->CmdSetBlendConstants(commandBuffer,
5759 blendConstants);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005760}
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005761
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005762VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
5763 vkCmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds,
5764 float maxDepthBounds) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005765 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005766 layer_data *dev_data =
5767 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5768 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005769 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005770 skipCall |= addCmd(dev_data, pCB, CMD_SETDEPTHBOUNDSSTATE,
5771 "vkCmdSetDepthBounds()");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005772 pCB->status |= CBSTATUS_DEPTH_BOUNDS_SET;
5773 pCB->minDepthBounds = minDepthBounds;
5774 pCB->maxDepthBounds = maxDepthBounds;
Cody Northrop82485a82015-08-18 15:21:16 -06005775 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005776 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005777 dev_data->device_dispatch_table->CmdSetDepthBounds(
5778 commandBuffer, minDepthBounds, maxDepthBounds);
Cody Northrop82485a82015-08-18 15:21:16 -06005779}
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005780
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005781VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
5782 vkCmdSetStencilCompareMask(VkCommandBuffer commandBuffer,
5783 VkStencilFaceFlags faceMask,
5784 uint32_t compareMask) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005785 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005786 layer_data *dev_data =
5787 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5788 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Cody Northrop82485a82015-08-18 15:21:16 -06005789 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005790 skipCall |= addCmd(dev_data, pCB, CMD_SETSTENCILREADMASKSTATE,
5791 "vkCmdSetStencilCompareMask()");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005792 if (faceMask & VK_STENCIL_FACE_FRONT_BIT) {
5793 pCB->front.compareMask = compareMask;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005794 }
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005795 if (faceMask & VK_STENCIL_FACE_BACK_BIT) {
5796 pCB->back.compareMask = compareMask;
5797 }
5798 /* TODO: Do we need to track front and back separately? */
5799 /* TODO: We aren't capturing the faceMask, do we need to? */
5800 pCB->status |= CBSTATUS_STENCIL_READ_MASK_SET;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005801 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005802 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005803 dev_data->device_dispatch_table->CmdSetStencilCompareMask(
5804 commandBuffer, faceMask, compareMask);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005805}
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005806
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005807VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
5808 vkCmdSetStencilWriteMask(VkCommandBuffer commandBuffer,
5809 VkStencilFaceFlags faceMask, uint32_t writeMask) {
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005810 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005811 layer_data *dev_data =
5812 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5813 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005814 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005815 skipCall |= addCmd(dev_data, pCB, CMD_SETSTENCILWRITEMASKSTATE,
5816 "vkCmdSetStencilWriteMask()");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005817 if (faceMask & VK_STENCIL_FACE_FRONT_BIT) {
5818 pCB->front.writeMask = writeMask;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005819 }
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005820 if (faceMask & VK_STENCIL_FACE_BACK_BIT) {
5821 pCB->back.writeMask = writeMask;
5822 }
5823 pCB->status |= CBSTATUS_STENCIL_WRITE_MASK_SET;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005824 }
5825 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005826 dev_data->device_dispatch_table->CmdSetStencilWriteMask(
5827 commandBuffer, faceMask, writeMask);
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005828}
5829
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005830VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
5831 vkCmdSetStencilReference(VkCommandBuffer commandBuffer,
5832 VkStencilFaceFlags faceMask, uint32_t reference) {
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005833 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005834 layer_data *dev_data =
5835 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5836 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005837 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005838 skipCall |= addCmd(dev_data, pCB, CMD_SETSTENCILREFERENCESTATE,
5839 "vkCmdSetStencilReference()");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005840 if (faceMask & VK_STENCIL_FACE_FRONT_BIT) {
5841 pCB->front.reference = reference;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005842 }
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005843 if (faceMask & VK_STENCIL_FACE_BACK_BIT) {
5844 pCB->back.reference = reference;
5845 }
5846 pCB->status |= CBSTATUS_STENCIL_REFERENCE_SET;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005847 }
5848 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005849 dev_data->device_dispatch_table->CmdSetStencilReference(
5850 commandBuffer, faceMask, reference);
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005851}
5852
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005853VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets(
5854 VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
5855 VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount,
5856 const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount,
5857 const uint32_t *pDynamicOffsets) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005858 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005859 layer_data *dev_data =
5860 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5861 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005862 if (pCB) {
Tobin Ehlisf6585052015-12-17 11:48:42 -07005863 if (pCB->state == CB_RECORDING) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005864 if ((VK_PIPELINE_BIND_POINT_COMPUTE == pipelineBindPoint) &&
5865 (pCB->activeRenderPass)) {
5866 skipCall |= log_msg(
5867 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5868 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
5869 DRAWSTATE_INVALID_RENDERPASS_CMD, "DS",
5870 "Incorrectly binding compute DescriptorSets during active "
5871 "RenderPass (%#" PRIxLEAST64 ")",
5872 (uint64_t)pCB->activeRenderPass);
Tobin Ehlisf6585052015-12-17 11:48:42 -07005873 } else if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005874 skipCall |=
5875 outsideRenderPass(dev_data, pCB, "vkCmdBindDescriptorSets");
Mark Lobodzinski74635932015-12-18 15:35:38 -07005876 }
Tobin Ehlisf6585052015-12-17 11:48:42 -07005877 if (VK_FALSE == skipCall) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005878 // Track total count of dynamic descriptor types to make sure we
5879 // have an offset for each one
Tobin Ehlisf6585052015-12-17 11:48:42 -07005880 uint32_t totalDynamicDescriptors = 0;
5881 string errorString = "";
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005882 uint32_t lastSetIndex = firstSet + setCount - 1;
Tobin Ehlisf6585052015-12-17 11:48:42 -07005883 if (lastSetIndex >= pCB->boundDescriptorSets.size())
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005884 pCB->boundDescriptorSets.resize(lastSetIndex + 1);
5885 VkDescriptorSet oldFinalBoundSet =
5886 pCB->boundDescriptorSets[lastSetIndex];
5887 for (uint32_t i = 0; i < setCount; i++) {
5888 SET_NODE *pSet = getSetNode(dev_data, pDescriptorSets[i]);
Tobin Ehlisf6585052015-12-17 11:48:42 -07005889 if (pSet) {
5890 loader_platform_thread_lock_mutex(&globalLock);
Tobin Ehlise6e574b2016-01-24 23:25:31 -07005891 pCB->uniqueBoundSets.insert(pDescriptorSets[i]);
5892 pSet->boundCmdBuffers.insert(commandBuffer);
Tobin Ehlisf6585052015-12-17 11:48:42 -07005893 pCB->lastBoundDescriptorSet = pDescriptorSets[i];
5894 pCB->lastBoundPipelineLayout = layout;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005895 pCB->boundDescriptorSets[i + firstSet] =
5896 pDescriptorSets[i];
Tobin Ehlisf6585052015-12-17 11:48:42 -07005897 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005898 skipCall |= log_msg(
5899 dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
5900 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
5901 (uint64_t)pDescriptorSets[i], __LINE__,
5902 DRAWSTATE_NONE, "DS",
5903 "DS %#" PRIxLEAST64 " bound on pipeline %s",
5904 (uint64_t)pDescriptorSets[i],
5905 string_VkPipelineBindPoint(pipelineBindPoint));
5906 if (!pSet->pUpdateStructs &&
5907 (pSet->descriptorCount != 0)) {
5908 skipCall |= log_msg(
5909 dev_data->report_data,
5910 VK_DEBUG_REPORT_WARN_BIT_EXT,
5911 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
5912 (uint64_t)pDescriptorSets[i], __LINE__,
5913 DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS",
5914 "DS %#" PRIxLEAST64
5915 " bound but it was never updated. You may want "
5916 "to either update it or not bind it.",
5917 (uint64_t)pDescriptorSets[i]);
Tobin Ehlisf6585052015-12-17 11:48:42 -07005918 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005919 // Verify that set being bound is compatible with
5920 // overlapping setLayout of pipelineLayout
5921 if (!verify_set_layout_compatibility(
5922 dev_data, pSet, layout, i + firstSet,
5923 errorString)) {
5924 skipCall |= log_msg(
5925 dev_data->report_data,
5926 VK_DEBUG_REPORT_ERROR_BIT_EXT,
5927 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
5928 (uint64_t)pDescriptorSets[i], __LINE__,
5929 DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS",
5930 "descriptorSet #%u being bound is not "
5931 "compatible with overlapping layout in "
5932 "pipelineLayout due to: %s",
5933 i, errorString.c_str());
Tobin Ehlisf6585052015-12-17 11:48:42 -07005934 }
5935 if (pSet->pLayout->dynamicDescriptorCount) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005936 // First make sure we won't overstep bounds of
5937 // pDynamicOffsets array
5938 if ((totalDynamicDescriptors +
5939 pSet->pLayout->dynamicDescriptorCount) >
5940 dynamicOffsetCount) {
5941 skipCall |= log_msg(
5942 dev_data->report_data,
5943 VK_DEBUG_REPORT_ERROR_BIT_EXT,
5944 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
5945 (uint64_t)pDescriptorSets[i], __LINE__,
5946 DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT,
5947 "DS", "descriptorSet #%u (%#" PRIxLEAST64
5948 ") requires %u dynamicOffsets, but "
5949 "only %u dynamicOffsets are left in "
5950 "pDynamicOffsets array. There must "
5951 "be one dynamic offset for each "
5952 "dynamic descriptor being bound.",
5953 i, (uint64_t)pDescriptorSets[i],
5954 pSet->pLayout->dynamicDescriptorCount,
5955 (dynamicOffsetCount -
5956 totalDynamicDescriptors));
5957 } else { // Validate and store dynamic offsets with
5958 // the set
Mark Lobodzinski941aea92016-01-13 10:23:15 -07005959 // Validate Dynamic Offset Minimums
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005960 uint32_t cur_dyn_offset =
5961 totalDynamicDescriptors;
5962 for (uint32_t d = 0; d < pSet->descriptorCount;
5963 d++) {
5964 if (pSet->pLayout->descriptorTypes[i] ==
5965 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
5966 if (vk_safe_modulo(
5967 pDynamicOffsets[cur_dyn_offset],
5968 dev_data
5969 ->physDevPropertyMap
5970 [pCB->device]
5971 .limits
5972 .minUniformBufferOffsetAlignment) !=
5973 0) {
5974 skipCall |= log_msg(
5975 dev_data->report_data,
5976 VK_DEBUG_REPORT_ERROR_BIT_EXT,
5977 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
5978 0, __LINE__,
5979 DRAWSTATE_INVALID_UNIFORM_BUFFER_OFFSET,
5980 "DS", "vkCmdBindDescriptorSets("
5981 "): pDynamicOffsets[%d] "
5982 "is %d but must be a "
5983 "multiple of device "
5984 "limit "
5985 "minUniformBufferOffsetAl"
5986 "ignment %#" PRIxLEAST64,
5987 cur_dyn_offset,
5988 pDynamicOffsets[cur_dyn_offset],
5989 dev_data
5990 ->physDevPropertyMap
5991 [pCB->device]
5992 .limits
5993 .minUniformBufferOffsetAlignment);
Mark Lobodzinski941aea92016-01-13 10:23:15 -07005994 }
5995 cur_dyn_offset++;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07005996 } else if (pSet->pLayout
5997 ->descriptorTypes[i] ==
5998 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
5999 if (vk_safe_modulo(
6000 pDynamicOffsets[cur_dyn_offset],
6001 dev_data
6002 ->physDevPropertyMap
6003 [pCB->device]
6004 .limits
6005 .minStorageBufferOffsetAlignment) !=
6006 0) {
6007 skipCall |= log_msg(
6008 dev_data->report_data,
6009 VK_DEBUG_REPORT_ERROR_BIT_EXT,
6010 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
6011 0, __LINE__,
6012 DRAWSTATE_INVALID_STORAGE_BUFFER_OFFSET,
6013 "DS", "vkCmdBindDescriptorSets("
6014 "): pDynamicOffsets[%d] "
6015 "is %d but must be a "
6016 "multiple of device "
6017 "limit "
6018 "minStorageBufferOffsetAl"
6019 "ignment %#" PRIxLEAST64,
6020 cur_dyn_offset,
6021 pDynamicOffsets[cur_dyn_offset],
6022 dev_data
6023 ->physDevPropertyMap
6024 [pCB->device]
6025 .limits
6026 .minStorageBufferOffsetAlignment);
Mark Lobodzinski941aea92016-01-13 10:23:15 -07006027 }
6028 cur_dyn_offset++;
6029 }
6030 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006031 // Keep running total of dynamic descriptor
6032 // count to verify at the end
6033 totalDynamicDescriptors +=
6034 pSet->pLayout->dynamicDescriptorCount;
Tobin Ehlisf6585052015-12-17 11:48:42 -07006035 }
6036 }
6037 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006038 skipCall |= log_msg(
6039 dev_data->report_data,
6040 VK_DEBUG_REPORT_ERROR_BIT_EXT,
6041 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
6042 (uint64_t)pDescriptorSets[i], __LINE__,
6043 DRAWSTATE_INVALID_SET, "DS",
6044 "Attempt to bind DS %#" PRIxLEAST64
6045 " that doesn't exist!",
6046 (uint64_t)pDescriptorSets[i]);
Tobin Ehlisf6585052015-12-17 11:48:42 -07006047 }
6048 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006049 skipCall |= addCmd(dev_data, pCB, CMD_BINDDESCRIPTORSETS,
6050 "vkCmdBindDescrsiptorSets()");
6051 // For any previously bound sets, need to set them to "invalid"
6052 // if they were disturbed by this update
Tobin Ehlisf6585052015-12-17 11:48:42 -07006053 if (firstSet > 0) { // Check set #s below the first bound set
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006054 for (uint32_t i = 0; i < firstSet; ++i) {
6055 if (pCB->boundDescriptorSets[i] &&
6056 !verify_set_layout_compatibility(
6057 dev_data,
6058 dev_data->setMap[pCB->boundDescriptorSets[i]],
6059 layout, i, errorString)) {
6060 skipCall |= log_msg(
6061 dev_data->report_data,
6062 VK_DEBUG_REPORT_PERF_WARN_BIT_EXT,
6063 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
6064 (uint64_t)pCB->boundDescriptorSets[i], __LINE__,
6065 DRAWSTATE_NONE, "DS",
6066 "DescriptorSetDS %#" PRIxLEAST64
6067 " previously bound as set #%u was disturbed by "
6068 "newly bound pipelineLayout (%#" PRIxLEAST64
6069 ")",
6070 (uint64_t)pCB->boundDescriptorSets[i], i,
6071 (uint64_t)layout);
Tobin Ehlisf6585052015-12-17 11:48:42 -07006072 pCB->boundDescriptorSets[i] = VK_NULL_HANDLE;
6073 }
6074 }
6075 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006076 // Check if newly last bound set invalidates any remaining bound
6077 // sets
6078 if ((pCB->boundDescriptorSets.size() - 1) > (lastSetIndex)) {
6079 if (oldFinalBoundSet &&
6080 !verify_set_layout_compatibility(
6081 dev_data, dev_data->setMap[oldFinalBoundSet],
6082 layout, lastSetIndex, errorString)) {
6083 skipCall |= log_msg(
6084 dev_data->report_data,
6085 VK_DEBUG_REPORT_PERF_WARN_BIT_EXT,
6086 VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
6087 (uint64_t)oldFinalBoundSet, __LINE__,
6088 DRAWSTATE_NONE, "DS",
6089 "DescriptorSetDS %#" PRIxLEAST64
6090 " previously bound as set #%u is incompatible with "
6091 "set %#" PRIxLEAST64
6092 " newly bound as set #%u so set #%u and any "
6093 "subsequent sets were disturbed by newly bound "
6094 "pipelineLayout (%#" PRIxLEAST64 ")",
6095 (uint64_t)oldFinalBoundSet, lastSetIndex,
6096 (uint64_t)pCB->boundDescriptorSets[lastSetIndex],
6097 lastSetIndex, lastSetIndex + 1, (uint64_t)layout);
6098 pCB->boundDescriptorSets.resize(lastSetIndex + 1);
Tobin Ehlisf6585052015-12-17 11:48:42 -07006099 }
6100 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006101 // dynamicOffsetCount must equal the total number of dynamic
6102 // descriptors in the sets being bound
Tobin Ehlisf6585052015-12-17 11:48:42 -07006103 if (totalDynamicDescriptors != dynamicOffsetCount) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006104 skipCall |= log_msg(
6105 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6106 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6107 (uint64_t)commandBuffer, __LINE__,
6108 DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS",
6109 "Attempting to bind %u descriptorSets with %u dynamic "
6110 "descriptors, but dynamicOffsetCount is %u. It should "
6111 "exactly match the number of dynamic descriptors.",
6112 setCount, totalDynamicDescriptors, dynamicOffsetCount);
Tobin Ehlisda2f0d02015-11-04 12:28:28 -07006113 }
Tobin Ehlisd2393772016-01-29 11:50:47 -07006114 if (dynamicOffsetCount) {
6115 // Save dynamicOffsets bound to this CB
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006116 pCB->dynamicOffsets.assign(
6117 pDynamicOffsets, pDynamicOffsets + dynamicOffsetCount);
Tobin Ehlisd2393772016-01-29 11:50:47 -07006118 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006119 }
Tobin Ehlisf6585052015-12-17 11:48:42 -07006120 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006121 skipCall |= report_error_no_cb_begin(dev_data, commandBuffer,
6122 "vkCmdBindDescriptorSets()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006123 }
6124 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006125 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006126 dev_data->device_dispatch_table->CmdBindDescriptorSets(
6127 commandBuffer, pipelineBindPoint, layout, firstSet, setCount,
6128 pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006129}
6130
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006131VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6132 vkCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer,
6133 VkDeviceSize offset, VkIndexType indexType) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006134 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006135 layer_data *dev_data =
6136 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6137 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006138 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006139 skipCall |= addCmd(dev_data, pCB, CMD_BINDINDEXBUFFER,
6140 "vkCmdBindIndexBuffer()");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006141 VkDeviceSize offset_align = 0;
6142 switch (indexType) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006143 case VK_INDEX_TYPE_UINT16:
6144 offset_align = 2;
6145 break;
6146 case VK_INDEX_TYPE_UINT32:
6147 offset_align = 4;
6148 break;
6149 default:
6150 // ParamChecker should catch bad enum, we'll also throw alignment
6151 // error below if offset_align stays 0
6152 break;
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006153 }
6154 if (!offset_align || (offset % offset_align)) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006155 skipCall |=
6156 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6157 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
6158 DRAWSTATE_VTX_INDEX_ALIGNMENT_ERROR, "DS",
6159 "vkCmdBindIndexBuffer() offset (%#" PRIxLEAST64
6160 ") does not fall on alignment (%s) boundary.",
6161 offset, string_VkIndexType(indexType));
Tobin Ehlis9c536442015-06-19 13:00:59 -06006162 }
Tobin Ehlisc4c23182015-09-17 12:24:13 -06006163 pCB->status |= CBSTATUS_INDEX_BUFFER_BOUND;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006164 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006165 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006166 dev_data->device_dispatch_table->CmdBindIndexBuffer(
6167 commandBuffer, buffer, offset, indexType);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006168}
6169
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006170void updateResourceTracking(GLOBAL_CB_NODE *pCB, uint32_t firstBinding,
6171 uint32_t bindingCount, const VkBuffer *pBuffers) {
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07006172 uint32_t end = firstBinding + bindingCount;
Michael Lentine700b0aa2015-10-30 17:57:32 -07006173 if (pCB->currentDrawData.buffers.size() < end) {
6174 pCB->currentDrawData.buffers.resize(end);
6175 }
6176 for (uint32_t i = 0; i < bindingCount; ++i) {
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07006177 pCB->currentDrawData.buffers[i + firstBinding] = pBuffers[i];
Michael Lentine700b0aa2015-10-30 17:57:32 -07006178 }
6179}
6180
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006181void updateResourceTrackingOnDraw(GLOBAL_CB_NODE *pCB) {
Michael Lentine700b0aa2015-10-30 17:57:32 -07006182 pCB->drawData.push_back(pCB->currentDrawData);
6183}
6184
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006185VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6186 vkCmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding,
6187 uint32_t bindingCount, const VkBuffer *pBuffers,
6188 const VkDeviceSize *pOffsets) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006189 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006190 layer_data *dev_data =
6191 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6192 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006193 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006194 addCmd(dev_data, pCB, CMD_BINDVERTEXBUFFER, "vkCmdBindVertexBuffer()");
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07006195 updateResourceTracking(pCB, firstBinding, bindingCount, pBuffers);
Michael Lentine700b0aa2015-10-30 17:57:32 -07006196 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006197 skipCall |= report_error_no_cb_begin(dev_data, commandBuffer,
6198 "vkCmdBindVertexBuffer()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006199 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006200 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006201 dev_data->device_dispatch_table->CmdBindVertexBuffers(
6202 commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006203}
6204
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006205VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6206 vkCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount,
6207 uint32_t instanceCount, uint32_t firstVertex,
6208 uint32_t firstInstance) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006209 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006210 layer_data *dev_data =
6211 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6212 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006213 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006214 skipCall |= addCmd(dev_data, pCB, CMD_DRAW, "vkCmdDraw()");
6215 pCB->drawCount[DRAW]++;
6216 skipCall |= validate_draw_state(dev_data, pCB, VK_FALSE);
6217 // TODO : Need to pass commandBuffer as srcObj here
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006218 skipCall |=
6219 log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
6220 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
6221 DRAWSTATE_NONE, "DS",
6222 "vkCmdDraw() call #%" PRIu64 ", reporting DS state:",
6223 g_drawCount[DRAW]++);
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006224 skipCall |= synchAndPrintDSConfig(dev_data, commandBuffer);
Michael Lentine700b0aa2015-10-30 17:57:32 -07006225 if (VK_FALSE == skipCall) {
6226 updateResourceTrackingOnDraw(pCB);
6227 }
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006228 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdDraw");
Jon Ashburn3950e1b2015-05-20 09:00:28 -06006229 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006230 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006231 dev_data->device_dispatch_table->CmdDraw(commandBuffer, vertexCount,
6232 instanceCount, firstVertex,
6233 firstInstance);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006234}
6235
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006236VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6237 vkCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount,
6238 uint32_t instanceCount, uint32_t firstIndex,
6239 int32_t vertexOffset, uint32_t firstInstance) {
6240 layer_data *dev_data =
6241 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6242 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006243 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006244 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006245 skipCall |=
6246 addCmd(dev_data, pCB, CMD_DRAWINDEXED, "vkCmdDrawIndexed()");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006247 pCB->drawCount[DRAW_INDEXED]++;
6248 skipCall |= validate_draw_state(dev_data, pCB, VK_TRUE);
6249 // TODO : Need to pass commandBuffer as srcObj here
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006250 skipCall |=
6251 log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
6252 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
6253 DRAWSTATE_NONE, "DS",
6254 "vkCmdDrawIndexed() call #%" PRIu64 ", reporting DS state:",
6255 g_drawCount[DRAW_INDEXED]++);
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006256 skipCall |= synchAndPrintDSConfig(dev_data, commandBuffer);
Michael Lentine700b0aa2015-10-30 17:57:32 -07006257 if (VK_FALSE == skipCall) {
6258 updateResourceTrackingOnDraw(pCB);
6259 }
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006260 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdDrawIndexed");
Jon Ashburn3950e1b2015-05-20 09:00:28 -06006261 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006262 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006263 dev_data->device_dispatch_table->CmdDrawIndexed(
6264 commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset,
6265 firstInstance);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006266}
6267
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006268VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6269 vkCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
6270 VkDeviceSize offset, uint32_t count, uint32_t stride) {
6271 layer_data *dev_data =
6272 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6273 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006274 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006275 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006276 skipCall |=
6277 addCmd(dev_data, pCB, CMD_DRAWINDIRECT, "vkCmdDrawIndirect()");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006278 pCB->drawCount[DRAW_INDIRECT]++;
6279 skipCall |= validate_draw_state(dev_data, pCB, VK_FALSE);
6280 // TODO : Need to pass commandBuffer as srcObj here
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006281 skipCall |=
6282 log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
6283 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
6284 DRAWSTATE_NONE, "DS", "vkCmdDrawIndirect() call #%" PRIu64
6285 ", reporting DS state:",
6286 g_drawCount[DRAW_INDIRECT]++);
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006287 skipCall |= synchAndPrintDSConfig(dev_data, commandBuffer);
Michael Lentine700b0aa2015-10-30 17:57:32 -07006288 if (VK_FALSE == skipCall) {
6289 updateResourceTrackingOnDraw(pCB);
6290 }
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006291 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdDrawIndirect");
Jon Ashburn3950e1b2015-05-20 09:00:28 -06006292 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006293 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006294 dev_data->device_dispatch_table->CmdDrawIndirect(commandBuffer, buffer,
6295 offset, count, stride);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006296}
6297
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006298VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6299 vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
6300 VkDeviceSize offset, uint32_t count,
6301 uint32_t stride) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006302 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006303 layer_data *dev_data =
6304 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6305 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006306 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006307 skipCall |= addCmd(dev_data, pCB, CMD_DRAWINDEXEDINDIRECT,
6308 "vkCmdDrawIndexedIndirect()");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006309 pCB->drawCount[DRAW_INDEXED_INDIRECT]++;
6310 skipCall |= validate_draw_state(dev_data, pCB, VK_TRUE);
6311 // TODO : Need to pass commandBuffer as srcObj here
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006312 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT,
6313 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
6314 __LINE__, DRAWSTATE_NONE, "DS",
6315 "vkCmdDrawIndexedIndirect() call #%" PRIu64
6316 ", reporting DS state:",
6317 g_drawCount[DRAW_INDEXED_INDIRECT]++);
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006318 skipCall |= synchAndPrintDSConfig(dev_data, commandBuffer);
Michael Lentine700b0aa2015-10-30 17:57:32 -07006319 if (VK_FALSE == skipCall) {
6320 updateResourceTrackingOnDraw(pCB);
6321 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006322 skipCall |=
6323 outsideRenderPass(dev_data, pCB, "vkCmdDrawIndexedIndirect");
Jon Ashburn3950e1b2015-05-20 09:00:28 -06006324 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006325 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006326 dev_data->device_dispatch_table->CmdDrawIndexedIndirect(
6327 commandBuffer, buffer, offset, count, stride);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006328}
6329
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006330VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6331 vkCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y,
6332 uint32_t z) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006333 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006334 layer_data *dev_data =
6335 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6336 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006337 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006338 skipCall |= addCmd(dev_data, pCB, CMD_DISPATCH, "vkCmdDispatch()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006339 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdDispatch");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006340 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006341 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08006342 dev_data->device_dispatch_table->CmdDispatch(commandBuffer, x, y, z);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006343}
6344
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006345VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6346 vkCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
6347 VkDeviceSize offset) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006348 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006349 layer_data *dev_data =
6350 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6351 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006352 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006353 skipCall |= addCmd(dev_data, pCB, CMD_DISPATCHINDIRECT,
6354 "vkCmdDispatchIndirect()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006355 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdDispatchIndirect");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006356 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006357 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006358 dev_data->device_dispatch_table->CmdDispatchIndirect(commandBuffer,
6359 buffer, offset);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006360}
6361
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006362VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6363 vkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
6364 VkBuffer dstBuffer, uint32_t regionCount,
6365 const VkBufferCopy *pRegions) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006366 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006367 layer_data *dev_data =
6368 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6369 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006370 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006371 skipCall |= addCmd(dev_data, pCB, CMD_COPYBUFFER, "vkCmdCopyBuffer()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006372 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyBuffer");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006373 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006374 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006375 dev_data->device_dispatch_table->CmdCopyBuffer(
6376 commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006377}
6378
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006379VkBool32 VerifySourceImageLayout(VkCommandBuffer cmdBuffer, VkImage srcImage,
6380 VkImageLayout srcImageLayout) {
Mark Youngb20a6a82016-01-07 15:41:43 -07006381 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07006382
6383#ifdef DISABLE_IMAGE_LAYOUT_VALIDATION
6384 // TODO: Fix -- initialLayout may have been set in a previous command buffer
6385 return skip_call;
6386#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
6387
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006388 layer_data *dev_data =
6389 get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
6390 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
Michael Lentineabc5e922015-10-12 11:30:14 -05006391 auto src_image_element = pCB->imageLayoutMap.find(srcImage);
6392 if (src_image_element == pCB->imageLayoutMap.end()) {
6393 pCB->imageLayoutMap[srcImage].initialLayout = srcImageLayout;
6394 pCB->imageLayoutMap[srcImage].layout = srcImageLayout;
Mark Youngb20a6a82016-01-07 15:41:43 -07006395 return VK_FALSE;
Michael Lentineabc5e922015-10-12 11:30:14 -05006396 }
6397 if (src_image_element->second.layout != srcImageLayout) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006398 skip_call |=
6399 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6400 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
6401 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
6402 "Cannot copy from an image whose source layout is %d and "
6403 "doesn't match the current layout %d.",
6404 srcImageLayout, src_image_element->second.layout);
Michael Lentineabc5e922015-10-12 11:30:14 -05006405 }
6406 if (srcImageLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) {
6407 if (srcImageLayout == VK_IMAGE_LAYOUT_GENERAL) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006408 // LAYOUT_GENERAL is allowed, but may not be performance optimal,
6409 // flag as perf warning.
6410 skip_call |= log_msg(dev_data->report_data,
6411 VK_DEBUG_REPORT_PERF_WARN_BIT_EXT,
6412 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
6413 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
6414 "Layout for input image should be "
6415 "TRANSFER_SRC_OPTIMAL instead of GENERAL.");
Michael Lentineabc5e922015-10-12 11:30:14 -05006416 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006417 skip_call |=
6418 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6419 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
6420 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
6421 "Layout for input image is %d but can only be "
6422 "TRANSFER_SRC_OPTIMAL or GENERAL.",
6423 srcImageLayout);
Michael Lentineabc5e922015-10-12 11:30:14 -05006424 }
6425 }
6426 return skip_call;
6427}
6428
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006429VkBool32 VerifyDestImageLayout(VkCommandBuffer cmdBuffer, VkImage destImage,
6430 VkImageLayout destImageLayout) {
Mark Youngb20a6a82016-01-07 15:41:43 -07006431 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07006432
6433#ifdef DISABLE_IMAGE_LAYOUT_VALIDATION
6434 // TODO: Fix -- initialLayout may have been set in a previous command buffer
6435 return skip_call;
6436#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
6437
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006438 layer_data *dev_data =
6439 get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
6440 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
Michael Lentineabc5e922015-10-12 11:30:14 -05006441 auto dest_image_element = pCB->imageLayoutMap.find(destImage);
6442 if (dest_image_element == pCB->imageLayoutMap.end()) {
6443 pCB->imageLayoutMap[destImage].initialLayout = destImageLayout;
6444 pCB->imageLayoutMap[destImage].layout = destImageLayout;
Mark Youngb20a6a82016-01-07 15:41:43 -07006445 return VK_FALSE;
Michael Lentineabc5e922015-10-12 11:30:14 -05006446 }
6447 if (dest_image_element->second.layout != destImageLayout) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006448 skip_call |=
6449 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6450 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
6451 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
6452 "Cannot copy from an image whose dest layout is %d and "
6453 "doesn't match the current layout %d.",
6454 destImageLayout, dest_image_element->second.layout);
Michael Lentineabc5e922015-10-12 11:30:14 -05006455 }
6456 if (destImageLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
6457 if (destImageLayout == VK_IMAGE_LAYOUT_GENERAL) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006458 // LAYOUT_GENERAL is allowed, but may not be performance optimal,
6459 // flag as perf warning.
6460 skip_call |= log_msg(dev_data->report_data,
6461 VK_DEBUG_REPORT_PERF_WARN_BIT_EXT,
6462 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
6463 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
6464 "Layout for output image should be "
6465 "TRANSFER_DST_OPTIMAL instead of GENERAL.");
Michael Lentineabc5e922015-10-12 11:30:14 -05006466 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006467 skip_call |=
6468 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6469 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
6470 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
6471 "Layout for output image is %d but can only be "
6472 "TRANSFER_DST_OPTIMAL or GENERAL.",
6473 destImageLayout);
Michael Lentineabc5e922015-10-12 11:30:14 -05006474 }
6475 }
6476 return skip_call;
6477}
6478
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006479VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6480 vkCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage,
6481 VkImageLayout srcImageLayout, VkImage dstImage,
6482 VkImageLayout dstImageLayout, uint32_t regionCount,
6483 const VkImageCopy *pRegions) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006484 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006485 layer_data *dev_data =
6486 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6487 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006488 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006489 skipCall |= addCmd(dev_data, pCB, CMD_COPYIMAGE, "vkCmdCopyImage()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006490 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyImage");
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006491 skipCall |=
6492 VerifySourceImageLayout(commandBuffer, srcImage, srcImageLayout);
6493 skipCall |=
6494 VerifyDestImageLayout(commandBuffer, dstImage, dstImageLayout);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006495 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006496 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006497 dev_data->device_dispatch_table->CmdCopyImage(
6498 commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout,
6499 regionCount, pRegions);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006500}
6501
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006502VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6503 vkCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage,
6504 VkImageLayout srcImageLayout, VkImage dstImage,
6505 VkImageLayout dstImageLayout, uint32_t regionCount,
6506 const VkImageBlit *pRegions, VkFilter filter) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006507 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006508 layer_data *dev_data =
6509 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6510 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Courtney Goeltzenleuchter91f9cee2015-04-03 14:42:51 -06006511 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006512 skipCall |= addCmd(dev_data, pCB, CMD_BLITIMAGE, "vkCmdBlitImage()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006513 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdBlitImage");
Courtney Goeltzenleuchter91f9cee2015-04-03 14:42:51 -06006514 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006515 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006516 dev_data->device_dispatch_table->CmdBlitImage(
6517 commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout,
6518 regionCount, pRegions, filter);
Courtney Goeltzenleuchter91f9cee2015-04-03 14:42:51 -06006519}
6520
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006521VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6522 vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
6523 VkImage dstImage, VkImageLayout dstImageLayout,
6524 uint32_t regionCount,
6525 const VkBufferImageCopy *pRegions) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006526 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006527 layer_data *dev_data =
6528 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6529 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006530 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006531 skipCall |= addCmd(dev_data, pCB, CMD_COPYBUFFERTOIMAGE,
6532 "vkCmdCopyBufferToImage()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006533 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyBufferToImage");
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006534 skipCall |=
6535 VerifyDestImageLayout(commandBuffer, dstImage, dstImageLayout);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006536 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006537 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006538 dev_data->device_dispatch_table->CmdCopyBufferToImage(
6539 commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount,
6540 pRegions);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006541}
6542
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006543VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6544 vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage,
6545 VkImageLayout srcImageLayout, VkBuffer dstBuffer,
6546 uint32_t regionCount,
6547 const VkBufferImageCopy *pRegions) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006548 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006549 layer_data *dev_data =
6550 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6551 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006552 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006553 skipCall |= addCmd(dev_data, pCB, CMD_COPYIMAGETOBUFFER,
6554 "vkCmdCopyImageToBuffer()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006555 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyImageToBuffer");
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006556 skipCall |=
6557 VerifySourceImageLayout(commandBuffer, srcImage, srcImageLayout);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006558 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006559 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006560 dev_data->device_dispatch_table->CmdCopyImageToBuffer(
6561 commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount,
6562 pRegions);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006563}
6564
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006565VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6566 vkCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
6567 VkDeviceSize dstOffset, VkDeviceSize dataSize,
6568 const uint32_t *pData) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006569 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006570 layer_data *dev_data =
6571 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6572 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006573 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006574 skipCall |=
6575 addCmd(dev_data, pCB, CMD_UPDATEBUFFER, "vkCmdUpdateBuffer()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006576 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyUpdateBuffer");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006577 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006578 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006579 dev_data->device_dispatch_table->CmdUpdateBuffer(
6580 commandBuffer, dstBuffer, dstOffset, dataSize, pData);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006581}
6582
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006583VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6584 vkCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
6585 VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006586 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006587 layer_data *dev_data =
6588 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6589 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006590 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006591 skipCall |= addCmd(dev_data, pCB, CMD_FILLBUFFER, "vkCmdFillBuffer()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006592 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyFillBuffer");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006593 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006594 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006595 dev_data->device_dispatch_table->CmdFillBuffer(commandBuffer, dstBuffer,
6596 dstOffset, size, data);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006597}
6598
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006599VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6600 vkCmdClearAttachments(VkCommandBuffer commandBuffer,
6601 uint32_t attachmentCount,
6602 const VkClearAttachment *pAttachments,
6603 uint32_t rectCount, const VkClearRect *pRects) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006604 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006605 layer_data *dev_data =
6606 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6607 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis53eddda2015-07-01 16:46:13 -06006608 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006609 skipCall |= addCmd(dev_data, pCB, CMD_CLEARATTACHMENTS,
6610 "vkCmdClearAttachments()");
6611 // Warn if this is issued prior to Draw Cmd and clearing the entire
6612 // attachment
6613 if (!hasDrawCmd(pCB) &&
6614 (pCB->activeRenderPassBeginInfo.renderArea.extent.width ==
6615 pRects[0].rect.extent.width) &&
6616 (pCB->activeRenderPassBeginInfo.renderArea.extent.height ==
6617 pRects[0].rect.extent.height)) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006618 // TODO : commandBuffer should be srcObj
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006619 skipCall |= log_msg(
6620 dev_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT,
6621 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
6622 DRAWSTATE_CLEAR_CMD_BEFORE_DRAW, "DS",
6623 "vkCmdClearAttachments() issued on CB object 0x%" PRIxLEAST64
6624 " prior to any Draw Cmds."
6625 " It is recommended you use RenderPass LOAD_OP_CLEAR on "
6626 "Attachments prior to any Draw.",
6627 (uint64_t)(commandBuffer));
Tobin Ehlis53eddda2015-07-01 16:46:13 -06006628 }
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06006629 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdClearAttachments");
6630 }
6631
6632 // Validate that attachment is in reference list of active subpass
6633 if (pCB->activeRenderPass) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006634 const VkRenderPassCreateInfo *pRPCI =
6635 dev_data->renderPassMap[pCB->activeRenderPass]->pCreateInfo;
6636 const VkSubpassDescription *pSD =
6637 &pRPCI->pSubpasses[pCB->activeSubpass];
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06006638
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006639 for (uint32_t attachment_idx = 0; attachment_idx < attachmentCount;
6640 attachment_idx++) {
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06006641 const VkClearAttachment *attachment = &pAttachments[attachment_idx];
6642 if (attachment->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
6643 VkBool32 found = VK_FALSE;
Chia-I Wud50a7d72015-10-26 20:48:51 +08006644 for (uint32_t i = 0; i < pSD->colorAttachmentCount; i++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006645 if (attachment->colorAttachment ==
6646 pSD->pColorAttachments[i].attachment) {
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06006647 found = VK_TRUE;
6648 break;
6649 }
6650 }
6651 if (VK_FALSE == found) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006652 skipCall |= log_msg(
6653 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6654 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6655 (uint64_t)commandBuffer, __LINE__,
6656 DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS",
6657 "vkCmdClearAttachments() attachment index %d not found "
6658 "in attachment reference array of active subpass %d",
6659 attachment->colorAttachment, pCB->activeSubpass);
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06006660 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006661 } else if (attachment->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT |
6662 VK_IMAGE_ASPECT_STENCIL_BIT)) {
6663 if (!pSD->pDepthStencilAttachment || // Says no DS will be used
6664 // in active subpass
6665 (pSD->pDepthStencilAttachment->attachment ==
6666 VK_ATTACHMENT_UNUSED)) { // Says no DS will be used in
6667 // active subpass
Mark Lobodzinskid6e7bff2015-11-17 15:11:24 -07006668
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006669 skipCall |= log_msg(
6670 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6671 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6672 (uint64_t)commandBuffer, __LINE__,
6673 DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS",
6674 "vkCmdClearAttachments() attachment index %d does not "
6675 "match depthStencilAttachment.attachment (%d) found in "
6676 "active subpass %d",
Mark Lobodzinskid6e7bff2015-11-17 15:11:24 -07006677 attachment->colorAttachment,
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006678 (pSD->pDepthStencilAttachment)
6679 ? pSD->pDepthStencilAttachment->attachment
6680 : VK_ATTACHMENT_UNUSED,
Mark Lobodzinskid6e7bff2015-11-17 15:11:24 -07006681 pCB->activeSubpass);
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06006682 }
6683 }
6684 }
Tobin Ehlis53eddda2015-07-01 16:46:13 -06006685 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006686 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006687 dev_data->device_dispatch_table->CmdClearAttachments(
6688 commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
Tobin Ehlis53eddda2015-07-01 16:46:13 -06006689}
6690
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006691VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6692 vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image,
6693 VkImageLayout imageLayout,
6694 const VkClearColorValue *pColor, uint32_t rangeCount,
6695 const VkImageSubresourceRange *pRanges) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006696 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006697 layer_data *dev_data =
6698 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6699 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006700 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006701 skipCall |= addCmd(dev_data, pCB, CMD_CLEARCOLORIMAGE,
6702 "vkCmdClearColorImage()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006703 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdClearColorImage");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006704 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006705 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006706 dev_data->device_dispatch_table->CmdClearColorImage(
6707 commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006708}
6709
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006710VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6711 vkCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image,
6712 VkImageLayout imageLayout,
6713 const VkClearDepthStencilValue *pDepthStencil,
6714 uint32_t rangeCount,
6715 const VkImageSubresourceRange *pRanges) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006716 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006717 layer_data *dev_data =
6718 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6719 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006720 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006721 skipCall |= addCmd(dev_data, pCB, CMD_CLEARDEPTHSTENCILIMAGE,
6722 "vkCmdClearDepthStencilImage()");
6723 skipCall |=
6724 insideRenderPass(dev_data, pCB, "vkCmdClearDepthStencilImage");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006725 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006726 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006727 dev_data->device_dispatch_table->CmdClearDepthStencilImage(
6728 commandBuffer, image, imageLayout, pDepthStencil, rangeCount,
6729 pRanges);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006730}
6731
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006732VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6733 vkCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage,
6734 VkImageLayout srcImageLayout, VkImage dstImage,
6735 VkImageLayout dstImageLayout, uint32_t regionCount,
6736 const VkImageResolve *pRegions) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006737 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006738 layer_data *dev_data =
6739 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6740 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006741 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006742 skipCall |=
6743 addCmd(dev_data, pCB, CMD_RESOLVEIMAGE, "vkCmdResolveImage()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006744 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdResolveImage");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006745 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006746 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006747 dev_data->device_dispatch_table->CmdResolveImage(
6748 commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout,
6749 regionCount, pRegions);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006750}
6751
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006752VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6753 vkCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event,
6754 VkPipelineStageFlags stageMask) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006755 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006756 layer_data *dev_data =
6757 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6758 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006759 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006760 skipCall |= addCmd(dev_data, pCB, CMD_SETEVENT, "vkCmdSetEvent()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006761 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdSetEvent");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006762 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006763 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006764 dev_data->device_dispatch_table->CmdSetEvent(commandBuffer, event,
6765 stageMask);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006766}
6767
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006768VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
6769 vkCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event,
6770 VkPipelineStageFlags stageMask) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006771 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006772 layer_data *dev_data =
6773 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
6774 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006775 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07006776 skipCall |= addCmd(dev_data, pCB, CMD_RESETEVENT, "vkCmdResetEvent()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06006777 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdResetEvent");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006778 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06006779 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006780 dev_data->device_dispatch_table->CmdResetEvent(commandBuffer, event,
6781 stageMask);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006782}
6783
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006784VkBool32 TransitionImageLayouts(VkCommandBuffer cmdBuffer,
6785 uint32_t memBarrierCount,
6786 const VkImageMemoryBarrier *pImgMemBarriers) {
6787 layer_data *dev_data =
6788 get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
6789 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
Mark Youngb20a6a82016-01-07 15:41:43 -07006790 VkBool32 skip = VK_FALSE;
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07006791
6792#ifdef DISABLE_IMAGE_LAYOUT_VALIDATION
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006793 // TODO: Fix -- pay attention to image subresource ranges -- not all
6794 // subresources transition at the same time
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07006795 return skip;
6796#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
6797
Michael Lentineabc5e922015-10-12 11:30:14 -05006798 for (uint32_t i = 0; i < memBarrierCount; ++i) {
Jon Ashburnf19916e2016-01-11 13:12:43 -07006799 auto mem_barrier = &pImgMemBarriers[i];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006800 if (mem_barrier &&
6801 mem_barrier->sType == VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER) {
Jon Ashburnf19916e2016-01-11 13:12:43 -07006802 auto image_data = pCB->imageLayoutMap.find(mem_barrier->image);
Michael Lentineabc5e922015-10-12 11:30:14 -05006803 if (image_data == pCB->imageLayoutMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006804 pCB->imageLayoutMap[mem_barrier->image].initialLayout =
6805 mem_barrier->oldLayout;
6806 pCB->imageLayoutMap[mem_barrier->image].layout =
6807 mem_barrier->newLayout;
Michael Lentineabc5e922015-10-12 11:30:14 -05006808 } else {
Jon Ashburnf19916e2016-01-11 13:12:43 -07006809 if (image_data->second.layout != mem_barrier->oldLayout) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006810 skip |= log_msg(
6811 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6812 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
6813 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
6814 "You cannot transition the layout from %d when current "
6815 "layout is %d.",
6816 mem_barrier->oldLayout, image_data->second.layout);
Michael Lentineabc5e922015-10-12 11:30:14 -05006817 }
Jon Ashburnf19916e2016-01-11 13:12:43 -07006818 image_data->second.layout = mem_barrier->newLayout;
Michael Lentineabc5e922015-10-12 11:30:14 -05006819 }
6820 }
6821 }
6822 return skip;
6823}
6824
Mark Lobodzinskia3a86112016-01-05 17:17:55 -07006825// Print readable FlagBits in FlagMask
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006826std::string string_VkAccessFlags(VkAccessFlags accessMask) {
Mark Lobodzinskia3a86112016-01-05 17:17:55 -07006827 std::string result;
6828 std::string separator;
6829
6830 if (accessMask == 0) {
6831 result = "[None]";
6832 } else {
6833 result = "[";
6834 for (auto i = 0; i < 32; i++) {
6835 if (accessMask & (1 << i)) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006836 result = result + separator +
6837 string_VkAccessFlagBits((VkAccessFlagBits)(1 << i));
Mark Lobodzinskia3a86112016-01-05 17:17:55 -07006838 separator = " | ";
6839 }
6840 }
6841 result = result + "]";
6842 }
6843 return result;
6844}
6845
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006846// AccessFlags MUST have 'required_bit' set, and may have one or more of
6847// 'optional_bits' set.
6848// If required_bit is zero, accessMask must have at least one of 'optional_bits'
6849// set
6850// TODO: Add tracking to ensure that at least one barrier has been set for these
6851// layout transitions
6852VkBool32 ValidateMaskBits(const layer_data *my_data, VkCommandBuffer cmdBuffer,
6853 const VkAccessFlags &accessMask,
6854 const VkImageLayout &layout,
6855 VkAccessFlags required_bit,
6856 VkAccessFlags optional_bits, const char *type) {
Mark Youngb20a6a82016-01-07 15:41:43 -07006857 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinski882655d2016-01-05 11:32:53 -07006858
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006859 if ((accessMask & required_bit) ||
6860 (!required_bit && (accessMask & optional_bits))) {
Michael Lentine97eb7462015-11-20 09:48:52 -08006861 if (accessMask & !(required_bit | optional_bits)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07006862 // TODO: Verify against Valid Use
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006863 skip_call |= log_msg(
6864 my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT,
6865 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
6866 DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s "
6867 "accessMask %d %s are "
6868 "specified when layout is %s.",
6869 type, accessMask, string_VkAccessFlags(accessMask).c_str(),
6870 string_VkImageLayout(layout));
Michael Lentineecc32b72015-10-16 18:08:09 -05006871 }
6872 } else {
Michael Lentine97eb7462015-11-20 09:48:52 -08006873 if (!required_bit) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006874 skip_call |= log_msg(
6875 my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT,
6876 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
6877 DRAWSTATE_INVALID_BARRIER, "DS",
6878 "%s AccessMask %d %s must contain at least one of access bits "
6879 "%d %s when layout is %s, unless the app has previously added "
6880 "a barrier for this transition.",
6881 type, accessMask, string_VkAccessFlags(accessMask).c_str(),
6882 optional_bits, string_VkAccessFlags(optional_bits).c_str(),
6883 string_VkImageLayout(layout));
Michael Lentine97eb7462015-11-20 09:48:52 -08006884 } else {
Mark Lobodzinskif2cc2a52016-01-05 13:35:29 -07006885 std::string opt_bits;
6886 if (optional_bits != 0) {
Michael Lentine6bd4f122016-01-19 14:00:53 -06006887 std::stringstream ss;
6888 ss << optional_bits;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006889 opt_bits = "and may have optional bits " + ss.str() + ' ' +
6890 string_VkAccessFlags(optional_bits);
Mark Lobodzinskif2cc2a52016-01-05 13:35:29 -07006891 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006892 skip_call |= log_msg(
6893 my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT,
6894 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
6895 DRAWSTATE_INVALID_BARRIER, "DS",
6896 "%s AccessMask %d %s must have required access bit %d %s %s "
6897 "when layout is %s, unless the app has previously added a "
6898 "barrier for this transition.",
6899 type, accessMask, string_VkAccessFlags(accessMask).c_str(),
6900 required_bit, string_VkAccessFlags(required_bit).c_str(),
6901 opt_bits.c_str(), string_VkImageLayout(layout));
Michael Lentine97eb7462015-11-20 09:48:52 -08006902 }
Michael Lentineecc32b72015-10-16 18:08:09 -05006903 }
6904 return skip_call;
6905}
6906
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006907VkBool32 ValidateMaskBitsFromLayouts(const layer_data *my_data,
6908 VkCommandBuffer cmdBuffer,
6909 const VkAccessFlags &accessMask,
6910 const VkImageLayout &layout,
6911 const char *type) {
Mark Youngb20a6a82016-01-07 15:41:43 -07006912 VkBool32 skip_call = VK_FALSE;
Michael Lentine97eb7462015-11-20 09:48:52 -08006913 switch (layout) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006914 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: {
6915 skip_call |=
6916 ValidateMaskBits(my_data, cmdBuffer, accessMask, layout,
6917 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
6918 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, type);
6919 break;
6920 }
6921 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: {
6922 skip_call |=
6923 ValidateMaskBits(my_data, cmdBuffer, accessMask, layout,
6924 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
6925 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, type);
6926 break;
6927 }
6928 case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: {
6929 skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout,
6930 VK_ACCESS_TRANSFER_WRITE_BIT, 0, type);
6931 break;
6932 }
6933 case VK_IMAGE_LAYOUT_PREINITIALIZED: {
6934 skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout,
6935 VK_ACCESS_HOST_WRITE_BIT, 0, type);
6936 break;
6937 }
6938 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: {
6939 skip_call |=
6940 ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, 0,
6941 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
6942 VK_ACCESS_SHADER_READ_BIT,
6943 type);
6944 break;
6945 }
6946 case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: {
6947 skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, 0,
6948 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
6949 VK_ACCESS_SHADER_READ_BIT,
6950 type);
6951 break;
6952 }
6953 case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: {
6954 skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout,
6955 VK_ACCESS_TRANSFER_READ_BIT, 0, type);
6956 break;
6957 }
6958 case VK_IMAGE_LAYOUT_UNDEFINED: {
6959 if (accessMask != 0) {
6960 // TODO: Verify against Valid Use section spec
6961 skip_call |= log_msg(
6962 my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT,
6963 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
6964 DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s "
6965 "accessMask %d %s are "
6966 "specified when layout is %s.",
6967 type, accessMask, string_VkAccessFlags(accessMask).c_str(),
6968 string_VkImageLayout(layout));
Michael Lentineecc32b72015-10-16 18:08:09 -05006969 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006970 break;
6971 }
6972 case VK_IMAGE_LAYOUT_GENERAL:
6973 default: { break; }
Michael Lentineecc32b72015-10-16 18:08:09 -05006974 }
6975 return skip_call;
6976}
6977
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006978VkBool32 ValidateBarriers(VkCommandBuffer cmdBuffer, uint32_t memBarrierCount,
6979 const VkMemoryBarrier *pMemBarriers,
6980 uint32_t imageMemBarrierCount,
6981 const VkImageMemoryBarrier *pImageMemBarriers) {
Mark Youngb20a6a82016-01-07 15:41:43 -07006982 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006983 layer_data *dev_data =
6984 get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
6985 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
Michael Lentine48930b82015-10-15 17:07:00 -05006986 if (pCB->activeRenderPass && memBarrierCount) {
6987 for (uint32_t i = 0; i < memBarrierCount; ++i) {
Jon Ashburnf19916e2016-01-11 13:12:43 -07006988 auto mem_barrier = &pMemBarriers[i];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006989 if (mem_barrier &&
6990 mem_barrier->sType != VK_STRUCTURE_TYPE_MEMORY_BARRIER) {
6991 skip_call |= log_msg(dev_data->report_data,
6992 VK_DEBUG_REPORT_ERROR_BIT_EXT,
6993 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
6994 DRAWSTATE_INVALID_BARRIER, "DS",
6995 "Image or Buffers Barriers cannot be used "
6996 "during a render pass.");
Michael Lentine48930b82015-10-15 17:07:00 -05006997 }
6998 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07006999 if (!dev_data->renderPassMap[pCB->activeRenderPass]
7000 ->hasSelfDependency[pCB->activeSubpass]) {
7001 skip_call |=
7002 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7003 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7004 DRAWSTATE_INVALID_BARRIER, "DS",
7005 "Barriers cannot be set during subpass %d with no self "
7006 "dependency specified.",
7007 pCB->activeSubpass);
Michael Lentine48930b82015-10-15 17:07:00 -05007008 }
7009 }
Mark Lobodzinski73a37ec2015-11-20 09:27:27 -07007010
Jon Ashburnf19916e2016-01-11 13:12:43 -07007011 for (uint32_t i = 0; i < imageMemBarrierCount; ++i) {
7012 auto mem_barrier = &pImageMemBarriers[i];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007013 if (mem_barrier &&
7014 mem_barrier->sType == VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER) {
7015 skip_call |= ValidateMaskBitsFromLayouts(
7016 dev_data, cmdBuffer, mem_barrier->srcAccessMask,
7017 mem_barrier->oldLayout, "Source");
7018 skip_call |= ValidateMaskBitsFromLayouts(
7019 dev_data, cmdBuffer, mem_barrier->dstAccessMask,
7020 mem_barrier->newLayout, "Dest");
Michael Lentineecc32b72015-10-16 18:08:09 -05007021 }
7022 }
Mark Lobodzinski3cba24a2015-12-03 15:42:32 -07007023
Michael Lentine48930b82015-10-15 17:07:00 -05007024 return skip_call;
7025}
7026
Jon Ashburnf19916e2016-01-11 13:12:43 -07007027VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents(
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007028 VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
7029 VkPipelineStageFlags sourceStageMask, VkPipelineStageFlags dstStageMask,
7030 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
7031 uint32_t bufferMemoryBarrierCount,
7032 const VkBufferMemoryBarrier *pBufferMemoryBarriers,
7033 uint32_t imageMemoryBarrierCount,
7034 const VkImageMemoryBarrier *pImageMemoryBarriers) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007035 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007036 layer_data *dev_data =
7037 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7038 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007039 if (pCB) {
Michael Lentineb887b0a2015-12-29 14:12:11 -06007040 for (uint32_t i = 0; i < eventCount; ++i) {
7041 pCB->waitedEvents.push_back(pEvents[i]);
7042 }
Mark Lobodzinskice738852016-01-07 10:04:02 -07007043 if (pCB->state == CB_RECORDING) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007044 skipCall |=
7045 addCmd(dev_data, pCB, CMD_WAITEVENTS, "vkCmdWaitEvents()");
Michael Lentineb887b0a2015-12-29 14:12:11 -06007046 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007047 skipCall |= report_error_no_cb_begin(dev_data, commandBuffer,
7048 "vkCmdWaitEvents()");
Michael Lentineb887b0a2015-12-29 14:12:11 -06007049 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007050 skipCall |= TransitionImageLayouts(
7051 commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers);
7052 skipCall |=
7053 ValidateBarriers(commandBuffer, memoryBarrierCount, pMemoryBarriers,
7054 imageMemoryBarrierCount, pImageMemoryBarriers);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007055 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007056 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007057 dev_data->device_dispatch_table->CmdWaitEvents(
7058 commandBuffer, eventCount, pEvents, sourceStageMask, dstStageMask,
7059 memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
7060 pBufferMemoryBarriers, imageMemoryBarrierCount,
7061 pImageMemoryBarriers);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007062}
7063
Jon Ashburnf19916e2016-01-11 13:12:43 -07007064VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier(
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007065 VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask,
7066 VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags,
7067 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
7068 uint32_t bufferMemoryBarrierCount,
7069 const VkBufferMemoryBarrier *pBufferMemoryBarriers,
7070 uint32_t imageMemoryBarrierCount,
7071 const VkImageMemoryBarrier *pImageMemoryBarriers) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007072 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007073 layer_data *dev_data =
7074 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7075 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007076 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007077 skipCall |= addCmd(dev_data, pCB, CMD_PIPELINEBARRIER,
7078 "vkCmdPipelineBarrier()");
7079 skipCall |= TransitionImageLayouts(
7080 commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers);
7081 skipCall |=
7082 ValidateBarriers(commandBuffer, memoryBarrierCount, pMemoryBarriers,
7083 imageMemoryBarrierCount, pImageMemoryBarriers);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007084 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007085 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007086 dev_data->device_dispatch_table->CmdPipelineBarrier(
7087 commandBuffer, srcStageMask, dstStageMask, dependencyFlags,
7088 memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
7089 pBufferMemoryBarriers, imageMemoryBarrierCount,
7090 pImageMemoryBarriers);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007091}
7092
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007093VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
7094 vkCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
7095 uint32_t slot, VkFlags flags) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007096 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007097 layer_data *dev_data =
7098 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7099 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007100 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07007101 skipCall |= addCmd(dev_data, pCB, CMD_BEGINQUERY, "vkCmdBeginQuery()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007102 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007103 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007104 dev_data->device_dispatch_table->CmdBeginQuery(commandBuffer, queryPool,
7105 slot, flags);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007106}
7107
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007108VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
7109 vkCmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
7110 uint32_t slot) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007111 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007112 layer_data *dev_data =
7113 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7114 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007115 if (pCB) {
Michael Lentineb887b0a2015-12-29 14:12:11 -06007116 QueryObject query = {queryPool, slot};
7117 pCB->queryToStateMap[query] = 1;
Mark Lobodzinskice738852016-01-07 10:04:02 -07007118 if (pCB->state == CB_RECORDING) {
7119 skipCall |= addCmd(dev_data, pCB, CMD_ENDQUERY, "VkCmdEndQuery()");
Michael Lentineb887b0a2015-12-29 14:12:11 -06007120 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007121 skipCall |= report_error_no_cb_begin(dev_data, commandBuffer,
7122 "vkCmdEndQuery()");
Michael Lentineb887b0a2015-12-29 14:12:11 -06007123 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007124 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007125 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007126 dev_data->device_dispatch_table->CmdEndQuery(commandBuffer, queryPool,
7127 slot);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007128}
7129
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007130VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
7131 vkCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
7132 uint32_t firstQuery, uint32_t queryCount) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007133 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007134 layer_data *dev_data =
7135 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7136 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007137 if (pCB) {
Michael Lentineb887b0a2015-12-29 14:12:11 -06007138 for (uint32_t i = 0; i < queryCount; i++) {
Mark Lobodzinskice738852016-01-07 10:04:02 -07007139 QueryObject query = {queryPool, firstQuery + i};
Michael Lentineb887b0a2015-12-29 14:12:11 -06007140 pCB->waitedEventsBeforeQueryReset[query] = pCB->waitedEvents;
7141 pCB->queryToStateMap[query] = 0;
7142 }
Mark Lobodzinskice738852016-01-07 10:04:02 -07007143 if (pCB->state == CB_RECORDING) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007144 skipCall |= addCmd(dev_data, pCB, CMD_RESETQUERYPOOL,
7145 "VkCmdResetQueryPool()");
Michael Lentineb887b0a2015-12-29 14:12:11 -06007146 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007147 skipCall |= report_error_no_cb_begin(dev_data, commandBuffer,
7148 "vkCmdResetQueryPool()");
Michael Lentineb887b0a2015-12-29 14:12:11 -06007149 }
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06007150 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdQueryPool");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007151 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007152 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007153 dev_data->device_dispatch_table->CmdResetQueryPool(
7154 commandBuffer, queryPool, firstQuery, queryCount);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007155}
7156
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007157VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
7158 vkCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer,
7159 VkQueryPool queryPool, uint32_t firstQuery,
7160 uint32_t queryCount, VkBuffer dstBuffer,
7161 VkDeviceSize dstOffset, VkDeviceSize stride,
7162 VkQueryResultFlags flags) {
Mark Lobodzinski5495d132015-09-30 16:19:16 -06007163 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007164 layer_data *dev_data =
7165 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7166 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Mark Lobodzinski5495d132015-09-30 16:19:16 -06007167 if (pCB) {
Michael Lentineb887b0a2015-12-29 14:12:11 -06007168 for (uint32_t i = 0; i < queryCount; i++) {
Mark Lobodzinskice738852016-01-07 10:04:02 -07007169 QueryObject query = {queryPool, firstQuery + i};
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007170 if (!pCB->queryToStateMap[query]) {
7171 skipCall |= log_msg(
7172 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7173 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7174 DRAWSTATE_INVALID_QUERY, "DS",
7175 "Requesting a copy from query to buffer with invalid "
7176 "query: queryPool %" PRIu64 ", index %d",
7177 (uint64_t)(queryPool), firstQuery + i);
Michael Lentineb887b0a2015-12-29 14:12:11 -06007178 }
7179 }
Mark Lobodzinskice738852016-01-07 10:04:02 -07007180 if (pCB->state == CB_RECORDING) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007181 skipCall |= addCmd(dev_data, pCB, CMD_COPYQUERYPOOLRESULTS,
7182 "vkCmdCopyQueryPoolResults()");
Michael Lentineb887b0a2015-12-29 14:12:11 -06007183 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007184 skipCall |= report_error_no_cb_begin(dev_data, commandBuffer,
7185 "vkCmdCopyQueryPoolResults()");
Michael Lentineb887b0a2015-12-29 14:12:11 -06007186 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007187 skipCall |=
7188 insideRenderPass(dev_data, pCB, "vkCmdCopyQueryPoolResults");
Mark Lobodzinski5495d132015-09-30 16:19:16 -06007189 }
7190 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007191 dev_data->device_dispatch_table->CmdCopyQueryPoolResults(
7192 commandBuffer, queryPool, firstQuery, queryCount, dstBuffer,
7193 dstOffset, stride, flags);
Mark Lobodzinski5495d132015-09-30 16:19:16 -06007194}
7195
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007196VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
7197 vkCmdWriteTimestamp(VkCommandBuffer commandBuffer,
7198 VkPipelineStageFlagBits pipelineStage,
7199 VkQueryPool queryPool, uint32_t slot) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007200 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007201 layer_data *dev_data =
7202 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7203 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007204 if (pCB) {
Michael Lentineb887b0a2015-12-29 14:12:11 -06007205 QueryObject query = {queryPool, slot};
7206 pCB->queryToStateMap[query] = 1;
Mark Lobodzinskice738852016-01-07 10:04:02 -07007207 if (pCB->state == CB_RECORDING) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007208 skipCall |= addCmd(dev_data, pCB, CMD_WRITETIMESTAMP,
7209 "vkCmdWriteTimestamp()");
Michael Lentineb887b0a2015-12-29 14:12:11 -06007210 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007211 skipCall |= report_error_no_cb_begin(dev_data, commandBuffer,
7212 "vkCmdWriteTimestamp()");
Michael Lentineb887b0a2015-12-29 14:12:11 -06007213 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007214 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007215 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007216 dev_data->device_dispatch_table->CmdWriteTimestamp(
7217 commandBuffer, pipelineStage, queryPool, slot);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007218}
7219
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007220VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
7221 vkCreateFramebuffer(VkDevice device,
7222 const VkFramebufferCreateInfo *pCreateInfo,
7223 const VkAllocationCallbacks *pAllocator,
7224 VkFramebuffer *pFramebuffer) {
7225 layer_data *dev_data =
7226 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
7227 VkResult result = dev_data->device_dispatch_table->CreateFramebuffer(
7228 device, pCreateInfo, pAllocator, pFramebuffer);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06007229 if (VK_SUCCESS == result) {
Tobin Ehliseba312c2015-04-01 08:40:34 -06007230 // Shadow create info and store in map
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007231 VkFramebufferCreateInfo *localFBCI =
7232 new VkFramebufferCreateInfo(*pCreateInfo);
Chia-I Wu08accc62015-07-07 11:50:03 +08007233 if (pCreateInfo->pAttachments) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007234 localFBCI->pAttachments =
7235 new VkImageView[localFBCI->attachmentCount];
7236 memcpy((void *)localFBCI->pAttachments, pCreateInfo->pAttachments,
7237 localFBCI->attachmentCount * sizeof(VkImageView));
Tobin Ehliseba312c2015-04-01 08:40:34 -06007238 }
Chia-I Wue2fc5522015-10-26 20:04:44 +08007239 dev_data->frameBufferMap[*pFramebuffer] = localFBCI;
Tobin Ehliseba312c2015-04-01 08:40:34 -06007240 }
7241 return result;
7242}
7243
Michael Lentineb6986752015-10-06 14:56:18 -07007244// Store the DAG.
7245struct DAGNode {
7246 uint32_t pass;
7247 std::vector<uint32_t> prev;
7248 std::vector<uint32_t> next;
7249};
7250
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007251VkBool32 FindDependency(const int index, const int dependent,
7252 const std::vector<DAGNode> &subpass_to_node,
7253 std::unordered_set<uint32_t> &processed_nodes) {
7254 // If we have already checked this node we have not found a dependency path
7255 // so return false.
Michael Lentineb6986752015-10-06 14:56:18 -07007256 if (processed_nodes.count(index))
Mark Youngb20a6a82016-01-07 15:41:43 -07007257 return VK_FALSE;
Michael Lentineb6986752015-10-06 14:56:18 -07007258 processed_nodes.insert(index);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007259 const DAGNode &node = subpass_to_node[index];
7260 // Look for a dependency path. If one exists return true else recurse on the
7261 // previous nodes.
7262 if (std::find(node.prev.begin(), node.prev.end(), dependent) ==
7263 node.prev.end()) {
Michael Lentineb6986752015-10-06 14:56:18 -07007264 for (auto elem : node.prev) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007265 if (FindDependency(elem, dependent, subpass_to_node,
7266 processed_nodes))
Mark Youngb20a6a82016-01-07 15:41:43 -07007267 return VK_TRUE;
Michael Lentineb6986752015-10-06 14:56:18 -07007268 }
7269 } else {
Mark Youngb20a6a82016-01-07 15:41:43 -07007270 return VK_TRUE;
Michael Lentineb6986752015-10-06 14:56:18 -07007271 }
Mark Youngb20a6a82016-01-07 15:41:43 -07007272 return VK_FALSE;
Michael Lentineb6986752015-10-06 14:56:18 -07007273}
7274
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007275VkBool32 CheckDependencyExists(const layer_data *my_data, VkDevice device,
7276 const int subpass,
7277 const std::vector<uint32_t> &dependent_subpasses,
7278 const std::vector<DAGNode> &subpass_to_node,
7279 VkBool32 &skip_call) {
Mark Youngb20a6a82016-01-07 15:41:43 -07007280 VkBool32 result = VK_TRUE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007281 // Loop through all subpasses that share the same attachment and make sure a
7282 // dependency exists
Michael Lentineb6986752015-10-06 14:56:18 -07007283 for (uint32_t k = 0; k < dependent_subpasses.size(); ++k) {
7284 if (subpass == dependent_subpasses[k])
7285 continue;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007286 const DAGNode &node = subpass_to_node[subpass];
7287 // Check for a specified dependency between the two nodes. If one exists
7288 // we are done.
7289 auto prev_elem = std::find(node.prev.begin(), node.prev.end(),
7290 dependent_subpasses[k]);
7291 auto next_elem = std::find(node.next.begin(), node.next.end(),
7292 dependent_subpasses[k]);
Michael Lentineb6986752015-10-06 14:56:18 -07007293 if (prev_elem == node.prev.end() && next_elem == node.next.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007294 // If no dependency exits an implicit dependency still might. If so,
7295 // warn and if not throw an error.
Michael Lentineb6986752015-10-06 14:56:18 -07007296 std::unordered_set<uint32_t> processed_nodes;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007297 if (FindDependency(subpass, dependent_subpasses[k], subpass_to_node,
7298 processed_nodes) ||
7299 FindDependency(dependent_subpasses[k], subpass, subpass_to_node,
7300 processed_nodes)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07007301 // TODO: Verify against Valid Use section of spec
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007302 skip_call |=
7303 log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT,
7304 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7305 DRAWSTATE_INVALID_RENDERPASS, "DS",
7306 "A dependency between subpasses %d and %d must "
7307 "exist but only an implicit one is specified.",
7308 subpass, dependent_subpasses[k]);
Michael Lentineb6986752015-10-06 14:56:18 -07007309 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007310 skip_call |=
7311 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7312 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7313 DRAWSTATE_INVALID_RENDERPASS, "DS",
7314 "A dependency between subpasses %d and %d must "
7315 "exist but one is not specified.",
7316 subpass, dependent_subpasses[k]);
Mark Youngb20a6a82016-01-07 15:41:43 -07007317 result = VK_FALSE;
Michael Lentineb6986752015-10-06 14:56:18 -07007318 }
7319 }
7320 }
7321 return result;
7322}
7323
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007324VkBool32 CheckPreserved(const layer_data *my_data, VkDevice device,
7325 const VkRenderPassCreateInfo *pCreateInfo,
7326 const int index, const uint32_t attachment,
7327 const std::vector<DAGNode> &subpass_to_node, int depth,
7328 VkBool32 &skip_call) {
7329 const DAGNode &node = subpass_to_node[index];
7330 // If this node writes to the attachment return true as next nodes need to
7331 // preserve the attachment.
7332 const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[index];
Chia-I Wud50a7d72015-10-26 20:48:51 +08007333 for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
Michael Lentineb6986752015-10-06 14:56:18 -07007334 if (attachment == subpass.pColorAttachments[j].attachment)
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -07007335 return VK_TRUE;
Michael Lentineb6986752015-10-06 14:56:18 -07007336 }
Chia-I Wu1efb7e52015-10-26 17:32:47 +08007337 if (subpass.pDepthStencilAttachment &&
7338 subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
7339 if (attachment == subpass.pDepthStencilAttachment->attachment)
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -07007340 return VK_TRUE;
Michael Lentineb6986752015-10-06 14:56:18 -07007341 }
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -07007342 VkBool32 result = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007343 // Loop through previous nodes and see if any of them write to the
7344 // attachment.
Michael Lentineb6986752015-10-06 14:56:18 -07007345 for (auto elem : node.prev) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007346 result |= CheckPreserved(my_data, device, pCreateInfo, elem, attachment,
7347 subpass_to_node, depth + 1, skip_call);
Michael Lentineb6986752015-10-06 14:56:18 -07007348 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007349 // If the attachment was written to by a previous node than this node needs
7350 // to preserve it.
Michael Lentineb6986752015-10-06 14:56:18 -07007351 if (result && depth > 0) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007352 const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[index];
Mark Youngb20a6a82016-01-07 15:41:43 -07007353 VkBool32 has_preserved = VK_FALSE;
Chia-I Wud50a7d72015-10-26 20:48:51 +08007354 for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) {
Jon Ashburnf19916e2016-01-11 13:12:43 -07007355 if (subpass.pPreserveAttachments[j] == attachment) {
Mark Youngb20a6a82016-01-07 15:41:43 -07007356 has_preserved = VK_TRUE;
Michael Lentineb6986752015-10-06 14:56:18 -07007357 break;
7358 }
7359 }
Mark Youngb20a6a82016-01-07 15:41:43 -07007360 if (has_preserved == VK_FALSE) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007361 skip_call |=
7362 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7363 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7364 DRAWSTATE_INVALID_RENDERPASS, "DS",
7365 "Attachment %d is used by a later subpass and must be "
7366 "preserved in subpass %d.",
7367 attachment, index);
Michael Lentineb6986752015-10-06 14:56:18 -07007368 }
7369 }
7370 return result;
7371}
7372
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007373VkBool32 ValidateDependencies(const layer_data *my_data, VkDevice device,
7374 const VkRenderPassCreateInfo *pCreateInfo,
7375 const std::vector<DAGNode> &subpass_to_node) {
Mark Youngb20a6a82016-01-07 15:41:43 -07007376 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007377 std::vector<std::vector<uint32_t>> output_attachment_to_subpass(
7378 pCreateInfo->attachmentCount);
7379 std::vector<std::vector<uint32_t>> input_attachment_to_subpass(
7380 pCreateInfo->attachmentCount);
Michael Lentineb6986752015-10-06 14:56:18 -07007381 // Find for each attachment the subpasses that use them.
7382 for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007383 const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
Chia-I Wud50a7d72015-10-26 20:48:51 +08007384 for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007385 input_attachment_to_subpass[subpass.pInputAttachments[j].attachment]
7386 .push_back(i);
Michael Lentineb6986752015-10-06 14:56:18 -07007387 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08007388 for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007389 output_attachment_to_subpass[subpass.pColorAttachments[j]
7390 .attachment].push_back(i);
Michael Lentineb6986752015-10-06 14:56:18 -07007391 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007392 if (subpass.pDepthStencilAttachment &&
7393 subpass.pDepthStencilAttachment->attachment !=
7394 VK_ATTACHMENT_UNUSED) {
7395 output_attachment_to_subpass[subpass.pDepthStencilAttachment
7396 ->attachment].push_back(i);
Michael Lentineb6986752015-10-06 14:56:18 -07007397 }
7398 }
7399 // If there is a dependency needed make sure one exists
7400 for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007401 const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
7402 // If the attachment is an input then all subpasses that output must
7403 // have a dependency relationship
Chia-I Wud50a7d72015-10-26 20:48:51 +08007404 for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007405 const uint32_t &attachment =
7406 subpass.pInputAttachments[j].attachment;
7407 CheckDependencyExists(my_data, device, i,
7408 output_attachment_to_subpass[attachment],
7409 subpass_to_node, skip_call);
Michael Lentineb6986752015-10-06 14:56:18 -07007410 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007411 // If the attachment is an output then all subpasses that use the
7412 // attachment must have a dependency relationship
Chia-I Wud50a7d72015-10-26 20:48:51 +08007413 for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007414 const uint32_t &attachment =
7415 subpass.pColorAttachments[j].attachment;
7416 CheckDependencyExists(my_data, device, i,
7417 output_attachment_to_subpass[attachment],
7418 subpass_to_node, skip_call);
7419 CheckDependencyExists(my_data, device, i,
7420 input_attachment_to_subpass[attachment],
7421 subpass_to_node, skip_call);
Michael Lentineb6986752015-10-06 14:56:18 -07007422 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007423 if (subpass.pDepthStencilAttachment &&
7424 subpass.pDepthStencilAttachment->attachment !=
7425 VK_ATTACHMENT_UNUSED) {
7426 const uint32_t &attachment =
7427 subpass.pDepthStencilAttachment->attachment;
7428 CheckDependencyExists(my_data, device, i,
7429 output_attachment_to_subpass[attachment],
7430 subpass_to_node, skip_call);
7431 CheckDependencyExists(my_data, device, i,
7432 input_attachment_to_subpass[attachment],
7433 subpass_to_node, skip_call);
Michael Lentineb6986752015-10-06 14:56:18 -07007434 }
7435 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007436 // Loop through implicit dependencies, if this pass reads make sure the
7437 // attachment is preserved for all passes after it was written.
Michael Lentineb6986752015-10-06 14:56:18 -07007438 for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007439 const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
Chia-I Wud50a7d72015-10-26 20:48:51 +08007440 for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007441 CheckPreserved(my_data, device, pCreateInfo, i,
7442 subpass.pInputAttachments[j].attachment,
7443 subpass_to_node, 0, skip_call);
Michael Lentineb6986752015-10-06 14:56:18 -07007444 }
7445 }
7446 return skip_call;
7447}
7448
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007449VkBool32 ValidateLayouts(const layer_data *my_data, VkDevice device,
7450 const VkRenderPassCreateInfo *pCreateInfo) {
Mark Youngb20a6a82016-01-07 15:41:43 -07007451 VkBool32 skip = VK_FALSE;
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07007452
7453#ifdef DISABLE_IMAGE_LAYOUT_VALIDATION
7454 return skip;
7455#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
7456
Michael Lentineabc5e922015-10-12 11:30:14 -05007457 for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007458 const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
Michael Lentineabc5e922015-10-12 11:30:14 -05007459 for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007460 if (subpass.pInputAttachments[j].layout !=
7461 VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
7462 subpass.pInputAttachments[j].layout !=
7463 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
7464 if (subpass.pInputAttachments[j].layout ==
7465 VK_IMAGE_LAYOUT_GENERAL) {
7466 // TODO: Verify Valid Use in spec. I believe this is allowed
7467 // (valid) but may not be optimal performance
7468 skip |= log_msg(my_data->report_data,
7469 VK_DEBUG_REPORT_WARN_BIT_EXT,
7470 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7471 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
7472 "Layout for input attachment is GENERAL "
7473 "but should be READ_ONLY_OPTIMAL.");
Michael Lentineabc5e922015-10-12 11:30:14 -05007474 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007475 skip |= log_msg(my_data->report_data,
7476 VK_DEBUG_REPORT_ERROR_BIT_EXT,
7477 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7478 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
7479 "Layout for input attachment is %d but can "
7480 "only be READ_ONLY_OPTIMAL or GENERAL.",
7481 subpass.pInputAttachments[j].attachment);
Michael Lentineabc5e922015-10-12 11:30:14 -05007482 }
7483 }
7484 }
7485 for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007486 if (subpass.pColorAttachments[j].layout !=
7487 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
7488 if (subpass.pColorAttachments[j].layout ==
7489 VK_IMAGE_LAYOUT_GENERAL) {
7490 // TODO: Verify Valid Use in spec. I believe this is allowed
7491 // (valid) but may not be optimal performance
7492 skip |= log_msg(my_data->report_data,
7493 VK_DEBUG_REPORT_WARN_BIT_EXT,
7494 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7495 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
7496 "Layout for color attachment is GENERAL "
7497 "but should be COLOR_ATTACHMENT_OPTIMAL.");
Michael Lentineabc5e922015-10-12 11:30:14 -05007498 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007499 skip |= log_msg(
7500 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7501 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7502 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
7503 "Layout for color attachment is %d but can only be "
7504 "COLOR_ATTACHMENT_OPTIMAL or GENERAL.",
7505 subpass.pColorAttachments[j].attachment);
Michael Lentineabc5e922015-10-12 11:30:14 -05007506 }
7507 }
7508 }
Mark Lobodzinski0f30f9e2015-10-28 13:03:56 -06007509 if ((subpass.pDepthStencilAttachment != NULL) &&
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007510 (subpass.pDepthStencilAttachment->attachment !=
7511 VK_ATTACHMENT_UNUSED)) {
7512 if (subpass.pDepthStencilAttachment->layout !=
7513 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
7514 if (subpass.pDepthStencilAttachment->layout ==
7515 VK_IMAGE_LAYOUT_GENERAL) {
7516 // TODO: Verify Valid Use in spec. I believe this is allowed
7517 // (valid) but may not be optimal performance
7518 skip |= log_msg(
7519 my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT,
7520 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7521 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
7522 "Layout for depth attachment is GENERAL but should be "
7523 "DEPTH_STENCIL_ATTACHMENT_OPTIMAL.");
Michael Lentineabc5e922015-10-12 11:30:14 -05007524 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007525 skip |= log_msg(
7526 my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7527 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7528 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
7529 "Layout for depth attachment is %d but can only be "
7530 "DEPTH_STENCIL_ATTACHMENT_OPTIMAL or GENERAL.",
7531 subpass.pDepthStencilAttachment->attachment);
Michael Lentineabc5e922015-10-12 11:30:14 -05007532 }
7533 }
7534 }
7535 }
7536 return skip;
7537}
7538
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007539VkBool32 CreatePassDAG(const layer_data *my_data, VkDevice device,
7540 const VkRenderPassCreateInfo *pCreateInfo,
7541 std::vector<DAGNode> &subpass_to_node,
7542 std::vector<bool> &has_self_dependency) {
Mark Youngb20a6a82016-01-07 15:41:43 -07007543 VkBool32 skip_call = VK_FALSE;
Michael Lentineabc5e922015-10-12 11:30:14 -05007544 for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007545 DAGNode &subpass_node = subpass_to_node[i];
Michael Lentineabc5e922015-10-12 11:30:14 -05007546 subpass_node.pass = i;
7547 }
7548 for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007549 const VkSubpassDependency &dependency = pCreateInfo->pDependencies[i];
7550 if (dependency.srcSubpass > dependency.dstSubpass &&
7551 dependency.srcSubpass != VK_SUBPASS_EXTERNAL &&
7552 dependency.dstSubpass != VK_SUBPASS_EXTERNAL) {
7553 skip_call |=
7554 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7555 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7556 DRAWSTATE_INVALID_RENDERPASS, "DS",
7557 "Depedency graph must be specified such that an "
7558 "earlier pass cannot depend on a later pass.");
7559 } else if (dependency.srcSubpass == VK_SUBPASS_EXTERNAL &&
7560 dependency.dstSubpass == VK_SUBPASS_EXTERNAL) {
7561 skip_call |=
7562 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7563 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7564 DRAWSTATE_INVALID_RENDERPASS, "DS",
7565 "The src and dest subpasses cannot both be external.");
Michael Lentine48930b82015-10-15 17:07:00 -05007566 } else if (dependency.srcSubpass == dependency.dstSubpass) {
7567 has_self_dependency[dependency.srcSubpass] = true;
Michael Lentineabc5e922015-10-12 11:30:14 -05007568 }
Michael Lentine6bd4f122016-01-19 14:00:53 -06007569 if (dependency.dstSubpass != VK_SUBPASS_EXTERNAL) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007570 subpass_to_node[dependency.dstSubpass].prev.push_back(
7571 dependency.srcSubpass);
Michael Lentine6bd4f122016-01-19 14:00:53 -06007572 }
7573 if (dependency.srcSubpass != VK_SUBPASS_EXTERNAL) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007574 subpass_to_node[dependency.srcSubpass].next.push_back(
7575 dependency.dstSubpass);
Michael Lentine6bd4f122016-01-19 14:00:53 -06007576 }
Michael Lentineabc5e922015-10-12 11:30:14 -05007577 }
7578 return skip_call;
7579}
Tobin Ehlis8fab6562015-12-01 09:57:09 -07007580// TODOSC : Add intercept of vkCreateShaderModule
Michael Lentineabc5e922015-10-12 11:30:14 -05007581
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007582VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
7583 vkCreateShaderModule(VkDevice device,
7584 const VkShaderModuleCreateInfo *pCreateInfo,
7585 const VkAllocationCallbacks *pAllocator,
7586 VkShaderModule *pShaderModule) {
7587 layer_data *my_data =
7588 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Mark Youngb20a6a82016-01-07 15:41:43 -07007589 VkBool32 skip_call = VK_FALSE;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07007590 if (!shader_is_spirv(pCreateInfo)) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007591 skip_call |=
7592 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7593 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
7594 /* dev */ 0, __LINE__, SHADER_CHECKER_NON_SPIRV_SHADER,
7595 "SC", "Shader is not SPIR-V");
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07007596 }
7597
Mark Youngb20a6a82016-01-07 15:41:43 -07007598 if (VK_FALSE != skip_call)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07007599 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07007600
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007601 VkResult res = my_data->device_dispatch_table->CreateShaderModule(
7602 device, pCreateInfo, pAllocator, pShaderModule);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07007603
7604 if (res == VK_SUCCESS) {
7605 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007606 my_data->shaderModuleMap[*pShaderModule] =
7607 new shader_module(pCreateInfo);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07007608 loader_platform_thread_unlock_mutex(&globalLock);
7609 }
7610 return res;
7611}
7612
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007613VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
7614 vkCreateRenderPass(VkDevice device,
7615 const VkRenderPassCreateInfo *pCreateInfo,
7616 const VkAllocationCallbacks *pAllocator,
7617 VkRenderPass *pRenderPass) {
Mark Youngb20a6a82016-01-07 15:41:43 -07007618 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007619 layer_data *dev_data =
7620 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Michael Lentineabc5e922015-10-12 11:30:14 -05007621 // Create DAG
Michael Lentine48930b82015-10-15 17:07:00 -05007622 std::vector<bool> has_self_dependency(pCreateInfo->subpassCount);
Michael Lentineabc5e922015-10-12 11:30:14 -05007623 std::vector<DAGNode> subpass_to_node(pCreateInfo->subpassCount);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007624 skip_call |= CreatePassDAG(dev_data, device, pCreateInfo, subpass_to_node,
7625 has_self_dependency);
Michael Lentineabc5e922015-10-12 11:30:14 -05007626 // Validate using DAG
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007627 skip_call |=
7628 ValidateDependencies(dev_data, device, pCreateInfo, subpass_to_node);
Michael Lentineabc5e922015-10-12 11:30:14 -05007629 skip_call |= ValidateLayouts(dev_data, device, pCreateInfo);
Mark Youngb20a6a82016-01-07 15:41:43 -07007630 if (VK_FALSE != skip_call) {
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07007631 return VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentineb6986752015-10-06 14:56:18 -07007632 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007633 VkResult result = dev_data->device_dispatch_table->CreateRenderPass(
7634 device, pCreateInfo, pAllocator, pRenderPass);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06007635 if (VK_SUCCESS == result) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07007636 // TODOSC : Merge in tracking of renderpass from ShaderChecker
Tobin Ehliseba312c2015-04-01 08:40:34 -06007637 // Shadow create info and store in map
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007638 VkRenderPassCreateInfo *localRPCI =
7639 new VkRenderPassCreateInfo(*pCreateInfo);
Chia-I Wu08accc62015-07-07 11:50:03 +08007640 if (pCreateInfo->pAttachments) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007641 localRPCI->pAttachments =
7642 new VkAttachmentDescription[localRPCI->attachmentCount];
7643 memcpy((void *)localRPCI->pAttachments, pCreateInfo->pAttachments,
7644 localRPCI->attachmentCount *
7645 sizeof(VkAttachmentDescription));
Tobin Ehliseba312c2015-04-01 08:40:34 -06007646 }
Chia-I Wu08accc62015-07-07 11:50:03 +08007647 if (pCreateInfo->pSubpasses) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007648 localRPCI->pSubpasses =
7649 new VkSubpassDescription[localRPCI->subpassCount];
7650 memcpy((void *)localRPCI->pSubpasses, pCreateInfo->pSubpasses,
7651 localRPCI->subpassCount * sizeof(VkSubpassDescription));
Chia-I Wu08accc62015-07-07 11:50:03 +08007652
7653 for (uint32_t i = 0; i < localRPCI->subpassCount; i++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007654 VkSubpassDescription *subpass =
7655 (VkSubpassDescription *)&localRPCI->pSubpasses[i];
7656 const uint32_t attachmentCount =
7657 subpass->inputAttachmentCount +
7658 subpass->colorAttachmentCount *
7659 (1 + (subpass->pResolveAttachments ? 1 : 0)) +
7660 ((subpass->pDepthStencilAttachment) ? 1 : 0) +
7661 subpass->preserveAttachmentCount;
7662 VkAttachmentReference *attachments =
7663 new VkAttachmentReference[attachmentCount];
Chia-I Wu08accc62015-07-07 11:50:03 +08007664
Cody Northropa505dda2015-08-04 11:16:41 -06007665 memcpy(attachments, subpass->pInputAttachments,
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007666 sizeof(attachments[0]) * subpass->inputAttachmentCount);
Cody Northropa505dda2015-08-04 11:16:41 -06007667 subpass->pInputAttachments = attachments;
Chia-I Wud50a7d72015-10-26 20:48:51 +08007668 attachments += subpass->inputAttachmentCount;
Chia-I Wu08accc62015-07-07 11:50:03 +08007669
Cody Northropa505dda2015-08-04 11:16:41 -06007670 memcpy(attachments, subpass->pColorAttachments,
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007671 sizeof(attachments[0]) * subpass->colorAttachmentCount);
Cody Northropa505dda2015-08-04 11:16:41 -06007672 subpass->pColorAttachments = attachments;
Chia-I Wud50a7d72015-10-26 20:48:51 +08007673 attachments += subpass->colorAttachmentCount;
Chia-I Wu08accc62015-07-07 11:50:03 +08007674
Cody Northropa505dda2015-08-04 11:16:41 -06007675 if (subpass->pResolveAttachments) {
7676 memcpy(attachments, subpass->pResolveAttachments,
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007677 sizeof(attachments[0]) *
7678 subpass->colorAttachmentCount);
Cody Northropa505dda2015-08-04 11:16:41 -06007679 subpass->pResolveAttachments = attachments;
Chia-I Wud50a7d72015-10-26 20:48:51 +08007680 attachments += subpass->colorAttachmentCount;
Chia-I Wu08accc62015-07-07 11:50:03 +08007681 }
7682
Chia-I Wu1efb7e52015-10-26 17:32:47 +08007683 if (subpass->pDepthStencilAttachment) {
7684 memcpy(attachments, subpass->pDepthStencilAttachment,
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007685 sizeof(attachments[0]) * 1);
Chia-I Wu1efb7e52015-10-26 17:32:47 +08007686 subpass->pDepthStencilAttachment = attachments;
7687 attachments += 1;
7688 }
7689
Cody Northropa505dda2015-08-04 11:16:41 -06007690 memcpy(attachments, subpass->pPreserveAttachments,
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007691 sizeof(attachments[0]) *
7692 subpass->preserveAttachmentCount);
Jon Ashburnf19916e2016-01-11 13:12:43 -07007693 subpass->pPreserveAttachments = &attachments->attachment;
Chia-I Wu08accc62015-07-07 11:50:03 +08007694 }
Tobin Ehliseba312c2015-04-01 08:40:34 -06007695 }
Chia-I Wu08accc62015-07-07 11:50:03 +08007696 if (pCreateInfo->pDependencies) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007697 localRPCI->pDependencies =
7698 new VkSubpassDependency[localRPCI->dependencyCount];
7699 memcpy((void *)localRPCI->pDependencies, pCreateInfo->pDependencies,
7700 localRPCI->dependencyCount * sizeof(VkSubpassDependency));
Tobin Ehliseba312c2015-04-01 08:40:34 -06007701 }
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07007702 loader_platform_thread_lock_mutex(&globalLock);
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07007703 dev_data->renderPassMap[*pRenderPass] = new RENDER_PASS_NODE(localRPCI);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007704 dev_data->renderPassMap[*pRenderPass]->hasSelfDependency =
7705 has_self_dependency;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07007706 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehliseba312c2015-04-01 08:40:34 -06007707 }
7708 return result;
7709}
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06007710// Free the renderpass shadow
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007711static void deleteRenderPasses(layer_data *my_data) {
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06007712 if (my_data->renderPassMap.size() <= 0)
7713 return;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007714 for (auto ii = my_data->renderPassMap.begin();
7715 ii != my_data->renderPassMap.end(); ++ii) {
7716 const VkRenderPassCreateInfo *pRenderPassInfo =
7717 (*ii).second->pCreateInfo;
Michael Lentine48930b82015-10-15 17:07:00 -05007718 if (pRenderPassInfo->pAttachments) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007719 delete[] pRenderPassInfo -> pAttachments;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06007720 }
Michael Lentine48930b82015-10-15 17:07:00 -05007721 if (pRenderPassInfo->pSubpasses) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007722 for (uint32_t i = 0; i < pRenderPassInfo->subpassCount; ++i) {
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06007723 // Attachements are all allocated in a block, so just need to
7724 // find the first non-null one to delete
Michael Lentine48930b82015-10-15 17:07:00 -05007725 if (pRenderPassInfo->pSubpasses[i].pInputAttachments) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007726 delete[] pRenderPassInfo -> pSubpasses[i].pInputAttachments;
Michael Lentine48930b82015-10-15 17:07:00 -05007727 } else if (pRenderPassInfo->pSubpasses[i].pColorAttachments) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007728 delete[] pRenderPassInfo -> pSubpasses[i].pColorAttachments;
Michael Lentine48930b82015-10-15 17:07:00 -05007729 } else if (pRenderPassInfo->pSubpasses[i].pResolveAttachments) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007730 delete[] pRenderPassInfo -> pSubpasses[i]
7731 .pResolveAttachments;
7732 } else if (pRenderPassInfo->pSubpasses[i]
7733 .pPreserveAttachments) {
7734 delete[] pRenderPassInfo -> pSubpasses[i]
7735 .pPreserveAttachments;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06007736 }
7737 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007738 delete[] pRenderPassInfo -> pSubpasses;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06007739 }
Michael Lentine48930b82015-10-15 17:07:00 -05007740 if (pRenderPassInfo->pDependencies) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007741 delete[] pRenderPassInfo -> pDependencies;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06007742 }
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07007743 delete pRenderPassInfo;
Michael Lentine48930b82015-10-15 17:07:00 -05007744 delete (*ii).second;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06007745 }
7746 my_data->renderPassMap.clear();
7747}
Michael Lentineabc5e922015-10-12 11:30:14 -05007748
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007749VkBool32 VerifyFramebufferAndRenderPassLayouts(
7750 VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo *pRenderPassBegin) {
Mark Youngb20a6a82016-01-07 15:41:43 -07007751 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007752 layer_data *dev_data =
7753 get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
7754 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
7755 const VkRenderPassCreateInfo *pRenderPassInfo =
7756 dev_data->renderPassMap[pRenderPassBegin->renderPass]->pCreateInfo;
7757 const VkFramebufferCreateInfo *pFramebufferInfo =
7758 dev_data->frameBufferMap[pRenderPassBegin->framebuffer];
Michael Lentineabc5e922015-10-12 11:30:14 -05007759 if (pRenderPassInfo->attachmentCount != pFramebufferInfo->attachmentCount) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007760 skip_call |=
7761 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7762 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7763 DRAWSTATE_INVALID_RENDERPASS, "DS",
7764 "You cannot start a render pass using a framebuffer with a "
7765 "different number of attachments.");
Michael Lentineabc5e922015-10-12 11:30:14 -05007766 }
7767 for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007768 const VkImageView &image_view = pFramebufferInfo->pAttachments[i];
7769 const VkImage &image = dev_data->imageViewMap[image_view]->image;
Michael Lentineabc5e922015-10-12 11:30:14 -05007770 auto image_data = pCB->imageLayoutMap.find(image);
7771 if (image_data == pCB->imageLayoutMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007772 pCB->imageLayoutMap[image].initialLayout =
7773 pRenderPassInfo->pAttachments[i].initialLayout;
7774 pCB->imageLayoutMap[image].layout =
7775 pRenderPassInfo->pAttachments[i].initialLayout;
7776 } else if (pRenderPassInfo->pAttachments[i].initialLayout !=
7777 image_data->second.layout) {
7778 skip_call |= log_msg(
7779 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7780 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7781 DRAWSTATE_INVALID_RENDERPASS, "DS",
7782 "You cannot start a render pass using attachment %i where the "
7783 "intial layout differs from the starting layout.",
7784 i);
Michael Lentineabc5e922015-10-12 11:30:14 -05007785 }
7786 }
7787 return skip_call;
7788}
7789
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007790void TransitionSubpassLayouts(VkCommandBuffer cmdBuffer,
7791 const VkRenderPassBeginInfo *pRenderPassBegin,
7792 const int subpass_index) {
7793 layer_data *dev_data =
7794 get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
7795 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
7796 auto render_pass_data =
7797 dev_data->renderPassMap.find(pRenderPassBegin->renderPass);
Michael Lentineabc5e922015-10-12 11:30:14 -05007798 if (render_pass_data == dev_data->renderPassMap.end()) {
7799 return;
7800 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007801 const VkRenderPassCreateInfo *pRenderPassInfo =
7802 render_pass_data->second->pCreateInfo;
7803 auto framebuffer_data =
7804 dev_data->frameBufferMap.find(pRenderPassBegin->framebuffer);
Michael Lentineabc5e922015-10-12 11:30:14 -05007805 if (framebuffer_data == dev_data->frameBufferMap.end()) {
7806 return;
7807 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007808 const VkFramebufferCreateInfo *pFramebufferInfo = framebuffer_data->second;
7809 const VkSubpassDescription &subpass =
7810 pRenderPassInfo->pSubpasses[subpass_index];
Michael Lentineabc5e922015-10-12 11:30:14 -05007811 for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007812 const VkImageView &image_view =
7813 pFramebufferInfo
7814 ->pAttachments[subpass.pInputAttachments[j].attachment];
Michael Lentineabc5e922015-10-12 11:30:14 -05007815 auto image_view_data = dev_data->imageViewMap.find(image_view);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007816 if (image_view_data != dev_data->imageViewMap.end()) {
7817 auto image_layout =
7818 pCB->imageLayoutMap.find(image_view_data->second->image);
Michael Lentineabc5e922015-10-12 11:30:14 -05007819 if (image_layout != pCB->imageLayoutMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007820 image_layout->second.layout =
7821 subpass.pInputAttachments[j].layout;
Michael Lentineabc5e922015-10-12 11:30:14 -05007822 }
7823 }
7824 }
7825 for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007826 const VkImageView &image_view =
7827 pFramebufferInfo
7828 ->pAttachments[subpass.pColorAttachments[j].attachment];
Michael Lentineabc5e922015-10-12 11:30:14 -05007829 auto image_view_data = dev_data->imageViewMap.find(image_view);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007830 if (image_view_data != dev_data->imageViewMap.end()) {
7831 auto image_layout =
7832 pCB->imageLayoutMap.find(image_view_data->second->image);
Michael Lentineabc5e922015-10-12 11:30:14 -05007833 if (image_layout != pCB->imageLayoutMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007834 image_layout->second.layout =
7835 subpass.pColorAttachments[j].layout;
Michael Lentineabc5e922015-10-12 11:30:14 -05007836 }
7837 }
7838 }
Michael Lentine3dea6512015-10-28 15:55:18 -07007839 if ((subpass.pDepthStencilAttachment != NULL) &&
Mark Lobodzinski0f30f9e2015-10-28 13:03:56 -06007840 (subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007841 const VkImageView &image_view =
7842 pFramebufferInfo
7843 ->pAttachments[subpass.pDepthStencilAttachment->attachment];
Michael Lentineabc5e922015-10-12 11:30:14 -05007844 auto image_view_data = dev_data->imageViewMap.find(image_view);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007845 if (image_view_data != dev_data->imageViewMap.end()) {
7846 auto image_layout =
7847 pCB->imageLayoutMap.find(image_view_data->second->image);
Michael Lentineabc5e922015-10-12 11:30:14 -05007848 if (image_layout != pCB->imageLayoutMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007849 image_layout->second.layout =
7850 subpass.pDepthStencilAttachment->layout;
Michael Lentineabc5e922015-10-12 11:30:14 -05007851 }
7852 }
7853 }
7854}
7855
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007856VkBool32 validatePrimaryCommandBuffer(const layer_data *my_data,
7857 const GLOBAL_CB_NODE *pCB,
7858 const std::string &cmd_name) {
Mark Youngb20a6a82016-01-07 15:41:43 -07007859 VkBool32 skip_call = VK_FALSE;
Michael Lentine3dea6512015-10-28 15:55:18 -07007860 if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007861 skip_call |=
7862 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7863 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7864 DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
7865 "Cannot execute command %s on a secondary command buffer.",
7866 cmd_name.c_str());
Michael Lentine3dea6512015-10-28 15:55:18 -07007867 }
7868 return skip_call;
7869}
7870
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007871void
7872TransitionFinalSubpassLayouts(VkCommandBuffer cmdBuffer,
7873 const VkRenderPassBeginInfo *pRenderPassBegin) {
7874 layer_data *dev_data =
7875 get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
7876 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
7877 auto render_pass_data =
7878 dev_data->renderPassMap.find(pRenderPassBegin->renderPass);
Michael Lentineabc5e922015-10-12 11:30:14 -05007879 if (render_pass_data == dev_data->renderPassMap.end()) {
7880 return;
7881 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007882 const VkRenderPassCreateInfo *pRenderPassInfo =
7883 render_pass_data->second->pCreateInfo;
7884 auto framebuffer_data =
7885 dev_data->frameBufferMap.find(pRenderPassBegin->framebuffer);
Michael Lentineabc5e922015-10-12 11:30:14 -05007886 if (framebuffer_data == dev_data->frameBufferMap.end()) {
7887 return;
7888 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007889 const VkFramebufferCreateInfo *pFramebufferInfo = framebuffer_data->second;
Michael Lentineabc5e922015-10-12 11:30:14 -05007890 for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007891 const VkImageView &image_view = pFramebufferInfo->pAttachments[i];
Michael Lentineabc5e922015-10-12 11:30:14 -05007892 auto image_view_data = dev_data->imageViewMap.find(image_view);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007893 if (image_view_data != dev_data->imageViewMap.end()) {
7894 auto image_layout =
7895 pCB->imageLayoutMap.find(image_view_data->second->image);
Michael Lentineabc5e922015-10-12 11:30:14 -05007896 if (image_layout != pCB->imageLayoutMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007897 image_layout->second.layout =
7898 pRenderPassInfo->pAttachments[i].finalLayout;
Michael Lentineabc5e922015-10-12 11:30:14 -05007899 }
7900 }
7901 }
7902}
7903
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007904VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
7905 vkCmdBeginRenderPass(VkCommandBuffer commandBuffer,
7906 const VkRenderPassBeginInfo *pRenderPassBegin,
7907 VkSubpassContents contents) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007908 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007909 layer_data *dev_data =
7910 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7911 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007912 if (pCB) {
Tobin Ehlis259730a2015-06-23 16:13:03 -06007913 if (pRenderPassBegin && pRenderPassBegin->renderPass) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007914 skipCall |= VerifyFramebufferAndRenderPassLayouts(commandBuffer,
7915 pRenderPassBegin);
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06007916 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdBeginRenderPass");
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007917 skipCall |= validatePrimaryCommandBuffer(dev_data, pCB,
7918 "vkCmdBeginRenderPass");
7919 skipCall |= addCmd(dev_data, pCB, CMD_BEGINRENDERPASS,
7920 "vkCmdBeginRenderPass()");
Mark Lobodzinski5495d132015-09-30 16:19:16 -06007921 pCB->activeRenderPass = pRenderPassBegin->renderPass;
Michael Lentineabc5e922015-10-12 11:30:14 -05007922 // This is a shallow copy as that is all that is needed for now
7923 pCB->activeRenderPassBeginInfo = *pRenderPassBegin;
Mark Lobodzinski5495d132015-09-30 16:19:16 -06007924 pCB->activeSubpass = 0;
Michael Lentine2e068b22015-12-29 16:05:27 -06007925 pCB->activeSubpassContents = contents;
Mark Lobodzinski5495d132015-09-30 16:19:16 -06007926 pCB->framebuffer = pRenderPassBegin->framebuffer;
Tobin Ehlis502480b2015-06-24 15:53:07 -06007927 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007928 skipCall |=
7929 log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7930 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
7931 DRAWSTATE_INVALID_RENDERPASS, "DS",
7932 "You cannot use a NULL RenderPass object in "
7933 "vkCmdBeginRenderPass()");
Tony Barbourbadda992015-04-06 11:09:26 -06007934 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007935 }
Mark Lobodzinski0f30f9e2015-10-28 13:03:56 -06007936 if (VK_FALSE == skipCall) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007937 dev_data->device_dispatch_table->CmdBeginRenderPass(
7938 commandBuffer, pRenderPassBegin, contents);
Mark Lobodzinski0f30f9e2015-10-28 13:03:56 -06007939 // This is a shallow copy as that is all that is needed for now
7940 dev_data->renderPassBeginInfo = *pRenderPassBegin;
7941 dev_data->currentSubpass = 0;
7942 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007943}
7944
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007945VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
7946 vkCmdNextSubpass(VkCommandBuffer commandBuffer,
7947 VkSubpassContents contents) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007948 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007949 layer_data *dev_data =
7950 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7951 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
7952 TransitionSubpassLayouts(commandBuffer, &dev_data->renderPassBeginInfo,
7953 ++dev_data->currentSubpass);
Chia-I Wu08accc62015-07-07 11:50:03 +08007954 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007955 skipCall |=
7956 validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdNextSubpass");
7957 skipCall |=
7958 addCmd(dev_data, pCB, CMD_NEXTSUBPASS, "vkCmdNextSubpass()");
Mark Lobodzinski5495d132015-09-30 16:19:16 -06007959 pCB->activeSubpass++;
Michael Lentine2e068b22015-12-29 16:05:27 -06007960 pCB->activeSubpassContents = contents;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007961 TransitionSubpassLayouts(commandBuffer, &pCB->activeRenderPassBeginInfo,
7962 pCB->activeSubpass);
Mark Lobodzinski5495d132015-09-30 16:19:16 -06007963 if (pCB->lastBoundPipeline) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007964 skipCall |= validatePipelineState(dev_data, pCB,
7965 VK_PIPELINE_BIND_POINT_GRAPHICS,
7966 pCB->lastBoundPipeline);
Chia-I Wu08accc62015-07-07 11:50:03 +08007967 }
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06007968 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdNextSubpass");
Chia-I Wu08accc62015-07-07 11:50:03 +08007969 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007970 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007971 dev_data->device_dispatch_table->CmdNextSubpass(commandBuffer,
7972 contents);
Chia-I Wu08accc62015-07-07 11:50:03 +08007973}
7974
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007975VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
7976 vkCmdEndRenderPass(VkCommandBuffer commandBuffer) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007977 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007978 layer_data *dev_data =
7979 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
7980 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
7981 TransitionFinalSubpassLayouts(commandBuffer,
7982 &dev_data->renderPassBeginInfo);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06007983 if (pCB) {
Michael Lentine3dea6512015-10-28 15:55:18 -07007984 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass");
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007985 skipCall |=
7986 validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass");
7987 skipCall |=
7988 addCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()");
7989 TransitionFinalSubpassLayouts(commandBuffer,
7990 &pCB->activeRenderPassBeginInfo);
Mark Lobodzinski5495d132015-09-30 16:19:16 -06007991 pCB->activeRenderPass = 0;
7992 pCB->activeSubpass = 0;
Chia-I Wu0b50a1c2015-06-26 15:34:39 +08007993 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06007994 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08007995 dev_data->device_dispatch_table->CmdEndRenderPass(commandBuffer);
Chia-I Wu0b50a1c2015-06-26 15:34:39 +08007996}
7997
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07007998VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
7999 vkCmdExecuteCommands(VkCommandBuffer commandBuffer,
8000 uint32_t commandBuffersCount,
8001 const VkCommandBuffer *pCommandBuffers) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06008002 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008003 layer_data *dev_data =
8004 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8005 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Chia-I Wu0b50a1c2015-06-26 15:34:39 +08008006 if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008007 GLOBAL_CB_NODE *pSubCB = NULL;
8008 for (uint32_t i = 0; i < commandBuffersCount; i++) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08008009 pSubCB = getCBNode(dev_data, pCommandBuffers[i]);
Tobin Ehlis4b34ddc2015-09-17 14:18:16 -06008010 if (!pSubCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008011 skipCall |= log_msg(
8012 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
8013 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
8014 DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
8015 "vkCmdExecuteCommands() called w/ invalid Cmd Buffer %p in "
8016 "element %u of pCommandBuffers array.",
8017 (void *)pCommandBuffers[i], i);
8018 } else if (VK_COMMAND_BUFFER_LEVEL_PRIMARY ==
8019 pSubCB->createInfo.level) {
8020 skipCall |= log_msg(
8021 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
8022 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
8023 DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
8024 "vkCmdExecuteCommands() called w/ Primary Cmd Buffer %p in "
8025 "element %u of pCommandBuffers array. All cmd buffers in "
8026 "pCommandBuffers array must be secondary.",
8027 (void *)pCommandBuffers[i], i);
8028 } else if (pCB->activeRenderPass) { // Secondary CB w/i RenderPass
8029 // must have *CONTINUE_BIT set
8030 if (!(pSubCB->beginInfo.flags &
8031 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
8032 skipCall |= log_msg(
8033 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
8034 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8035 (uint64_t)pCommandBuffers[i], __LINE__,
8036 DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
8037 "vkCmdExecuteCommands(): Secondary Command Buffer (%p) "
8038 "executed within render pass (%#" PRIxLEAST64
8039 ") must have had vkBeginCommandBuffer() called w/ "
8040 "VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT set.",
8041 (void *)pCommandBuffers[i],
8042 (uint64_t)pCB->activeRenderPass);
Tobin Ehlis651d9b02015-12-16 05:01:22 -07008043 }
8044 string errorString = "";
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008045 if (!verify_renderpass_compatibility(
8046 dev_data, pCB->activeRenderPass,
8047 pSubCB->beginInfo.pInheritanceInfo->renderPass,
8048 errorString)) {
8049 skipCall |= log_msg(
8050 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
8051 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8052 (uint64_t)pCommandBuffers[i], __LINE__,
8053 DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
8054 "vkCmdExecuteCommands(): Secondary Command Buffer (%p) "
8055 "w/ render pass (%#" PRIxLEAST64
8056 ") is incompatible w/ primary command buffer (%p) w/ "
8057 "render pass (%#" PRIxLEAST64 ") due to: %s",
8058 (void *)pCommandBuffers[i],
8059 (uint64_t)
8060 pSubCB->beginInfo.pInheritanceInfo->renderPass,
8061 (void *)commandBuffer, (uint64_t)pCB->activeRenderPass,
8062 errorString.c_str());
Tobin Ehlis651d9b02015-12-16 05:01:22 -07008063 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008064 // If framebuffer for secondary CB is not NULL, then it must
8065 // match FB from vkCmdBeginRenderPass()
8066 // that this CB will be executed in AND framebuffer must have
8067 // been created w/ RP compatible w/ renderpass
Jon Ashburnf19916e2016-01-11 13:12:43 -07008068 if (pSubCB->beginInfo.pInheritanceInfo->framebuffer) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008069 if (pSubCB->beginInfo.pInheritanceInfo->framebuffer !=
8070 pCB->activeRenderPassBeginInfo.framebuffer) {
8071 skipCall |= log_msg(
8072 dev_data->report_data,
8073 VK_DEBUG_REPORT_ERROR_BIT_EXT,
8074 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8075 (uint64_t)pCommandBuffers[i], __LINE__,
8076 DRAWSTATE_FRAMEBUFFER_INCOMPATIBLE, "DS",
8077 "vkCmdExecuteCommands(): Secondary Command Buffer "
8078 "(%p) references framebuffer (%#" PRIxLEAST64
8079 ") that does not match framebuffer (%#" PRIxLEAST64
8080 ") in active renderpass (%#" PRIxLEAST64 ").",
8081 (void *)pCommandBuffers[i],
8082 (uint64_t)
8083 pSubCB->beginInfo.pInheritanceInfo->framebuffer,
8084 (uint64_t)
8085 pCB->activeRenderPassBeginInfo.framebuffer,
8086 (uint64_t)pCB->activeRenderPass);
Tobin Ehlis651d9b02015-12-16 05:01:22 -07008087 }
8088 }
Tobin Ehlis4b34ddc2015-09-17 14:18:16 -06008089 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008090 // Secondary cmdBuffers are considered pending execution starting w/
8091 // being recorded
8092 if (!(pSubCB->beginInfo.flags &
8093 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
8094 if (dev_data->globalInFlightCmdBuffers.find(
8095 pSubCB->commandBuffer) !=
8096 dev_data->globalInFlightCmdBuffers.end()) {
8097 skipCall |= log_msg(
8098 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
8099 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8100 (uint64_t)(pCB->commandBuffer), __LINE__,
8101 DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS",
8102 "Attempt to simultaneously execute CB %#" PRIxLEAST64
8103 " w/o VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT "
8104 "set!",
8105 (uint64_t)(pCB->commandBuffer));
Tobin Ehlisf4aafc02016-01-15 13:34:44 -07008106 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008107 if (pCB->beginInfo.flags &
8108 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) {
8109 // Warn that non-simultaneous secondary cmd buffer renders
8110 // primary non-simultaneous
8111 skipCall |= log_msg(
8112 dev_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT,
8113 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8114 (uint64_t)(pCommandBuffers[i]), __LINE__,
8115 DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS",
8116 "vkCmdExecuteCommands(): Secondary Command Buffer "
8117 "(%#" PRIxLEAST64
8118 ") does not have "
8119 "VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set and "
8120 "will cause primary command buffer (%#" PRIxLEAST64
8121 ") to be treated as if it does not have "
8122 "VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set, "
8123 "even though it does.",
8124 (uint64_t)(pCommandBuffers[i]),
8125 (uint64_t)(pCB->commandBuffer));
8126 pCB->beginInfo.flags &=
8127 ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
Tobin Ehlisf4aafc02016-01-15 13:34:44 -07008128 }
8129 }
8130 pCB->secondaryCommandBuffers.insert(pSubCB->commandBuffer);
Tobin Ehlis74714d22016-01-25 15:24:34 -08008131 dev_data->globalInFlightCmdBuffers.insert(pSubCB->commandBuffer);
Tobin Ehlis4b34ddc2015-09-17 14:18:16 -06008132 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008133 skipCall |=
8134 validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdExecuteComands");
8135 skipCall |=
8136 addCmd(dev_data, pCB, CMD_EXECUTECOMMANDS, "vkCmdExecuteComands()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06008137 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06008138 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008139 dev_data->device_dispatch_table->CmdExecuteCommands(
8140 commandBuffer, commandBuffersCount, pCommandBuffers);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06008141}
8142
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07008143VkBool32 ValidateMapImageLayouts(VkDevice device, VkDeviceMemory mem) {
Mark Youngb20a6a82016-01-07 15:41:43 -07008144 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008145 layer_data *dev_data =
8146 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Michael Lentine7b236262015-10-23 12:41:44 -07008147 auto mem_data = dev_data->memImageMap.find(mem);
8148 if (mem_data != dev_data->memImageMap.end()) {
8149 auto image_data = dev_data->imageLayoutMap.find(mem_data->second);
8150 if (image_data != dev_data->imageLayoutMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008151 if (image_data->second->layout != VK_IMAGE_LAYOUT_PREINITIALIZED &&
8152 image_data->second->layout != VK_IMAGE_LAYOUT_GENERAL) {
8153 skip_call |= log_msg(dev_data->report_data,
8154 VK_DEBUG_REPORT_ERROR_BIT_EXT,
8155 (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
8156 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
8157 "Cannot map an image with layout %d. Only "
8158 "GENERAL or PREINITIALIZED are supported.",
8159 image_data->second->layout);
Michael Lentine7b236262015-10-23 12:41:44 -07008160 }
8161 }
8162 }
8163 return skip_call;
8164}
8165
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008166VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
8167 vkMapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset,
8168 VkDeviceSize size, VkFlags flags, void **ppData) {
8169 layer_data *dev_data =
8170 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07008171
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07008172 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07008173#ifndef DISABLE_IMAGE_LAYOUT_VALIDATION
8174 skip_call = ValidateMapImageLayouts(device, mem);
8175#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
8176
Michael Lentine7b236262015-10-23 12:41:44 -07008177 if (VK_FALSE == skip_call) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008178 return dev_data->device_dispatch_table->MapMemory(device, mem, offset,
8179 size, flags, ppData);
Michael Lentine7b236262015-10-23 12:41:44 -07008180 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07008181 return VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentine7b236262015-10-23 12:41:44 -07008182}
8183
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008184VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory(VkDevice device, VkImage image,
8185 VkDeviceMemory mem,
8186 VkDeviceSize memOffset) {
8187 layer_data *dev_data =
8188 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
8189 VkResult result = dev_data->device_dispatch_table->BindImageMemory(
8190 device, image, mem, memOffset);
Michael Lentine7b236262015-10-23 12:41:44 -07008191 loader_platform_thread_lock_mutex(&globalLock);
8192 dev_data->memImageMap[mem] = image;
8193 loader_platform_thread_unlock_mutex(&globalLock);
8194 return result;
8195}
8196
Michael Lentineb887b0a2015-12-29 14:12:11 -06008197VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent(VkDevice device, VkEvent event) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008198 layer_data *dev_data =
8199 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Michael Lentineb887b0a2015-12-29 14:12:11 -06008200 dev_data->eventMap[event].needsSignaled = false;
8201 VkResult result = dev_data->device_dispatch_table->SetEvent(device, event);
8202 return result;
8203}
8204
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008205VKAPI_ATTR VkResult VKAPI_CALL
8206 vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount,
8207 const VkBindSparseInfo *pBindInfo, VkFence fence) {
8208 layer_data *dev_data =
8209 get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Mark Youngb20a6a82016-01-07 15:41:43 -07008210 VkBool32 skip_call = VK_FALSE;
Michael Lentine15a47882016-01-06 10:05:48 -06008211
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008212 for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) {
8213 const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx];
8214 for (uint32_t i = 0; i < bindInfo.waitSemaphoreCount; ++i) {
Michael Lentine15a47882016-01-06 10:05:48 -06008215 if (dev_data->semaphoreSignaledMap[bindInfo.pWaitSemaphores[i]]) {
8216 dev_data->semaphoreSignaledMap[bindInfo.pWaitSemaphores[i]] = 0;
8217 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008218 skip_call |= log_msg(
8219 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
8220 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
8221 DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
8222 "Queue %#" PRIx64 " is waiting on semaphore %#" PRIx64
8223 " that has no way to be signaled.",
8224 (uint64_t)(queue), (uint64_t)(bindInfo.pWaitSemaphores[i]));
Michael Lentine15a47882016-01-06 10:05:48 -06008225 }
8226 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008227 for (uint32_t i = 0; i < bindInfo.signalSemaphoreCount; ++i) {
Michael Lentine15a47882016-01-06 10:05:48 -06008228 dev_data->semaphoreSignaledMap[bindInfo.pSignalSemaphores[i]] = 1;
8229 }
8230 }
8231
Mark Youngb20a6a82016-01-07 15:41:43 -07008232 if (VK_FALSE == skip_call)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008233 return dev_data->device_dispatch_table->QueueBindSparse(
8234 queue, bindInfoCount, pBindInfo, fence);
Mark Youngb20a6a82016-01-07 15:41:43 -07008235 else
8236 return VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentine15a47882016-01-06 10:05:48 -06008237}
8238
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008239VKAPI_ATTR VkResult VKAPI_CALL
8240 vkCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo,
8241 const VkAllocationCallbacks *pAllocator,
8242 VkSemaphore *pSemaphore) {
8243 layer_data *dev_data =
8244 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
8245 VkResult result = dev_data->device_dispatch_table->CreateSemaphore(
8246 device, pCreateInfo, pAllocator, pSemaphore);
Michael Lentine15a47882016-01-06 10:05:48 -06008247 if (result == VK_SUCCESS) {
8248 dev_data->semaphoreSignaledMap[*pSemaphore] = 0;
8249 }
Tobin Ehlis51b78af2016-01-06 10:27:47 -07008250 return result;
Michael Lentine15a47882016-01-06 10:05:48 -06008251}
8252
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008253VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
8254 vkCreateSwapchainKHR(VkDevice device,
8255 const VkSwapchainCreateInfoKHR *pCreateInfo,
8256 const VkAllocationCallbacks *pAllocator,
8257 VkSwapchainKHR *pSwapchain) {
8258 layer_data *dev_data =
8259 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
8260 VkResult result = dev_data->device_dispatch_table->CreateSwapchainKHR(
8261 device, pCreateInfo, pAllocator, pSwapchain);
Michael Lentineabc5e922015-10-12 11:30:14 -05008262
8263 if (VK_SUCCESS == result) {
Tobin Ehlis75cd1c52016-01-21 10:21:04 -07008264 SWAPCHAIN_NODE *swapchain_data = new SWAPCHAIN_NODE(pCreateInfo);
Michael Lentineabc5e922015-10-12 11:30:14 -05008265 loader_platform_thread_lock_mutex(&globalLock);
8266 dev_data->device_extensions.swapchainMap[*pSwapchain] = swapchain_data;
8267 loader_platform_thread_unlock_mutex(&globalLock);
8268 }
8269
8270 return result;
8271}
8272
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008273VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
8274 vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain,
8275 const VkAllocationCallbacks *pAllocator) {
8276 layer_data *dev_data =
8277 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Michael Lentineabc5e922015-10-12 11:30:14 -05008278
8279 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008280 auto swapchain_data =
8281 dev_data->device_extensions.swapchainMap.find(swapchain);
Michael Lentineabc5e922015-10-12 11:30:14 -05008282 if (swapchain_data != dev_data->device_extensions.swapchainMap.end()) {
8283 if (swapchain_data->second->images.size() > 0) {
8284 for (auto swapchain_image : swapchain_data->second->images) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008285 auto image_item =
8286 dev_data->imageLayoutMap.find(swapchain_image);
Michael Lentineabc5e922015-10-12 11:30:14 -05008287 if (image_item != dev_data->imageLayoutMap.end())
8288 dev_data->imageLayoutMap.erase(image_item);
8289 }
8290 }
8291 delete swapchain_data->second;
8292 dev_data->device_extensions.swapchainMap.erase(swapchain);
8293 }
8294 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008295 return dev_data->device_dispatch_table->DestroySwapchainKHR(
8296 device, swapchain, pAllocator);
Michael Lentineabc5e922015-10-12 11:30:14 -05008297}
8298
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008299VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
8300 vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain,
8301 uint32_t *pCount, VkImage *pSwapchainImages) {
8302 layer_data *dev_data =
8303 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
8304 VkResult result = dev_data->device_dispatch_table->GetSwapchainImagesKHR(
8305 device, swapchain, pCount, pSwapchainImages);
Michael Lentineabc5e922015-10-12 11:30:14 -05008306
8307 if (result == VK_SUCCESS && pSwapchainImages != NULL) {
8308 // This should never happen and is checked by param checker.
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008309 if (!pCount)
8310 return result;
Michael Lentineabc5e922015-10-12 11:30:14 -05008311 for (uint32_t i = 0; i < *pCount; ++i) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008312 IMAGE_NODE *image_node = new IMAGE_NODE;
Michael Lentineabc5e922015-10-12 11:30:14 -05008313 image_node->layout = VK_IMAGE_LAYOUT_UNDEFINED;
8314 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008315 auto swapchain_node =
8316 dev_data->device_extensions.swapchainMap[swapchain];
Tobin Ehlis75cd1c52016-01-21 10:21:04 -07008317 image_node->format = swapchain_node->createInfo.imageFormat;
8318 swapchain_node->images.push_back(pSwapchainImages[i]);
Michael Lentineabc5e922015-10-12 11:30:14 -05008319 dev_data->imageLayoutMap[pSwapchainImages[i]] = image_node;
8320 loader_platform_thread_unlock_mutex(&globalLock);
8321 }
8322 }
8323 return result;
8324}
8325
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008326VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
8327 vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
8328 layer_data *dev_data =
8329 get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Mark Youngb20a6a82016-01-07 15:41:43 -07008330 VkBool32 skip_call = VK_FALSE;
Michael Lentineabc5e922015-10-12 11:30:14 -05008331
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07008332#ifndef DISABLE_IMAGE_LAYOUT_VALIDATION
Michael Lentineabc5e922015-10-12 11:30:14 -05008333 if (pPresentInfo) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008334 for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) {
8335 if (dev_data
8336 ->semaphoreSignaledMap[pPresentInfo->pWaitSemaphores[i]]) {
8337 dev_data
8338 ->semaphoreSignaledMap[pPresentInfo->pWaitSemaphores[i]] =
8339 0;
Michael Lentine15a47882016-01-06 10:05:48 -06008340 } else {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008341 skipCall |= log_msg(
8342 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
8343 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__,
8344 DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
8345 "Queue %#" PRIx64 " is waiting on semaphore %#" PRIx64
8346 " that has no way to be signaled.",
8347 (uint64_t)(queue),
8348 (uint64_t)(pPresentInfo->pWaitSemaphores[i]));
Michael Lentine15a47882016-01-06 10:05:48 -06008349 }
8350 }
Michael Lentineabc5e922015-10-12 11:30:14 -05008351 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008352 auto swapchain_data = dev_data->device_extensions.swapchainMap.find(
8353 pPresentInfo->pSwapchains[i]);
8354 if (swapchain_data !=
8355 dev_data->device_extensions.swapchainMap.end() &&
8356 pPresentInfo->pImageIndices[i] <
8357 swapchain_data->second->images.size()) {
8358 VkImage image = swapchain_data->second
8359 ->images[pPresentInfo->pImageIndices[i]];
Michael Lentineabc5e922015-10-12 11:30:14 -05008360 auto image_data = dev_data->imageLayoutMap.find(image);
8361 if (image_data != dev_data->imageLayoutMap.end()) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008362 if (image_data->second->layout !=
8363 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
8364 skip_call |=
8365 log_msg(dev_data->report_data,
8366 VK_DEBUG_REPORT_ERROR_BIT_EXT,
8367 VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT,
8368 (uint64_t)queue, __LINE__,
8369 DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
8370 "Images passed to present must be in "
8371 "layout PRESENT_SOURCE_KHR but is in %d",
8372 image_data->second->layout);
Michael Lentineabc5e922015-10-12 11:30:14 -05008373 }
8374 }
8375 }
8376 }
8377 }
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07008378#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
Michael Lentineabc5e922015-10-12 11:30:14 -05008379
8380 if (VK_FALSE == skip_call)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008381 return dev_data->device_dispatch_table->QueuePresentKHR(queue,
8382 pPresentInfo);
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07008383 return VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentineabc5e922015-10-12 11:30:14 -05008384}
8385
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008386VKAPI_ATTR VkResult VKAPI_CALL
8387 vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain,
8388 uint64_t timeout, VkSemaphore semaphore,
8389 VkFence fence, uint32_t *pImageIndex) {
8390 layer_data *dev_data =
8391 get_my_data_ptr(get_dispatch_key(device), layer_data_map);
8392 VkResult result = dev_data->device_dispatch_table->AcquireNextImageKHR(
8393 device, swapchain, timeout, semaphore, fence, pImageIndex);
Michael Lentine15a47882016-01-06 10:05:48 -06008394 dev_data->semaphoreSignaledMap[semaphore] = 1;
Tobin Ehlis51b78af2016-01-06 10:27:47 -07008395 return result;
Michael Lentine15a47882016-01-06 10:05:48 -06008396}
8397
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07008398VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008399 VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
8400 const VkAllocationCallbacks *pAllocator,
8401 VkDebugReportCallbackEXT *pMsgCallback) {
8402 layer_data *my_data =
8403 get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07008404 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008405 VkResult res = pTable->CreateDebugReportCallbackEXT(
8406 instance, pCreateInfo, pAllocator, pMsgCallback);
Tobin Ehlisc16c3e92015-06-16 09:04:30 -06008407 if (VK_SUCCESS == res) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008408 res = layer_create_msg_callback(my_data->report_data, pCreateInfo,
8409 pAllocator, pMsgCallback);
Tobin Ehlisc16c3e92015-06-16 09:04:30 -06008410 }
8411 return res;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06008412}
8413
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008414VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
8415 vkDestroyDebugReportCallbackEXT(VkInstance instance,
8416 VkDebugReportCallbackEXT msgCallback,
8417 const VkAllocationCallbacks *pAllocator) {
8418 layer_data *my_data =
8419 get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07008420 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07008421 pTable->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07008422 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06008423}
8424
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008425VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
8426 vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
8427 VkDebugReportObjectTypeEXT objType, uint64_t object,
8428 size_t location, int32_t msgCode,
8429 const char *pLayerPrefix, const char *pMsg) {
8430 layer_data *my_data =
8431 get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
8432 my_data->instance_dispatch_table->DebugReportMessageEXT(
8433 instance, flags, objType, object, location, msgCode, pLayerPrefix,
8434 pMsg);
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07008435}
8436
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008437VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
8438 vkCmdDbgMarkerBegin(VkCommandBuffer commandBuffer, const char *pMarker) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06008439 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008440 layer_data *dev_data =
8441 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8442 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis0b632332015-10-07 09:38:40 -06008443 if (!dev_data->device_extensions.debug_marker_enabled) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008444 skipCall |= log_msg(
8445 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
8446 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8447 (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_EXTENSION,
8448 "DS", "Attempt to use CmdDbgMarkerBegin but extension disabled!");
Jon Ashburneab34492015-06-01 09:37:38 -06008449 return;
Tobin Ehlisce132d82015-06-19 15:07:05 -06008450 } else if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008451 skipCall |=
8452 addCmd(dev_data, pCB, CMD_DBGMARKERBEGIN, "vkCmdDbgMarkerBegin()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06008453 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06008454 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008455 debug_marker_dispatch_table(commandBuffer)
8456 ->CmdDbgMarkerBegin(commandBuffer, pMarker);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06008457}
8458
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008459VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
8460 vkCmdDbgMarkerEnd(VkCommandBuffer commandBuffer) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06008461 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008462 layer_data *dev_data =
8463 get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
8464 GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis0b632332015-10-07 09:38:40 -06008465 if (!dev_data->device_extensions.debug_marker_enabled) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008466 skipCall |= log_msg(
8467 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
8468 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8469 (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_EXTENSION,
8470 "DS", "Attempt to use CmdDbgMarkerEnd but extension disabled!");
Jon Ashburneab34492015-06-01 09:37:38 -06008471 return;
Tobin Ehlisce132d82015-06-19 15:07:05 -06008472 } else if (pCB) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008473 skipCall |=
8474 addCmd(dev_data, pCB, CMD_DBGMARKEREND, "vkCmdDbgMarkerEnd()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06008475 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06008476 if (VK_FALSE == skipCall)
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008477 debug_marker_dispatch_table(commandBuffer)
8478 ->CmdDbgMarkerEnd(commandBuffer);
Jon Ashburneab34492015-06-01 09:37:38 -06008479}
8480
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008481VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
8482 vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07008483 if (!strcmp(funcName, "vkGetDeviceProcAddr"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008484 return (PFN_vkVoidFunction)vkGetDeviceProcAddr;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008485 if (!strcmp(funcName, "vkDestroyDevice"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008486 return (PFN_vkVoidFunction)vkDestroyDevice;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008487 if (!strcmp(funcName, "vkQueueSubmit"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008488 return (PFN_vkVoidFunction)vkQueueSubmit;
Michael Lentine700b0aa2015-10-30 17:57:32 -07008489 if (!strcmp(funcName, "vkWaitForFences"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008490 return (PFN_vkVoidFunction)vkWaitForFences;
Michael Lentine700b0aa2015-10-30 17:57:32 -07008491 if (!strcmp(funcName, "vkGetFenceStatus"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008492 return (PFN_vkVoidFunction)vkGetFenceStatus;
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07008493 if (!strcmp(funcName, "vkQueueWaitIdle"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008494 return (PFN_vkVoidFunction)vkQueueWaitIdle;
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07008495 if (!strcmp(funcName, "vkDeviceWaitIdle"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008496 return (PFN_vkVoidFunction)vkDeviceWaitIdle;
Michael Lentine700b0aa2015-10-30 17:57:32 -07008497 if (!strcmp(funcName, "vkGetDeviceQueue"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008498 return (PFN_vkVoidFunction)vkGetDeviceQueue;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008499 if (!strcmp(funcName, "vkDestroyInstance"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008500 return (PFN_vkVoidFunction)vkDestroyInstance;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008501 if (!strcmp(funcName, "vkDestroyDevice"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008502 return (PFN_vkVoidFunction)vkDestroyDevice;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008503 if (!strcmp(funcName, "vkDestroyFence"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008504 return (PFN_vkVoidFunction)vkDestroyFence;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008505 if (!strcmp(funcName, "vkDestroySemaphore"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008506 return (PFN_vkVoidFunction)vkDestroySemaphore;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008507 if (!strcmp(funcName, "vkDestroyEvent"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008508 return (PFN_vkVoidFunction)vkDestroyEvent;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008509 if (!strcmp(funcName, "vkDestroyQueryPool"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008510 return (PFN_vkVoidFunction)vkDestroyQueryPool;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008511 if (!strcmp(funcName, "vkDestroyBuffer"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008512 return (PFN_vkVoidFunction)vkDestroyBuffer;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008513 if (!strcmp(funcName, "vkDestroyBufferView"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008514 return (PFN_vkVoidFunction)vkDestroyBufferView;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008515 if (!strcmp(funcName, "vkDestroyImage"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008516 return (PFN_vkVoidFunction)vkDestroyImage;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008517 if (!strcmp(funcName, "vkDestroyImageView"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008518 return (PFN_vkVoidFunction)vkDestroyImageView;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008519 if (!strcmp(funcName, "vkDestroyShaderModule"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008520 return (PFN_vkVoidFunction)vkDestroyShaderModule;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008521 if (!strcmp(funcName, "vkDestroyPipeline"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008522 return (PFN_vkVoidFunction)vkDestroyPipeline;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008523 if (!strcmp(funcName, "vkDestroyPipelineLayout"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008524 return (PFN_vkVoidFunction)vkDestroyPipelineLayout;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008525 if (!strcmp(funcName, "vkDestroySampler"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008526 return (PFN_vkVoidFunction)vkDestroySampler;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008527 if (!strcmp(funcName, "vkDestroyDescriptorSetLayout"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008528 return (PFN_vkVoidFunction)vkDestroyDescriptorSetLayout;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008529 if (!strcmp(funcName, "vkDestroyDescriptorPool"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008530 return (PFN_vkVoidFunction)vkDestroyDescriptorPool;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008531 if (!strcmp(funcName, "vkDestroyFramebuffer"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008532 return (PFN_vkVoidFunction)vkDestroyFramebuffer;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06008533 if (!strcmp(funcName, "vkDestroyRenderPass"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008534 return (PFN_vkVoidFunction)vkDestroyRenderPass;
Tobin Ehlisa1c28562015-10-23 16:00:08 -06008535 if (!strcmp(funcName, "vkCreateBuffer"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008536 return (PFN_vkVoidFunction)vkCreateBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008537 if (!strcmp(funcName, "vkCreateBufferView"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008538 return (PFN_vkVoidFunction)vkCreateBufferView;
Tobin Ehlisa1c28562015-10-23 16:00:08 -06008539 if (!strcmp(funcName, "vkCreateImage"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008540 return (PFN_vkVoidFunction)vkCreateImage;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008541 if (!strcmp(funcName, "vkCreateImageView"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008542 return (PFN_vkVoidFunction)vkCreateImageView;
Jon Ashburnc669cc62015-07-09 15:02:25 -06008543 if (!strcmp(funcName, "CreatePipelineCache"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008544 return (PFN_vkVoidFunction)vkCreatePipelineCache;
Jon Ashburnc669cc62015-07-09 15:02:25 -06008545 if (!strcmp(funcName, "DestroyPipelineCache"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008546 return (PFN_vkVoidFunction)vkDestroyPipelineCache;
Jon Ashburnc669cc62015-07-09 15:02:25 -06008547 if (!strcmp(funcName, "GetPipelineCacheData"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008548 return (PFN_vkVoidFunction)vkGetPipelineCacheData;
Jon Ashburnc669cc62015-07-09 15:02:25 -06008549 if (!strcmp(funcName, "MergePipelineCaches"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008550 return (PFN_vkVoidFunction)vkMergePipelineCaches;
Jon Ashburnc669cc62015-07-09 15:02:25 -06008551 if (!strcmp(funcName, "vkCreateGraphicsPipelines"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008552 return (PFN_vkVoidFunction)vkCreateGraphicsPipelines;
Mark Lobodzinski475a2182015-11-10 15:25:01 -07008553 if (!strcmp(funcName, "vkCreateComputePipelines"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008554 return (PFN_vkVoidFunction)vkCreateComputePipelines;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008555 if (!strcmp(funcName, "vkCreateSampler"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008556 return (PFN_vkVoidFunction)vkCreateSampler;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008557 if (!strcmp(funcName, "vkCreateDescriptorSetLayout"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008558 return (PFN_vkVoidFunction)vkCreateDescriptorSetLayout;
Mark Lobodzinski0fadf5f2015-04-17 14:11:39 -05008559 if (!strcmp(funcName, "vkCreatePipelineLayout"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008560 return (PFN_vkVoidFunction)vkCreatePipelineLayout;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008561 if (!strcmp(funcName, "vkCreateDescriptorPool"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008562 return (PFN_vkVoidFunction)vkCreateDescriptorPool;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008563 if (!strcmp(funcName, "vkResetDescriptorPool"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008564 return (PFN_vkVoidFunction)vkResetDescriptorPool;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08008565 if (!strcmp(funcName, "vkAllocateDescriptorSets"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008566 return (PFN_vkVoidFunction)vkAllocateDescriptorSets;
Tobin Ehlise735c692015-10-08 13:13:50 -06008567 if (!strcmp(funcName, "vkFreeDescriptorSets"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008568 return (PFN_vkVoidFunction)vkFreeDescriptorSets;
Chia-I Wu9d00ed72015-05-25 16:27:55 +08008569 if (!strcmp(funcName, "vkUpdateDescriptorSets"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008570 return (PFN_vkVoidFunction)vkUpdateDescriptorSets;
Mark Lobodzinski39298632015-11-18 08:38:27 -07008571 if (!strcmp(funcName, "vkCreateCommandPool"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008572 return (PFN_vkVoidFunction)vkCreateCommandPool;
Mark Lobodzinski39298632015-11-18 08:38:27 -07008573 if (!strcmp(funcName, "vkDestroyCommandPool"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008574 return (PFN_vkVoidFunction)vkDestroyCommandPool;
Tobin Ehlisac0ef842015-12-14 13:46:38 -07008575 if (!strcmp(funcName, "vkResetCommandPool"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008576 return (PFN_vkVoidFunction)vkResetCommandPool;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08008577 if (!strcmp(funcName, "vkAllocateCommandBuffers"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008578 return (PFN_vkVoidFunction)vkAllocateCommandBuffers;
Mark Lobodzinski39298632015-11-18 08:38:27 -07008579 if (!strcmp(funcName, "vkFreeCommandBuffers"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008580 return (PFN_vkVoidFunction)vkFreeCommandBuffers;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008581 if (!strcmp(funcName, "vkBeginCommandBuffer"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008582 return (PFN_vkVoidFunction)vkBeginCommandBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008583 if (!strcmp(funcName, "vkEndCommandBuffer"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008584 return (PFN_vkVoidFunction)vkEndCommandBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008585 if (!strcmp(funcName, "vkResetCommandBuffer"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008586 return (PFN_vkVoidFunction)vkResetCommandBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008587 if (!strcmp(funcName, "vkCmdBindPipeline"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008588 return (PFN_vkVoidFunction)vkCmdBindPipeline;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06008589 if (!strcmp(funcName, "vkCmdSetViewport"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008590 return (PFN_vkVoidFunction)vkCmdSetViewport;
Courtney Goeltzenleuchter078f8172015-09-21 11:44:06 -06008591 if (!strcmp(funcName, "vkCmdSetScissor"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008592 return (PFN_vkVoidFunction)vkCmdSetScissor;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06008593 if (!strcmp(funcName, "vkCmdSetLineWidth"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008594 return (PFN_vkVoidFunction)vkCmdSetLineWidth;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06008595 if (!strcmp(funcName, "vkCmdSetDepthBias"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008596 return (PFN_vkVoidFunction)vkCmdSetDepthBias;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06008597 if (!strcmp(funcName, "vkCmdSetBlendConstants"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008598 return (PFN_vkVoidFunction)vkCmdSetBlendConstants;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06008599 if (!strcmp(funcName, "vkCmdSetDepthBounds"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008600 return (PFN_vkVoidFunction)vkCmdSetDepthBounds;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06008601 if (!strcmp(funcName, "vkCmdSetStencilCompareMask"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008602 return (PFN_vkVoidFunction)vkCmdSetStencilCompareMask;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06008603 if (!strcmp(funcName, "vkCmdSetStencilWriteMask"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008604 return (PFN_vkVoidFunction)vkCmdSetStencilWriteMask;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06008605 if (!strcmp(funcName, "vkCmdSetStencilReference"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008606 return (PFN_vkVoidFunction)vkCmdSetStencilReference;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008607 if (!strcmp(funcName, "vkCmdBindDescriptorSets"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008608 return (PFN_vkVoidFunction)vkCmdBindDescriptorSets;
Courtney Goeltzenleuchterf68ad722015-04-16 13:38:46 -06008609 if (!strcmp(funcName, "vkCmdBindVertexBuffers"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008610 return (PFN_vkVoidFunction)vkCmdBindVertexBuffers;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008611 if (!strcmp(funcName, "vkCmdBindIndexBuffer"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008612 return (PFN_vkVoidFunction)vkCmdBindIndexBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008613 if (!strcmp(funcName, "vkCmdDraw"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008614 return (PFN_vkVoidFunction)vkCmdDraw;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008615 if (!strcmp(funcName, "vkCmdDrawIndexed"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008616 return (PFN_vkVoidFunction)vkCmdDrawIndexed;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008617 if (!strcmp(funcName, "vkCmdDrawIndirect"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008618 return (PFN_vkVoidFunction)vkCmdDrawIndirect;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008619 if (!strcmp(funcName, "vkCmdDrawIndexedIndirect"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008620 return (PFN_vkVoidFunction)vkCmdDrawIndexedIndirect;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008621 if (!strcmp(funcName, "vkCmdDispatch"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008622 return (PFN_vkVoidFunction)vkCmdDispatch;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008623 if (!strcmp(funcName, "vkCmdDispatchIndirect"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008624 return (PFN_vkVoidFunction)vkCmdDispatchIndirect;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008625 if (!strcmp(funcName, "vkCmdCopyBuffer"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008626 return (PFN_vkVoidFunction)vkCmdCopyBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008627 if (!strcmp(funcName, "vkCmdCopyImage"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008628 return (PFN_vkVoidFunction)vkCmdCopyImage;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008629 if (!strcmp(funcName, "vkCmdCopyBufferToImage"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008630 return (PFN_vkVoidFunction)vkCmdCopyBufferToImage;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008631 if (!strcmp(funcName, "vkCmdCopyImageToBuffer"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008632 return (PFN_vkVoidFunction)vkCmdCopyImageToBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008633 if (!strcmp(funcName, "vkCmdUpdateBuffer"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008634 return (PFN_vkVoidFunction)vkCmdUpdateBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008635 if (!strcmp(funcName, "vkCmdFillBuffer"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008636 return (PFN_vkVoidFunction)vkCmdFillBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008637 if (!strcmp(funcName, "vkCmdClearColorImage"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008638 return (PFN_vkVoidFunction)vkCmdClearColorImage;
Chris Forbesd9be82b2015-06-22 17:21:59 +12008639 if (!strcmp(funcName, "vkCmdClearDepthStencilImage"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008640 return (PFN_vkVoidFunction)vkCmdClearDepthStencilImage;
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06008641 if (!strcmp(funcName, "vkCmdClearAttachments"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008642 return (PFN_vkVoidFunction)vkCmdClearAttachments;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008643 if (!strcmp(funcName, "vkCmdResolveImage"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008644 return (PFN_vkVoidFunction)vkCmdResolveImage;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008645 if (!strcmp(funcName, "vkCmdSetEvent"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008646 return (PFN_vkVoidFunction)vkCmdSetEvent;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008647 if (!strcmp(funcName, "vkCmdResetEvent"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008648 return (PFN_vkVoidFunction)vkCmdResetEvent;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008649 if (!strcmp(funcName, "vkCmdWaitEvents"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008650 return (PFN_vkVoidFunction)vkCmdWaitEvents;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008651 if (!strcmp(funcName, "vkCmdPipelineBarrier"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008652 return (PFN_vkVoidFunction)vkCmdPipelineBarrier;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008653 if (!strcmp(funcName, "vkCmdBeginQuery"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008654 return (PFN_vkVoidFunction)vkCmdBeginQuery;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008655 if (!strcmp(funcName, "vkCmdEndQuery"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008656 return (PFN_vkVoidFunction)vkCmdEndQuery;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008657 if (!strcmp(funcName, "vkCmdResetQueryPool"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008658 return (PFN_vkVoidFunction)vkCmdResetQueryPool;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008659 if (!strcmp(funcName, "vkCmdWriteTimestamp"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008660 return (PFN_vkVoidFunction)vkCmdWriteTimestamp;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008661 if (!strcmp(funcName, "vkCreateFramebuffer"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008662 return (PFN_vkVoidFunction)vkCreateFramebuffer;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07008663 if (!strcmp(funcName, "vkCreateShaderModule"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008664 return (PFN_vkVoidFunction)vkCreateShaderModule;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008665 if (!strcmp(funcName, "vkCreateRenderPass"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008666 return (PFN_vkVoidFunction)vkCreateRenderPass;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008667 if (!strcmp(funcName, "vkCmdBeginRenderPass"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008668 return (PFN_vkVoidFunction)vkCmdBeginRenderPass;
Chia-I Wu08accc62015-07-07 11:50:03 +08008669 if (!strcmp(funcName, "vkCmdNextSubpass"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008670 return (PFN_vkVoidFunction)vkCmdNextSubpass;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06008671 if (!strcmp(funcName, "vkCmdEndRenderPass"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008672 return (PFN_vkVoidFunction)vkCmdEndRenderPass;
Tobin Ehlis4b34ddc2015-09-17 14:18:16 -06008673 if (!strcmp(funcName, "vkCmdExecuteCommands"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008674 return (PFN_vkVoidFunction)vkCmdExecuteCommands;
Michael Lentineb887b0a2015-12-29 14:12:11 -06008675 if (!strcmp(funcName, "vkSetEvent"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008676 return (PFN_vkVoidFunction)vkSetEvent;
Michael Lentine7b236262015-10-23 12:41:44 -07008677 if (!strcmp(funcName, "vkMapMemory"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008678 return (PFN_vkVoidFunction)vkMapMemory;
Michael Lentineb887b0a2015-12-29 14:12:11 -06008679 if (!strcmp(funcName, "vkGetQueryPoolResults"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008680 return (PFN_vkVoidFunction)vkGetQueryPoolResults;
Michael Lentine15a47882016-01-06 10:05:48 -06008681 if (!strcmp(funcName, "vkBindImageMemory"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008682 return (PFN_vkVoidFunction)vkBindImageMemory;
Michael Lentine15a47882016-01-06 10:05:48 -06008683 if (!strcmp(funcName, "vkQueueBindSparse"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008684 return (PFN_vkVoidFunction)vkQueueBindSparse;
Michael Lentine15a47882016-01-06 10:05:48 -06008685 if (!strcmp(funcName, "vkCreateSemaphore"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008686 return (PFN_vkVoidFunction)vkCreateSemaphore;
Jon Ashburneab34492015-06-01 09:37:38 -06008687
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07008688 if (dev == NULL)
8689 return NULL;
8690
8691 layer_data *dev_data;
8692 dev_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);
8693
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008694 if (dev_data->device_extensions.wsi_enabled) {
Michael Lentineabc5e922015-10-12 11:30:14 -05008695 if (!strcmp(funcName, "vkCreateSwapchainKHR"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008696 return (PFN_vkVoidFunction)vkCreateSwapchainKHR;
Michael Lentineabc5e922015-10-12 11:30:14 -05008697 if (!strcmp(funcName, "vkDestroySwapchainKHR"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008698 return (PFN_vkVoidFunction)vkDestroySwapchainKHR;
Michael Lentineabc5e922015-10-12 11:30:14 -05008699 if (!strcmp(funcName, "vkGetSwapchainImagesKHR"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008700 return (PFN_vkVoidFunction)vkGetSwapchainImagesKHR;
Michael Lentine15a47882016-01-06 10:05:48 -06008701 if (!strcmp(funcName, "vkAcquireNextImageKHR"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008702 return (PFN_vkVoidFunction)vkAcquireNextImageKHR;
Michael Lentineabc5e922015-10-12 11:30:14 -05008703 if (!strcmp(funcName, "vkQueuePresentKHR"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008704 return (PFN_vkVoidFunction)vkQueuePresentKHR;
Michael Lentineabc5e922015-10-12 11:30:14 -05008705 }
8706
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008707 VkLayerDispatchTable *pTable = dev_data->device_dispatch_table;
8708 if (dev_data->device_extensions.debug_marker_enabled) {
Jon Ashburn747f2b62015-06-18 15:02:58 -06008709 if (!strcmp(funcName, "vkCmdDbgMarkerBegin"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008710 return (PFN_vkVoidFunction)vkCmdDbgMarkerBegin;
Jon Ashburn747f2b62015-06-18 15:02:58 -06008711 if (!strcmp(funcName, "vkCmdDbgMarkerEnd"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008712 return (PFN_vkVoidFunction)vkCmdDbgMarkerEnd;
Jon Ashburneab34492015-06-01 09:37:38 -06008713 }
8714 {
Jon Ashburn8fd08252015-05-28 16:25:02 -06008715 if (pTable->GetDeviceProcAddr == NULL)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06008716 return NULL;
Jon Ashburn8fd08252015-05-28 16:25:02 -06008717 return pTable->GetDeviceProcAddr(dev, funcName);
Jon Ashburnf6b33db2015-05-05 14:22:52 -06008718 }
8719}
8720
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008721VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
8722 vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07008723 if (!strcmp(funcName, "vkGetInstanceProcAddr"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008724 return (PFN_vkVoidFunction)vkGetInstanceProcAddr;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07008725 if (!strcmp(funcName, "vkGetDeviceProcAddr"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008726 return (PFN_vkVoidFunction)vkGetDeviceProcAddr;
Courtney Goeltzenleuchterabc035e2015-06-01 14:29:58 -06008727 if (!strcmp(funcName, "vkCreateInstance"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008728 return (PFN_vkVoidFunction)vkCreateInstance;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07008729 if (!strcmp(funcName, "vkCreateDevice"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008730 return (PFN_vkVoidFunction)vkCreateDevice;
Jon Ashburn3950e1b2015-05-20 09:00:28 -06008731 if (!strcmp(funcName, "vkDestroyInstance"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008732 return (PFN_vkVoidFunction)vkDestroyInstance;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06008733 if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008734 return (PFN_vkVoidFunction)vkEnumerateInstanceLayerProperties;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06008735 if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008736 return (PFN_vkVoidFunction)vkEnumerateInstanceExtensionProperties;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06008737 if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008738 return (PFN_vkVoidFunction)vkEnumerateDeviceLayerProperties;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06008739 if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008740 return (PFN_vkVoidFunction)vkEnumerateDeviceExtensionProperties;
Courtney Goeltzenleuchteree562872015-06-01 14:33:14 -06008741
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07008742 if (instance == NULL)
8743 return NULL;
8744
8745 PFN_vkVoidFunction fptr;
8746
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008747 layer_data *my_data;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07008748 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Tobin Ehlisa16e8922015-06-16 15:50:44 -06008749 fptr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
Courtney Goeltzenleuchteree562872015-06-01 14:33:14 -06008750 if (fptr)
8751 return fptr;
8752
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07008753 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07008754 if (pTable->GetInstanceProcAddr == NULL)
8755 return NULL;
8756 return pTable->GetInstanceProcAddr(instance, funcName);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06008757}