blob: 3245813700ab500c562033539de9350a0a4c4984 [file] [log] [blame]
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001/*
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002 *
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06003 * Copyright (C) 2015 Valve Corporation
Michael Lentineb6986752015-10-06 14:56:18 -07004 * Copyright (C) 2015 Google, Inc.
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060023 *
Tobin Ehlis88452832015-12-03 09:40:56 -070024 * Author: Cody Northrop <cnorthrop@google.com>
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060025 * Author: Michael Lentine <mlentine@google.com>
Tobin Ehlis88452832015-12-03 09:40:56 -070026 * Author: Tobin Ehlis <tobine@google.com>
27 * Author: Chia-I Wu <olv@google.com>
Tobin Ehlis7e2ad752015-12-01 09:48:58 -070028 * Author: Chris Forbes <chrisf@ijw.co.nz>
Mark Lobodzinski78da8cb2015-12-28 15:51:07 -070029 * Author: Mark Lobodzinski <mark@lunarg.com>
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060030 */
31
Mark Lobodzinski78da8cb2015-12-28 15:51:07 -070032// Allow use of STL min and max functions in Windows
33#define NOMINMAX
34
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060035#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
Tobin Ehlis7e2ad752015-12-01 09:48:58 -070038#include <assert.h>
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060039#include <unordered_map>
Michael Lentineb6986752015-10-06 14:56:18 -070040#include <unordered_set>
Tobin Ehlis7e2ad752015-12-01 09:48:58 -070041#include <map>
42#include <string>
43#include <iostream>
44#include <algorithm>
Mark Lobodzinski39298632015-11-18 08:38:27 -070045#include <list>
Tobin Ehlis7e2ad752015-12-01 09:48:58 -070046#include <spirv.hpp>
Tobin Ehlis88452832015-12-03 09:40:56 -070047#include <set>
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060048
Tobin Ehlisb835d1b2015-07-03 10:34:49 -060049#include "vk_loader_platform.h"
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060050#include "vk_dispatch_table_helper.h"
51#include "vk_struct_string_helper_cpp.h"
Tony Barbour18f71552015-04-22 11:36:22 -060052#if defined(__GNUC__)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060053#pragma GCC diagnostic ignored "-Wwrite-strings"
Tony Barbour18f71552015-04-22 11:36:22 -060054#endif
Tony Barbour18f71552015-04-22 11:36:22 -060055#if defined(__GNUC__)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060056#pragma GCC diagnostic warning "-Wwrite-strings"
Tony Barbour18f71552015-04-22 11:36:22 -060057#endif
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060058#include "vk_struct_size_helper.h"
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060059#include "draw_state.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060060#include "vk_layer_config.h"
Michael Lentine97eb7462015-11-20 09:48:52 -080061#include "vulkan/vk_debug_marker_layer.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060062#include "vk_layer_table.h"
63#include "vk_layer_debug_marker_table.h"
64#include "vk_layer_data.h"
65#include "vk_layer_logging.h"
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -060066#include "vk_layer_extension_utils.h"
Tobin Ehlisa1c28562015-10-23 16:00:08 -060067#include "vk_layer_utils.h"
Tobin Ehlis10ae8c12015-03-17 16:24:32 -060068
Mark Lobodzinski31e5f282015-11-30 16:48:53 -070069// This definition controls whether image layout transitions are enabled/disabled.
70// disable until corner cases are fixed
71#define DISABLE_IMAGE_LAYOUT_VALIDATION
72
Tobin Ehlis7e2ad752015-12-01 09:48:58 -070073using std::unordered_map;
74using std::unordered_set;
75
Tobin Ehlisac0ef842015-12-14 13:46:38 -070076// Track command pools and their command buffers
77struct CMD_POOL_INFO {
78 VkCommandPoolCreateFlags createFlags;
79 list<VkCommandBuffer> commandBuffers; // list container of cmd buffers allocated from this pool
80};
81
Tobin Ehlis0b632332015-10-07 09:38:40 -060082struct devExts {
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -070083 VkBool32 debug_marker_enabled;
Michael Lentineabc5e922015-10-12 11:30:14 -050084 VkBool32 wsi_enabled;
85 unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE*> swapchainMap;
Tobin Ehlis0b632332015-10-07 09:38:40 -060086};
87
Tobin Ehlis7e2ad752015-12-01 09:48:58 -070088// fwd decls
89struct shader_module;
90struct render_pass;
91
Cody Northrop55443ef2015-09-28 15:09:32 -060092struct layer_data {
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -070093 debug_report_data* report_data;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -070094 std::vector<VkDebugReportCallbackEXT> logging_callback;
Tobin Ehlis0b632332015-10-07 09:38:40 -060095 VkLayerDispatchTable* device_dispatch_table;
96 VkLayerInstanceDispatchTable* instance_dispatch_table;
97 devExts device_extensions;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -060098 // Layer specific data
Mark Lobodzinski39298632015-11-18 08:38:27 -070099 unordered_map<VkSampler, unique_ptr<SAMPLER_NODE>> sampleMap;
100 unordered_map<VkImageView, unique_ptr<VkImageViewCreateInfo>> imageViewMap;
101 unordered_map<VkImage, unique_ptr<VkImageCreateInfo>> imageMap;
102 unordered_map<VkBufferView, unique_ptr<VkBufferViewCreateInfo>> bufferViewMap;
Michael Lentine700b0aa2015-10-30 17:57:32 -0700103 unordered_map<VkBuffer, BUFFER_NODE> bufferMap;
Mark Lobodzinski39298632015-11-18 08:38:27 -0700104 unordered_map<VkPipeline, PIPELINE_NODE*> pipelineMap;
Tobin Ehlisac0ef842015-12-14 13:46:38 -0700105 unordered_map<VkCommandPool, CMD_POOL_INFO> commandPoolMap;
Mark Lobodzinski39298632015-11-18 08:38:27 -0700106 unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_NODE*> descriptorPoolMap;
107 unordered_map<VkDescriptorSet, SET_NODE*> setMap;
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -0700108 unordered_map<VkDescriptorSetLayout, LAYOUT_NODE*> descriptorSetLayoutMap;
Mark Lobodzinski39298632015-11-18 08:38:27 -0700109 unordered_map<VkPipelineLayout, PIPELINE_LAYOUT_NODE> pipelineLayoutMap;
110 unordered_map<VkDeviceMemory, VkImage> memImageMap;
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -0700111 unordered_map<VkFence, FENCE_NODE> fenceMap;
112 unordered_map<VkQueue, QUEUE_NODE> queueMap;
113 unordered_map<VkDevice, DEVICE_NODE> deviceMap;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -0600114 // Map for layout chains
Mark Lobodzinski39298632015-11-18 08:38:27 -0700115 unordered_map<void*, GLOBAL_CB_NODE*> commandBufferMap;
116 unordered_map<VkFramebuffer, VkFramebufferCreateInfo*> frameBufferMap;
117 unordered_map<VkImage, IMAGE_NODE*> imageLayoutMap;
118 unordered_map<VkRenderPass, RENDER_PASS_NODE*> renderPassMap;
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -0700119 unordered_map<VkShaderModule, shader_module*> shaderModuleMap;
Michael Lentineabc5e922015-10-12 11:30:14 -0500120 // Current render pass
121 VkRenderPassBeginInfo renderPassBeginInfo;
122 uint32_t currentSubpass;
Cody Northrop55443ef2015-09-28 15:09:32 -0600123
124 layer_data() :
125 report_data(nullptr),
Tobin Ehlis0b632332015-10-07 09:38:40 -0600126 device_dispatch_table(nullptr),
127 instance_dispatch_table(nullptr),
128 device_extensions()
Cody Northrop55443ef2015-09-28 15:09:32 -0600129 {};
130};
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700131// Code imported from ShaderChecker
132static void
133build_type_def_index(std::vector<unsigned> const &words, std::unordered_map<unsigned, unsigned> &type_def_index);
134
135struct shader_module {
136 /* the spirv image itself */
137 vector<uint32_t> words;
138 /* a mapping of <id> to the first word of its def. this is useful because walking type
139 * trees requires jumping all over the instruction stream.
140 */
141 unordered_map<unsigned, unsigned> type_def_index;
142
143 shader_module(VkShaderModuleCreateInfo const *pCreateInfo) :
144 words((uint32_t *)pCreateInfo->pCode, (uint32_t *)pCreateInfo->pCode + pCreateInfo->codeSize / sizeof(uint32_t)),
145 type_def_index() {
146
147 build_type_def_index(words, type_def_index);
148 }
149};
150
Tobin Ehlisb212dfc2015-10-07 15:40:22 -0600151// TODO : Do we need to guard access to layer_data_map w/ lock?
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -0700152static unordered_map<void*, layer_data*> layer_data_map;
Courtney Goeltzenleuchter3d0dfad2015-06-13 21:23:09 -0600153
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600154static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(g_initOnce);
155// TODO : This can be much smarter, using separate locks for separate global data
156static int globalLockInitialized = 0;
157static loader_platform_thread_mutex globalLock;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600158#define MAX_TID 513
159static loader_platform_thread_id g_tidMapping[MAX_TID] = {0};
160static uint32_t g_maxTID = 0;
Tobin Ehlisa16e8922015-06-16 15:50:44 -0600161
162template layer_data *get_my_data_ptr<layer_data>(
163 void *data_key,
164 std::unordered_map<void *, layer_data *> &data_map);
165
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600166// Map actual TID to an index value and return that index
167// This keeps TIDs in range from 0-MAX_TID and simplifies compares between runs
168static uint32_t getTIDIndex() {
169 loader_platform_thread_id tid = loader_platform_get_thread_id();
170 for (uint32_t i = 0; i < g_maxTID; i++) {
171 if (tid == g_tidMapping[i])
172 return i;
173 }
174 // Don't yet have mapping, set it and return newly set index
175 uint32_t retVal = (uint32_t) g_maxTID;
176 g_tidMapping[g_maxTID++] = tid;
177 assert(g_maxTID < MAX_TID);
178 return retVal;
179}
Tobin Ehlis559c6382015-11-05 09:52:49 -0700180
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600181// Return a string representation of CMD_TYPE enum
182static string cmdTypeToString(CMD_TYPE cmd)
183{
184 switch (cmd)
185 {
186 case CMD_BINDPIPELINE:
187 return "CMD_BINDPIPELINE";
188 case CMD_BINDPIPELINEDELTA:
189 return "CMD_BINDPIPELINEDELTA";
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -0600190 case CMD_SETVIEWPORTSTATE:
191 return "CMD_SETVIEWPORTSTATE";
192 case CMD_SETLINEWIDTHSTATE:
193 return "CMD_SETLINEWIDTHSTATE";
194 case CMD_SETDEPTHBIASSTATE:
195 return "CMD_SETDEPTHBIASSTATE";
196 case CMD_SETBLENDSTATE:
197 return "CMD_SETBLENDSTATE";
198 case CMD_SETDEPTHBOUNDSSTATE:
199 return "CMD_SETDEPTHBOUNDSSTATE";
200 case CMD_SETSTENCILREADMASKSTATE:
201 return "CMD_SETSTENCILREADMASKSTATE";
202 case CMD_SETSTENCILWRITEMASKSTATE:
203 return "CMD_SETSTENCILWRITEMASKSTATE";
204 case CMD_SETSTENCILREFERENCESTATE:
205 return "CMD_SETSTENCILREFERENCESTATE";
Tobin Ehlis793ad302015-04-03 12:01:11 -0600206 case CMD_BINDDESCRIPTORSETS:
207 return "CMD_BINDDESCRIPTORSETS";
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600208 case CMD_BINDINDEXBUFFER:
209 return "CMD_BINDINDEXBUFFER";
210 case CMD_BINDVERTEXBUFFER:
211 return "CMD_BINDVERTEXBUFFER";
212 case CMD_DRAW:
213 return "CMD_DRAW";
214 case CMD_DRAWINDEXED:
215 return "CMD_DRAWINDEXED";
216 case CMD_DRAWINDIRECT:
217 return "CMD_DRAWINDIRECT";
218 case CMD_DRAWINDEXEDINDIRECT:
219 return "CMD_DRAWINDEXEDINDIRECT";
220 case CMD_DISPATCH:
221 return "CMD_DISPATCH";
222 case CMD_DISPATCHINDIRECT:
223 return "CMD_DISPATCHINDIRECT";
224 case CMD_COPYBUFFER:
225 return "CMD_COPYBUFFER";
226 case CMD_COPYIMAGE:
227 return "CMD_COPYIMAGE";
Tobin Ehlis793ad302015-04-03 12:01:11 -0600228 case CMD_BLITIMAGE:
229 return "CMD_BLITIMAGE";
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600230 case CMD_COPYBUFFERTOIMAGE:
231 return "CMD_COPYBUFFERTOIMAGE";
232 case CMD_COPYIMAGETOBUFFER:
233 return "CMD_COPYIMAGETOBUFFER";
234 case CMD_CLONEIMAGEDATA:
235 return "CMD_CLONEIMAGEDATA";
236 case CMD_UPDATEBUFFER:
237 return "CMD_UPDATEBUFFER";
238 case CMD_FILLBUFFER:
239 return "CMD_FILLBUFFER";
240 case CMD_CLEARCOLORIMAGE:
241 return "CMD_CLEARCOLORIMAGE";
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -0600242 case CMD_CLEARATTACHMENTS:
Tobin Ehlis53eddda2015-07-01 16:46:13 -0600243 return "CMD_CLEARCOLORATTACHMENT";
244 case CMD_CLEARDEPTHSTENCILIMAGE:
245 return "CMD_CLEARDEPTHSTENCILIMAGE";
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600246 case CMD_RESOLVEIMAGE:
247 return "CMD_RESOLVEIMAGE";
248 case CMD_SETEVENT:
249 return "CMD_SETEVENT";
250 case CMD_RESETEVENT:
251 return "CMD_RESETEVENT";
252 case CMD_WAITEVENTS:
253 return "CMD_WAITEVENTS";
254 case CMD_PIPELINEBARRIER:
255 return "CMD_PIPELINEBARRIER";
256 case CMD_BEGINQUERY:
257 return "CMD_BEGINQUERY";
258 case CMD_ENDQUERY:
259 return "CMD_ENDQUERY";
260 case CMD_RESETQUERYPOOL:
261 return "CMD_RESETQUERYPOOL";
Mark Lobodzinski5495d132015-09-30 16:19:16 -0600262 case CMD_COPYQUERYPOOLRESULTS:
263 return "CMD_COPYQUERYPOOLRESULTS";
Tobin Ehlis10ae8c12015-03-17 16:24:32 -0600264 case CMD_WRITETIMESTAMP:
265 return "CMD_WRITETIMESTAMP";
266 case CMD_INITATOMICCOUNTERS:
267 return "CMD_INITATOMICCOUNTERS";
268 case CMD_LOADATOMICCOUNTERS:
269 return "CMD_LOADATOMICCOUNTERS";
270 case CMD_SAVEATOMICCOUNTERS:
271 return "CMD_SAVEATOMICCOUNTERS";
272 case CMD_BEGINRENDERPASS:
273 return "CMD_BEGINRENDERPASS";
274 case CMD_ENDRENDERPASS:
275 return "CMD_ENDRENDERPASS";
276 case CMD_DBGMARKERBEGIN:
277 return "CMD_DBGMARKERBEGIN";
278 case CMD_DBGMARKEREND:
279 return "CMD_DBGMARKEREND";
280 default:
281 return "UNKNOWN";
282 }
283}
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700284
285// SPIRV utility functions
286static void
287build_type_def_index(std::vector<unsigned> const &words, std::unordered_map<unsigned, unsigned> &type_def_index)
288{
289 unsigned int const *code = (unsigned int const *)&words[0];
290 size_t size = words.size();
291
292 unsigned word = 5;
293 while (word < size) {
294 unsigned opcode = code[word] & 0x0ffffu;
295 unsigned oplen = (code[word] & 0xffff0000u) >> 16;
296
297 switch (opcode) {
298 case spv::OpTypeVoid:
299 case spv::OpTypeBool:
300 case spv::OpTypeInt:
301 case spv::OpTypeFloat:
302 case spv::OpTypeVector:
303 case spv::OpTypeMatrix:
304 case spv::OpTypeImage:
305 case spv::OpTypeSampler:
306 case spv::OpTypeSampledImage:
307 case spv::OpTypeArray:
308 case spv::OpTypeRuntimeArray:
309 case spv::OpTypeStruct:
310 case spv::OpTypeOpaque:
311 case spv::OpTypePointer:
312 case spv::OpTypeFunction:
313 case spv::OpTypeEvent:
314 case spv::OpTypeDeviceEvent:
315 case spv::OpTypeReserveId:
316 case spv::OpTypeQueue:
317 case spv::OpTypePipe:
318 type_def_index[code[word+1]] = word;
319 break;
320
321 default:
322 /* We only care about type definitions */
323 break;
324 }
325
326 word += oplen;
327 }
328}
329
330bool
331shader_is_spirv(VkShaderModuleCreateInfo const *pCreateInfo)
332{
333 uint32_t *words = (uint32_t *)pCreateInfo->pCode;
334 size_t sizeInWords = pCreateInfo->codeSize / sizeof(uint32_t);
335
336 /* Just validate that the header makes sense. */
337 return sizeInWords >= 5 && words[0] == spv::MagicNumber && words[1] == spv::Version;
338}
339
340static char const *
341storage_class_name(unsigned sc)
342{
343 switch (sc) {
344 case spv::StorageClassInput: return "input";
345 case spv::StorageClassOutput: return "output";
346 case spv::StorageClassUniformConstant: return "const uniform";
347 case spv::StorageClassUniform: return "uniform";
348 case spv::StorageClassWorkgroup: return "workgroup local";
349 case spv::StorageClassCrossWorkgroup: return "workgroup global";
350 case spv::StorageClassPrivate: return "private global";
351 case spv::StorageClassFunction: return "function";
352 case spv::StorageClassGeneric: return "generic";
353 case spv::StorageClassAtomicCounter: return "atomic counter";
354 case spv::StorageClassImage: return "image";
355 default: return "unknown";
356 }
357}
358
359/* returns ptr to null terminator */
360static char *
361describe_type(char *dst, shader_module const *src, unsigned type)
362{
363 auto type_def_it = src->type_def_index.find(type);
364
365 if (type_def_it == src->type_def_index.end()) {
366 return dst + sprintf(dst, "undef");
367 }
368
369 unsigned int const *code = (unsigned int const *)&src->words[type_def_it->second];
370 unsigned opcode = code[0] & 0x0ffffu;
371 switch (opcode) {
372 case spv::OpTypeBool:
373 return dst + sprintf(dst, "bool");
374 case spv::OpTypeInt:
375 return dst + sprintf(dst, "%cint%d", code[3] ? 's' : 'u', code[2]);
376 case spv::OpTypeFloat:
377 return dst + sprintf(dst, "float%d", code[2]);
378 case spv::OpTypeVector:
379 dst += sprintf(dst, "vec%d of ", code[3]);
380 return describe_type(dst, src, code[2]);
381 case spv::OpTypeMatrix:
382 dst += sprintf(dst, "mat%d of ", code[3]);
383 return describe_type(dst, src, code[2]);
384 case spv::OpTypeArray:
385 dst += sprintf(dst, "arr[%d] of ", code[3]);
386 return describe_type(dst, src, code[2]);
387 case spv::OpTypePointer:
388 dst += sprintf(dst, "ptr to %s ", storage_class_name(code[2]));
389 return describe_type(dst, src, code[3]);
390 case spv::OpTypeStruct:
391 {
392 unsigned oplen = code[0] >> 16;
393 dst += sprintf(dst, "struct of (");
394 for (unsigned i = 2; i < oplen; i++) {
395 dst = describe_type(dst, src, code[i]);
396 dst += sprintf(dst, i == oplen-1 ? ")" : ", ");
397 }
398 return dst;
399 }
400 case spv::OpTypeSampler:
401 return dst + sprintf(dst, "sampler");
402 default:
403 return dst + sprintf(dst, "oddtype");
404 }
405}
406
407static bool
408types_match(shader_module const *a, shader_module const *b, unsigned a_type, unsigned b_type, bool b_arrayed)
409{
410 auto a_type_def_it = a->type_def_index.find(a_type);
411 auto b_type_def_it = b->type_def_index.find(b_type);
412
413 if (a_type_def_it == a->type_def_index.end()) {
414 return false;
415 }
416
417 if (b_type_def_it == b->type_def_index.end()) {
418 return false;
419 }
420
421 /* walk two type trees together, and complain about differences */
422 unsigned int const *a_code = (unsigned int const *)&a->words[a_type_def_it->second];
423 unsigned int const *b_code = (unsigned int const *)&b->words[b_type_def_it->second];
424
425 unsigned a_opcode = a_code[0] & 0x0ffffu;
426 unsigned b_opcode = b_code[0] & 0x0ffffu;
427
428 if (b_arrayed && b_opcode == spv::OpTypeArray) {
429 /* we probably just found the extra level of arrayness in b_type: compare the type inside it to a_type */
430 return types_match(a, b, a_type, b_code[2], false);
431 }
432
433 if (a_opcode != b_opcode) {
434 return false;
435 }
436
437 switch (a_opcode) {
438 /* if b_arrayed and we hit a leaf type, then we can't match -- there's nowhere for the extra OpTypeArray to be! */
439 case spv::OpTypeBool:
440 return true && !b_arrayed;
441 case spv::OpTypeInt:
442 /* match on width, signedness */
443 return a_code[2] == b_code[2] && a_code[3] == b_code[3] && !b_arrayed;
444 case spv::OpTypeFloat:
445 /* match on width */
446 return a_code[2] == b_code[2] && !b_arrayed;
447 case spv::OpTypeVector:
448 case spv::OpTypeMatrix:
449 case spv::OpTypeArray:
450 /* match on element type, count. these all have the same layout. we don't get here if
451 * b_arrayed -- that is handled above. */
452 return !b_arrayed && types_match(a, b, a_code[2], b_code[2], b_arrayed) && a_code[3] == b_code[3];
453 case spv::OpTypeStruct:
454 /* match on all element types */
455 {
456 if (b_arrayed) {
457 /* for the purposes of matching different levels of arrayness, structs are leaves. */
458 return false;
459 }
460
461 unsigned a_len = a_code[0] >> 16;
462 unsigned b_len = b_code[0] >> 16;
463
464 if (a_len != b_len) {
465 return false; /* structs cannot match if member counts differ */
466 }
467
468 for (unsigned i = 2; i < a_len; i++) {
469 if (!types_match(a, b, a_code[i], b_code[i], b_arrayed)) {
470 return false;
471 }
472 }
473
474 return true;
475 }
476 case spv::OpTypePointer:
477 /* match on pointee type. storage class is expected to differ */
478 return types_match(a, b, a_code[3], b_code[3], b_arrayed);
479
480 default:
481 /* remaining types are CLisms, or may not appear in the interfaces we
482 * are interested in. Just claim no match.
483 */
484 return false;
485
486 }
487}
488
489static int
490value_or_default(std::unordered_map<unsigned, unsigned> const &map, unsigned id, int def)
491{
492 auto it = map.find(id);
493 if (it == map.end())
494 return def;
495 else
496 return it->second;
497}
498
499
500static unsigned
501get_locations_consumed_by_type(shader_module const *src, unsigned type, bool strip_array_level)
502{
503 auto type_def_it = src->type_def_index.find(type);
504
505 if (type_def_it == src->type_def_index.end()) {
506 return 1; /* This is actually broken SPIR-V... */
507 }
508
509 unsigned int const *code = (unsigned int const *)&src->words[type_def_it->second];
510 unsigned opcode = code[0] & 0x0ffffu;
511
512 switch (opcode) {
513 case spv::OpTypePointer:
514 /* see through the ptr -- this is only ever at the toplevel for graphics shaders;
515 * we're never actually passing pointers around. */
516 return get_locations_consumed_by_type(src, code[3], strip_array_level);
517 case spv::OpTypeArray:
518 if (strip_array_level) {
519 return get_locations_consumed_by_type(src, code[2], false);
520 }
521 else {
522 return code[3] * get_locations_consumed_by_type(src, code[2], false);
523 }
524 case spv::OpTypeMatrix:
525 /* num locations is the dimension * element size */
526 return code[3] * get_locations_consumed_by_type(src, code[2], false);
527 default:
528 /* everything else is just 1. */
529 return 1;
530
531 /* TODO: extend to handle 64bit scalar types, whose vectors may need
532 * multiple locations. */
533 }
534}
535
536
537struct interface_var {
538 uint32_t id;
539 uint32_t type_id;
540 uint32_t offset;
541 /* TODO: collect the name, too? Isn't required to be present. */
542};
543
544static void
545collect_interface_by_location(layer_data *my_data, VkDevice dev,
546 shader_module const *src, spv::StorageClass sinterface,
547 std::map<uint32_t, interface_var> &out,
548 std::map<uint32_t, interface_var> &builtins_out,
549 bool is_array_of_verts)
550{
551 unsigned int const *code = (unsigned int const *)&src->words[0];
552 size_t size = src->words.size();
553
554 std::unordered_map<unsigned, unsigned> var_locations;
555 std::unordered_map<unsigned, unsigned> var_builtins;
556
557 unsigned word = 5;
558 while (word < size) {
559
560 unsigned opcode = code[word] & 0x0ffffu;
561 unsigned oplen = (code[word] & 0xffff0000u) >> 16;
562
563 /* We consider two interface models: SSO rendezvous-by-location, and
564 * builtins. Complain about anything that fits neither model.
565 */
566 if (opcode == spv::OpDecorate) {
567 if (code[word+2] == spv::DecorationLocation) {
568 var_locations[code[word+1]] = code[word+3];
569 }
570
571 if (code[word+2] == spv::DecorationBuiltIn) {
572 var_builtins[code[word+1]] = code[word+3];
573 }
574 }
575
576 /* TODO: handle grouped decorations */
577 /* TODO: handle index=1 dual source outputs from FS -- two vars will
578 * have the same location, and we DONT want to clobber. */
579
580 if (opcode == spv::OpVariable && code[word+3] == sinterface) {
581 unsigned id = code[word+2];
582 unsigned type = code[word+1];
583
584 int location = value_or_default(var_locations, code[word+2], -1);
585 int builtin = value_or_default(var_builtins, code[word+2], -1);
586
587 if (location == -1 && builtin == -1) {
588 /* No location defined, and not bound to an API builtin.
589 * The spec says nothing about how this case works (or doesn't)
590 * for interface matching.
591 */
Mark Lobodzinskib01451b2016-01-04 13:18:10 -0700592 log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__, SHADER_CHECKER_INCONSISTENT_SPIRV, "SC",
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700593 "var %d (type %d) in %s interface has no Location or Builtin decoration",
594 code[word+2], code[word+1], storage_class_name(sinterface));
595 }
596 else if (location != -1) {
597 /* A user-defined interface variable, with a location. Where a variable
598 * occupied multiple locations, emit one result for each. */
599 unsigned num_locations = get_locations_consumed_by_type(src, type,
600 is_array_of_verts);
Courtney Goeltzenleuchter51239472015-12-16 16:06:06 -0700601 for (unsigned int offset = 0; offset < num_locations; offset++) {
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700602 interface_var v;
603 v.id = id;
604 v.type_id = type;
605 v.offset = offset;
606 out[location + offset] = v;
607 }
608 }
609 else {
610 /* A builtin interface variable */
611 /* Note that since builtin interface variables do not consume numbered
612 * locations, there is no larger-than-vec4 consideration as above
613 */
614 interface_var v;
615 v.id = id;
616 v.type_id = type;
617 v.offset = 0;
618 builtins_out[builtin] = v;
619 }
620 }
621
622 word += oplen;
623 }
624}
625
626static void
627collect_interface_by_descriptor_slot(layer_data *my_data, VkDevice dev,
628 shader_module const *src, spv::StorageClass sinterface,
629 std::map<std::pair<unsigned, unsigned>, interface_var> &out)
630{
631 unsigned int const *code = (unsigned int const *)&src->words[0];
632 size_t size = src->words.size();
633
634 std::unordered_map<unsigned, unsigned> var_sets;
635 std::unordered_map<unsigned, unsigned> var_bindings;
636
637 unsigned word = 5;
638 while (word < size) {
639
640 unsigned opcode = code[word] & 0x0ffffu;
641 unsigned oplen = (code[word] & 0xffff0000u) >> 16;
642
643 /* All variables in the Uniform or UniformConstant storage classes are required to be decorated with both
644 * DecorationDescriptorSet and DecorationBinding.
645 */
646 if (opcode == spv::OpDecorate) {
647 if (code[word+2] == spv::DecorationDescriptorSet) {
648 var_sets[code[word+1]] = code[word+3];
649 }
650
651 if (code[word+2] == spv::DecorationBinding) {
652 var_bindings[code[word+1]] = code[word+3];
653 }
654 }
655
656 if (opcode == spv::OpVariable && (code[word+3] == spv::StorageClassUniform ||
657 code[word+3] == spv::StorageClassUniformConstant)) {
658 unsigned set = value_or_default(var_sets, code[word+2], 0);
659 unsigned binding = value_or_default(var_bindings, code[word+2], 0);
660
661 auto existing_it = out.find(std::make_pair(set, binding));
662 if (existing_it != out.end()) {
663 /* conflict within spv image */
Mark Lobodzinskib01451b2016-01-04 13:18:10 -0700664 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__,
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700665 SHADER_CHECKER_INCONSISTENT_SPIRV, "SC",
666 "var %d (type %d) in %s interface in descriptor slot (%u,%u) conflicts with existing definition",
667 code[word+2], code[word+1], storage_class_name(sinterface),
668 existing_it->first.first, existing_it->first.second);
669 }
670
671 interface_var v;
672 v.id = code[word+2];
673 v.type_id = code[word+1];
674 out[std::make_pair(set, binding)] = v;
675 }
676
677 word += oplen;
678 }
679}
680
681static bool
682validate_interface_between_stages(layer_data *my_data, VkDevice dev,
683 shader_module const *producer, char const *producer_name,
684 shader_module const *consumer, char const *consumer_name,
685 bool consumer_arrayed_input)
686{
687 std::map<uint32_t, interface_var> outputs;
688 std::map<uint32_t, interface_var> inputs;
689
690 std::map<uint32_t, interface_var> builtin_outputs;
691 std::map<uint32_t, interface_var> builtin_inputs;
692
693 bool pass = true;
694
695 collect_interface_by_location(my_data, dev, producer, spv::StorageClassOutput, outputs, builtin_outputs, false);
696 collect_interface_by_location(my_data, dev, consumer, spv::StorageClassInput, inputs, builtin_inputs,
697 consumer_arrayed_input);
698
699 auto a_it = outputs.begin();
700 auto b_it = inputs.begin();
701
702 /* maps sorted by key (location); walk them together to find mismatches */
703 while ((outputs.size() > 0 && a_it != outputs.end()) || ( inputs.size() && b_it != inputs.end())) {
704 bool a_at_end = outputs.size() == 0 || a_it == outputs.end();
705 bool b_at_end = inputs.size() == 0 || b_it == inputs.end();
706 auto a_first = a_at_end ? 0 : a_it->first;
707 auto b_first = b_at_end ? 0 : b_it->first;
708
709 if (b_at_end || ((!a_at_end) && (a_first < b_first))) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -0700710 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_PERF_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC",
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700711 "%s writes to output location %d which is not consumed by %s", producer_name, a_first, consumer_name)) {
712 pass = false;
713 }
714 a_it++;
715 }
716 else if (a_at_end || a_first > b_first) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -0700717 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC",
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700718 "%s consumes input location %d which is not written by %s", consumer_name, b_first, producer_name)) {
719 pass = false;
720 }
721 b_it++;
722 }
723 else {
724 if (types_match(producer, consumer, a_it->second.type_id, b_it->second.type_id, consumer_arrayed_input)) {
725 /* OK! */
726 }
727 else {
728 char producer_type[1024];
729 char consumer_type[1024];
730 describe_type(producer_type, producer, a_it->second.type_id);
731 describe_type(consumer_type, consumer, b_it->second.type_id);
732
Mark Lobodzinskib01451b2016-01-04 13:18:10 -0700733 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC",
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700734 "Type mismatch on location %d: '%s' vs '%s'", a_it->first, producer_type, consumer_type)) {
735 pass = false;
736 }
737 }
738 a_it++;
739 b_it++;
740 }
741 }
742
743 return pass;
744}
745
746enum FORMAT_TYPE {
747 FORMAT_TYPE_UNDEFINED,
748 FORMAT_TYPE_FLOAT, /* UNORM, SNORM, FLOAT, USCALED, SSCALED, SRGB -- anything we consider float in the shader */
749 FORMAT_TYPE_SINT,
750 FORMAT_TYPE_UINT,
751};
752
753static unsigned
754get_format_type(VkFormat fmt) {
755 switch (fmt) {
756 case VK_FORMAT_UNDEFINED:
757 return FORMAT_TYPE_UNDEFINED;
758 case VK_FORMAT_R8_SINT:
759 case VK_FORMAT_R8G8_SINT:
760 case VK_FORMAT_R8G8B8_SINT:
761 case VK_FORMAT_R8G8B8A8_SINT:
762 case VK_FORMAT_R16_SINT:
763 case VK_FORMAT_R16G16_SINT:
764 case VK_FORMAT_R16G16B16_SINT:
765 case VK_FORMAT_R16G16B16A16_SINT:
766 case VK_FORMAT_R32_SINT:
767 case VK_FORMAT_R32G32_SINT:
768 case VK_FORMAT_R32G32B32_SINT:
769 case VK_FORMAT_R32G32B32A32_SINT:
770 case VK_FORMAT_B8G8R8_SINT:
771 case VK_FORMAT_B8G8R8A8_SINT:
772 case VK_FORMAT_A2B10G10R10_SINT_PACK32:
773 case VK_FORMAT_A2R10G10B10_SINT_PACK32:
774 return FORMAT_TYPE_SINT;
775 case VK_FORMAT_R8_UINT:
776 case VK_FORMAT_R8G8_UINT:
777 case VK_FORMAT_R8G8B8_UINT:
778 case VK_FORMAT_R8G8B8A8_UINT:
779 case VK_FORMAT_R16_UINT:
780 case VK_FORMAT_R16G16_UINT:
781 case VK_FORMAT_R16G16B16_UINT:
782 case VK_FORMAT_R16G16B16A16_UINT:
783 case VK_FORMAT_R32_UINT:
784 case VK_FORMAT_R32G32_UINT:
785 case VK_FORMAT_R32G32B32_UINT:
786 case VK_FORMAT_R32G32B32A32_UINT:
787 case VK_FORMAT_B8G8R8_UINT:
788 case VK_FORMAT_B8G8R8A8_UINT:
789 case VK_FORMAT_A2B10G10R10_UINT_PACK32:
790 case VK_FORMAT_A2R10G10B10_UINT_PACK32:
791 return FORMAT_TYPE_UINT;
792 default:
793 return FORMAT_TYPE_FLOAT;
794 }
795}
796
797/* characterizes a SPIR-V type appearing in an interface to a FF stage,
798 * for comparison to a VkFormat's characterization above. */
799static unsigned
800get_fundamental_type(shader_module const *src, unsigned type)
801{
802 auto type_def_it = src->type_def_index.find(type);
803
804 if (type_def_it == src->type_def_index.end()) {
805 return FORMAT_TYPE_UNDEFINED;
806 }
807
808 unsigned int const *code = (unsigned int const *)&src->words[type_def_it->second];
809 unsigned opcode = code[0] & 0x0ffffu;
810 switch (opcode) {
811 case spv::OpTypeInt:
812 return code[3] ? FORMAT_TYPE_SINT : FORMAT_TYPE_UINT;
813 case spv::OpTypeFloat:
814 return FORMAT_TYPE_FLOAT;
815 case spv::OpTypeVector:
816 return get_fundamental_type(src, code[2]);
817 case spv::OpTypeMatrix:
818 return get_fundamental_type(src, code[2]);
819 case spv::OpTypeArray:
820 return get_fundamental_type(src, code[2]);
821 case spv::OpTypePointer:
822 return get_fundamental_type(src, code[3]);
823 default:
824 return FORMAT_TYPE_UNDEFINED;
825 }
826}
827
828static bool
829validate_vi_consistency(layer_data *my_data, VkDevice dev, VkPipelineVertexInputStateCreateInfo const *vi)
830{
831 /* walk the binding descriptions, which describe the step rate and stride of each vertex buffer.
832 * each binding should be specified only once.
833 */
834 std::unordered_map<uint32_t, VkVertexInputBindingDescription const *> bindings;
835 bool pass = true;
836
837 for (unsigned i = 0; i < vi->vertexBindingDescriptionCount; i++) {
838 auto desc = &vi->pVertexBindingDescriptions[i];
839 auto & binding = bindings[desc->binding];
840 if (binding) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -0700841 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__, SHADER_CHECKER_INCONSISTENT_VI, "SC",
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700842 "Duplicate vertex input binding descriptions for binding %d", desc->binding)) {
843 pass = false;
844 }
845 }
846 else {
847 binding = desc;
848 }
849 }
850
851 return pass;
852}
853
854static bool
855validate_vi_against_vs_inputs(layer_data *my_data, VkDevice dev, VkPipelineVertexInputStateCreateInfo const *vi, shader_module const *vs)
856{
857 std::map<uint32_t, interface_var> inputs;
858 /* we collect builtin inputs, but they will never appear in the VI state --
859 * the vs builtin inputs are generated in the pipeline, not sourced from buffers (VertexID, etc)
860 */
861 std::map<uint32_t, interface_var> builtin_inputs;
862 bool pass = true;
863
864 collect_interface_by_location(my_data, dev, vs, spv::StorageClassInput, inputs, builtin_inputs, false);
865
866 /* Build index by location */
867 std::map<uint32_t, VkVertexInputAttributeDescription const *> attribs;
868 if (vi) {
869 for (unsigned i = 0; i < vi->vertexAttributeDescriptionCount; i++)
870 attribs[vi->pVertexAttributeDescriptions[i].location] = &vi->pVertexAttributeDescriptions[i];
871 }
872
873 auto it_a = attribs.begin();
874 auto it_b = inputs.begin();
875
876 while ((attribs.size() > 0 && it_a != attribs.end()) || (inputs.size() > 0 && it_b != inputs.end())) {
877 bool a_at_end = attribs.size() == 0 || it_a == attribs.end();
878 bool b_at_end = inputs.size() == 0 || it_b == inputs.end();
879 auto a_first = a_at_end ? 0 : it_a->first;
880 auto b_first = b_at_end ? 0 : it_b->first;
881 if (b_at_end || a_first < b_first) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -0700882 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_PERF_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC",
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700883 "Vertex attribute at location %d not consumed by VS", a_first)) {
884 pass = false;
885 }
886 it_a++;
887 }
888 else if (a_at_end || b_first < a_first) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -0700889 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC",
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700890 "VS consumes input at location %d but not provided", b_first)) {
891 pass = false;
892 }
893 it_b++;
894 }
895 else {
896 unsigned attrib_type = get_format_type(it_a->second->format);
897 unsigned input_type = get_fundamental_type(vs, it_b->second.type_id);
898
899 /* type checking */
900 if (attrib_type != FORMAT_TYPE_UNDEFINED && input_type != FORMAT_TYPE_UNDEFINED && attrib_type != input_type) {
901 char vs_type[1024];
902 describe_type(vs_type, vs, it_b->second.type_id);
Mark Lobodzinskib01451b2016-01-04 13:18:10 -0700903 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC",
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700904 "Attribute type of `%s` at location %d does not match VS input type of `%s`",
905 string_VkFormat(it_a->second->format), a_first, vs_type)) {
906 pass = false;
907 }
908 }
909
910 /* OK! */
911 it_a++;
912 it_b++;
913 }
914 }
915
916 return pass;
917}
918
919static bool
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -0700920validate_fs_outputs_against_render_pass(layer_data *my_data, VkDevice dev, shader_module const *fs, RENDER_PASS_NODE const *rp, uint32_t subpass)
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700921{
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -0700922 const std::vector<VkFormat> &color_formats = rp->subpassColorFormats[subpass];
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700923 std::map<uint32_t, interface_var> outputs;
924 std::map<uint32_t, interface_var> builtin_outputs;
925 bool pass = true;
926
927 /* TODO: dual source blend index (spv::DecIndex, zero if not provided) */
928
929 collect_interface_by_location(my_data, dev, fs, spv::StorageClassOutput, outputs, builtin_outputs, false);
930
931 auto it = outputs.begin();
932 uint32_t attachment = 0;
933
934 /* Walk attachment list and outputs together -- this is a little overpowered since attachments
935 * are currently dense, but the parallel with matching between shader stages is nice.
936 */
937
938 /* TODO: Figure out compile error with cb->attachmentCount */
939 while ((outputs.size() > 0 && it != outputs.end()) || attachment < color_formats.size()) {
940 if (attachment == color_formats.size() || ( it != outputs.end() && it->first < attachment)) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -0700941 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC",
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700942 "FS writes to output location %d with no matching attachment", it->first)) {
943 pass = false;
944 }
945 it++;
946 }
947 else if (it == outputs.end() || it->first > attachment) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -0700948 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC",
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700949 "Attachment %d not written by FS", attachment)) {
950 pass = false;
951 }
952 attachment++;
953 }
954 else {
955 unsigned output_type = get_fundamental_type(fs, it->second.type_id);
956 unsigned att_type = get_format_type(color_formats[attachment]);
957
958 /* type checking */
959 if (att_type != FORMAT_TYPE_UNDEFINED && output_type != FORMAT_TYPE_UNDEFINED && att_type != output_type) {
960 char fs_type[1024];
961 describe_type(fs_type, fs, it->second.type_id);
Mark Lobodzinskib01451b2016-01-04 13:18:10 -0700962 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC",
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700963 "Attachment %d of type `%s` does not match FS output type of `%s`",
964 attachment, string_VkFormat(color_formats[attachment]), fs_type)) {
965 pass = false;
966 }
967 }
968
969 /* OK! */
970 it++;
971 attachment++;
972 }
973 }
974
975 return pass;
976}
977
978
979struct shader_stage_attributes {
980 char const * const name;
981 bool arrayed_input;
982};
983
984
985static shader_stage_attributes
986shader_stage_attribs[] = {
987 { "vertex shader", false },
988 { "tessellation control shader", true },
989 { "tessellation evaluation shader", false },
990 { "geometry shader", true },
991 { "fragment shader", false },
992};
993
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -0700994// For given pipelineLayout verify that the setLayout at slot.first
995// has the requested binding at slot.second
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700996static bool
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -0700997has_descriptor_binding(layer_data* my_data,
998 vector<VkDescriptorSetLayout>* pipelineLayout,
Tobin Ehlis7e2ad752015-12-01 09:48:58 -0700999 std::pair<unsigned, unsigned> slot)
1000{
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001001 if (!pipelineLayout)
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001002 return false;
1003
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001004 if (slot.first >= pipelineLayout->size())
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001005 return false;
1006
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001007 auto set = my_data->descriptorSetLayoutMap[(*pipelineLayout)[slot.first]]->bindings;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001008
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001009 return (set.find(slot.second) != set.end());
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001010}
1011
1012static uint32_t get_shader_stage_id(VkShaderStageFlagBits stage)
1013{
1014 uint32_t bit_pos = u_ffs(stage);
1015 return bit_pos-1;
1016}
1017
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001018// Block of code at start here for managing/tracking Pipeline state that this layer cares about
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001019
1020static uint64_t g_drawCount[NUM_DRAW_TYPES] = {0, 0, 0, 0};
1021
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001022// TODO : Should be tracking lastBound per commandBuffer and when draws occur, report based on that cmd buffer lastBound
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001023// Then need to synchronize the accesses based on cmd buffer so that if I'm reading state on one cmd buffer, updates
1024// to that same cmd buffer by separate thread are not changing state from underneath us
1025// Track the last cmd buffer touched by this thread
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001026
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06001027// prototype
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001028static GLOBAL_CB_NODE* getCBNode(layer_data*, const VkCommandBuffer);
Tobin Ehlis559c6382015-11-05 09:52:49 -07001029
Courtney Goeltzenleuchtercd2a0992015-07-09 11:44:38 -06001030static VkBool32 hasDrawCmd(GLOBAL_CB_NODE* pCB)
Tobin Ehlis53eddda2015-07-01 16:46:13 -06001031{
1032 for (uint32_t i=0; i<NUM_DRAW_TYPES; i++) {
1033 if (pCB->drawCount[i])
1034 return VK_TRUE;
1035 }
1036 return VK_FALSE;
1037}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001038
Tobin Ehlise382c5a2015-06-10 12:57:07 -06001039// Check object status for selected flag state
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06001040static VkBool32 validate_status(layer_data* my_data, GLOBAL_CB_NODE* pNode, CBStatusFlags enable_mask, CBStatusFlags status_mask, CBStatusFlags status_flag, VkFlags msg_flags, DRAW_STATE_ERROR error_code, const char* fail_msg)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001041{
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001042 // If non-zero enable mask is present, check it against status but if enable_mask
1043 // is 0 then no enable required so we should always just check status
1044 if ((!enable_mask) || (enable_mask & pNode->status)) {
1045 if ((pNode->status & status_mask) != status_flag) {
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06001046 // TODO : How to pass dispatchable objects as srcObject? Here src obj should be cmd buffer
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001047 return log_msg(my_data->report_data, msg_flags, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, error_code, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001048 "CB object %#" PRIxLEAST64 ": %s", reinterpret_cast<uint64_t>(pNode->commandBuffer), fail_msg);
Tobin Ehlise382c5a2015-06-10 12:57:07 -06001049 }
Tobin Ehlise382c5a2015-06-10 12:57:07 -06001050 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001051 return VK_FALSE;
Tobin Ehlise382c5a2015-06-10 12:57:07 -06001052}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001053
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001054// Retrieve pipeline node ptr for given pipeline object
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06001055static PIPELINE_NODE* getPipeline(layer_data* my_data, const VkPipeline pipeline)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001056{
1057 loader_platform_thread_lock_mutex(&globalLock);
Chia-I Wue2fc5522015-10-26 20:04:44 +08001058 if (my_data->pipelineMap.find(pipeline) == my_data->pipelineMap.end()) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001059 loader_platform_thread_unlock_mutex(&globalLock);
1060 return NULL;
1061 }
1062 loader_platform_thread_unlock_mutex(&globalLock);
Chia-I Wue2fc5522015-10-26 20:04:44 +08001063 return my_data->pipelineMap[pipeline];
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001064}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001065
Tobin Ehlisd332f282015-10-02 11:00:56 -06001066// Return VK_TRUE if for a given PSO, the given state enum is dynamic, else return VK_FALSE
1067static VkBool32 isDynamic(const PIPELINE_NODE* pPipeline, const VkDynamicState state)
1068{
1069 if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) {
1070 for (uint32_t i=0; i<pPipeline->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) {
1071 if (state == pPipeline->graphicsPipelineCI.pDynamicState->pDynamicStates[i])
1072 return VK_TRUE;
1073 }
1074 }
1075 return VK_FALSE;
1076}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001077
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001078// Validate state stored as flags at time of draw call
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06001079static VkBool32 validate_draw_state_flags(layer_data* my_data, GLOBAL_CB_NODE* pCB, VkBool32 indexedDraw) {
Courtney Goeltzenleuchtercd2a0992015-07-09 11:44:38 -06001080 VkBool32 result;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001081 result = validate_status(my_data, pCB, CBSTATUS_NONE, CBSTATUS_VIEWPORT_SET, CBSTATUS_VIEWPORT_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_VIEWPORT_NOT_BOUND, "Dynamic viewport state not set for this command buffer");
1082 result |= validate_status(my_data, pCB, CBSTATUS_NONE, CBSTATUS_SCISSOR_SET, CBSTATUS_SCISSOR_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_SCISSOR_NOT_BOUND, "Dynamic scissor state not set for this command buffer");
1083 result |= validate_status(my_data, pCB, CBSTATUS_NONE, CBSTATUS_LINE_WIDTH_SET, CBSTATUS_LINE_WIDTH_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_LINE_WIDTH_NOT_BOUND, "Dynamic line width state not set for this command buffer");
1084 result |= validate_status(my_data, pCB, CBSTATUS_NONE, CBSTATUS_DEPTH_BIAS_SET, CBSTATUS_DEPTH_BIAS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_DEPTH_BIAS_NOT_BOUND, "Dynamic depth bias state not set for this command buffer");
1085 result |= validate_status(my_data, pCB, CBSTATUS_COLOR_BLEND_WRITE_ENABLE, CBSTATUS_BLEND_SET, CBSTATUS_BLEND_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_BLEND_NOT_BOUND, "Dynamic blend object state not set for this command buffer");
1086 result |= validate_status(my_data, pCB, CBSTATUS_DEPTH_WRITE_ENABLE, CBSTATUS_DEPTH_BOUNDS_SET, CBSTATUS_DEPTH_BOUNDS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_DEPTH_BOUNDS_NOT_BOUND, "Dynamic depth bounds state not set for this command buffer");
1087 result |= validate_status(my_data, pCB, CBSTATUS_STENCIL_TEST_ENABLE, CBSTATUS_STENCIL_READ_MASK_SET, CBSTATUS_STENCIL_READ_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil read mask state not set for this command buffer");
1088 result |= validate_status(my_data, pCB, CBSTATUS_STENCIL_TEST_ENABLE, CBSTATUS_STENCIL_WRITE_MASK_SET, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil write mask state not set for this command buffer");
1089 result |= validate_status(my_data, pCB, CBSTATUS_STENCIL_TEST_ENABLE, CBSTATUS_STENCIL_REFERENCE_SET, CBSTATUS_STENCIL_REFERENCE_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil reference state not set for this command buffer");
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001090 if (indexedDraw)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001091 result |= validate_status(my_data, pCB, CBSTATUS_NONE, CBSTATUS_INDEX_BUFFER_BOUND, CBSTATUS_INDEX_BUFFER_BOUND, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_INDEX_BUFFER_NOT_BOUND, "Index buffer object not bound to this command buffer when Indexed Draw attempted");
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001092 return result;
1093}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001094
Tobin Ehlis651d9b02015-12-16 05:01:22 -07001095// Verify attachment reference compatibility according to spec
1096// If one array is larger, treat missing elements of shorter array as VK_ATTACHMENT_UNUSED & other array much match this
1097// If both AttachmentReference arrays have requested index, check their corresponding AttachementDescriptions
1098// to make sure that format and samples counts match.
1099// If not, they are not compatible.
1100static bool attachment_references_compatible(const uint32_t index, const VkAttachmentReference* pPrimary, const uint32_t primaryCount, const VkAttachmentDescription* pPrimaryAttachments,
1101 const VkAttachmentReference* pSecondary, const uint32_t secondaryCount, const VkAttachmentDescription* pSecondaryAttachments)
1102{
1103 if (index >= primaryCount) { // Check secondary as if primary is VK_ATTACHMENT_UNUSED
1104 if (VK_ATTACHMENT_UNUSED != pSecondary[index].attachment)
1105 return false;
1106 } else if (index >= secondaryCount) { // Check primary as if secondary is VK_ATTACHMENT_UNUSED
1107 if (VK_ATTACHMENT_UNUSED != pPrimary[index].attachment)
1108 return false;
1109 } else { // format and sample count must match
1110 if ((pPrimaryAttachments[pPrimary[index].attachment].format == pSecondaryAttachments[pSecondary[index].attachment].format) &&
1111 (pPrimaryAttachments[pPrimary[index].attachment].samples == pSecondaryAttachments[pSecondary[index].attachment].samples))
1112 return true;
1113 }
1114 // Format and sample counts didn't match
1115 return false;
1116}
1117
1118// For give primary and secondary RenderPass objects, verify that they're compatible
1119static bool verify_renderpass_compatibility(layer_data* my_data, const VkRenderPass primaryRP, const VkRenderPass secondaryRP, string& errorMsg)
1120{
1121 stringstream errorStr;
1122 if (my_data->renderPassMap.find(primaryRP) == my_data->renderPassMap.end()) {
1123 errorStr << "invalid VkRenderPass (" << primaryRP << ")";
1124 errorMsg = errorStr.str();
1125 return false;
1126 } else if (my_data->renderPassMap.find(secondaryRP) == my_data->renderPassMap.end()) {
1127 errorStr << "invalid VkRenderPass (" << secondaryRP << ")";
1128 errorMsg = errorStr.str();
1129 return false;
1130 }
1131 // Trivial pass case is exact same RP
1132 if (primaryRP == secondaryRP)
1133 return true;
1134 const VkRenderPassCreateInfo* primaryRPCI = my_data->renderPassMap[primaryRP]->pCreateInfo;
1135 const VkRenderPassCreateInfo* secondaryRPCI = my_data->renderPassMap[secondaryRP]->pCreateInfo;
1136 if (primaryRPCI->subpassCount != secondaryRPCI->subpassCount) {
1137 errorStr << "RenderPass for primary cmdBuffer has " << primaryRPCI->subpassCount << " subpasses but renderPass for secondary cmdBuffer has " << secondaryRPCI->subpassCount << " subpasses.";
1138 errorMsg = errorStr.str();
1139 return false;
1140 }
1141 uint32_t spIndex = 0;
1142 for (spIndex = 0; spIndex < primaryRPCI->subpassCount; ++spIndex) {
1143 // For each subpass, verify that corresponding color, input, resolve & depth/stencil attachment references are compatible
1144 uint32_t primaryColorCount = primaryRPCI->pSubpasses[spIndex].colorAttachmentCount;
1145 uint32_t secondaryColorCount = secondaryRPCI->pSubpasses[spIndex].colorAttachmentCount;
1146 uint32_t colorMax = std::max(primaryColorCount, secondaryColorCount);
1147 for (uint32_t cIdx = 0; cIdx < colorMax; ++cIdx) {
1148 if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pColorAttachments, primaryColorCount, primaryRPCI->pAttachments,
1149 secondaryRPCI->pSubpasses[spIndex].pColorAttachments, secondaryColorCount, secondaryRPCI->pAttachments)) {
1150 errorStr << "color attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible.";
1151 errorMsg = errorStr.str();
1152 return false;
1153 } else if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pResolveAttachments, primaryColorCount, primaryRPCI->pAttachments,
1154 secondaryRPCI->pSubpasses[spIndex].pResolveAttachments, secondaryColorCount, secondaryRPCI->pAttachments)) {
1155 errorStr << "resolve attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible.";
1156 errorMsg = errorStr.str();
1157 return false;
1158 } else if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, primaryColorCount, primaryRPCI->pAttachments,
1159 secondaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, secondaryColorCount, secondaryRPCI->pAttachments)) {
1160 errorStr << "depth/stencil attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible.";
1161 errorMsg = errorStr.str();
1162 return false;
1163 }
1164 }
1165 uint32_t primaryInputCount = primaryRPCI->pSubpasses[spIndex].inputAttachmentCount;
1166 uint32_t secondaryInputCount = secondaryRPCI->pSubpasses[spIndex].inputAttachmentCount;
1167 uint32_t inputMax = std::max(primaryInputCount, secondaryInputCount);
1168 for (uint32_t i = 0; i < inputMax; ++i) {
1169 if (!attachment_references_compatible(i, primaryRPCI->pSubpasses[spIndex].pInputAttachments, primaryColorCount, primaryRPCI->pAttachments,
1170 secondaryRPCI->pSubpasses[spIndex].pInputAttachments, secondaryColorCount, secondaryRPCI->pAttachments)) {
1171 errorStr << "input attachments at index " << i << " of subpass index " << spIndex << " are not compatible.";
1172 errorMsg = errorStr.str();
1173 return false;
1174 }
1175 }
1176 }
1177 return true;
1178}
1179
Tobin Ehlis559c6382015-11-05 09:52:49 -07001180// For give SET_NODE, verify that its Set is compatible w/ the setLayout corresponding to pipelineLayout[layoutIndex]
1181static bool verify_set_layout_compatibility(layer_data* my_data, const SET_NODE* pSet, const VkPipelineLayout layout, const uint32_t layoutIndex, string& errorMsg)
1182{
Tobin Ehlis8fab6562015-12-01 09:57:09 -07001183 stringstream errorStr;
Tobin Ehlis559c6382015-11-05 09:52:49 -07001184 if (my_data->pipelineLayoutMap.find(layout) == my_data->pipelineLayoutMap.end()) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07001185 errorStr << "invalid VkPipelineLayout (" << layout << ")";
1186 errorMsg = errorStr.str();
Tobin Ehlis559c6382015-11-05 09:52:49 -07001187 return false;
1188 }
1189 PIPELINE_LAYOUT_NODE pl = my_data->pipelineLayoutMap[layout];
1190 if (layoutIndex >= pl.descriptorSetLayouts.size()) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07001191 errorStr << "VkPipelineLayout (" << layout << ") only contains " << pl.descriptorSetLayouts.size() << " setLayouts corresponding to sets 0-" << pl.descriptorSetLayouts.size()-1 << ", but you're attempting to bind set to index " << layoutIndex;
1192 errorMsg = errorStr.str();
Tobin Ehlis559c6382015-11-05 09:52:49 -07001193 return false;
1194 }
1195 // Get the specific setLayout from PipelineLayout that overlaps this set
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001196 LAYOUT_NODE* pLayoutNode = my_data->descriptorSetLayoutMap[pl.descriptorSetLayouts[layoutIndex]];
Tobin Ehlis559c6382015-11-05 09:52:49 -07001197 if (pLayoutNode->layout == pSet->pLayout->layout) { // trivial pass case
1198 return true;
1199 }
Courtney Goeltzenleuchter51239472015-12-16 16:06:06 -07001200 size_t descriptorCount = pLayoutNode->descriptorTypes.size();
Tobin Ehlis559c6382015-11-05 09:52:49 -07001201 if (descriptorCount != pSet->pLayout->descriptorTypes.size()) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07001202 errorStr << "setLayout " << layoutIndex << " from pipelineLayout " << layout << " has " << descriptorCount << " descriptors, but corresponding set being bound has " << pSet->pLayout->descriptorTypes.size() << " descriptors.";
1203 errorMsg = errorStr.str();
Tobin Ehlis559c6382015-11-05 09:52:49 -07001204 return false; // trivial fail case
1205 }
1206 // Now need to check set against corresponding pipelineLayout to verify compatibility
Courtney Goeltzenleuchter51239472015-12-16 16:06:06 -07001207 for (size_t i=0; i<descriptorCount; ++i) {
Tobin Ehlis559c6382015-11-05 09:52:49 -07001208 // Need to verify that layouts are identically defined
1209 // TODO : Is below sufficient? Making sure that types & stageFlags match per descriptor
1210 // do we also need to check immutable samplers?
1211 if (pLayoutNode->descriptorTypes[i] != pSet->pLayout->descriptorTypes[i]) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07001212 errorStr << "descriptor " << i << " for descriptorSet being bound is type '" << string_VkDescriptorType(pSet->pLayout->descriptorTypes[i]) << "' but corresponding descriptor from pipelineLayout is type '" << string_VkDescriptorType(pLayoutNode->descriptorTypes[i]) << "'";
1213 errorMsg = errorStr.str();
Tobin Ehlis559c6382015-11-05 09:52:49 -07001214 return false;
1215 }
1216 if (pLayoutNode->stageFlags[i] != pSet->pLayout->stageFlags[i]) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07001217 errorStr << "stageFlags " << i << " for descriptorSet being bound is " << pSet->pLayout->stageFlags[i] << "' but corresponding descriptor from pipelineLayout has stageFlags " << pLayoutNode->stageFlags[i];
1218 errorMsg = errorStr.str();
Tobin Ehlis559c6382015-11-05 09:52:49 -07001219 return false;
1220 }
1221 }
1222 return true;
1223}
1224
Tobin Ehlis88452832015-12-03 09:40:56 -07001225// Validate that the shaders used by the given pipeline
1226// As a side effect this function also records the sets that are actually used by the pipeline
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07001227static VkBool32
Tobin Ehlis88452832015-12-03 09:40:56 -07001228validate_pipeline_shaders(layer_data *my_data, VkDevice dev, PIPELINE_NODE* pPipeline)
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001229{
Tobin Ehlis88452832015-12-03 09:40:56 -07001230 VkGraphicsPipelineCreateInfo const *pCreateInfo = &pPipeline->graphicsPipelineCI;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001231 /* We seem to allow pipeline stages to be specified out of order, so collect and identify them
1232 * before trying to do anything more: */
1233 int vertex_stage = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT);
1234 int geometry_stage = get_shader_stage_id(VK_SHADER_STAGE_GEOMETRY_BIT);
1235 int fragment_stage = get_shader_stage_id(VK_SHADER_STAGE_FRAGMENT_BIT);
1236
1237 shader_module **shaders = new shader_module*[fragment_stage + 1]; /* exclude CS */
1238 memset(shaders, 0, sizeof(shader_module *) * (fragment_stage +1));
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001239 RENDER_PASS_NODE const *rp = 0;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001240 VkPipelineVertexInputStateCreateInfo const *vi = 0;
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07001241 VkBool32 pass = true;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001242
1243 for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
1244 VkPipelineShaderStageCreateInfo const *pStage = &pCreateInfo->pStages[i];
1245 if (pStage->sType == VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO) {
1246
1247 if ((pStage->stage & (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_FRAGMENT_BIT
1248 | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) == 0) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001249 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__, SHADER_CHECKER_UNKNOWN_STAGE, "SC",
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001250 "Unknown shader stage %d", pStage->stage)) {
1251 pass = false;
1252 }
1253 }
1254 else {
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001255 shader_module *module = my_data->shaderModuleMap[pStage->module];
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001256 shaders[get_shader_stage_id(pStage->stage)] = module;
1257
1258 /* validate descriptor set layout against what the spirv module actually uses */
1259 std::map<std::pair<unsigned, unsigned>, interface_var> descriptor_uses;
1260 collect_interface_by_descriptor_slot(my_data, dev, module, spv::StorageClassUniform,
1261 descriptor_uses);
1262
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001263 auto layouts = pCreateInfo->layout != VK_NULL_HANDLE ?
1264 &(my_data->pipelineLayoutMap[pCreateInfo->layout].descriptorSetLayouts) : nullptr;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001265
1266 for (auto it = descriptor_uses.begin(); it != descriptor_uses.end(); it++) {
Tobin Ehlis88452832015-12-03 09:40:56 -07001267 // As a side-effect of this function, capture which sets are used by the pipeline
1268 pPipeline->active_sets.insert(it->first.first);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001269
1270 /* find the matching binding */
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001271 auto found = has_descriptor_binding(my_data, layouts, it->first);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001272
1273 if (!found) {
1274 char type_name[1024];
1275 describe_type(type_name, module, it->second.type_id);
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001276 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /*dev*/0, __LINE__,
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001277 SHADER_CHECKER_MISSING_DESCRIPTOR, "SC",
1278 "Shader uses descriptor slot %u.%u (used as type `%s`) but not declared in pipeline layout",
1279 it->first.first, it->first.second, type_name)) {
1280 pass = false;
1281 }
1282 }
1283 }
1284 }
1285 }
1286 }
1287
1288 if (pCreateInfo->renderPass != VK_NULL_HANDLE)
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001289 rp = my_data->renderPassMap[pCreateInfo->renderPass];
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07001290
1291 vi = pCreateInfo->pVertexInputState;
1292
1293 if (vi) {
1294 pass = validate_vi_consistency(my_data, dev, vi) && pass;
1295 }
1296
1297 if (shaders[vertex_stage]) {
1298 pass = validate_vi_against_vs_inputs(my_data, dev, vi, shaders[vertex_stage]) && pass;
1299 }
1300
1301 /* TODO: enforce rules about present combinations of shaders */
1302 int producer = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT);
1303 int consumer = get_shader_stage_id(VK_SHADER_STAGE_GEOMETRY_BIT);
1304
1305 while (!shaders[producer] && producer != fragment_stage) {
1306 producer++;
1307 consumer++;
1308 }
1309
1310 for (; producer != fragment_stage && consumer <= fragment_stage; consumer++) {
1311 assert(shaders[producer]);
1312 if (shaders[consumer]) {
1313 pass = validate_interface_between_stages(my_data, dev,
1314 shaders[producer], shader_stage_attribs[producer].name,
1315 shaders[consumer], shader_stage_attribs[consumer].name,
1316 shader_stage_attribs[consumer].arrayed_input) && pass;
1317
1318 producer = consumer;
1319 }
1320 }
1321
1322 if (shaders[fragment_stage] && rp) {
1323 pass = validate_fs_outputs_against_render_pass(my_data, dev, shaders[fragment_stage], rp, pCreateInfo->subpass) && pass;
1324 }
1325
1326 delete shaders;
1327
1328 return pass;
1329}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001330
Tobin Ehlisf6585052015-12-17 11:48:42 -07001331// Return Set node ptr for specified set or else NULL
1332static SET_NODE* getSetNode(layer_data* my_data, const VkDescriptorSet set)
1333{
1334 loader_platform_thread_lock_mutex(&globalLock);
1335 if (my_data->setMap.find(set) == my_data->setMap.end()) {
1336 loader_platform_thread_unlock_mutex(&globalLock);
1337 return NULL;
1338 }
1339 loader_platform_thread_unlock_mutex(&globalLock);
1340 return my_data->setMap[set];
1341}
1342
1343// For the given set, verify that for each dynamic descriptor in that set that its
1344// dynamic offset combined with the offet and range from its descriptor update
1345// do not overflow the size of its buffer being updated
1346static VkBool32 validate_dynamic_offsets(layer_data* my_data, const SET_NODE* pSet)
1347{
1348 VkBool32 result = VK_FALSE;
1349 if (pSet->dynamicOffsets.empty())
1350 return result;
1351
1352 VkWriteDescriptorSet* pWDS = NULL;
1353 uint32_t dynOffsetIndex = 0;
1354 VkDeviceSize bufferSize = 0;
1355 for (uint32_t i=0; i < pSet->descriptorCount; ++i) {
1356 switch (pSet->ppDescriptors[i]->sType) {
1357 case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
1358 pWDS = (VkWriteDescriptorSet*)pSet->ppDescriptors[i];
1359 if ((pWDS->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
1360 (pWDS->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
1361 for (uint32_t j=0; j<pWDS->descriptorCount; ++j) {
Michael Lentine700b0aa2015-10-30 17:57:32 -07001362 bufferSize = my_data->bufferMap[pWDS->pBufferInfo[j].buffer].create_info->size;
Tobin Ehlisf6585052015-12-17 11:48:42 -07001363 if ((pSet->dynamicOffsets[dynOffsetIndex] + pWDS->pBufferInfo[j].offset + pWDS->pBufferInfo[j].range) > bufferSize) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001364 result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pSet->set, __LINE__, DRAWSTATE_DYNAMIC_OFFSET_OVERFLOW, "DS",
Tobin Ehlisf6585052015-12-17 11:48:42 -07001365 "VkDescriptorSet (%#" PRIxLEAST64 ") bound as set #%u has dynamic offset %u. Combined with offet %#" PRIxLEAST64 " and range %#" PRIxLEAST64 " from its update, this oversteps its buffer (%#" PRIxLEAST64 ") which has a size of %#" PRIxLEAST64 ".",
1366 (uint64_t)pSet->set, i, pSet->dynamicOffsets[dynOffsetIndex], pWDS->pBufferInfo[j].offset, pWDS->pBufferInfo[j].range, (uint64_t)pWDS->pBufferInfo[j].buffer, bufferSize);
1367 }
1368 dynOffsetIndex++;
1369 i += j; // Advance i to end of this set of descriptors (++i at end of for loop will move 1 index past last of these descriptors)
1370 }
1371 }
1372 break;
1373 default: // Currently only shadowing Write update nodes so shouldn't get here
1374 assert(0);
1375 continue;
1376 }
1377 }
1378 return result;
1379}
1380
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001381// Validate overall state at the time of a draw call
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06001382static VkBool32 validate_draw_state(layer_data* my_data, GLOBAL_CB_NODE* pCB, VkBool32 indexedDraw) {
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001383 // First check flag states
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06001384 VkBool32 result = validate_draw_state_flags(my_data, pCB, indexedDraw);
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06001385 PIPELINE_NODE* pPipe = getPipeline(my_data, pCB->lastBoundPipeline);
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001386 // Now complete other state checks
Tobin Ehlise90e66d2015-09-09 13:31:01 -06001387 // TODO : Currently only performing next check if *something* was bound (non-zero last bound)
1388 // There is probably a better way to gate when this check happens, and to know if something *should* have been bound
1389 // We should have that check separately and then gate this check based on that check
Mark Lobodzinski74635932015-12-18 15:35:38 -07001390 if (pPipe) {
1391 if (pCB->lastBoundPipelineLayout) {
1392 string errorString;
1393 for (auto setIndex : pPipe->active_sets) {
1394 // If valid set is not bound throw an error
1395 if ((pCB->boundDescriptorSets.size() <= setIndex) || (!pCB->boundDescriptorSets[setIndex])) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001396 result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS",
Mark Lobodzinski74635932015-12-18 15:35:38 -07001397 "VkPipeline %#" PRIxLEAST64 " uses set #%u but that set is not bound.", (uint64_t)pPipe->pipeline, setIndex);
1398 } else if (!verify_set_layout_compatibility(my_data, my_data->setMap[pCB->boundDescriptorSets[setIndex]], pPipe->graphicsPipelineCI.layout, setIndex, errorString)) {
1399 // Set is bound but not compatible w/ overlapping pipelineLayout from PSO
1400 VkDescriptorSet setHandle = my_data->setMap[pCB->boundDescriptorSets[setIndex]]->set;
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001401 result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)setHandle, __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS",
Mark Lobodzinski74635932015-12-18 15:35:38 -07001402 "VkDescriptorSet (%#" PRIxLEAST64 ") bound as set #%u is not compatible with overlapping VkPipelineLayout %#" PRIxLEAST64 " due to: %s",
1403 (uint64_t)setHandle, setIndex, (uint64_t)pPipe->graphicsPipelineCI.layout, errorString.c_str());
Tobin Ehlisf6585052015-12-17 11:48:42 -07001404 } else { // Valid set is bound and layout compatible, validate any dynamic offsets
1405 // Pull the set node, and for each dynamic descriptor, make sure dynamic offset doesn't overstep buffer
1406 SET_NODE* pSet = getSetNode(my_data, pCB->boundDescriptorSets[setIndex]);
1407 result |= validate_dynamic_offsets(my_data, pSet);
Mark Lobodzinski74635932015-12-18 15:35:38 -07001408 }
Tobin Ehlis88452832015-12-03 09:40:56 -07001409 }
1410 }
Mark Lobodzinskidfcd9b62015-12-14 15:14:10 -07001411
Mark Lobodzinski74635932015-12-18 15:35:38 -07001412 // Verify Vtx binding
1413 if (pPipe->vtxBindingCount > 0) {
1414 VkPipelineVertexInputStateCreateInfo *vtxInCI = &pPipe->vertexInputCI;
1415 for (uint32_t i = 0; i < vtxInCI->vertexBindingDescriptionCount; i++) {
Michael Lentine700b0aa2015-10-30 17:57:32 -07001416 if ((pCB->currentDrawData.buffers.size() < (i+1)) || (pCB->currentDrawData.buffers[i] == VK_NULL_HANDLE)) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001417 result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
Mark Lobodzinski74635932015-12-18 15:35:38 -07001418 "The Pipeline State Object (%#" PRIxLEAST64 ") expects that this Command Buffer's vertex binding Index %d should be set via vkCmdBindVertexBuffers.",
1419 (uint64_t)pCB->lastBoundPipeline, i);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001420
Mark Lobodzinski74635932015-12-18 15:35:38 -07001421 }
1422 }
1423 } else {
Michael Lentine700b0aa2015-10-30 17:57:32 -07001424 if (!pCB->currentDrawData.buffers.empty()) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001425 result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_PERF_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS,
Mark Lobodzinski74635932015-12-18 15:35:38 -07001426 "DS", "Vertex buffers are bound to command buffer (%#" PRIxLEAST64 ") but no vertex buffers are attached to this Pipeline State Object (%#" PRIxLEAST64 ").",
1427 (uint64_t)pCB->commandBuffer, (uint64_t)pCB->lastBoundPipeline);
Tobin Ehlisf7bf4502015-09-09 15:12:35 -06001428 }
1429 }
Mark Lobodzinskidfcd9b62015-12-14 15:14:10 -07001430
Mark Lobodzinski74635932015-12-18 15:35:38 -07001431 // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count
1432 VkBool32 dynViewport = isDynamic(pPipe, VK_DYNAMIC_STATE_VIEWPORT);
1433 VkBool32 dynScissor = isDynamic(pPipe, VK_DYNAMIC_STATE_SCISSOR);
1434 if (dynViewport) {
1435 if (pCB->viewports.size() != pPipe->graphicsPipelineCI.pViewportState->viewportCount) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001436 result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
Mark Lobodzinski74635932015-12-18 15:35:38 -07001437 "Dynamic viewportCount from vkCmdSetViewport() is " PRINTF_SIZE_T_SPECIFIER ", but PSO viewportCount is %u. These counts must match.", pCB->viewports.size(), pPipe->graphicsPipelineCI.pViewportState->viewportCount);
1438 }
Tobin Ehlisd332f282015-10-02 11:00:56 -06001439 }
Mark Lobodzinski74635932015-12-18 15:35:38 -07001440 if (dynScissor) {
1441 if (pCB->scissors.size() != pPipe->graphicsPipelineCI.pViewportState->scissorCount) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001442 result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
Mark Lobodzinski74635932015-12-18 15:35:38 -07001443 "Dynamic scissorCount from vkCmdSetScissor() is " PRINTF_SIZE_T_SPECIFIER ", but PSO scissorCount is %u. These counts must match.", pCB->scissors.size(), pPipe->graphicsPipelineCI.pViewportState->scissorCount);
1444 }
Tobin Ehlisd332f282015-10-02 11:00:56 -06001445 }
1446 }
Tobin Ehlis429b91d2015-06-22 17:20:50 -06001447 return result;
1448}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001449
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001450// Verify that create state for a pipeline is valid
Tobin Ehlis88452832015-12-03 09:40:56 -07001451static VkBool32 verifyPipelineCreateState(layer_data* my_data, const VkDevice device, PIPELINE_NODE* pPipeline)
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001452{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001453 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinski2fd2d032015-12-16 14:25:22 -07001454
Tobin Ehlis88452832015-12-03 09:40:56 -07001455 if (!validate_pipeline_shaders(my_data, device, pPipeline)) {
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001456 skipCall = VK_TRUE;
1457 }
Mark Lobodzinski2fd2d032015-12-16 14:25:22 -07001458
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001459 // VS is required
1460 if (!(pPipeline->active_shaders & VK_SHADER_STAGE_VERTEX_BIT)) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001461 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001462 "Invalid Pipeline CreateInfo State: Vtx Shader required");
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001463 }
1464 // Either both or neither TC/TE shaders should be defined
Courtney Goeltzenleuchter96835892015-10-15 17:35:38 -06001465 if (((pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) == 0) !=
1466 ((pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) == 0) ) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001467 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001468 "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair");
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001469 }
1470 // Compute shaders should be specified independent of Gfx shaders
1471 if ((pPipeline->active_shaders & VK_SHADER_STAGE_COMPUTE_BIT) &&
Courtney Goeltzenleuchter96835892015-10-15 17:35:38 -06001472 (pPipeline->active_shaders & (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
1473 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_GEOMETRY_BIT |
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001474 VK_SHADER_STAGE_FRAGMENT_BIT))) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001475 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001476 "Invalid Pipeline CreateInfo State: Do not specify Compute Shader for Gfx Pipeline");
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001477 }
Chia-I Wu515eb8f2015-10-31 00:31:16 +08001478 // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology is only valid for tessellation pipelines.
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001479 // Mismatching primitive topology and tessellation fails graphics pipeline creation.
Courtney Goeltzenleuchter96835892015-10-15 17:35:38 -06001480 if (pPipeline->active_shaders & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) &&
Chia-I Wu515eb8f2015-10-31 00:31:16 +08001481 (pPipeline->iaStateCI.topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001482 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
Chia-I Wu515eb8f2015-10-31 00:31:16 +08001483 "Invalid Pipeline CreateInfo State: VK_PRIMITIVE_TOPOLOGY_PATCH_LIST must be set as IA topology for tessellation pipelines");
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001484 }
Chia-I Wu515eb8f2015-10-31 00:31:16 +08001485 if (pPipeline->iaStateCI.topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) {
Courtney Goeltzenleuchter96835892015-10-15 17:35:38 -06001486 if (~pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001487 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
Chia-I Wu515eb8f2015-10-31 00:31:16 +08001488 "Invalid Pipeline CreateInfo State: VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology is only valid for tessellation pipelines");
Tobin Ehlis912df022015-09-17 08:46:18 -06001489 }
1490 if (!pPipeline->tessStateCI.patchControlPoints || (pPipeline->tessStateCI.patchControlPoints > 32)) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001491 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
Chia-I Wu515eb8f2015-10-31 00:31:16 +08001492 "Invalid Pipeline CreateInfo State: VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology used with patchControlPoints value %u."
Tobin Ehlis912df022015-09-17 08:46:18 -06001493 " patchControlPoints should be >0 and <=32.", pPipeline->tessStateCI.patchControlPoints);
1494 }
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001495 }
Tobin Ehlisd332f282015-10-02 11:00:56 -06001496 // Viewport state must be included and viewport and scissor counts should always match
Tobin Ehlise68360f2015-10-01 11:15:13 -06001497 // NOTE : Even if these are flagged as dynamic, counts need to be set correctly for shader compiler
Tobin Ehlisd332f282015-10-02 11:00:56 -06001498 if (!pPipeline->graphicsPipelineCI.pViewportState) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001499 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
Tobin Ehlisd332f282015-10-02 11:00:56 -06001500 "Gfx Pipeline pViewportState is null. Even if viewport and scissors are dynamic PSO must include viewportCount and scissorCount in pViewportState.");
1501 } else if (pPipeline->graphicsPipelineCI.pViewportState->scissorCount != pPipeline->graphicsPipelineCI.pViewportState->viewportCount) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001502 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
Tobin Ehlise68360f2015-10-01 11:15:13 -06001503 "Gfx Pipeline viewport count (%u) must match scissor count (%u).", pPipeline->vpStateCI.viewportCount, pPipeline->vpStateCI.scissorCount);
Tobin Ehlisd332f282015-10-02 11:00:56 -06001504 } else {
1505 // If viewport or scissor are not dynamic, then verify that data is appropriate for count
1506 VkBool32 dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT);
1507 VkBool32 dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR);
1508 if (!dynViewport) {
1509 if (pPipeline->graphicsPipelineCI.pViewportState->viewportCount && !pPipeline->graphicsPipelineCI.pViewportState->pViewports) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001510 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
Courtney Goeltzenleuchterb19042e2015-11-25 11:38:54 -07001511 "Gfx Pipeline viewportCount is %u, but pViewports is NULL. For non-zero viewportCount, you must either include pViewports data, or include viewport in pDynamicState and set it with vkCmdSetViewport().", pPipeline->graphicsPipelineCI.pViewportState->viewportCount);
Tobin Ehlise68360f2015-10-01 11:15:13 -06001512 }
1513 }
Tobin Ehlisd332f282015-10-02 11:00:56 -06001514 if (!dynScissor) {
1515 if (pPipeline->graphicsPipelineCI.pViewportState->scissorCount && !pPipeline->graphicsPipelineCI.pViewportState->pScissors) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001516 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
Courtney Goeltzenleuchterb19042e2015-11-25 11:38:54 -07001517 "Gfx Pipeline scissorCount is %u, but pScissors is NULL. For non-zero scissorCount, you must either include pScissors data, or include scissor in pDynamicState and set it with vkCmdSetScissor().", pPipeline->graphicsPipelineCI.pViewportState->scissorCount);
Tobin Ehlisd332f282015-10-02 11:00:56 -06001518 }
Tobin Ehlise68360f2015-10-01 11:15:13 -06001519 }
1520 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001521 return skipCall;
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001522}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001523
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001524// Init the pipeline mapping info based on pipeline create info LL tree
1525// Threading note : Calls to this function should wrapped in mutex
Tobin Ehlis88452832015-12-03 09:40:56 -07001526// TODO : this should really just be in the constructor for PIPELINE_NODE
Mark Lobodzinski475a2182015-11-10 15:25:01 -07001527static PIPELINE_NODE* initGraphicsPipeline(layer_data* dev_data, const VkGraphicsPipelineCreateInfo* pCreateInfo, PIPELINE_NODE* pBasePipeline)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001528{
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001529 PIPELINE_NODE* pPipeline = new PIPELINE_NODE;
Mark Lobodzinskic44baa52015-12-11 11:56:07 -07001530
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001531 if (pBasePipeline) {
Mark Lobodzinskic44baa52015-12-11 11:56:07 -07001532 *pPipeline = *pBasePipeline;
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001533 }
Mark Lobodzinskic44baa52015-12-11 11:56:07 -07001534
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001535 // First init create info
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001536 memcpy(&pPipeline->graphicsPipelineCI, pCreateInfo, sizeof(VkGraphicsPipelineCreateInfo));
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001537
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001538 size_t bufferSize = 0;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001539 const VkPipelineVertexInputStateCreateInfo* pVICI = NULL;
Tobin Ehlis5a65cca2015-07-13 13:14:24 -06001540 const VkPipelineColorBlendStateCreateInfo* pCBCI = NULL;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001541
1542 for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
1543 const VkPipelineShaderStageCreateInfo *pPSSCI = &pCreateInfo->pStages[i];
1544
Chia-I Wu28e06912015-10-31 00:31:16 +08001545 switch (pPSSCI->stage) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001546 case VK_SHADER_STAGE_VERTEX_BIT:
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001547 memcpy(&pPipeline->vsCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
1548 pPipeline->active_shaders |= VK_SHADER_STAGE_VERTEX_BIT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001549 break;
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001550 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001551 memcpy(&pPipeline->tcsCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
Courtney Goeltzenleuchter96835892015-10-15 17:35:38 -06001552 pPipeline->active_shaders |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001553 break;
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001554 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001555 memcpy(&pPipeline->tesCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
Courtney Goeltzenleuchter96835892015-10-15 17:35:38 -06001556 pPipeline->active_shaders |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001557 break;
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001558 case VK_SHADER_STAGE_GEOMETRY_BIT:
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001559 memcpy(&pPipeline->gsCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
1560 pPipeline->active_shaders |= VK_SHADER_STAGE_GEOMETRY_BIT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001561 break;
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001562 case VK_SHADER_STAGE_FRAGMENT_BIT:
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001563 memcpy(&pPipeline->fsCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
1564 pPipeline->active_shaders |= VK_SHADER_STAGE_FRAGMENT_BIT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001565 break;
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001566 case VK_SHADER_STAGE_COMPUTE_BIT:
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001567 // TODO : Flag error, CS is specified through VkComputePipelineCreateInfo
1568 pPipeline->active_shaders |= VK_SHADER_STAGE_COMPUTE_BIT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001569 break;
1570 default:
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001571 // TODO : Flag error
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001572 break;
1573 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001574 }
Tobin Ehlis963a4042015-09-29 08:18:34 -06001575 // Copy over GraphicsPipelineCreateInfo structure embedded pointers
1576 if (pCreateInfo->stageCount != 0) {
1577 pPipeline->graphicsPipelineCI.pStages = new VkPipelineShaderStageCreateInfo[pCreateInfo->stageCount];
1578 bufferSize = pCreateInfo->stageCount * sizeof(VkPipelineShaderStageCreateInfo);
1579 memcpy((void*)pPipeline->graphicsPipelineCI.pStages, pCreateInfo->pStages, bufferSize);
1580 }
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001581 if (pCreateInfo->pVertexInputState != NULL) {
1582 memcpy((void*)&pPipeline->vertexInputCI, pCreateInfo->pVertexInputState , sizeof(VkPipelineVertexInputStateCreateInfo));
1583 // Copy embedded ptrs
1584 pVICI = pCreateInfo->pVertexInputState;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001585 pPipeline->vtxBindingCount = pVICI->vertexBindingDescriptionCount;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001586 if (pPipeline->vtxBindingCount) {
1587 pPipeline->pVertexBindingDescriptions = new VkVertexInputBindingDescription[pPipeline->vtxBindingCount];
1588 bufferSize = pPipeline->vtxBindingCount * sizeof(VkVertexInputBindingDescription);
1589 memcpy((void*)pPipeline->pVertexBindingDescriptions, pVICI->pVertexBindingDescriptions, bufferSize);
1590 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08001591 pPipeline->vtxAttributeCount = pVICI->vertexAttributeDescriptionCount;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001592 if (pPipeline->vtxAttributeCount) {
1593 pPipeline->pVertexAttributeDescriptions = new VkVertexInputAttributeDescription[pPipeline->vtxAttributeCount];
1594 bufferSize = pPipeline->vtxAttributeCount * sizeof(VkVertexInputAttributeDescription);
1595 memcpy((void*)pPipeline->pVertexAttributeDescriptions, pVICI->pVertexAttributeDescriptions, bufferSize);
1596 }
1597 pPipeline->graphicsPipelineCI.pVertexInputState = &pPipeline->vertexInputCI;
1598 }
Tony Barbourdd6e32e2015-07-10 15:29:03 -06001599 if (pCreateInfo->pInputAssemblyState != NULL) {
1600 memcpy((void*)&pPipeline->iaStateCI, pCreateInfo->pInputAssemblyState, sizeof(VkPipelineInputAssemblyStateCreateInfo));
1601 pPipeline->graphicsPipelineCI.pInputAssemblyState = &pPipeline->iaStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001602 }
Tony Barbourdd6e32e2015-07-10 15:29:03 -06001603 if (pCreateInfo->pTessellationState != NULL) {
1604 memcpy((void*)&pPipeline->tessStateCI, pCreateInfo->pTessellationState, sizeof(VkPipelineTessellationStateCreateInfo));
1605 pPipeline->graphicsPipelineCI.pTessellationState = &pPipeline->tessStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001606 }
Tony Barbourdd6e32e2015-07-10 15:29:03 -06001607 if (pCreateInfo->pViewportState != NULL) {
1608 memcpy((void*)&pPipeline->vpStateCI, pCreateInfo->pViewportState, sizeof(VkPipelineViewportStateCreateInfo));
1609 pPipeline->graphicsPipelineCI.pViewportState = &pPipeline->vpStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001610 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001611 if (pCreateInfo->pRasterizationState != NULL) {
1612 memcpy((void*)&pPipeline->rsStateCI, pCreateInfo->pRasterizationState, sizeof(VkPipelineRasterizationStateCreateInfo));
1613 pPipeline->graphicsPipelineCI.pRasterizationState = &pPipeline->rsStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001614 }
Tony Barbourdd6e32e2015-07-10 15:29:03 -06001615 if (pCreateInfo->pMultisampleState != NULL) {
1616 memcpy((void*)&pPipeline->msStateCI, pCreateInfo->pMultisampleState, sizeof(VkPipelineMultisampleStateCreateInfo));
1617 pPipeline->graphicsPipelineCI.pMultisampleState = &pPipeline->msStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001618 }
Tobin Ehlis963a4042015-09-29 08:18:34 -06001619 if (pCreateInfo->pDepthStencilState != NULL) {
1620 memcpy((void*)&pPipeline->dsStateCI, pCreateInfo->pDepthStencilState, sizeof(VkPipelineDepthStencilStateCreateInfo));
1621 pPipeline->graphicsPipelineCI.pDepthStencilState = &pPipeline->dsStateCI;
1622 }
Tony Barbourdd6e32e2015-07-10 15:29:03 -06001623 if (pCreateInfo->pColorBlendState != NULL) {
1624 memcpy((void*)&pPipeline->cbStateCI, pCreateInfo->pColorBlendState, sizeof(VkPipelineColorBlendStateCreateInfo));
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001625 // Copy embedded ptrs
Tony Barbourdd6e32e2015-07-10 15:29:03 -06001626 pCBCI = pCreateInfo->pColorBlendState;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001627 pPipeline->attachmentCount = pCBCI->attachmentCount;
1628 if (pPipeline->attachmentCount) {
Tony Barbourdd6e32e2015-07-10 15:29:03 -06001629 pPipeline->pAttachments = new VkPipelineColorBlendAttachmentState[pPipeline->attachmentCount];
1630 bufferSize = pPipeline->attachmentCount * sizeof(VkPipelineColorBlendAttachmentState);
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001631 memcpy((void*)pPipeline->pAttachments, pCBCI->pAttachments, bufferSize);
1632 }
Tony Barbourdd6e32e2015-07-10 15:29:03 -06001633 pPipeline->graphicsPipelineCI.pColorBlendState = &pPipeline->cbStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001634 }
Tobin Ehlis963a4042015-09-29 08:18:34 -06001635 if (pCreateInfo->pDynamicState != NULL) {
1636 memcpy((void*)&pPipeline->dynStateCI, pCreateInfo->pDynamicState, sizeof(VkPipelineDynamicStateCreateInfo));
1637 if (pPipeline->dynStateCI.dynamicStateCount) {
1638 pPipeline->dynStateCI.pDynamicStates = new VkDynamicState[pPipeline->dynStateCI.dynamicStateCount];
1639 bufferSize = pPipeline->dynStateCI.dynamicStateCount * sizeof(VkDynamicState);
1640 memcpy((void*)pPipeline->dynStateCI.pDynamicStates, pCreateInfo->pDynamicState->pDynamicStates, bufferSize);
1641 }
1642 pPipeline->graphicsPipelineCI.pDynamicState = &pPipeline->dynStateCI;
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001643 }
Tobin Ehlis88452832015-12-03 09:40:56 -07001644 pPipeline->active_sets.clear();
Tobin Ehlis75283bf2015-06-18 15:59:33 -06001645 return pPipeline;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001646}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001647
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001648// Free the Pipeline nodes
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06001649static void deletePipelines(layer_data* my_data)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001650{
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06001651 if (my_data->pipelineMap.size() <= 0)
David Pinedod8f83d82015-04-27 16:36:17 -06001652 return;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06001653 for (auto ii=my_data->pipelineMap.begin(); ii!=my_data->pipelineMap.end(); ++ii) {
Mark Lobodzinskid5732f32015-06-23 15:11:57 -06001654 if ((*ii).second->graphicsPipelineCI.stageCount != 0) {
1655 delete[] (*ii).second->graphicsPipelineCI.pStages;
1656 }
Tobin Ehlisf313c8b2015-04-01 11:59:08 -06001657 if ((*ii).second->pVertexBindingDescriptions) {
1658 delete[] (*ii).second->pVertexBindingDescriptions;
1659 }
1660 if ((*ii).second->pVertexAttributeDescriptions) {
1661 delete[] (*ii).second->pVertexAttributeDescriptions;
1662 }
1663 if ((*ii).second->pAttachments) {
1664 delete[] (*ii).second->pAttachments;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001665 }
Tobin Ehlis963a4042015-09-29 08:18:34 -06001666 if ((*ii).second->dynStateCI.dynamicStateCount != 0) {
1667 delete[] (*ii).second->dynStateCI.pDynamicStates;
1668 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001669 delete (*ii).second;
1670 }
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06001671 my_data->pipelineMap.clear();
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001672}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001673
Tobin Ehliseba312c2015-04-01 08:40:34 -06001674// For given pipeline, return number of MSAA samples, or one if MSAA disabled
Chia-I Wu5c17c962015-10-31 00:31:16 +08001675static VkSampleCountFlagBits getNumSamples(layer_data* my_data, const VkPipeline pipeline)
Tobin Ehliseba312c2015-04-01 08:40:34 -06001676{
Chia-I Wue2fc5522015-10-26 20:04:44 +08001677 PIPELINE_NODE* pPipe = my_data->pipelineMap[pipeline];
Tobin Ehlis577188e2015-07-13 14:51:15 -06001678 if (VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO == pPipe->msStateCI.sType) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001679 return pPipe->msStateCI.rasterizationSamples;
Tobin Ehlis577188e2015-07-13 14:51:15 -06001680 }
Chia-I Wu5c17c962015-10-31 00:31:16 +08001681 return VK_SAMPLE_COUNT_1_BIT;
Tobin Ehliseba312c2015-04-01 08:40:34 -06001682}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001683
Tobin Ehliseba312c2015-04-01 08:40:34 -06001684// Validate state related to the PSO
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06001685static VkBool32 validatePipelineState(layer_data* my_data, const GLOBAL_CB_NODE* pCB, const VkPipelineBindPoint pipelineBindPoint, const VkPipeline pipeline)
Tobin Ehliseba312c2015-04-01 08:40:34 -06001686{
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001687 if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) {
Tobin Ehliseba312c2015-04-01 08:40:34 -06001688 // Verify that any MSAA request in PSO matches sample# in bound FB
Chia-I Wu5c17c962015-10-31 00:31:16 +08001689 VkSampleCountFlagBits psoNumSamples = getNumSamples(my_data, pipeline);
Tobin Ehliseba312c2015-04-01 08:40:34 -06001690 if (pCB->activeRenderPass) {
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001691 const VkRenderPassCreateInfo* pRPCI = my_data->renderPassMap[pCB->activeRenderPass]->pCreateInfo;
Chia-I Wu08accc62015-07-07 11:50:03 +08001692 const VkSubpassDescription* pSD = &pRPCI->pSubpasses[pCB->activeSubpass];
Chia-I Wu5c17c962015-10-31 00:31:16 +08001693 VkSampleCountFlagBits subpassNumSamples = (VkSampleCountFlagBits) 0;
Chia-I Wu08accc62015-07-07 11:50:03 +08001694 uint32_t i;
1695
Chia-I Wud50a7d72015-10-26 20:48:51 +08001696 for (i = 0; i < pSD->colorAttachmentCount; i++) {
Chia-I Wu5c17c962015-10-31 00:31:16 +08001697 VkSampleCountFlagBits samples;
Chia-I Wu08accc62015-07-07 11:50:03 +08001698
Cody Northropa505dda2015-08-04 11:16:41 -06001699 if (pSD->pColorAttachments[i].attachment == VK_ATTACHMENT_UNUSED)
Chia-I Wu08accc62015-07-07 11:50:03 +08001700 continue;
1701
Cody Northropa505dda2015-08-04 11:16:41 -06001702 samples = pRPCI->pAttachments[pSD->pColorAttachments[i].attachment].samples;
Chia-I Wu5c17c962015-10-31 00:31:16 +08001703 if (subpassNumSamples == (VkSampleCountFlagBits) 0) {
Chia-I Wu08accc62015-07-07 11:50:03 +08001704 subpassNumSamples = samples;
1705 } else if (subpassNumSamples != samples) {
Chia-I Wu5c17c962015-10-31 00:31:16 +08001706 subpassNumSamples = (VkSampleCountFlagBits) -1;
Chia-I Wu08accc62015-07-07 11:50:03 +08001707 break;
1708 }
1709 }
Chia-I Wu1efb7e52015-10-26 17:32:47 +08001710 if (pSD->pDepthStencilAttachment && pSD->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
Chia-I Wu5c17c962015-10-31 00:31:16 +08001711 const VkSampleCountFlagBits samples = pRPCI->pAttachments[pSD->pDepthStencilAttachment->attachment].samples;
1712 if (subpassNumSamples == (VkSampleCountFlagBits) 0)
Chia-I Wu08accc62015-07-07 11:50:03 +08001713 subpassNumSamples = samples;
1714 else if (subpassNumSamples != samples)
Chia-I Wu5c17c962015-10-31 00:31:16 +08001715 subpassNumSamples = (VkSampleCountFlagBits) -1;
Chia-I Wu08accc62015-07-07 11:50:03 +08001716 }
1717
1718 if (psoNumSamples != subpassNumSamples) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001719 return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, (uint64_t) pipeline, __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS",
Mark Lobodzinski5495d132015-09-30 16:19:16 -06001720 "Num samples mismatch! Binding PSO (%#" PRIxLEAST64 ") with %u samples while current RenderPass (%#" PRIxLEAST64 ") w/ %u samples!",
Chia-I Wue2fc5522015-10-26 20:04:44 +08001721 (uint64_t) pipeline, psoNumSamples, (uint64_t) pCB->activeRenderPass, subpassNumSamples);
Tobin Ehliseba312c2015-04-01 08:40:34 -06001722 }
1723 } else {
1724 // TODO : I believe it's an error if we reach this point and don't have an activeRenderPass
1725 // Verify and flag error as appropriate
1726 }
1727 // TODO : Add more checks here
1728 } else {
1729 // TODO : Validate non-gfx pipeline updates
1730 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001731 return VK_FALSE;
Tobin Ehliseba312c2015-04-01 08:40:34 -06001732}
1733
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001734// Block of code at start here specifically for managing/tracking DSs
1735
Tobin Ehlis793ad302015-04-03 12:01:11 -06001736// Return Pool node ptr for specified pool or else NULL
Mark Lobodzinski39298632015-11-18 08:38:27 -07001737static DESCRIPTOR_POOL_NODE* getPoolNode(layer_data* my_data, const VkDescriptorPool pool)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001738{
1739 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07001740 if (my_data->descriptorPoolMap.find(pool) == my_data->descriptorPoolMap.end()) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001741 loader_platform_thread_unlock_mutex(&globalLock);
1742 return NULL;
1743 }
1744 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07001745 return my_data->descriptorPoolMap[pool];
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001746}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001747
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06001748static LAYOUT_NODE* getLayoutNode(layer_data* my_data, const VkDescriptorSetLayout layout) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001749 loader_platform_thread_lock_mutex(&globalLock);
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001750 if (my_data->descriptorSetLayoutMap.find(layout) == my_data->descriptorSetLayoutMap.end()) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001751 loader_platform_thread_unlock_mutex(&globalLock);
1752 return NULL;
1753 }
1754 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07001755 return my_data->descriptorSetLayoutMap[layout];
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001756}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001757
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001758// Return VK_FALSE if update struct is of valid type, otherwise flag error and return code from callback
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06001759static VkBool32 validUpdateStruct(layer_data* my_data, const VkDevice device, const GENERIC_HEADER* pUpdateStruct)
Tobin Ehlis0174fed2015-05-28 12:10:17 -06001760{
Tobin Ehlis0174fed2015-05-28 12:10:17 -06001761 switch (pUpdateStruct->sType)
1762 {
Chia-I Wu9d00ed72015-05-25 16:27:55 +08001763 case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
1764 case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001765 return VK_FALSE;
Tobin Ehlis0174fed2015-05-28 12:10:17 -06001766 default:
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001767 return log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_UPDATE_STRUCT, "DS",
Tobin Ehlisa16e8922015-06-16 15:50:44 -06001768 "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
Tobin Ehlis0174fed2015-05-28 12:10:17 -06001769 }
1770}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001771
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001772// Set count for given update struct in the last parameter
Courtney Goeltzenleuchter085f8dd2015-12-16 16:08:44 -07001773// Return value of skipCall, which is only VK_TRUE if error occurs and callback signals execution to cease
Tobin Ehlisbaca3ab2015-10-27 12:54:50 -06001774static uint32_t getUpdateCount(layer_data* my_data, const VkDevice device, const GENERIC_HEADER* pUpdateStruct)
Tobin Ehlis793ad302015-04-03 12:01:11 -06001775{
1776 switch (pUpdateStruct->sType)
1777 {
Chia-I Wu9d00ed72015-05-25 16:27:55 +08001778 case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
Chia-I Wud50a7d72015-10-26 20:48:51 +08001779 return ((VkWriteDescriptorSet*)pUpdateStruct)->descriptorCount;
Chia-I Wu9d00ed72015-05-25 16:27:55 +08001780 case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
Tobin Ehlis793ad302015-04-03 12:01:11 -06001781 // TODO : Need to understand this case better and make sure code is correct
Chia-I Wud50a7d72015-10-26 20:48:51 +08001782 return ((VkCopyDescriptorSet*)pUpdateStruct)->descriptorCount;
Tobin Ehlis793ad302015-04-03 12:01:11 -06001783 }
Courtney Goeltzenleuchter7f47bca2015-12-16 16:08:08 -07001784
1785 return 0;
Tobin Ehlis793ad302015-04-03 12:01:11 -06001786}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001787
Tobin Ehlis793ad302015-04-03 12:01:11 -06001788// For given Layout Node and binding, return index where that binding begins
1789static uint32_t getBindingStartIndex(const LAYOUT_NODE* pLayout, const uint32_t binding)
1790{
1791 uint32_t offsetIndex = 0;
Chia-I Wud46e6ae2015-10-31 00:31:16 +08001792 for (uint32_t i = 0; i < pLayout->createInfo.bindingCount; i++) {
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07001793 if (pLayout->createInfo.pBindings[i].binding == binding)
Chia-I Wud46e6ae2015-10-31 00:31:16 +08001794 break;
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07001795 offsetIndex += pLayout->createInfo.pBindings[i].descriptorCount;
Tobin Ehlis793ad302015-04-03 12:01:11 -06001796 }
1797 return offsetIndex;
1798}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001799
Tobin Ehlis793ad302015-04-03 12:01:11 -06001800// For given layout node and binding, return last index that is updated
1801static uint32_t getBindingEndIndex(const LAYOUT_NODE* pLayout, const uint32_t binding)
1802{
1803 uint32_t offsetIndex = 0;
Chia-I Wud46e6ae2015-10-31 00:31:16 +08001804 for (uint32_t i = 0; i < pLayout->createInfo.bindingCount; i++) {
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07001805 offsetIndex += pLayout->createInfo.pBindings[i].descriptorCount;
1806 if (pLayout->createInfo.pBindings[i].binding == binding)
Chia-I Wud46e6ae2015-10-31 00:31:16 +08001807 break;
Tobin Ehlis793ad302015-04-03 12:01:11 -06001808 }
1809 return offsetIndex-1;
1810}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001811
Tobin Ehlisbaca3ab2015-10-27 12:54:50 -06001812// For given layout and update, return the first overall index of the layout that is updated
Tobin Ehlis8a62e632015-10-27 15:43:38 -06001813static uint32_t getUpdateStartIndex(layer_data* my_data, const VkDevice device, const LAYOUT_NODE* pLayout, const uint32_t binding, const uint32_t arrayIndex, const GENERIC_HEADER* pUpdateStruct)
Tobin Ehlis793ad302015-04-03 12:01:11 -06001814{
Tobin Ehlisbaca3ab2015-10-27 12:54:50 -06001815 return getBindingStartIndex(pLayout, binding)+arrayIndex;
Tobin Ehlis793ad302015-04-03 12:01:11 -06001816}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001817
Tobin Ehlis8a62e632015-10-27 15:43:38 -06001818// For given layout and update, return the last overall index of the layout that is updated
1819static uint32_t getUpdateEndIndex(layer_data* my_data, const VkDevice device, const LAYOUT_NODE* pLayout, const uint32_t binding, const uint32_t arrayIndex, const GENERIC_HEADER* pUpdateStruct)
Tobin Ehlis793ad302015-04-03 12:01:11 -06001820{
Tobin Ehlis8a62e632015-10-27 15:43:38 -06001821 uint32_t count = getUpdateCount(my_data, device, pUpdateStruct);
Tobin Ehlisbaca3ab2015-10-27 12:54:50 -06001822 return getBindingStartIndex(pLayout, binding)+arrayIndex+count-1;
Tobin Ehlis793ad302015-04-03 12:01:11 -06001823}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001824
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001825// Verify that the descriptor type in the update struct matches what's expected by the layout
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06001826static VkBool32 validateUpdateConsistency(layer_data* my_data, const VkDevice device, const LAYOUT_NODE* pLayout, const GENERIC_HEADER* pUpdateStruct, uint32_t startIndex, uint32_t endIndex)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001827{
1828 // First get actual type of update
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001829 VkBool32 skipCall = VK_FALSE;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001830 VkDescriptorType actualType;
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06001831 uint32_t i = 0;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001832 switch (pUpdateStruct->sType)
1833 {
Chia-I Wu9d00ed72015-05-25 16:27:55 +08001834 case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
1835 actualType = ((VkWriteDescriptorSet*)pUpdateStruct)->descriptorType;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001836 break;
Chia-I Wu9d00ed72015-05-25 16:27:55 +08001837 case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
1838 /* no need to validate */
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001839 return VK_FALSE;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001840 break;
1841 default:
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001842 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_UPDATE_STRUCT, "DS",
Tobin Ehlisa16e8922015-06-16 15:50:44 -06001843 "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001844 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001845 if (VK_FALSE == skipCall) {
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06001846 // Set first stageFlags as reference and verify that all other updates match it
1847 VkShaderStageFlags refStageFlags = pLayout->stageFlags[startIndex];
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001848 for (i = startIndex; i <= endIndex; i++) {
Tobin Ehlis644ff042015-10-20 10:11:55 -06001849 if (pLayout->descriptorTypes[i] != actualType) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001850 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_DESCRIPTOR_TYPE_MISMATCH, "DS",
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06001851 "Write descriptor update has descriptor type %s that does not match overlapping binding descriptor type of %s!",
1852 string_VkDescriptorType(actualType), string_VkDescriptorType(pLayout->descriptorTypes[i]));
1853 }
1854 if (pLayout->stageFlags[i] != refStageFlags) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001855 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_DESCRIPTOR_STAGEFLAGS_MISMATCH, "DS",
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06001856 "Write descriptor update has stageFlags %x that do not match overlapping binding descriptor stageFlags of %x!",
1857 refStageFlags, pLayout->stageFlags[i]);
Tobin Ehlis483cc352015-09-30 08:30:20 -06001858 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001859 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001860 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001861 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001862}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001863
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001864// Determine the update type, allocate a new struct of that type, shadow the given pUpdate
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001865// struct into the pNewNode param. Return VK_TRUE if error condition encountered and callback signals early exit.
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001866// NOTE : Calls to this function should be wrapped in mutex
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06001867static VkBool32 shadowUpdateNode(layer_data* my_data, const VkDevice device, GENERIC_HEADER* pUpdate, GENERIC_HEADER** pNewNode)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001868{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001869 VkBool32 skipCall = VK_FALSE;
Chia-I Wu9d00ed72015-05-25 16:27:55 +08001870 VkWriteDescriptorSet* pWDS = NULL;
1871 VkCopyDescriptorSet* pCDS = NULL;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001872 size_t array_size = 0;
1873 size_t base_array_size = 0;
1874 size_t total_array_size = 0;
1875 size_t baseBuffAddr = 0;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001876 switch (pUpdate->sType)
1877 {
Chia-I Wu9d00ed72015-05-25 16:27:55 +08001878 case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
1879 pWDS = new VkWriteDescriptorSet;
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001880 *pNewNode = (GENERIC_HEADER*)pWDS;
Chia-I Wu9d00ed72015-05-25 16:27:55 +08001881 memcpy(pWDS, pUpdate, sizeof(VkWriteDescriptorSet));
Courtney Goeltzenleuchter4cb6d922015-10-23 13:38:14 -06001882
1883 switch (pWDS->descriptorType) {
1884 case VK_DESCRIPTOR_TYPE_SAMPLER:
1885 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1886 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1887 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1888 {
Chia-I Wud50a7d72015-10-26 20:48:51 +08001889 VkDescriptorImageInfo *info = new VkDescriptorImageInfo[pWDS->descriptorCount];
1890 memcpy(info, pWDS->pImageInfo, pWDS->descriptorCount * sizeof(VkDescriptorImageInfo));
Courtney Goeltzenleuchter4cb6d922015-10-23 13:38:14 -06001891 pWDS->pImageInfo = info;
Tobin Ehlis8fab6562015-12-01 09:57:09 -07001892 }
Courtney Goeltzenleuchter4cb6d922015-10-23 13:38:14 -06001893 break;
1894 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1895 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1896 {
Chia-I Wud50a7d72015-10-26 20:48:51 +08001897 VkBufferView *info = new VkBufferView[pWDS->descriptorCount];
1898 memcpy(info, pWDS->pTexelBufferView, pWDS->descriptorCount * sizeof(VkBufferView));
Courtney Goeltzenleuchter4cb6d922015-10-23 13:38:14 -06001899 pWDS->pTexelBufferView = info;
1900 }
1901 break;
1902 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1903 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1904 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1905 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1906 {
Chia-I Wud50a7d72015-10-26 20:48:51 +08001907 VkDescriptorBufferInfo *info = new VkDescriptorBufferInfo[pWDS->descriptorCount];
1908 memcpy(info, pWDS->pBufferInfo, pWDS->descriptorCount * sizeof(VkDescriptorBufferInfo));
Courtney Goeltzenleuchter4cb6d922015-10-23 13:38:14 -06001909 pWDS->pBufferInfo = info;
1910 }
1911 break;
1912 default:
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07001913 return VK_ERROR_VALIDATION_FAILED_EXT;
Courtney Goeltzenleuchter4cb6d922015-10-23 13:38:14 -06001914 break;
1915 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001916 break;
Chia-I Wu9d00ed72015-05-25 16:27:55 +08001917 case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
1918 pCDS = new VkCopyDescriptorSet;
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001919 *pNewNode = (GENERIC_HEADER*)pCDS;
Chia-I Wu9d00ed72015-05-25 16:27:55 +08001920 memcpy(pCDS, pUpdate, sizeof(VkCopyDescriptorSet));
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001921 break;
1922 default:
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001923 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_UPDATE_STRUCT, "DS",
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001924 "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdate->sType), pUpdate->sType))
1925 return VK_TRUE;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001926 }
1927 // Make sure that pNext for the end of shadow copy is NULL
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06001928 (*pNewNode)->pNext = NULL;
1929 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06001930}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001931
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001932// Verify that given sampler is valid
1933static VkBool32 validateSampler(const layer_data* my_data, const VkSampler* pSampler, const VkBool32 immutable)
1934{
1935 VkBool32 skipCall = VK_FALSE;
Chia-I Wue2fc5522015-10-26 20:04:44 +08001936 auto sampIt = my_data->sampleMap.find(*pSampler);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001937 if (sampIt == my_data->sampleMap.end()) {
1938 if (!immutable) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001939 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, (uint64_t) *pSampler, __LINE__, DRAWSTATE_SAMPLER_DESCRIPTOR_ERROR, "DS",
Chia-I Wue2fc5522015-10-26 20:04:44 +08001940 "vkUpdateDescriptorSets: Attempt to update descriptor with invalid sampler %#" PRIxLEAST64, (uint64_t) *pSampler);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001941 } else { // immutable
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001942 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, (uint64_t) *pSampler, __LINE__, DRAWSTATE_SAMPLER_DESCRIPTOR_ERROR, "DS",
Chia-I Wue2fc5522015-10-26 20:04:44 +08001943 "vkUpdateDescriptorSets: Attempt to update descriptor whose binding has an invalid immutable sampler %#" PRIxLEAST64, (uint64_t) *pSampler);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001944 }
1945 } else {
1946 // TODO : Any further checks we want to do on the sampler?
1947 }
1948 return skipCall;
1949}
Tobin Ehlis559c6382015-11-05 09:52:49 -07001950
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001951// Verify that given imageView is valid
1952static VkBool32 validateImageView(const layer_data* my_data, const VkImageView* pImageView, const VkImageLayout imageLayout)
1953{
1954 VkBool32 skipCall = VK_FALSE;
Chia-I Wue2fc5522015-10-26 20:04:44 +08001955 auto ivIt = my_data->imageViewMap.find(*pImageView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001956 if (ivIt == my_data->imageViewMap.end()) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001957 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT, (uint64_t) *pImageView, __LINE__, DRAWSTATE_IMAGEVIEW_DESCRIPTOR_ERROR, "DS",
Chia-I Wue2fc5522015-10-26 20:04:44 +08001958 "vkUpdateDescriptorSets: Attempt to update descriptor with invalid imageView %#" PRIxLEAST64, (uint64_t) *pImageView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001959 } else {
1960 // Validate that imageLayout is compatible with aspectMask and image format
1961 VkImageAspectFlags aspectMask = ivIt->second->subresourceRange.aspectMask;
Chia-I Wue2fc5522015-10-26 20:04:44 +08001962 VkImage image = ivIt->second->image;
Michael Lentine7b236262015-10-23 12:41:44 -07001963 // TODO : Check here in case we have a bad image
Chia-I Wue2fc5522015-10-26 20:04:44 +08001964 auto imgIt = my_data->imageMap.find(image);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001965 if (imgIt == my_data->imageMap.end()) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001966 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t) image, __LINE__, DRAWSTATE_IMAGEVIEW_DESCRIPTOR_ERROR, "DS",
Michael Lentine7b236262015-10-23 12:41:44 -07001967 "vkUpdateDescriptorSets: Attempt to update descriptor with invalid image %#" PRIxLEAST64 " in imageView %#" PRIxLEAST64, (uint64_t) image, (uint64_t) *pImageView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001968 } else {
1969 VkFormat format = (*imgIt).second->format;
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -07001970 VkBool32 ds = vk_format_is_depth_or_stencil(format);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001971 switch (imageLayout) {
1972 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
1973 // Only Color bit must be set
1974 if ((aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001975 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT, (uint64_t) *pImageView, __LINE__,
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001976 DRAWSTATE_INVALID_IMAGE_ASPECT, "DS", "vkUpdateDescriptorSets: Updating descriptor with layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL and imageView %#" PRIxLEAST64 ""
Chia-I Wue2fc5522015-10-26 20:04:44 +08001977 " that does not have VK_IMAGE_ASPECT_COLOR_BIT set.", (uint64_t) *pImageView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001978 }
1979 // format must NOT be DS
1980 if (ds) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001981 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT, (uint64_t) *pImageView, __LINE__,
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001982 DRAWSTATE_IMAGEVIEW_DESCRIPTOR_ERROR, "DS", "vkUpdateDescriptorSets: Updating descriptor with layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL and imageView %#" PRIxLEAST64 ""
Chia-I Wue2fc5522015-10-26 20:04:44 +08001983 " but the image format is %s which is not a color format.", (uint64_t) *pImageView, string_VkFormat(format));
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001984 }
1985 break;
1986 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
1987 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
1988 // Depth or stencil bit must be set, but both must NOT be set
1989 if (aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) {
1990 if (aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) {
1991 // both must NOT be set
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001992 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT, (uint64_t) *pImageView, __LINE__,
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001993 DRAWSTATE_INVALID_IMAGE_ASPECT, "DS", "vkUpdateDescriptorSets: Updating descriptor with imageView %#" PRIxLEAST64 ""
Chia-I Wue2fc5522015-10-26 20:04:44 +08001994 " that has both STENCIL and DEPTH aspects set", (uint64_t) *pImageView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001995 }
1996 } else if (!(aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
1997 // Neither were set
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07001998 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT, (uint64_t) *pImageView, __LINE__,
Tobin Ehlisa1c28562015-10-23 16:00:08 -06001999 DRAWSTATE_INVALID_IMAGE_ASPECT, "DS", "vkUpdateDescriptorSets: Updating descriptor with layout %s and imageView %#" PRIxLEAST64 ""
Chia-I Wue2fc5522015-10-26 20:04:44 +08002000 " that does not have STENCIL or DEPTH aspect set.", string_VkImageLayout(imageLayout), (uint64_t) *pImageView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002001 }
2002 // format must be DS
2003 if (!ds) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002004 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT, (uint64_t) *pImageView, __LINE__,
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002005 DRAWSTATE_IMAGEVIEW_DESCRIPTOR_ERROR, "DS", "vkUpdateDescriptorSets: Updating descriptor with layout %s and imageView %#" PRIxLEAST64 ""
Chia-I Wue2fc5522015-10-26 20:04:44 +08002006 " but the image format is %s which is not a depth/stencil format.", string_VkImageLayout(imageLayout), (uint64_t) *pImageView, string_VkFormat(format));
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002007 }
2008 break;
2009 default:
2010 // anything to check for other layouts?
2011 break;
2012 }
2013 }
2014 }
2015 return skipCall;
2016}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002017
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002018// Verify that given bufferView is valid
2019static VkBool32 validateBufferView(const layer_data* my_data, const VkBufferView* pBufferView)
2020{
2021 VkBool32 skipCall = VK_FALSE;
Chia-I Wue2fc5522015-10-26 20:04:44 +08002022 auto sampIt = my_data->bufferViewMap.find(*pBufferView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002023 if (sampIt == my_data->bufferViewMap.end()) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002024 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT, (uint64_t) *pBufferView, __LINE__, DRAWSTATE_BUFFERVIEW_DESCRIPTOR_ERROR, "DS",
Chia-I Wue2fc5522015-10-26 20:04:44 +08002025 "vkUpdateDescriptorSets: Attempt to update descriptor with invalid bufferView %#" PRIxLEAST64, (uint64_t) *pBufferView);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002026 } else {
2027 // TODO : Any further checks we want to do on the bufferView?
2028 }
2029 return skipCall;
2030}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002031
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002032// Verify that given bufferInfo is valid
2033static VkBool32 validateBufferInfo(const layer_data* my_data, const VkDescriptorBufferInfo* pBufferInfo)
2034{
2035 VkBool32 skipCall = VK_FALSE;
Chia-I Wue2fc5522015-10-26 20:04:44 +08002036 auto sampIt = my_data->bufferMap.find(pBufferInfo->buffer);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002037 if (sampIt == my_data->bufferMap.end()) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002038 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, (uint64_t) pBufferInfo->buffer, __LINE__, DRAWSTATE_BUFFERINFO_DESCRIPTOR_ERROR, "DS",
Chia-I Wue2fc5522015-10-26 20:04:44 +08002039 "vkUpdateDescriptorSets: Attempt to update descriptor where bufferInfo has invalid buffer %#" PRIxLEAST64, (uint64_t) pBufferInfo->buffer);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002040 } else {
2041 // TODO : Any further checks we want to do on the bufferView?
2042 }
2043 return skipCall;
2044}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002045
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002046static VkBool32 validateUpdateContents(const layer_data* my_data, const VkWriteDescriptorSet *pWDS, const VkDescriptorSetLayoutBinding* pLayoutBinding)
2047{
2048 VkBool32 skipCall = VK_FALSE;
2049 // First verify that for the given Descriptor type, the correct DescriptorInfo data is supplied
2050 VkBufferView* pBufferView = NULL;
2051 const VkSampler* pSampler = NULL;
2052 VkImageView* pImageView = NULL;
2053 VkImageLayout* pImageLayout = NULL;
2054 VkDescriptorBufferInfo* pBufferInfo = NULL;
2055 VkBool32 immutable = VK_FALSE;
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002056 uint32_t i = 0;
2057 // For given update type, verify that update contents are correct
2058 switch (pWDS->descriptorType) {
2059 case VK_DESCRIPTOR_TYPE_SAMPLER:
Chia-I Wud50a7d72015-10-26 20:48:51 +08002060 for (i=0; i<pWDS->descriptorCount; ++i) {
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002061 skipCall |= validateSampler(my_data, &(pWDS->pImageInfo[i].sampler), immutable);
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002062 }
2063 break;
2064 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
Chia-I Wud50a7d72015-10-26 20:48:51 +08002065 for (i=0; i<pWDS->descriptorCount; ++i) {
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002066 if (NULL == pLayoutBinding->pImmutableSamplers) {
2067 pSampler = &(pWDS->pImageInfo[i].sampler);
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002068 if (immutable) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002069 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, (uint64_t) *pSampler, __LINE__, DRAWSTATE_INCONSISTENT_IMMUTABLE_SAMPLER_UPDATE, "DS",
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002070 "vkUpdateDescriptorSets: Update #%u is not an immutable sampler %#" PRIxLEAST64 ", but previous update(s) from this "
2071 "VkWriteDescriptorSet struct used an immutable sampler. All updates from a single struct must either "
Chia-I Wue2fc5522015-10-26 20:04:44 +08002072 "use immutable or non-immutable samplers.", i, (uint64_t) *pSampler);
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002073 }
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002074 } else {
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002075 if (i>0 && !immutable) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002076 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, (uint64_t) *pSampler, __LINE__, DRAWSTATE_INCONSISTENT_IMMUTABLE_SAMPLER_UPDATE, "DS",
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002077 "vkUpdateDescriptorSets: Update #%u is an immutable sampler, but previous update(s) from this "
2078 "VkWriteDescriptorSet struct used a non-immutable sampler. All updates from a single struct must either "
2079 "use immutable or non-immutable samplers.", i);
2080 }
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002081 immutable = VK_TRUE;
2082 pSampler = &(pLayoutBinding->pImmutableSamplers[i]);
2083 }
2084 skipCall |= validateSampler(my_data, pSampler, immutable);
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002085 }
2086 // Intentionally fall through here to also validate image stuff
2087 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2088 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2089 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
Chia-I Wud50a7d72015-10-26 20:48:51 +08002090 for (i=0; i<pWDS->descriptorCount; ++i) {
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002091 skipCall |= validateImageView(my_data, &(pWDS->pImageInfo[i].imageView), pWDS->pImageInfo[i].imageLayout);
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002092 }
2093 break;
2094 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2095 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
Chia-I Wud50a7d72015-10-26 20:48:51 +08002096 for (i=0; i<pWDS->descriptorCount; ++i) {
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002097 skipCall |= validateBufferView(my_data, &(pWDS->pTexelBufferView[i]));
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002098 }
2099 break;
2100 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2101 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2102 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2103 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
Chia-I Wud50a7d72015-10-26 20:48:51 +08002104 for (i=0; i<pWDS->descriptorCount; ++i) {
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002105 skipCall |= validateBufferInfo(my_data, &(pWDS->pBufferInfo[i]));
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002106 }
2107 break;
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002108 }
2109 return skipCall;
2110}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002111
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002112// update DS mappings based on write and copy update arrays
Chia-I Wu40cf0ae2015-10-26 17:20:32 +08002113static VkBool32 dsUpdate(layer_data* my_data, VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pWDS, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pCDS)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002114{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002115 VkBool32 skipCall = VK_FALSE;
Chia-I Wu9d00ed72015-05-25 16:27:55 +08002116
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002117 loader_platform_thread_lock_mutex(&globalLock);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002118 LAYOUT_NODE* pLayout = NULL;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06002119 VkDescriptorSetLayoutCreateInfo* pLayoutCI = NULL;
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002120 // Validate Write updates
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002121 uint32_t i = 0;
Chia-I Wu40cf0ae2015-10-26 17:20:32 +08002122 for (i=0; i < descriptorWriteCount; i++) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002123 VkDescriptorSet ds = pWDS[i].dstSet;
Chia-I Wue2fc5522015-10-26 20:04:44 +08002124 SET_NODE* pSet = my_data->setMap[ds];
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002125 GENERIC_HEADER* pUpdate = (GENERIC_HEADER*) &pWDS[i];
Tobin Ehlis793ad302015-04-03 12:01:11 -06002126 pLayout = pSet->pLayout;
Tobin Ehlis0174fed2015-05-28 12:10:17 -06002127 // First verify valid update struct
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06002128 if ((skipCall = validUpdateStruct(my_data, device, pUpdate)) == VK_TRUE) {
Tobin Ehlis0174fed2015-05-28 12:10:17 -06002129 break;
2130 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002131 uint32_t binding = 0, endIndex = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002132 binding = pWDS[i].dstBinding;
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002133 // Make sure that layout being updated has the binding being updated
Chia-I Wud46e6ae2015-10-31 00:31:16 +08002134 if (pLayout->bindings.find(binding) == pLayout->bindings.end()) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002135 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) ds, __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS",
Michael Lentine010f4692015-11-03 16:19:46 -08002136 "Descriptor Set %" PRIu64 " does not have binding to match update binding %u for update type %s!", reinterpret_cast<uint64_t>(ds), binding, string_VkStructureType(pUpdate->sType));
Tobin Ehlis9c536442015-06-19 13:00:59 -06002137 } else {
Tobin Ehlis793ad302015-04-03 12:01:11 -06002138 // Next verify that update falls within size of given binding
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002139 endIndex = getUpdateEndIndex(my_data, device, pLayout, binding, pWDS[i].dstArrayElement, pUpdate);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002140 if (getBindingEndIndex(pLayout, binding) < endIndex) {
Tobin Ehlis793ad302015-04-03 12:01:11 -06002141 pLayoutCI = &pLayout->createInfo;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06002142 string DSstr = vk_print_vkdescriptorsetlayoutcreateinfo(pLayoutCI, "{DS} ");
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002143 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) ds, __LINE__, DRAWSTATE_DESCRIPTOR_UPDATE_OUT_OF_BOUNDS, "DS",
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002144 "Descriptor update type of %s is out of bounds for matching binding %u in Layout w/ CI:\n%s!", string_VkStructureType(pUpdate->sType), binding, DSstr.c_str());
Tobin Ehlis9c536442015-06-19 13:00:59 -06002145 } else { // TODO : should we skip update on a type mismatch or force it?
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002146 uint32_t startIndex;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002147 startIndex = getUpdateStartIndex(my_data, device, pLayout, binding, pWDS[i].dstArrayElement, pUpdate);
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06002148 // Layout bindings match w/ update, now verify that update type & stageFlags are the same for entire update
2149 if ((skipCall = validateUpdateConsistency(my_data, device, pLayout, pUpdate, startIndex, endIndex)) == VK_FALSE) {
2150 // The update is within bounds and consistent, but need to make sure contents make sense as well
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07002151 if ((skipCall = validateUpdateContents(my_data, &pWDS[i], &pLayout->createInfo.pBindings[binding])) == VK_FALSE) {
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002152 // Update is good. Save the update info
2153 // Create new update struct for this set's shadow copy
2154 GENERIC_HEADER* pNewNode = NULL;
2155 skipCall |= shadowUpdateNode(my_data, device, pUpdate, &pNewNode);
2156 if (NULL == pNewNode) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002157 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) ds, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS",
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002158 "Out of memory while attempting to allocate UPDATE struct in vkUpdateDescriptors()");
2159 } else {
2160 // Insert shadow node into LL of updates for this set
2161 pNewNode->pNext = pSet->pUpdateStructs;
2162 pSet->pUpdateStructs = pNewNode;
2163 // Now update appropriate descriptor(s) to point to new Update node
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002164 for (uint32_t j = startIndex; j <= endIndex; j++) {
2165 assert(j<pSet->descriptorCount);
2166 pSet->ppDescriptors[j] = pNewNode;
2167 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002168 }
2169 }
2170 }
2171 }
2172 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002173 }
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002174 // Now validate copy updates
Chia-I Wu40cf0ae2015-10-26 17:20:32 +08002175 for (i=0; i < descriptorCopyCount; ++i) {
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002176 SET_NODE *pSrcSet = NULL, *pDstSet = NULL;
2177 LAYOUT_NODE *pSrcLayout = NULL, *pDstLayout = NULL;
2178 uint32_t srcStartIndex = 0, srcEndIndex = 0, dstStartIndex = 0, dstEndIndex = 0;
2179 // For each copy make sure that update falls within given layout and that types match
Chia-I Wue2fc5522015-10-26 20:04:44 +08002180 pSrcSet = my_data->setMap[pCDS[i].srcSet];
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002181 pDstSet = my_data->setMap[pCDS[i].dstSet];
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002182 pSrcLayout = pSrcSet->pLayout;
2183 pDstLayout = pDstSet->pLayout;
2184 // Validate that src binding is valid for src set layout
Chia-I Wud46e6ae2015-10-31 00:31:16 +08002185 if (pSrcLayout->bindings.find(pCDS[i].srcBinding) == pSrcLayout->bindings.end()) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002186 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) pSrcSet->set, __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS",
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002187 "Copy descriptor update %u has srcBinding %u which is out of bounds for underlying SetLayout %#" PRIxLEAST64 " which only has bindings 0-%u.",
Chia-I Wud50a7d72015-10-26 20:48:51 +08002188 i, pCDS[i].srcBinding, (uint64_t) pSrcLayout->layout, pSrcLayout->createInfo.bindingCount-1);
Chia-I Wud46e6ae2015-10-31 00:31:16 +08002189 } else if (pDstLayout->bindings.find(pCDS[i].dstBinding) == pDstLayout->bindings.end()) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002190 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) pDstSet->set, __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002191 "Copy descriptor update %u has dstBinding %u which is out of bounds for underlying SetLayout %#" PRIxLEAST64 " which only has bindings 0-%u.",
2192 i, pCDS[i].dstBinding, (uint64_t) pDstLayout->layout, pDstLayout->createInfo.bindingCount-1);
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002193 } else {
2194 // Proceed with validation. Bindings are ok, but make sure update is within bounds of given layout
2195 srcEndIndex = getUpdateEndIndex(my_data, device, pSrcLayout, pCDS[i].srcBinding, pCDS[i].srcArrayElement, (const GENERIC_HEADER*)&(pCDS[i]));
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002196 dstEndIndex = getUpdateEndIndex(my_data, device, pDstLayout, pCDS[i].dstBinding, pCDS[i].dstArrayElement, (const GENERIC_HEADER*)&(pCDS[i]));
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002197 if (getBindingEndIndex(pSrcLayout, pCDS[i].srcBinding) < srcEndIndex) {
2198 pLayoutCI = &pSrcLayout->createInfo;
2199 string DSstr = vk_print_vkdescriptorsetlayoutcreateinfo(pLayoutCI, "{DS} ");
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002200 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) pSrcSet->set, __LINE__, DRAWSTATE_DESCRIPTOR_UPDATE_OUT_OF_BOUNDS, "DS",
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002201 "Copy descriptor src update is out of bounds for matching binding %u in Layout w/ CI:\n%s!", pCDS[i].srcBinding, DSstr.c_str());
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002202 } else if (getBindingEndIndex(pDstLayout, pCDS[i].dstBinding) < dstEndIndex) {
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002203 pLayoutCI = &pDstLayout->createInfo;
2204 string DSstr = vk_print_vkdescriptorsetlayoutcreateinfo(pLayoutCI, "{DS} ");
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002205 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) pDstSet->set, __LINE__, DRAWSTATE_DESCRIPTOR_UPDATE_OUT_OF_BOUNDS, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002206 "Copy descriptor dest update is out of bounds for matching binding %u in Layout w/ CI:\n%s!", pCDS[i].dstBinding, DSstr.c_str());
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002207 } else {
2208 srcStartIndex = getUpdateStartIndex(my_data, device, pSrcLayout, pCDS[i].srcBinding, pCDS[i].srcArrayElement, (const GENERIC_HEADER*)&(pCDS[i]));
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002209 dstStartIndex = getUpdateStartIndex(my_data, device, pDstLayout, pCDS[i].dstBinding, pCDS[i].dstArrayElement, (const GENERIC_HEADER*)&(pCDS[i]));
Chia-I Wud50a7d72015-10-26 20:48:51 +08002210 for (uint32_t j=0; j<pCDS[i].descriptorCount; ++j) {
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002211 // For copy just make sure that the types match and then perform the update
2212 if (pSrcLayout->descriptorTypes[srcStartIndex+j] != pDstLayout->descriptorTypes[dstStartIndex+j]) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002213 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_DESCRIPTOR_TYPE_MISMATCH, "DS",
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002214 "Copy descriptor update index %u, update count #%u, has src update descriptor type %s that does not match overlapping dest descriptor type of %s!",
2215 i, j+1, string_VkDescriptorType(pSrcLayout->descriptorTypes[srcStartIndex+j]), string_VkDescriptorType(pDstLayout->descriptorTypes[dstStartIndex+j]));
2216 } else {
2217 // point dst descriptor at corresponding src descriptor
Tobin Ehlisf6585052015-12-17 11:48:42 -07002218 // TODO : This may be a hole. I believe copy should be its own copy,
2219 // otherwise a subsequent write update to src will incorrectly affect the copy
Tobin Ehlis8a62e632015-10-27 15:43:38 -06002220 pDstSet->ppDescriptors[j+dstStartIndex] = pSrcSet->ppDescriptors[j+srcStartIndex];
2221 }
2222 }
2223 }
2224 }
2225 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002226 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002227 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002228}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002229
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06002230// Verify that given pool has descriptors that are being requested for allocation
Mark Lobodzinski39298632015-11-18 08:38:27 -07002231static VkBool32 validate_descriptor_availability_in_pool(layer_data* dev_data, DESCRIPTOR_POOL_NODE* pPoolNode, uint32_t count, const VkDescriptorSetLayout* pSetLayouts)
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06002232{
2233 VkBool32 skipCall = VK_FALSE;
2234 uint32_t i = 0, j = 0;
2235 for (i=0; i<count; ++i) {
2236 LAYOUT_NODE* pLayout = getLayoutNode(dev_data, pSetLayouts[i]);
2237 if (NULL == pLayout) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002238 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, (uint64_t) pSetLayouts[i], __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002239 "Unable to find set layout node for layout %#" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", (uint64_t) pSetLayouts[i]);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06002240 } else {
Chia-I Wu1b99bb22015-10-27 19:25:11 +08002241 uint32_t typeIndex = 0, poolSizeCount = 0;
Chia-I Wud50a7d72015-10-26 20:48:51 +08002242 for (j=0; j<pLayout->createInfo.bindingCount; ++j) {
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07002243 typeIndex = static_cast<uint32_t>(pLayout->createInfo.pBindings[j].descriptorType);
2244 poolSizeCount = pLayout->createInfo.pBindings[j].descriptorCount;
Chia-I Wu1b99bb22015-10-27 19:25:11 +08002245 if (poolSizeCount > pPoolNode->availableDescriptorTypeCount[typeIndex]) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002246 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, (uint64_t) pLayout->layout, __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS",
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06002247 "Unable to allocate %u descriptors of type %s from pool %#" PRIxLEAST64 ". This pool only has %u descriptors of this type remaining.",
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07002248 poolSizeCount, string_VkDescriptorType(pLayout->createInfo.pBindings[j].descriptorType), (uint64_t) pPoolNode->pool, pPoolNode->availableDescriptorTypeCount[typeIndex]);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06002249 } else { // Decrement available descriptors of this type
Chia-I Wu1b99bb22015-10-27 19:25:11 +08002250 pPoolNode->availableDescriptorTypeCount[typeIndex] -= poolSizeCount;
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06002251 }
2252 }
2253 }
2254 }
2255 return skipCall;
2256}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002257
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002258// Free the shadowed update node for this Set
2259// NOTE : Calls to this function should be wrapped in mutex
2260static void freeShadowUpdateTree(SET_NODE* pSet)
2261{
2262 GENERIC_HEADER* pShadowUpdate = pSet->pUpdateStructs;
2263 pSet->pUpdateStructs = NULL;
2264 GENERIC_HEADER* pFreeUpdate = pShadowUpdate;
2265 // Clear the descriptor mappings as they will now be invalid
2266 memset(pSet->ppDescriptors, 0, pSet->descriptorCount*sizeof(GENERIC_HEADER*));
2267 while(pShadowUpdate) {
2268 pFreeUpdate = pShadowUpdate;
2269 pShadowUpdate = (GENERIC_HEADER*)pShadowUpdate->pNext;
2270 uint32_t index = 0;
Chia-I Wu9d00ed72015-05-25 16:27:55 +08002271 VkWriteDescriptorSet * pWDS = NULL;
2272 VkCopyDescriptorSet * pCDS = NULL;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002273 void** ppToFree = NULL;
2274 switch (pFreeUpdate->sType)
2275 {
Chia-I Wu9d00ed72015-05-25 16:27:55 +08002276 case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
2277 pWDS = (VkWriteDescriptorSet*)pFreeUpdate;
Tony Barbourb1947942015-11-02 11:46:29 -07002278 switch (pWDS->descriptorType) {
2279 case VK_DESCRIPTOR_TYPE_SAMPLER:
2280 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2281 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2282 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2283 {
2284 delete[] pWDS->pImageInfo;
2285 }
2286 break;
2287 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2288 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2289 {
2290 delete[] pWDS->pTexelBufferView;
2291 }
2292 break;
2293 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2294 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2295 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2296 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2297 {
2298 delete[] pWDS->pBufferInfo;
2299 }
2300 break;
2301 default:
2302 break;
Courtney Goeltzenleuchteraa132e72015-10-22 15:31:56 -06002303 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002304 break;
Chia-I Wu9d00ed72015-05-25 16:27:55 +08002305 case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002306 break;
2307 default:
2308 assert(0);
2309 break;
2310 }
Tobin Ehlisecc6bd02015-04-08 10:58:37 -06002311 delete pFreeUpdate;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002312 }
2313}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002314
Tobin Ehlis793ad302015-04-03 12:01:11 -06002315// Free all DS Pools including their Sets & related sub-structs
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002316// NOTE : Calls to this function should be wrapped in mutex
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002317static void deletePools(layer_data* my_data)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002318{
Mark Lobodzinski39298632015-11-18 08:38:27 -07002319 if (my_data->descriptorPoolMap.size() <= 0)
David Pinedod8f83d82015-04-27 16:36:17 -06002320 return;
Mark Lobodzinski39298632015-11-18 08:38:27 -07002321 for (auto ii=my_data->descriptorPoolMap.begin(); ii!=my_data->descriptorPoolMap.end(); ++ii) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002322 SET_NODE* pSet = (*ii).second->pSets;
2323 SET_NODE* pFreeSet = pSet;
2324 while (pSet) {
2325 pFreeSet = pSet;
2326 pSet = pSet->pNext;
Tobin Ehlisecc6bd02015-04-08 10:58:37 -06002327 // Freeing layouts handled in deleteLayouts() function
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002328 // Free Update shadow struct tree
2329 freeShadowUpdateTree(pFreeSet);
2330 if (pFreeSet->ppDescriptors) {
Chris Forbes02038792015-06-04 10:49:27 +12002331 delete[] pFreeSet->ppDescriptors;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002332 }
2333 delete pFreeSet;
2334 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002335 delete (*ii).second;
2336 }
Mark Lobodzinski39298632015-11-18 08:38:27 -07002337 my_data->descriptorPoolMap.clear();
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002338}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002339
Tobin Ehlisecc6bd02015-04-08 10:58:37 -06002340// WARN : Once deleteLayouts() called, any layout ptrs in Pool/Set data structure will be invalid
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002341// NOTE : Calls to this function should be wrapped in mutex
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002342static void deleteLayouts(layer_data* my_data)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002343{
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07002344 if (my_data->descriptorSetLayoutMap.size() <= 0)
David Pinedod8f83d82015-04-27 16:36:17 -06002345 return;
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07002346 for (auto ii=my_data->descriptorSetLayoutMap.begin(); ii!=my_data->descriptorSetLayoutMap.end(); ++ii) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002347 LAYOUT_NODE* pLayout = (*ii).second;
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07002348 if (pLayout->createInfo.pBindings) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08002349 for (uint32_t i=0; i<pLayout->createInfo.bindingCount; i++) {
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07002350 if (pLayout->createInfo.pBindings[i].pImmutableSamplers)
2351 delete[] pLayout->createInfo.pBindings[i].pImmutableSamplers;
Tobin Ehlisecc6bd02015-04-08 10:58:37 -06002352 }
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07002353 delete[] pLayout->createInfo.pBindings;
Tobin Ehlisecc6bd02015-04-08 10:58:37 -06002354 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002355 delete pLayout;
2356 }
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07002357 my_data->descriptorSetLayoutMap.clear();
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002358}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002359
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002360// Currently clearing a set is removing all previous updates to that set
2361// TODO : Validate if this is correct clearing behavior
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002362static void clearDescriptorSet(layer_data* my_data, VkDescriptorSet set)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002363{
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002364 SET_NODE* pSet = getSetNode(my_data, set);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002365 if (!pSet) {
2366 // TODO : Return error
Tobin Ehlisce132d82015-06-19 15:07:05 -06002367 } else {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002368 loader_platform_thread_lock_mutex(&globalLock);
2369 freeShadowUpdateTree(pSet);
2370 loader_platform_thread_unlock_mutex(&globalLock);
2371 }
2372}
2373
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06002374static void clearDescriptorPool(layer_data* my_data, const VkDevice device, const VkDescriptorPool pool, VkDescriptorPoolResetFlags flags)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002375{
Mark Lobodzinski39298632015-11-18 08:38:27 -07002376 DESCRIPTOR_POOL_NODE* pPool = getPoolNode(my_data, pool);
Tobin Ehlis793ad302015-04-03 12:01:11 -06002377 if (!pPool) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002378 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, (uint64_t) pool, __LINE__, DRAWSTATE_INVALID_POOL, "DS",
Chia-I Wue2fc5522015-10-26 20:04:44 +08002379 "Unable to find pool node for pool %#" PRIxLEAST64 " specified in vkResetDescriptorPool() call", (uint64_t) pool);
Tobin Ehlisce132d82015-06-19 15:07:05 -06002380 } else {
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06002381 // TODO: validate flags
Tobin Ehlis793ad302015-04-03 12:01:11 -06002382 // For every set off of this pool, clear it
2383 SET_NODE* pSet = pPool->pSets;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002384 while (pSet) {
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002385 clearDescriptorSet(my_data, pSet->set);
Mark Lobodzinskidcce0792016-01-04 09:40:19 -07002386 pSet = pSet->pNext;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002387 }
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06002388 // Reset available count to max count for this pool
2389 for (uint32_t i=0; i<pPool->availableDescriptorTypeCount.size(); ++i) {
2390 pPool->availableDescriptorTypeCount[i] = pPool->maxDescriptorTypeCount[i];
2391 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002392 }
2393}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002394
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002395// For given CB object, fetch associated CB Node from map
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002396static GLOBAL_CB_NODE* getCBNode(layer_data* my_data, const VkCommandBuffer cb)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002397{
2398 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07002399 if (my_data->commandBufferMap.count(cb) == 0) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002400 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06002401 // TODO : How to pass cb as srcObj here?
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002402 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002403 "Attempt to use CommandBuffer %#" PRIxLEAST64 " that doesn't exist!", reinterpret_cast<uint64_t>(cb));
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002404 return NULL;
2405 }
2406 loader_platform_thread_unlock_mutex(&globalLock);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002407 return my_data->commandBufferMap[cb];
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002408}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002409
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002410// Free all CB Nodes
2411// NOTE : Calls to this function should be wrapped in mutex
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002412static void deleteCommandBuffers(layer_data* my_data)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002413{
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07002414 if (my_data->commandBufferMap.size() <= 0) {
David Pinedod8f83d82015-04-27 16:36:17 -06002415 return;
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07002416 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002417 for (auto ii=my_data->commandBufferMap.begin(); ii!=my_data->commandBufferMap.end(); ++ii) {
Courtney Goeltzenleuchterea3117c2015-04-27 15:04:43 -06002418 vector<CMD_NODE*> cmd_node_list = (*ii).second->pCmds;
2419 while (!cmd_node_list.empty()) {
2420 CMD_NODE* cmd_node = cmd_node_list.back();
2421 delete cmd_node;
2422 cmd_node_list.pop_back();
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002423 }
2424 delete (*ii).second;
2425 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002426 my_data->commandBufferMap.clear();
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002427}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002428
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002429static VkBool32 report_error_no_cb_begin(const layer_data* dev_data, const VkCommandBuffer cb, const char* caller_name)
Tobin Ehlis9c536442015-06-19 13:00:59 -06002430{
Tobin Ehlis61b36f32015-12-16 08:19:42 -07002431 return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002432 (uint64_t)cb, __LINE__, DRAWSTATE_NO_BEGIN_COMMAND_BUFFER, "DS",
Tobin Ehlis61b36f32015-12-16 08:19:42 -07002433 "You must call vkBeginCommandBuffer() before this call to %s", caller_name);
Tobin Ehlis9c536442015-06-19 13:00:59 -06002434}
Michael Lentine3dea6512015-10-28 15:55:18 -07002435
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07002436VkBool32 validateCmdsInCmdBuffer(const layer_data* dev_data, const GLOBAL_CB_NODE* pCB, const CMD_TYPE cmd_type) {
Tony Barbour352108f2015-12-17 15:54:05 -07002437 // TODO : I think this is trying to validate this part of the spec:
2438 // If contents is VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, the contents are recorded in secondary command
2439 // buffers that will be called from the primary command buffer, and vkCmdExecuteCommands is the only valid command
2440 // on the command buffer until vkCmdNextSubpass or vkCmdEndRenderPass.
2441 //
2442 // But the code below is forceing vkCmdExecuteCommands to be the only thing in the command buffer which is not necessary
2443 // it just needs to be the only thing in the renderpass
2444 //
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07002445 VkBool32 skip_call = false;
Tony Barbour352108f2015-12-17 15:54:05 -07002446 //for (auto cmd : pCB->pCmds) {
2447 // if (cmd_type == CMD_EXECUTECOMMANDS && cmd->type != CMD_EXECUTECOMMANDS) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002448 // skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
Tony Barbour352108f2015-12-17 15:54:05 -07002449 // "vkCmdExecuteCommands() cannot be called on a cmd buffer with exsiting commands.");
2450 // }
2451 // if (cmd_type != CMD_EXECUTECOMMANDS && cmd->type == CMD_EXECUTECOMMANDS) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002452 // skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
Tony Barbour352108f2015-12-17 15:54:05 -07002453 // "Commands cannot be added to a cmd buffer with exsiting secondary commands.");
2454 // }
2455 //}
Michael Lentine3dea6512015-10-28 15:55:18 -07002456 return skip_call;
2457}
2458
Tobin Ehlis61b36f32015-12-16 08:19:42 -07002459// Add specified CMD to the CmdBuffer in given pCB, flagging errors if CB is not
2460// in the recording state or if there's an issue with the Cmd ordering
2461static VkBool32 addCmd(const layer_data* my_data, GLOBAL_CB_NODE* pCB, const CMD_TYPE cmd, const char* caller_name)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002462{
Tobin Ehlis61b36f32015-12-16 08:19:42 -07002463 VkBool32 skipCall = VK_FALSE;
2464 if (pCB->state != CB_RECORDING) {
2465 skipCall |= report_error_no_cb_begin(my_data, pCB->commandBuffer, caller_name);
2466 skipCall |= validateCmdsInCmdBuffer(my_data, pCB, cmd);
2467 CMD_NODE* pCmd = new CMD_NODE;
2468 if (pCmd) {
2469 // init cmd node and append to end of cmd LL
2470 memset(pCmd, 0, sizeof(CMD_NODE));
2471 pCmd->cmdNumber = ++pCB->numCmds;
2472 pCmd->type = cmd;
2473 pCB->pCmds.push_back(pCmd);
2474 } else {
2475 // TODO : How to pass cb as srcObj here?
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002476 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS",
Tobin Ehlis61b36f32015-12-16 08:19:42 -07002477 "Out of memory while attempting to allocate new CMD_NODE for commandBuffer %#" PRIxLEAST64, reinterpret_cast<uint64_t>(pCB->commandBuffer));
2478 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002479 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002480 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002481}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002482
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002483static void resetCB(layer_data* my_data, const VkCommandBuffer cb)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002484{
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002485 GLOBAL_CB_NODE* pCB = getCBNode(my_data, cb);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002486 if (pCB) {
Courtney Goeltzenleuchter3597a202015-04-27 17:16:56 -06002487 vector<CMD_NODE*> cmd_list = pCB->pCmds;
2488 while (!cmd_list.empty()) {
2489 delete cmd_list.back();
2490 cmd_list.pop_back();
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002491 }
Courtney Goeltzenleuchter3597a202015-04-27 17:16:56 -06002492 pCB->pCmds.clear();
Tobin Ehlis59278bf2015-08-18 07:10:58 -06002493 // Reset CB state (need to save createInfo)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002494 VkCommandBufferAllocateInfo saveCBCI = pCB->createInfo;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002495 pCB->commandBuffer = cb;
Tobin Ehlis59278bf2015-08-18 07:10:58 -06002496 pCB->createInfo = saveCBCI;
Michael Lentineabc5e922015-10-12 11:30:14 -05002497 memset(&pCB->beginInfo, 0, sizeof(VkCommandBufferBeginInfo));
2498 pCB->fence = 0;
2499 pCB->numCmds = 0;
2500 memset(pCB->drawCount, 0, NUM_DRAW_TYPES * sizeof(uint64_t));
2501 pCB->state = CB_NEW;
2502 pCB->submitCount = 0;
2503 pCB->status = 0;
2504 pCB->pCmds.clear();
2505 pCB->lastBoundPipeline = 0;
2506 pCB->viewports.clear();
2507 pCB->scissors.clear();
2508 pCB->lineWidth = 0;
2509 pCB->depthBiasConstantFactor = 0;
2510 pCB->depthBiasClamp = 0;
2511 pCB->depthBiasSlopeFactor = 0;
2512 memset(pCB->blendConstants, 0, 4 * sizeof(float));
2513 pCB->minDepthBounds = 0;
2514 pCB->maxDepthBounds = 0;
2515 memset(&pCB->front, 0, sizeof(stencil_data));
2516 memset(&pCB->back, 0, sizeof(stencil_data));
2517 pCB->lastBoundDescriptorSet = 0;
2518 pCB->lastBoundPipelineLayout = 0;
2519 pCB->activeRenderPass = 0;
2520 pCB->activeSubpass = 0;
2521 pCB->framebuffer = 0;
Michael Lentineabc5e922015-10-12 11:30:14 -05002522 pCB->boundDescriptorSets.clear();
Michael Lentine700b0aa2015-10-30 17:57:32 -07002523 pCB->drawData.clear();
2524 pCB->currentDrawData.buffers.clear();
Michael Lentineabc5e922015-10-12 11:30:14 -05002525 pCB->imageLayoutMap.clear();
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002526 }
2527}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002528
Tobin Ehlis963a4042015-09-29 08:18:34 -06002529// Set PSO-related status bits for CB, including dynamic state set via PSO
Tobin Ehlise382c5a2015-06-10 12:57:07 -06002530static void set_cb_pso_status(GLOBAL_CB_NODE* pCB, const PIPELINE_NODE* pPipe)
2531{
2532 for (uint32_t i = 0; i < pPipe->cbStateCI.attachmentCount; i++) {
Chia-I Wu1b99bb22015-10-27 19:25:11 +08002533 if (0 != pPipe->pAttachments[i].colorWriteMask) {
Tobin Ehlise382c5a2015-06-10 12:57:07 -06002534 pCB->status |= CBSTATUS_COLOR_BLEND_WRITE_ENABLE;
2535 }
2536 }
2537 if (pPipe->dsStateCI.depthWriteEnable) {
Cody Northrop82485a82015-08-18 15:21:16 -06002538 pCB->status |= CBSTATUS_DEPTH_WRITE_ENABLE;
2539 }
Cody Northrop82485a82015-08-18 15:21:16 -06002540 if (pPipe->dsStateCI.stencilTestEnable) {
2541 pCB->status |= CBSTATUS_STENCIL_TEST_ENABLE;
Tobin Ehlise382c5a2015-06-10 12:57:07 -06002542 }
Tobin Ehlisd332f282015-10-02 11:00:56 -06002543 // Account for any dynamic state not set via this PSO
2544 if (!pPipe->dynStateCI.dynamicStateCount) { // All state is static
2545 pCB->status = CBSTATUS_ALL;
2546 } else {
Tobin Ehlis5e5a1e92015-10-01 09:24:40 -06002547 // First consider all state on
2548 // Then unset any state that's noted as dynamic in PSO
2549 // Finally OR that into CB statemask
2550 CBStatusFlags psoDynStateMask = CBSTATUS_ALL;
Tobin Ehlis963a4042015-09-29 08:18:34 -06002551 for (uint32_t i=0; i < pPipe->dynStateCI.dynamicStateCount; i++) {
2552 switch (pPipe->dynStateCI.pDynamicStates[i]) {
2553 case VK_DYNAMIC_STATE_VIEWPORT:
Tobin Ehlis5e5a1e92015-10-01 09:24:40 -06002554 psoDynStateMask &= ~CBSTATUS_VIEWPORT_SET;
Tobin Ehlis963a4042015-09-29 08:18:34 -06002555 break;
2556 case VK_DYNAMIC_STATE_SCISSOR:
Tobin Ehlis5e5a1e92015-10-01 09:24:40 -06002557 psoDynStateMask &= ~CBSTATUS_SCISSOR_SET;
Tobin Ehlis963a4042015-09-29 08:18:34 -06002558 break;
2559 case VK_DYNAMIC_STATE_LINE_WIDTH:
Tobin Ehlis5e5a1e92015-10-01 09:24:40 -06002560 psoDynStateMask &= ~CBSTATUS_LINE_WIDTH_SET;
Tobin Ehlis963a4042015-09-29 08:18:34 -06002561 break;
2562 case VK_DYNAMIC_STATE_DEPTH_BIAS:
Tobin Ehlis5e5a1e92015-10-01 09:24:40 -06002563 psoDynStateMask &= ~CBSTATUS_DEPTH_BIAS_SET;
Tobin Ehlis963a4042015-09-29 08:18:34 -06002564 break;
2565 case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
Tobin Ehlis5e5a1e92015-10-01 09:24:40 -06002566 psoDynStateMask &= ~CBSTATUS_BLEND_SET;
Tobin Ehlis963a4042015-09-29 08:18:34 -06002567 break;
2568 case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
Tobin Ehlis5e5a1e92015-10-01 09:24:40 -06002569 psoDynStateMask &= ~CBSTATUS_DEPTH_BOUNDS_SET;
Tobin Ehlis963a4042015-09-29 08:18:34 -06002570 break;
2571 case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
Tobin Ehlis5e5a1e92015-10-01 09:24:40 -06002572 psoDynStateMask &= ~CBSTATUS_STENCIL_READ_MASK_SET;
Tobin Ehlis963a4042015-09-29 08:18:34 -06002573 break;
2574 case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
Tobin Ehlis5e5a1e92015-10-01 09:24:40 -06002575 psoDynStateMask &= ~CBSTATUS_STENCIL_WRITE_MASK_SET;
Tobin Ehlis963a4042015-09-29 08:18:34 -06002576 break;
2577 case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
Tobin Ehlis5e5a1e92015-10-01 09:24:40 -06002578 psoDynStateMask &= ~CBSTATUS_STENCIL_REFERENCE_SET;
Tobin Ehlis963a4042015-09-29 08:18:34 -06002579 break;
2580 default:
2581 // TODO : Flag error here
2582 break;
2583 }
2584 }
Tobin Ehlis5e5a1e92015-10-01 09:24:40 -06002585 pCB->status |= psoDynStateMask;
Tobin Ehlis963a4042015-09-29 08:18:34 -06002586 }
Tobin Ehlise382c5a2015-06-10 12:57:07 -06002587}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002588
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002589// Print the last bound Gfx Pipeline
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002590static VkBool32 printPipeline(layer_data* my_data, const VkCommandBuffer cb)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002591{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002592 VkBool32 skipCall = VK_FALSE;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002593 GLOBAL_CB_NODE* pCB = getCBNode(my_data, cb);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002594 if (pCB) {
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002595 PIPELINE_NODE *pPipeTrav = getPipeline(my_data, pCB->lastBoundPipeline);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002596 if (!pPipeTrav) {
2597 // nothing to print
Tobin Ehlisce132d82015-06-19 15:07:05 -06002598 } else {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002599 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_NONE, "DS",
Michael Lentine010f4692015-11-03 16:19:46 -08002600 "%s", vk_print_vkgraphicspipelinecreateinfo(&pPipeTrav->graphicsPipelineCI, "{DS}").c_str());
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002601 }
2602 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002603 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002604}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002605
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002606// Print details of DS config to stdout
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002607static VkBool32 printDSConfig(layer_data* my_data, const VkCommandBuffer cb)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002608{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002609 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002610 char ds_config_str[1024*256] = {0}; // TODO : Currently making this buffer HUGE w/o overrun protection. Need to be smarter, start smaller, and grow as needed.
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002611 GLOBAL_CB_NODE* pCB = getCBNode(my_data, cb);
Tobin Ehlis93f89e82015-06-09 08:39:32 -06002612 if (pCB && pCB->lastBoundDescriptorSet) {
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002613 SET_NODE* pSet = getSetNode(my_data, pCB->lastBoundDescriptorSet);
Mark Lobodzinski39298632015-11-18 08:38:27 -07002614 DESCRIPTOR_POOL_NODE* pPool = getPoolNode(my_data, pSet->pool);
Tobin Ehlis793ad302015-04-03 12:01:11 -06002615 // Print out pool details
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002616 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_NONE, "DS",
Chia-I Wue2fc5522015-10-26 20:04:44 +08002617 "Details for pool %#" PRIxLEAST64 ".", (uint64_t) pPool->pool);
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06002618 string poolStr = vk_print_vkdescriptorpoolcreateinfo(&pPool->createInfo, " ");
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002619 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_NONE, "DS",
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002620 "%s", poolStr.c_str());
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002621 // Print out set details
2622 char prefix[10];
2623 uint32_t index = 0;
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002624 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_NONE, "DS",
Chia-I Wue2fc5522015-10-26 20:04:44 +08002625 "Details for descriptor set %#" PRIxLEAST64 ".", (uint64_t) pSet->set);
Tobin Ehlis793ad302015-04-03 12:01:11 -06002626 LAYOUT_NODE* pLayout = pSet->pLayout;
2627 // Print layout details
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002628 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_NONE, "DS",
Michael Lentine010f4692015-11-03 16:19:46 -08002629 "Layout #%u, (object %#" PRIxLEAST64 ") for DS %#" PRIxLEAST64 ".", index+1, reinterpret_cast<uint64_t>(pLayout->layout), reinterpret_cast<uint64_t>(pSet->set));
Tobin Ehlis793ad302015-04-03 12:01:11 -06002630 sprintf(prefix, " [L%u] ", index);
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06002631 string DSLstr = vk_print_vkdescriptorsetlayoutcreateinfo(&pLayout->createInfo, prefix).c_str();
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002632 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_NONE, "DS",
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002633 "%s", DSLstr.c_str());
Tobin Ehlis793ad302015-04-03 12:01:11 -06002634 index++;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002635 GENERIC_HEADER* pUpdate = pSet->pUpdateStructs;
2636 if (pUpdate) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002637 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_NONE, "DS",
Chia-I Wue2fc5522015-10-26 20:04:44 +08002638 "Update Chain [UC] for descriptor set %#" PRIxLEAST64 ":", (uint64_t) pSet->set);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002639 sprintf(prefix, " [UC] ");
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002640 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_NONE, "DS",
Michael Lentine010f4692015-11-03 16:19:46 -08002641 "%s", dynamic_display(pUpdate, prefix).c_str());
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002642 // TODO : If there is a "view" associated with this update, print CI for that view
Tobin Ehlisce132d82015-06-19 15:07:05 -06002643 } else {
Tobin Ehlisbf081f32015-06-15 08:41:17 -06002644 if (0 != pSet->descriptorCount) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002645 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_NONE, "DS",
Chia-I Wue2fc5522015-10-26 20:04:44 +08002646 "No Update Chain for descriptor set %#" PRIxLEAST64 " which has %u descriptors (vkUpdateDescriptors has not been called)", (uint64_t) pSet->set, pSet->descriptorCount);
Tobin Ehlisce132d82015-06-19 15:07:05 -06002647 } else {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002648 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_NONE, "DS",
Chia-I Wue2fc5522015-10-26 20:04:44 +08002649 "FYI: No descriptors in descriptor set %#" PRIxLEAST64 ".", (uint64_t) pSet->set);
Tobin Ehlisbf081f32015-06-15 08:41:17 -06002650 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002651 }
2652 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002653 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002654}
2655
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002656static void printCB(layer_data* my_data, const VkCommandBuffer cb)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002657{
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002658 GLOBAL_CB_NODE* pCB = getCBNode(my_data, cb);
David Pinedod8f83d82015-04-27 16:36:17 -06002659 if (pCB && pCB->pCmds.size() > 0) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002660 log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_NONE, "DS",
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002661 "Cmds in CB %p", (void*)cb);
Courtney Goeltzenleuchterba348a92015-04-27 11:16:35 -06002662 vector<CMD_NODE*> pCmds = pCB->pCmds;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06002663 for (auto ii=pCmds.begin(); ii!=pCmds.end(); ++ii) {
2664 // TODO : Need to pass cb as srcObj here
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002665 log_msg(my_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_NONE, "DS",
Michael Lentine010f4692015-11-03 16:19:46 -08002666 " CMD#%" PRIu64 ": %s", (*ii)->cmdNumber, cmdTypeToString((*ii)->type).c_str());
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002667 }
Tobin Ehlisce132d82015-06-19 15:07:05 -06002668 } else {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002669 // Nothing to print
2670 }
2671}
2672
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002673static VkBool32 synchAndPrintDSConfig(layer_data* my_data, const VkCommandBuffer cb)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002674{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002675 VkBool32 skipCall = VK_FALSE;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002676 if (!(my_data->report_data->active_flags & VK_DEBUG_REPORT_INFO_BIT_EXT)) {
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002677 return skipCall;
Mike Stroyanba35e352015-08-12 17:11:28 -06002678 }
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002679 skipCall |= printDSConfig(my_data, cb);
2680 skipCall |= printPipeline(my_data, cb);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06002681 return skipCall;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002682}
2683
Mark Lobodzinski5495d132015-09-30 16:19:16 -06002684// Flags validation error if the associated call is made inside a render pass. The apiName
2685// routine should ONLY be called outside a render pass.
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06002686static VkBool32 insideRenderPass(const layer_data* my_data, GLOBAL_CB_NODE *pCB, const char *apiName)
Mark Lobodzinski5495d132015-09-30 16:19:16 -06002687{
2688 VkBool32 inside = VK_FALSE;
2689 if (pCB->activeRenderPass) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002690 inside = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002691 (uint64_t)pCB->commandBuffer, __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS",
Mark Lobodzinski5495d132015-09-30 16:19:16 -06002692 "%s: It is invalid to issue this call inside an active render pass (%#" PRIxLEAST64 ")",
Chia-I Wue2fc5522015-10-26 20:04:44 +08002693 apiName, (uint64_t) pCB->activeRenderPass);
Mark Lobodzinski5495d132015-09-30 16:19:16 -06002694 }
2695 return inside;
2696}
2697
2698// Flags validation error if the associated call is made outside a render pass. The apiName
2699// routine should ONLY be called inside a render pass.
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06002700static VkBool32 outsideRenderPass(const layer_data* my_data, GLOBAL_CB_NODE *pCB, const char *apiName)
Mark Lobodzinski5495d132015-09-30 16:19:16 -06002701{
2702 VkBool32 outside = VK_FALSE;
Mark Lobodzinski74635932015-12-18 15:35:38 -07002703 if (((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) &&
2704 (!pCB->activeRenderPass)) ||
2705 ((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) &&
2706 (!pCB->activeRenderPass) &&
2707 !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002708 outside = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002709 (uint64_t)pCB->commandBuffer, __LINE__, DRAWSTATE_NO_ACTIVE_RENDERPASS, "DS",
Mark Lobodzinski5495d132015-09-30 16:19:16 -06002710 "%s: This call must be issued inside an active render pass.", apiName);
2711 }
2712 return outside;
2713}
2714
Courtney Goeltzenleuchter6d8e8182015-11-25 14:31:49 -07002715static void init_draw_state(layer_data *my_data, const VkAllocationCallbacks *pAllocator)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002716{
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002717 uint32_t report_flags = 0;
2718 uint32_t debug_action = 0;
2719 FILE *log_output = NULL;
2720 const char *option_str;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002721 VkDebugReportCallbackEXT callback;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002722 // initialize DrawState options
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002723 report_flags = getLayerOptionFlags("DrawStateReportFlags", 0);
2724 getLayerOptionEnum("DrawStateDebugAction", (uint32_t *) &debug_action);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002725
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002726 if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002727 {
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002728 option_str = getLayerOption("DrawStateLogFilename");
Tobin Ehlisb1df55e2015-09-15 09:55:54 -06002729 log_output = getLayerLogOutput(option_str, "DrawState");
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002730 VkDebugReportCallbackCreateInfoEXT dbgInfo;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07002731 memset(&dbgInfo, 0, sizeof(dbgInfo));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002732 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07002733 dbgInfo.pfnCallback = log_callback;
2734 dbgInfo.pUserData = log_output;
2735 dbgInfo.flags = report_flags;
2736 layer_create_msg_callback(my_data->report_data, &dbgInfo, pAllocator, &callback);
Courtney Goeltzenleuchter62d945a2015-10-05 15:58:38 -06002737 my_data->logging_callback.push_back(callback);
2738 }
2739
2740 if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002741 VkDebugReportCallbackCreateInfoEXT dbgInfo;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07002742 memset(&dbgInfo, 0, sizeof(dbgInfo));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002743 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07002744 dbgInfo.pfnCallback = win32_debug_output_msg;
2745 dbgInfo.pUserData = log_output;
2746 dbgInfo.flags = report_flags;
2747 layer_create_msg_callback(my_data->report_data, &dbgInfo, pAllocator, &callback);
Courtney Goeltzenleuchter62d945a2015-10-05 15:58:38 -06002748 my_data->logging_callback.push_back(callback);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002749 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002750
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002751 if (!globalLockInitialized)
2752 {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002753 loader_platform_thread_create_mutex(&globalLock);
2754 globalLockInitialized = 1;
2755 }
2756}
2757
Chia-I Wu9ab61502015-11-06 06:42:02 +08002758VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
Courtney Goeltzenleuchterabc035e2015-06-01 14:29:58 -06002759{
Tobin Ehlis8fab6562015-12-01 09:57:09 -07002760 // TODOSC : Shouldn't need any customization here
Tobin Ehlis0b632332015-10-07 09:38:40 -06002761 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
2762 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Chia-I Wuf7458c52015-10-26 21:10:41 +08002763 VkResult result = pTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
Courtney Goeltzenleuchterabc035e2015-06-01 14:29:58 -06002764
2765 if (result == VK_SUCCESS) {
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002766 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
2767 my_data->report_data = debug_report_create_instance(
2768 pTable,
2769 *pInstance,
Chia-I Wud50a7d72015-10-26 20:48:51 +08002770 pCreateInfo->enabledExtensionNameCount,
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06002771 pCreateInfo->ppEnabledExtensionNames);
Courtney Goeltzenleuchterd02a9642015-06-08 14:58:39 -06002772
Courtney Goeltzenleuchter6d8e8182015-11-25 14:31:49 -07002773 init_draw_state(my_data, pAllocator);
Courtney Goeltzenleuchterabc035e2015-06-01 14:29:58 -06002774 }
2775 return result;
2776}
2777
Jon Ashburn3950e1b2015-05-20 09:00:28 -06002778/* hook DestroyInstance to remove tableInstanceMap entry */
Chia-I Wu9ab61502015-11-06 06:42:02 +08002779VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator)
Jon Ashburn3950e1b2015-05-20 09:00:28 -06002780{
Tobin Ehlis8fab6562015-12-01 09:57:09 -07002781 // TODOSC : Shouldn't need any customization here
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002782 dispatch_key key = get_dispatch_key(instance);
Tobin Ehlis0b632332015-10-07 09:38:40 -06002783 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
2784 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Chia-I Wuf7458c52015-10-26 21:10:41 +08002785 pTable->DestroyInstance(instance, pAllocator);
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002786
2787 // Clean up logging callback, if any
Courtney Goeltzenleuchter62d945a2015-10-05 15:58:38 -06002788 while (my_data->logging_callback.size() > 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002789 VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07002790 layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
Courtney Goeltzenleuchter62d945a2015-10-05 15:58:38 -06002791 my_data->logging_callback.pop_back();
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002792 }
2793
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -06002794 layer_debug_report_destroy_instance(my_data->report_data);
Tobin Ehlis0b632332015-10-07 09:38:40 -06002795 delete my_data->instance_dispatch_table;
2796 layer_data_map.erase(key);
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002797 // TODO : Potential race here with separate threads creating/destroying instance
Tobin Ehlis0b632332015-10-07 09:38:40 -06002798 if (layer_data_map.empty()) {
Mike Stroyanfcb4ba62015-08-18 15:56:18 -06002799 // Release mutex when destroying last instance.
2800 loader_platform_thread_delete_mutex(&globalLock);
2801 globalLockInitialized = 0;
2802 }
Jon Ashburn3950e1b2015-05-20 09:00:28 -06002803}
2804
Jon Ashburne68a9ff2015-05-25 14:11:37 -06002805static void createDeviceRegisterExtensions(const VkDeviceCreateInfo* pCreateInfo, VkDevice device)
2806{
Tony Barbour3b4732f2015-07-13 13:37:24 -06002807 uint32_t i;
Tobin Ehlis0b632332015-10-07 09:38:40 -06002808 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2809 dev_data->device_extensions.debug_marker_enabled = false;
Michael Lentineabc5e922015-10-12 11:30:14 -05002810 dev_data->device_extensions.wsi_enabled = false;
2811
2812
2813 VkLayerDispatchTable *pDisp = dev_data->device_dispatch_table;
2814 PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
2815
Michael Lentineabc5e922015-10-12 11:30:14 -05002816 pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) gpa(device, "vkCreateSwapchainKHR");
2817 pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR) gpa(device, "vkDestroySwapchainKHR");
2818 pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) gpa(device, "vkGetSwapchainImagesKHR");
2819 pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) gpa(device, "vkAcquireNextImageKHR");
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07002820 pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR) gpa(device, "vkQueuePresentKHR");
Jon Ashburne68a9ff2015-05-25 14:11:37 -06002821
Chia-I Wud50a7d72015-10-26 20:48:51 +08002822 for (i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Ian Elliott05846062015-11-20 14:13:17 -07002823 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
Michael Lentineabc5e922015-10-12 11:30:14 -05002824 dev_data->device_extensions.wsi_enabled = true;
2825 }
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06002826 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], DEBUG_MARKER_EXTENSION_NAME) == 0) {
Jon Ashburneab34492015-06-01 09:37:38 -06002827 /* Found a matching extension name, mark it enabled and init dispatch table*/
Tobin Ehlis0b632332015-10-07 09:38:40 -06002828 dev_data->device_extensions.debug_marker_enabled = true;
Jon Ashburn1d4b1282015-12-10 19:12:21 -07002829 initDebugMarkerTable(device);
2830
Jon Ashburne68a9ff2015-05-25 14:11:37 -06002831 }
Jon Ashburne68a9ff2015-05-25 14:11:37 -06002832 }
2833}
2834
Chia-I Wu9ab61502015-11-06 06:42:02 +08002835VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002836{
Tobin Ehlis0b632332015-10-07 09:38:40 -06002837 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08002838 VkResult result = dev_data->device_dispatch_table->CreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
Tobin Ehlis8fab6562015-12-01 09:57:09 -07002839 // TODOSC : shouldn't need any customization here
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002840 if (result == VK_SUCCESS) {
2841 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
Tobin Ehlis0b632332015-10-07 09:38:40 -06002842 dev_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
Jon Ashburn747f2b62015-06-18 15:02:58 -06002843 createDeviceRegisterExtensions(pCreateInfo, *pDevice);
Tobin Ehlisa16e8922015-06-16 15:50:44 -06002844 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002845 return result;
2846}
Tobin Ehlis559c6382015-11-05 09:52:49 -07002847
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002848// prototype
2849static void deleteRenderPasses(layer_data*);
Chia-I Wu9ab61502015-11-06 06:42:02 +08002850VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002851{
Tobin Ehlis8fab6562015-12-01 09:57:09 -07002852 // TODOSC : Shouldn't need any customization here
Jeremy Hayes5d29ce32015-06-19 11:37:38 -06002853 dispatch_key key = get_dispatch_key(device);
Tobin Ehlis0b632332015-10-07 09:38:40 -06002854 layer_data* dev_data = get_my_data_ptr(key, layer_data_map);
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002855 // Free all the memory
2856 loader_platform_thread_lock_mutex(&globalLock);
2857 deletePipelines(dev_data);
2858 deleteRenderPasses(dev_data);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002859 deleteCommandBuffers(dev_data);
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002860 deletePools(dev_data);
2861 deleteLayouts(dev_data);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06002862 dev_data->imageViewMap.clear();
2863 dev_data->imageMap.clear();
2864 dev_data->bufferViewMap.clear();
2865 dev_data->bufferMap.clear();
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002866 loader_platform_thread_unlock_mutex(&globalLock);
2867
Chia-I Wuf7458c52015-10-26 21:10:41 +08002868 dev_data->device_dispatch_table->DestroyDevice(device, pAllocator);
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06002869 tableDebugMarkerMap.erase(key);
Tobin Ehlis0b632332015-10-07 09:38:40 -06002870 delete dev_data->device_dispatch_table;
2871 layer_data_map.erase(key);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06002872}
2873
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002874static const VkExtensionProperties instance_extensions[] = {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002875 {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002876 VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
2877 VK_EXT_DEBUG_REPORT_REVISION
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002878 }
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06002879};
2880
Chia-I Wu9ab61502015-11-06 06:42:02 +08002881VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06002882 const char *pLayerName,
2883 uint32_t *pCount,
2884 VkExtensionProperties* pProperties)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06002885{
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002886 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06002887}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06002888
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002889static const VkLayerProperties ds_global_layers[] = {
2890 {
Michael Lentine03107b42015-12-11 10:49:51 -08002891 "VK_LAYER_LUNARG_draw_state",
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002892 VK_API_VERSION,
2893 VK_MAKE_VERSION(0, 1, 0),
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002894 "Validation layer: draw_state",
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002895 }
2896};
2897
Chia-I Wu9ab61502015-11-06 06:42:02 +08002898VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06002899 uint32_t *pCount,
2900 VkLayerProperties* pProperties)
2901{
2902 return util_GetLayerProperties(ARRAY_SIZE(ds_global_layers),
2903 ds_global_layers,
2904 pCount, pProperties);
2905}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06002906
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06002907static const VkExtensionProperties ds_device_extensions[] = {
2908 {
2909 DEBUG_MARKER_EXTENSION_NAME,
2910 VK_MAKE_VERSION(0, 1, 0),
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06002911 }
2912};
2913
2914static const VkLayerProperties ds_device_layers[] = {
2915 {
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002916 "draw_state",
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06002917 VK_API_VERSION,
2918 VK_MAKE_VERSION(0, 1, 0),
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -07002919 "Validation layer: draw_state",
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06002920 }
2921};
2922
Chia-I Wu9ab61502015-11-06 06:42:02 +08002923VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06002924 VkPhysicalDevice physicalDevice,
2925 const char* pLayerName,
2926 uint32_t* pCount,
2927 VkExtensionProperties* pProperties)
2928{
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07002929 // DrawState does not have any physical device extensions
Jon Ashburn751c4842015-11-02 17:37:20 -07002930 if (pLayerName == NULL) {
2931 dispatch_key key = get_dispatch_key(physicalDevice);
2932 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07002933 return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(
Jon Ashburn751c4842015-11-02 17:37:20 -07002934 physicalDevice,
2935 NULL,
2936 pCount,
2937 pProperties);
2938 } else {
2939 return util_GetExtensionProperties(ARRAY_SIZE(ds_device_extensions),
2940 ds_device_extensions,
2941 pCount, pProperties);
2942 }
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06002943}
2944
Chia-I Wu9ab61502015-11-06 06:42:02 +08002945VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06002946 VkPhysicalDevice physicalDevice,
2947 uint32_t* pCount,
2948 VkLayerProperties* pProperties)
2949{
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07002950 /* DrawState physical device layers are the same as global */
Courtney Goeltzenleuchter7ad58c02015-07-06 22:31:52 -06002951 return util_GetLayerProperties(ARRAY_SIZE(ds_device_layers), ds_device_layers,
2952 pCount, pProperties);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06002953}
2954
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07002955VkBool32 ValidateCmdBufImageLayouts(VkCommandBuffer cmdBuffer) {
2956 VkBool32 skip_call = false;
Michael Lentineabc5e922015-10-12 11:30:14 -05002957 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
2958 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, cmdBuffer);
2959 for (auto cb_image_data : pCB->imageLayoutMap) {
2960 auto image_data = dev_data->imageLayoutMap.find(cb_image_data.first);
2961 if (image_data == dev_data->imageLayoutMap.end()) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002962 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentine010f4692015-11-03 16:19:46 -08002963 "Cannot submit cmd buffer using deleted image %" PRIu64 ".", reinterpret_cast<uint64_t>(cb_image_data.first));
Michael Lentineabc5e922015-10-12 11:30:14 -05002964 } else {
2965 if (dev_data->imageLayoutMap[cb_image_data.first]->layout != cb_image_data.second.initialLayout) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07002966 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05002967 "Cannot submit cmd buffer using image with layout %d when first use is %d.", dev_data->imageLayoutMap[cb_image_data.first]->layout, cb_image_data.second.initialLayout);
2968 }
2969 dev_data->imageLayoutMap[cb_image_data.first]->layout = cb_image_data.second.layout;
2970 }
2971 }
2972 return skip_call;
2973}
2974
Michael Lentine700b0aa2015-10-30 17:57:32 -07002975bool validateAndIncrementResources(layer_data* my_data, GLOBAL_CB_NODE* pCB) {
2976 bool skip_call = false;
2977 for (auto drawDataElement : pCB->drawData) {
2978 for (auto buffer : drawDataElement.buffers) {
2979 auto buffer_data = my_data->bufferMap.find(buffer);
2980 if (buffer_data == my_data->bufferMap.end()) {
2981 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 0, DRAWSTATE_INVALID_BUFFER, "DS",
2982 "Cannot submit cmd buffer using deleted buffer %" PRIu64 ".", reinterpret_cast<uint64_t>(buffer));
2983 } else {
2984 buffer_data->second.in_use.fetch_add(1);
2985 }
2986 }
2987 }
2988}
2989
2990void decrementResources(layer_data* my_data, VkCommandBuffer cmdBuffer) {
2991 GLOBAL_CB_NODE* pCB = getCBNode(my_data, cmdBuffer);
2992 for (auto drawDataElement : pCB->drawData) {
2993 for (auto buffer : drawDataElement.buffers) {
2994 auto buffer_data = my_data->bufferMap.find(buffer);
2995 if (buffer_data != my_data->bufferMap.end()) {
2996 buffer_data->second.in_use.fetch_sub(1);
2997 }
2998 }
2999 }
3000}
3001
3002void decrementResources(layer_data* my_data, uint32_t fenceCount, const VkFence* pFences) {
3003 for (uint32_t i = 0; i < fenceCount; ++i) {
3004 auto fence_data = my_data->fenceMap.find(pFences[i]);
3005 if (fence_data == my_data->fenceMap.end() || !fence_data->second.needsSignaled) return;
3006 fence_data->second.needsSignaled = false;
3007 if (fence_data->second.priorFence != VK_NULL_HANDLE) {
3008 decrementResources(my_data, 1, &fence_data->second.priorFence);
3009 }
3010 for (auto cmdBuffer : fence_data->second.cmdBuffers) {
3011 decrementResources(my_data, cmdBuffer);
3012 }
3013 }
3014}
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07003015
Michael Lentine700b0aa2015-10-30 17:57:32 -07003016void decrementResources(layer_data* my_data, VkQueue queue) {
3017 auto queue_data = my_data->queueMap.find(queue);
3018 if (queue_data != my_data->queueMap.end()) {
3019 for (auto cmdBuffer : queue_data->second.untrackedCmdBuffers) {
3020 decrementResources(my_data, cmdBuffer);
3021 }
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07003022 queue_data->second.untrackedCmdBuffers.clear();
Michael Lentine700b0aa2015-10-30 17:57:32 -07003023 decrementResources(my_data, 1, &queue_data->second.priorFence);
3024 }
3025}
3026
3027void trackCommandBuffers(layer_data* my_data, VkQueue queue, uint32_t cmdBufferCount, const VkCommandBuffer* pCmdBuffers, VkFence fence) {
3028 auto queue_data = my_data->queueMap.find(queue);
3029 if (fence != VK_NULL_HANDLE) {
3030 VkFence priorFence = VK_NULL_HANDLE;
3031 if (queue_data != my_data->queueMap.end()) {
3032 priorFence = queue_data->second.priorFence;
3033 queue_data->second.priorFence = fence;
3034 for (auto cmdBuffer : queue_data->second.untrackedCmdBuffers) {
3035 my_data->fenceMap[fence].cmdBuffers.push_back(cmdBuffer);
3036 }
3037 queue_data->second.untrackedCmdBuffers.clear();
3038 }
3039 my_data->fenceMap[fence].cmdBuffers.clear();
3040 my_data->fenceMap[fence].priorFence = priorFence;
3041 my_data->fenceMap[fence].needsSignaled = true;
3042 for (uint32_t i = 0; i < cmdBufferCount; ++i) {
3043 my_data->fenceMap[fence].cmdBuffers.push_back(pCmdBuffers[i]);
3044 }
3045 } else {
3046 if (queue_data != my_data->queueMap.end()) {
3047 for (uint32_t i = 0; i < cmdBufferCount; ++i) {
3048 queue_data->second.untrackedCmdBuffers.push_back(pCmdBuffers[i]);
3049 }
3050 }
3051 }
3052}
3053
Chia-I Wu9ab61502015-11-06 06:42:02 +08003054VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003055{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003056 VkBool32 skipCall = VK_FALSE;
Tobin Ehlisa9f3d762015-05-22 12:38:16 -06003057 GLOBAL_CB_NODE* pCB = NULL;
Tobin Ehlis0b632332015-10-07 09:38:40 -06003058 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Tobin Ehlis651d9b02015-12-16 05:01:22 -07003059 // TODO : Any pCommandBuffers must have USAGE_SIMULTANEOUS_USE_BIT set or cannot already be executing on device
3060 // Same goes for any secondary CBs under the primary CB
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06003061 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
Chia-I Wu40cf0ae2015-10-26 17:20:32 +08003062 const VkSubmitInfo *submit = &pSubmits[submit_idx];
Chia-I Wud50a7d72015-10-26 20:48:51 +08003063 for (uint32_t i=0; i < submit->commandBufferCount; i++) {
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07003064
3065#ifndef DISABLE_IMAGE_LAYOUT_VALIDATION
3066 skipCall |= ValidateCmdBufImageLayouts(submit->pCommandBuffers[i]);
3067#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
3068
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06003069 // Validate that cmd buffers have been updated
3070 pCB = getCBNode(dev_data, submit->pCommandBuffers[i]);
3071 loader_platform_thread_lock_mutex(&globalLock);
3072 pCB->submitCount++; // increment submit count
Michael Lentine700b0aa2015-10-30 17:57:32 -07003073 skipCall |= validateAndIncrementResources(dev_data, pCB);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003074 if ((pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) && (pCB->submitCount > 1)) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003075 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05003076 "CB %#" PRIxLEAST64 " was begun w/ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT set, but has been submitted %#" PRIxLEAST64 " times.",
3077 reinterpret_cast<uint64_t>(pCB->commandBuffer), pCB->submitCount);
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06003078 }
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003079 if (CB_RECORDED != pCB->state) {
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06003080 // Flag error for using CB w/o vkEndCommandBuffer() called
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003081 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_NO_END_COMMAND_BUFFER, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003082 "You must call vkEndCommandBuffer() on CB %#" PRIxLEAST64 " before this call to vkQueueSubmit()!", reinterpret_cast<uint64_t>(pCB->commandBuffer));
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06003083 loader_platform_thread_unlock_mutex(&globalLock);
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003084 return VK_ERROR_VALIDATION_FAILED_EXT;
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06003085 }
Tobin Ehlisc4bdde12015-05-27 14:30:06 -06003086 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlisa9f3d762015-05-22 12:38:16 -06003087 }
Michael Lentine700b0aa2015-10-30 17:57:32 -07003088 trackCommandBuffers(dev_data, queue, submit->commandBufferCount, submit->pCommandBuffers, fence);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003089 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003090 if (VK_FALSE == skipCall)
Chia-I Wu40cf0ae2015-10-26 17:20:32 +08003091 return dev_data->device_dispatch_table->QueueSubmit(queue, submitCount, pSubmits, fence);
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003092 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003093}
3094
Michael Lentine700b0aa2015-10-30 17:57:32 -07003095VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout)
3096{
3097 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3098 VkResult result = dev_data->device_dispatch_table->WaitForFences(device, fenceCount, pFences, waitAll, timeout);
3099 if ((waitAll || fenceCount == 1) && result == VK_SUCCESS) {
3100 decrementResources(dev_data, fenceCount, pFences);
3101 }
3102 return result;
3103}
3104
3105
3106VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus(VkDevice device, VkFence fence)
3107{
3108 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3109 VkResult result = dev_data->device_dispatch_table->GetFenceStatus(device, fence);
3110 if (result == VK_SUCCESS) {
3111 decrementResources(dev_data, 1, &fence);
3112 }
3113 return result;
3114}
3115
3116VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue)
3117{
3118 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3119 dev_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
3120 dev_data->deviceMap[device].queues.push_back(*pQueue);
3121 dev_data->queueMap[*pQueue].device = device;
3122}
3123
3124VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle(VkQueue queue)
3125{
3126 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
3127 decrementResources(dev_data, queue);
3128 return dev_data->device_dispatch_table->QueueWaitIdle(queue);
3129}
3130
3131VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle(VkDevice device)
3132{
3133 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3134 auto device_data = dev_data->deviceMap.find(device);
3135 if (device_data != dev_data->deviceMap.end()) {
3136 for (auto queue : device_data->second.queues) {
3137 decrementResources(dev_data, queue);
3138 }
3139 }
3140 return dev_data->device_dispatch_table->DeviceWaitIdle(device);
3141}
3142
Chia-I Wu9ab61502015-11-06 06:42:02 +08003143VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003144{
Chia-I Wuf7458c52015-10-26 21:10:41 +08003145 get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroyFence(device, fence, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003146 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003147}
3148
Chia-I Wu9ab61502015-11-06 06:42:02 +08003149VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003150{
Chia-I Wuf7458c52015-10-26 21:10:41 +08003151 get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroySemaphore(device, semaphore, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003152 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003153}
3154
Chia-I Wu9ab61502015-11-06 06:42:02 +08003155VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003156{
Chia-I Wuf7458c52015-10-26 21:10:41 +08003157 get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroyEvent(device, event, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003158 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003159}
3160
Chia-I Wu9ab61502015-11-06 06:42:02 +08003161VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003162{
Chia-I Wuf7458c52015-10-26 21:10:41 +08003163 get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroyQueryPool(device, queryPool, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003164 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003165}
3166
Michael Lentine700b0aa2015-10-30 17:57:32 -07003167bool validateIdleBuffer(const layer_data* my_data, VkBuffer buffer) {
3168 bool skip_call = false;
3169 auto buffer_data = my_data->bufferMap.find(buffer);
3170 if (buffer_data == my_data->bufferMap.end()) {
3171 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 0, DRAWSTATE_DOUBLE_DESTROY, "DS",
3172 "Cannot free buffer %" PRIxLEAST64 " that has not been allocated.", reinterpret_cast<uint64_t>(buffer));
3173 } else {
3174 if (buffer_data->second.in_use.load()) {
3175 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 0, DRAWSTATE_OBJECT_INUSE, "DS",
3176 "Cannot free buffer %" PRIxLEAST64 " that is in use by a command buffer.", reinterpret_cast<uint64_t>(buffer));
3177
3178 }
3179 }
3180 return skip_call;
3181}
3182
Chia-I Wu9ab61502015-11-06 06:42:02 +08003183VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003184{
Tobin Ehlisa1c28562015-10-23 16:00:08 -06003185 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Michael Lentine700b0aa2015-10-30 17:57:32 -07003186 bool skip_call = false;
3187 if (!validateIdleBuffer(dev_data, buffer)) {
3188 dev_data->device_dispatch_table->DestroyBuffer(device, buffer, pAllocator);
3189 }
Chia-I Wue2fc5522015-10-26 20:04:44 +08003190 dev_data->bufferMap.erase(buffer);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003191}
3192
Chia-I Wu9ab61502015-11-06 06:42:02 +08003193VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003194{
Tobin Ehlisa1c28562015-10-23 16:00:08 -06003195 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08003196 dev_data->device_dispatch_table->DestroyBufferView(device, bufferView, pAllocator);
Chia-I Wue2fc5522015-10-26 20:04:44 +08003197 dev_data->bufferViewMap.erase(bufferView);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003198}
3199
Chia-I Wu9ab61502015-11-06 06:42:02 +08003200VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003201{
Tobin Ehlisa1c28562015-10-23 16:00:08 -06003202 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08003203 dev_data->device_dispatch_table->DestroyImage(device, image, pAllocator);
Chia-I Wue2fc5522015-10-26 20:04:44 +08003204 dev_data->imageMap.erase(image);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003205}
3206
Chia-I Wu9ab61502015-11-06 06:42:02 +08003207VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003208{
Chia-I Wuf7458c52015-10-26 21:10:41 +08003209 get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroyImageView(device, imageView, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003210 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003211}
3212
Chia-I Wu9ab61502015-11-06 06:42:02 +08003213VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003214{
Chia-I Wuf7458c52015-10-26 21:10:41 +08003215 get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroyShaderModule(device, shaderModule, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003216 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003217}
3218
Chia-I Wu9ab61502015-11-06 06:42:02 +08003219VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003220{
Chia-I Wuf7458c52015-10-26 21:10:41 +08003221 get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroyPipeline(device, pipeline, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003222 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003223}
3224
Chia-I Wu9ab61502015-11-06 06:42:02 +08003225VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003226{
Chia-I Wuf7458c52015-10-26 21:10:41 +08003227 get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroyPipelineLayout(device, pipelineLayout, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003228 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003229}
3230
Chia-I Wu9ab61502015-11-06 06:42:02 +08003231VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003232{
Chia-I Wuf7458c52015-10-26 21:10:41 +08003233 get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroySampler(device, sampler, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003234 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003235}
3236
Chia-I Wu9ab61502015-11-06 06:42:02 +08003237VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003238{
Chia-I Wuf7458c52015-10-26 21:10:41 +08003239 get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003240 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003241}
3242
Chia-I Wu9ab61502015-11-06 06:42:02 +08003243VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003244{
Chia-I Wuf7458c52015-10-26 21:10:41 +08003245 get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroyDescriptorPool(device, descriptorPool, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003246 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003247}
3248
Chia-I Wu9ab61502015-11-06 06:42:02 +08003249VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t count, const VkCommandBuffer *pCommandBuffers)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003250{
Mark Lobodzinski39298632015-11-18 08:38:27 -07003251 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3252
Courtney Goeltzenleuchter51239472015-12-16 16:06:06 -07003253 for (uint32_t i = 0; i < count; i++) {
Mark Lobodzinski39298632015-11-18 08:38:27 -07003254 // Delete CB information structure, and remove from commandBufferMap
3255 auto cb = dev_data->commandBufferMap.find(pCommandBuffers[i]);
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07003256 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07003257 if (cb != dev_data->commandBufferMap.end()) {
3258 delete (*cb).second;
3259 dev_data->commandBufferMap.erase(cb);
3260 }
3261
3262 // Remove commandBuffer reference from commandPoolMap
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003263 dev_data->commandPoolMap[commandPool].commandBuffers.remove(pCommandBuffers[i]);
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07003264 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07003265 }
3266
3267 dev_data->device_dispatch_table->FreeCommandBuffers(device, commandPool, count, pCommandBuffers);
3268}
3269
3270VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool)
3271{
3272 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3273
3274 VkResult result = dev_data->device_dispatch_table->CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
3275
3276 if (VK_SUCCESS == result) {
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07003277 loader_platform_thread_lock_mutex(&globalLock);
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003278 dev_data->commandPoolMap[*pCommandPool].createFlags = pCreateInfo->flags;
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07003279 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07003280 }
3281 return result;
3282}
3283
3284VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator)
3285{
3286 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07003287 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07003288
3289 // Must remove cmdpool from cmdpoolmap, after removing all cmdbuffers in its list from the commandPoolMap
3290 if (dev_data->commandPoolMap.find(commandPool) != dev_data->commandPoolMap.end()) {
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003291 for (auto poolCb = dev_data->commandPoolMap[commandPool].commandBuffers.begin(); poolCb != dev_data->commandPoolMap[commandPool].commandBuffers.end();) {
Mark Lobodzinski39298632015-11-18 08:38:27 -07003292 auto del_cb = dev_data->commandBufferMap.find(*poolCb);
3293 delete (*del_cb).second; // delete CB info structure
3294 dev_data->commandBufferMap.erase(del_cb); // Remove this command buffer from cbMap
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003295 poolCb = dev_data->commandPoolMap[commandPool].commandBuffers.erase(poolCb); // Remove CB reference from commandPoolMap's list
Mark Lobodzinski39298632015-11-18 08:38:27 -07003296 }
3297 }
3298 dev_data->commandPoolMap.erase(commandPool);
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07003299
3300 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07003301 dev_data->device_dispatch_table->DestroyCommandPool(device, commandPool, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003302}
3303
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003304VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandPool(
3305 VkDevice device,
3306 VkCommandPool commandPool,
3307 VkCommandPoolResetFlags flags)
3308{
3309 layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003310 VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003311
3312 result = dev_data->device_dispatch_table->ResetCommandPool(device, commandPool, flags);
3313 // Reset all of the CBs allocated from this pool
3314 if (VK_SUCCESS == result) {
3315 auto it = dev_data->commandPoolMap[commandPool].commandBuffers.begin();
3316 while (it != dev_data->commandPoolMap[commandPool].commandBuffers.end()) {
3317 resetCB(dev_data, (*it));
3318 ++it;
3319 }
3320 }
3321 return result;
3322}
3323
Chia-I Wu9ab61502015-11-06 06:42:02 +08003324VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003325{
Chia-I Wuf7458c52015-10-26 21:10:41 +08003326 get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroyFramebuffer(device, framebuffer, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003327 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003328}
3329
Chia-I Wu9ab61502015-11-06 06:42:02 +08003330VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003331{
Chia-I Wuf7458c52015-10-26 21:10:41 +08003332 get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroyRenderPass(device, renderPass, pAllocator);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003333 // TODO : Clean up any internal data structures using this obj.
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003334}
3335
Chia-I Wu9ab61502015-11-06 06:42:02 +08003336VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer)
Tobin Ehlisa1c28562015-10-23 16:00:08 -06003337{
3338 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08003339 VkResult result = dev_data->device_dispatch_table->CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06003340 if (VK_SUCCESS == result) {
3341 loader_platform_thread_lock_mutex(&globalLock);
3342 // TODO : This doesn't create deep copy of pQueueFamilyIndices so need to fix that if/when we want that data to be valid
Michael Lentine700b0aa2015-10-30 17:57:32 -07003343 dev_data->bufferMap[*pBuffer].create_info = unique_ptr<VkBufferCreateInfo>(new VkBufferCreateInfo(*pCreateInfo));
3344 dev_data->bufferMap[*pBuffer].in_use.store(0);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06003345 loader_platform_thread_unlock_mutex(&globalLock);
3346 }
3347 return result;
3348}
3349
Chia-I Wu9ab61502015-11-06 06:42:02 +08003350VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003351{
Tobin Ehlis0b632332015-10-07 09:38:40 -06003352 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08003353 VkResult result = dev_data->device_dispatch_table->CreateBufferView(device, pCreateInfo, pAllocator, pView);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06003354 if (VK_SUCCESS == result) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003355 loader_platform_thread_lock_mutex(&globalLock);
Chia-I Wue2fc5522015-10-26 20:04:44 +08003356 dev_data->bufferViewMap[*pView] = unique_ptr<VkBufferViewCreateInfo>(new VkBufferViewCreateInfo(*pCreateInfo));
Tobin Ehlisa1c28562015-10-23 16:00:08 -06003357 loader_platform_thread_unlock_mutex(&globalLock);
3358 }
3359 return result;
3360}
3361
Chia-I Wu9ab61502015-11-06 06:42:02 +08003362VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage)
Tobin Ehlisa1c28562015-10-23 16:00:08 -06003363{
3364 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08003365 VkResult result = dev_data->device_dispatch_table->CreateImage(device, pCreateInfo, pAllocator, pImage);
Tobin Ehlisa1c28562015-10-23 16:00:08 -06003366 if (VK_SUCCESS == result) {
Michael Lentineabc5e922015-10-12 11:30:14 -05003367 IMAGE_NODE* image_node = new IMAGE_NODE;
3368 image_node->layout = pCreateInfo->initialLayout;
Tobin Ehlisa1c28562015-10-23 16:00:08 -06003369 loader_platform_thread_lock_mutex(&globalLock);
Chia-I Wue2fc5522015-10-26 20:04:44 +08003370 dev_data->imageMap[*pImage] = unique_ptr<VkImageCreateInfo>(new VkImageCreateInfo(*pCreateInfo));
Michael Lentineabc5e922015-10-12 11:30:14 -05003371 dev_data->imageLayoutMap[*pImage] = image_node;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003372 loader_platform_thread_unlock_mutex(&globalLock);
3373 }
3374 return result;
3375}
3376
Chia-I Wu9ab61502015-11-06 06:42:02 +08003377VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003378{
Tobin Ehlis0b632332015-10-07 09:38:40 -06003379 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08003380 VkResult result = dev_data->device_dispatch_table->CreateImageView(device, pCreateInfo, pAllocator, pView);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06003381 if (VK_SUCCESS == result) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003382 loader_platform_thread_lock_mutex(&globalLock);
Chia-I Wue2fc5522015-10-26 20:04:44 +08003383 dev_data->imageViewMap[*pView] = unique_ptr<VkImageViewCreateInfo>(new VkImageViewCreateInfo(*pCreateInfo));
Tobin Ehlis53eddda2015-07-01 16:46:13 -06003384 loader_platform_thread_unlock_mutex(&globalLock);
3385 }
3386 return result;
3387}
3388
Jon Ashburnc669cc62015-07-09 15:02:25 -06003389//TODO handle pipeline caches
Chia-I Wu9ab61502015-11-06 06:42:02 +08003390VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineCache(
Jon Ashburnc669cc62015-07-09 15:02:25 -06003391 VkDevice device,
3392 const VkPipelineCacheCreateInfo* pCreateInfo,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003393 const VkAllocationCallbacks* pAllocator,
Jon Ashburnc669cc62015-07-09 15:02:25 -06003394 VkPipelineCache* pPipelineCache)
3395{
Tobin Ehlis0b632332015-10-07 09:38:40 -06003396 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08003397 VkResult result = dev_data->device_dispatch_table->CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache);
Jon Ashburnc669cc62015-07-09 15:02:25 -06003398 return result;
3399}
3400
Chia-I Wu9ab61502015-11-06 06:42:02 +08003401VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineCache(
Jon Ashburnc669cc62015-07-09 15:02:25 -06003402 VkDevice device,
Chia-I Wuf7458c52015-10-26 21:10:41 +08003403 VkPipelineCache pipelineCache,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003404 const VkAllocationCallbacks* pAllocator)
Jon Ashburnc669cc62015-07-09 15:02:25 -06003405{
Tobin Ehlis0b632332015-10-07 09:38:40 -06003406 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08003407 dev_data->device_dispatch_table->DestroyPipelineCache(device, pipelineCache, pAllocator);
Jon Ashburnc669cc62015-07-09 15:02:25 -06003408}
3409
Chia-I Wu9ab61502015-11-06 06:42:02 +08003410VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineCacheData(
Jon Ashburnc669cc62015-07-09 15:02:25 -06003411 VkDevice device,
3412 VkPipelineCache pipelineCache,
Chia-I Wub16facd2015-10-26 19:17:06 +08003413 size_t* pDataSize,
Jon Ashburnc669cc62015-07-09 15:02:25 -06003414 void* pData)
3415{
Tobin Ehlis0b632332015-10-07 09:38:40 -06003416 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wub16facd2015-10-26 19:17:06 +08003417 VkResult result = dev_data->device_dispatch_table->GetPipelineCacheData(device, pipelineCache, pDataSize, pData);
Jon Ashburnc669cc62015-07-09 15:02:25 -06003418 return result;
3419}
3420
Chia-I Wu9ab61502015-11-06 06:42:02 +08003421VKAPI_ATTR VkResult VKAPI_CALL vkMergePipelineCaches(
Jon Ashburnc669cc62015-07-09 15:02:25 -06003422 VkDevice device,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003423 VkPipelineCache dstCache,
Jon Ashburnc669cc62015-07-09 15:02:25 -06003424 uint32_t srcCacheCount,
3425 const VkPipelineCache* pSrcCaches)
3426{
Tobin Ehlis0b632332015-10-07 09:38:40 -06003427 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003428 VkResult result = dev_data->device_dispatch_table->MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches);
Jon Ashburnc669cc62015-07-09 15:02:25 -06003429 return result;
3430}
3431
Mark Lobodzinski475a2182015-11-10 15:25:01 -07003432VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateGraphicsPipelines(
3433 VkDevice device,
3434 VkPipelineCache pipelineCache,
3435 uint32_t count,
3436 const VkGraphicsPipelineCreateInfo *pCreateInfos,
3437 const VkAllocationCallbacks *pAllocator,
3438 VkPipeline *pPipelines)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003439{
Courtney Goeltzenleuchtered894072015-09-04 13:39:59 -06003440 VkResult result = VK_SUCCESS;
Tobin Ehlis11efc302015-09-16 10:33:53 -06003441 //TODO What to do with pipelineCache?
Tobin Ehlis75283bf2015-06-18 15:59:33 -06003442 // The order of operations here is a little convoluted but gets the job done
3443 // 1. Pipeline create state is first shadowed into PIPELINE_NODE struct
3444 // 2. Create state is then validated (which uses flags setup during shadowing)
3445 // 3. If everything looks good, we'll then create the pipeline and add NODE to pipelineMap
Tobin Ehlis11efc302015-09-16 10:33:53 -06003446 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis65399772015-09-17 16:33:58 -06003447 // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic
3448 vector<PIPELINE_NODE*> pPipeNode(count);
Tobin Ehlis0b632332015-10-07 09:38:40 -06003449 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski475a2182015-11-10 15:25:01 -07003450
Tobin Ehlis11efc302015-09-16 10:33:53 -06003451 uint32_t i=0;
Tobin Ehlis75283bf2015-06-18 15:59:33 -06003452 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski475a2182015-11-10 15:25:01 -07003453
Tobin Ehlis11efc302015-09-16 10:33:53 -06003454 for (i=0; i<count; i++) {
Mark Lobodzinski475a2182015-11-10 15:25:01 -07003455 pPipeNode[i] = initGraphicsPipeline(dev_data, &pCreateInfos[i], NULL);
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06003456 skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode[i]);
Tobin Ehlis11efc302015-09-16 10:33:53 -06003457 }
Mark Lobodzinski475a2182015-11-10 15:25:01 -07003458
Tobin Ehlis75283bf2015-06-18 15:59:33 -06003459 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07003460
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07003461 if (VK_FALSE == skipCall) {
Mark Lobodzinski475a2182015-11-10 15:25:01 -07003462 result = dev_data->device_dispatch_table->CreateGraphicsPipelines(device,
3463 pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
Tobin Ehlis75283bf2015-06-18 15:59:33 -06003464 loader_platform_thread_lock_mutex(&globalLock);
Tobin Ehlis11efc302015-09-16 10:33:53 -06003465 for (i=0; i<count; i++) {
3466 pPipeNode[i]->pipeline = pPipelines[i];
Chia-I Wue2fc5522015-10-26 20:04:44 +08003467 dev_data->pipelineMap[pPipeNode[i]->pipeline] = pPipeNode[i];
Tobin Ehlis11efc302015-09-16 10:33:53 -06003468 }
Tobin Ehlis75283bf2015-06-18 15:59:33 -06003469 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlisce132d82015-06-19 15:07:05 -06003470 } else {
Tobin Ehlis11efc302015-09-16 10:33:53 -06003471 for (i=0; i<count; i++) {
3472 if (pPipeNode[i]) {
3473 // If we allocated a pipeNode, need to clean it up here
3474 delete[] pPipeNode[i]->pVertexBindingDescriptions;
3475 delete[] pPipeNode[i]->pVertexAttributeDescriptions;
3476 delete[] pPipeNode[i]->pAttachments;
3477 delete pPipeNode[i];
3478 }
Tobin Ehlis75283bf2015-06-18 15:59:33 -06003479 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003480 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis75283bf2015-06-18 15:59:33 -06003481 }
Courtney Goeltzenleuchtere2aaad02015-04-13 16:16:04 -06003482 return result;
3483}
3484
Mark Lobodzinski475a2182015-11-10 15:25:01 -07003485VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateComputePipelines(
3486 VkDevice device,
3487 VkPipelineCache pipelineCache,
3488 uint32_t count,
3489 const VkComputePipelineCreateInfo *pCreateInfos,
3490 const VkAllocationCallbacks *pAllocator,
3491 VkPipeline *pPipelines)
3492{
3493 VkResult result = VK_SUCCESS;
3494 VkBool32 skipCall = VK_FALSE;
3495
3496 // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic
3497 vector<PIPELINE_NODE*> pPipeNode(count);
3498 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3499
3500 uint32_t i=0;
3501 loader_platform_thread_lock_mutex(&globalLock);
3502 for (i=0; i<count; i++) {
3503 // TODO: Verify compute stage bits
3504
3505 // Create and initialize internal tracking data structure
3506 pPipeNode[i] = new PIPELINE_NODE;
3507 memset((void*)pPipeNode[i], 0, sizeof(PIPELINE_NODE));
3508 memcpy(&pPipeNode[i]->computePipelineCI, (const void*)&pCreateInfos[i], sizeof(VkComputePipelineCreateInfo));
3509
3510 // TODO: Add Compute Pipeline Verification
3511 // skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode[i]);
3512 }
3513 loader_platform_thread_unlock_mutex(&globalLock);
3514
3515 if (VK_FALSE == skipCall) {
3516 result = dev_data->device_dispatch_table->CreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
3517 loader_platform_thread_lock_mutex(&globalLock);
3518 for (i=0; i<count; i++) {
3519 pPipeNode[i]->pipeline = pPipelines[i];
3520 dev_data->pipelineMap[pPipeNode[i]->pipeline] = pPipeNode[i];
3521 }
3522 loader_platform_thread_unlock_mutex(&globalLock);
3523 } else {
3524 for (i=0; i<count; i++) {
3525 if (pPipeNode[i]) {
3526 // Clean up any locally allocated data structures
3527 delete pPipeNode[i];
3528 }
3529 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003530 return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski475a2182015-11-10 15:25:01 -07003531 }
3532 return result;
3533}
3534
Chia-I Wu9ab61502015-11-06 06:42:02 +08003535VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003536{
Tobin Ehlis0b632332015-10-07 09:38:40 -06003537 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08003538 VkResult result = dev_data->device_dispatch_table->CreateSampler(device, pCreateInfo, pAllocator, pSampler);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06003539 if (VK_SUCCESS == result) {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003540 loader_platform_thread_lock_mutex(&globalLock);
Chia-I Wue2fc5522015-10-26 20:04:44 +08003541 dev_data->sampleMap[*pSampler] = unique_ptr<SAMPLER_NODE>(new SAMPLER_NODE(pSampler, pCreateInfo));
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003542 loader_platform_thread_unlock_mutex(&globalLock);
3543 }
3544 return result;
3545}
3546
Chia-I Wu9ab61502015-11-06 06:42:02 +08003547VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003548{
Tobin Ehlis0b632332015-10-07 09:38:40 -06003549 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08003550 VkResult result = dev_data->device_dispatch_table->CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06003551 if (VK_SUCCESS == result) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07003552 // TODOSC : Capture layout bindings set
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003553 LAYOUT_NODE* pNewNode = new LAYOUT_NODE;
3554 if (NULL == pNewNode) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003555 if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, (uint64_t) *pSetLayout, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS",
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003556 "Out of memory while attempting to allocate LAYOUT_NODE in vkCreateDescriptorSetLayout()"))
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003557 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003558 }
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06003559 memcpy((void*)&pNewNode->createInfo, pCreateInfo, sizeof(VkDescriptorSetLayoutCreateInfo));
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07003560 pNewNode->createInfo.pBindings = new VkDescriptorSetLayoutBinding[pCreateInfo->bindingCount];
3561 memcpy((void*)pNewNode->createInfo.pBindings, pCreateInfo->pBindings, sizeof(VkDescriptorSetLayoutBinding)*pCreateInfo->bindingCount);
Chia-I Wud46e6ae2015-10-31 00:31:16 +08003562 // g++ does not like reserve with size 0
3563 if (pCreateInfo->bindingCount)
3564 pNewNode->bindings.reserve(pCreateInfo->bindingCount);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003565 uint32_t totalCount = 0;
Chia-I Wud50a7d72015-10-26 20:48:51 +08003566 for (uint32_t i=0; i<pCreateInfo->bindingCount; i++) {
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07003567 if (!pNewNode->bindings.insert(pCreateInfo->pBindings[i].binding).second) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003568 if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, (uint64_t) *pSetLayout, __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
Chia-I Wud46e6ae2015-10-31 00:31:16 +08003569 "duplicated binding number in VkDescriptorSetLayoutBinding"))
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003570 return VK_ERROR_VALIDATION_FAILED_EXT;
Chia-I Wud46e6ae2015-10-31 00:31:16 +08003571 }
3572
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07003573 totalCount += pCreateInfo->pBindings[i].descriptorCount;
3574 if (pCreateInfo->pBindings[i].pImmutableSamplers) {
3575 VkSampler** ppIS = (VkSampler**)&pNewNode->createInfo.pBindings[i].pImmutableSamplers;
3576 *ppIS = new VkSampler[pCreateInfo->pBindings[i].descriptorCount];
3577 memcpy(*ppIS, pCreateInfo->pBindings[i].pImmutableSamplers, pCreateInfo->pBindings[i].descriptorCount*sizeof(VkSampler));
Tobin Ehlis793ad302015-04-03 12:01:11 -06003578 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003579 }
3580 if (totalCount > 0) {
Cody Northrop43751cc2015-10-26 14:07:35 -06003581 pNewNode->descriptorTypes.resize(totalCount);
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06003582 pNewNode->stageFlags.resize(totalCount);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003583 uint32_t offset = 0;
Tobin Ehlis793ad302015-04-03 12:01:11 -06003584 uint32_t j = 0;
Tobin Ehlisda2f0d02015-11-04 12:28:28 -07003585 VkDescriptorType dType;
Chia-I Wud50a7d72015-10-26 20:48:51 +08003586 for (uint32_t i=0; i<pCreateInfo->bindingCount; i++) {
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07003587 dType = pCreateInfo->pBindings[i].descriptorType;
3588 for (j = 0; j < pCreateInfo->pBindings[i].descriptorCount; j++) {
Tobin Ehlisda2f0d02015-11-04 12:28:28 -07003589 pNewNode->descriptorTypes[offset + j] = dType;
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07003590 pNewNode->stageFlags[offset + j] = pCreateInfo->pBindings[i].stageFlags;
Tobin Ehlisda2f0d02015-11-04 12:28:28 -07003591 if ((dType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
3592 (dType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
3593 pNewNode->dynamicDescriptorCount++;
3594 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003595 }
Tobin Ehlis793ad302015-04-03 12:01:11 -06003596 offset += j;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003597 }
3598 }
3599 pNewNode->layout = *pSetLayout;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003600 pNewNode->startIndex = 0;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003601 pNewNode->endIndex = pNewNode->startIndex + totalCount - 1;
3602 assert(pNewNode->endIndex >= pNewNode->startIndex);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003603 // Put new node at Head of global Layer list
3604 loader_platform_thread_lock_mutex(&globalLock);
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07003605 dev_data->descriptorSetLayoutMap[*pSetLayout] = pNewNode;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003606 loader_platform_thread_unlock_mutex(&globalLock);
3607 }
3608 return result;
3609}
3610
Chia-I Wu9ab61502015-11-06 06:42:02 +08003611VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003612{
Tobin Ehlis0b632332015-10-07 09:38:40 -06003613 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08003614 VkResult result = dev_data->device_dispatch_table->CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06003615 if (VK_SUCCESS == result) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07003616 // TODOSC : Merge capture of the setLayouts per pipeline
Tobin Ehlis559c6382015-11-05 09:52:49 -07003617 PIPELINE_LAYOUT_NODE& plNode = dev_data->pipelineLayoutMap[*pPipelineLayout];
Chia-I Wud50a7d72015-10-26 20:48:51 +08003618 plNode.descriptorSetLayouts.resize(pCreateInfo->setLayoutCount);
Tobin Ehlis644ff042015-10-20 10:11:55 -06003619 uint32_t i = 0;
Chia-I Wud50a7d72015-10-26 20:48:51 +08003620 for (i=0; i<pCreateInfo->setLayoutCount; ++i) {
Tobin Ehlis644ff042015-10-20 10:11:55 -06003621 plNode.descriptorSetLayouts[i] = pCreateInfo->pSetLayouts[i];
3622 }
Cody Northrop43751cc2015-10-26 14:07:35 -06003623 plNode.pushConstantRanges.resize(pCreateInfo->pushConstantRangeCount);
Tobin Ehlis644ff042015-10-20 10:11:55 -06003624 for (i=0; i<pCreateInfo->pushConstantRangeCount; ++i) {
3625 plNode.pushConstantRanges[i] = pCreateInfo->pPushConstantRanges[i];
3626 }
Tobin Ehlis793ad302015-04-03 12:01:11 -06003627 }
3628 return result;
3629}
3630
Chia-I Wu9ab61502015-11-06 06:42:02 +08003631VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003632{
Tobin Ehlis0b632332015-10-07 09:38:40 -06003633 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08003634 VkResult result = dev_data->device_dispatch_table->CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06003635 if (VK_SUCCESS == result) {
Tobin Ehlis793ad302015-04-03 12:01:11 -06003636 // Insert this pool into Global Pool LL at head
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003637 if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, (uint64_t) *pDescriptorPool, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS",
Chia-I Wue2fc5522015-10-26 20:04:44 +08003638 "Created Descriptor Pool %#" PRIxLEAST64, (uint64_t) *pDescriptorPool))
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003639 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003640 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07003641 DESCRIPTOR_POOL_NODE* pNewNode = new DESCRIPTOR_POOL_NODE(*pDescriptorPool, pCreateInfo);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003642 if (NULL == pNewNode) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003643 if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, (uint64_t) *pDescriptorPool, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS",
Mark Lobodzinski39298632015-11-18 08:38:27 -07003644 "Out of memory while attempting to allocate DESCRIPTOR_POOL_NODE in vkCreateDescriptorPool()"))
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003645 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlisce132d82015-06-19 15:07:05 -06003646 } else {
Mark Lobodzinski39298632015-11-18 08:38:27 -07003647 dev_data->descriptorPoolMap[*pDescriptorPool] = pNewNode;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003648 }
3649 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlisce132d82015-06-19 15:07:05 -06003650 } else {
Tobin Ehlis793ad302015-04-03 12:01:11 -06003651 // Need to do anything if pool create fails?
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003652 }
3653 return result;
3654}
3655
Chia-I Wu9ab61502015-11-06 06:42:02 +08003656VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003657{
Tobin Ehlis0b632332015-10-07 09:38:40 -06003658 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06003659 VkResult result = dev_data->device_dispatch_table->ResetDescriptorPool(device, descriptorPool, flags);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06003660 if (VK_SUCCESS == result) {
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06003661 clearDescriptorPool(dev_data, device, descriptorPool, flags);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003662 }
3663 return result;
3664}
3665
Chia-I Wu9ab61502015-11-06 06:42:02 +08003666VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003667{
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003668 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis0b632332015-10-07 09:38:40 -06003669 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003670 // Verify that requested descriptorSets are available in pool
Mark Lobodzinski39298632015-11-18 08:38:27 -07003671 DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, pAllocateInfo->descriptorPool);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003672 if (!pPoolNode) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003673 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, (uint64_t) pAllocateInfo->descriptorPool, __LINE__, DRAWSTATE_INVALID_POOL, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003674 "Unable to find pool node for pool %#" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", (uint64_t) pAllocateInfo->descriptorPool);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003675 } else { // Make sure pool has all the available descriptors before calling down chain
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003676 skipCall |= validate_descriptor_availability_in_pool(dev_data, pPoolNode, pAllocateInfo->setLayoutCount, pAllocateInfo->pSetLayouts);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003677 }
3678 if (skipCall)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003679 return VK_ERROR_VALIDATION_FAILED_EXT;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003680 VkResult result = dev_data->device_dispatch_table->AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
Cody Northrop1e4f8022015-08-03 12:47:29 -06003681 if (VK_SUCCESS == result) {
Mark Lobodzinski39298632015-11-18 08:38:27 -07003682 DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, pAllocateInfo->descriptorPool);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003683 if (pPoolNode) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003684 if (pAllocateInfo->setLayoutCount == 0) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003685 log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, pAllocateInfo->setLayoutCount, __LINE__, DRAWSTATE_NONE, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003686 "AllocateDescriptorSets called with 0 count");
Cody Northrop1e4f8022015-08-03 12:47:29 -06003687 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003688 for (uint32_t i = 0; i < pAllocateInfo->setLayoutCount; i++) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003689 log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) pDescriptorSets[i], __LINE__, DRAWSTATE_NONE, "DS",
Chia-I Wue2fc5522015-10-26 20:04:44 +08003690 "Created Descriptor Set %#" PRIxLEAST64, (uint64_t) pDescriptorSets[i]);
Tobin Ehlis793ad302015-04-03 12:01:11 -06003691 // Create new set node and add to head of pool nodes
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003692 SET_NODE* pNewNode = new SET_NODE;
3693 if (NULL == pNewNode) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003694 if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) pDescriptorSets[i], __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003695 "Out of memory while attempting to allocate SET_NODE in vkAllocateDescriptorSets()"))
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003696 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlisce132d82015-06-19 15:07:05 -06003697 } else {
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003698 memset(pNewNode, 0, sizeof(SET_NODE));
Tobin Ehlis8b5b28c2015-10-19 12:09:13 -06003699 // TODO : Pool should store a total count of each type of Descriptor available
3700 // When descriptors are allocated, decrement the count and validate here
3701 // that the count doesn't go below 0. One reset/free need to bump count back up.
Tobin Ehlis793ad302015-04-03 12:01:11 -06003702 // Insert set at head of Set LL for this pool
3703 pNewNode->pNext = pPoolNode->pSets;
3704 pPoolNode->pSets = pNewNode;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003705 LAYOUT_NODE* pLayout = getLayoutNode(dev_data, pAllocateInfo->pSetLayouts[i]);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003706 if (NULL == pLayout) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003707 if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, (uint64_t) pAllocateInfo->pSetLayouts[i], __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003708 "Unable to find set layout node for layout %#" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", (uint64_t) pAllocateInfo->pSetLayouts[i]))
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003709 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003710 }
Tobin Ehlis793ad302015-04-03 12:01:11 -06003711 pNewNode->pLayout = pLayout;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003712 pNewNode->pool = pAllocateInfo->descriptorPool;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003713 pNewNode->set = pDescriptorSets[i];
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003714 pNewNode->descriptorCount = pLayout->endIndex + 1;
3715 if (pNewNode->descriptorCount) {
3716 size_t descriptorArraySize = sizeof(GENERIC_HEADER*)*pNewNode->descriptorCount;
3717 pNewNode->ppDescriptors = new GENERIC_HEADER*[descriptorArraySize];
3718 memset(pNewNode->ppDescriptors, 0, descriptorArraySize);
3719 }
Chia-I Wue2fc5522015-10-26 20:04:44 +08003720 dev_data->setMap[pDescriptorSets[i]] = pNewNode;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003721 }
3722 }
3723 }
3724 }
3725 return result;
3726}
3727
Chia-I Wu9ab61502015-11-06 06:42:02 +08003728VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, const VkDescriptorSet* pDescriptorSets)
Tony Barbour34ec6922015-07-10 10:50:45 -06003729{
Tobin Ehlise735c692015-10-08 13:13:50 -06003730 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis0b632332015-10-07 09:38:40 -06003731 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski39298632015-11-18 08:38:27 -07003732 DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, descriptorPool);
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06003733 if (pPoolNode && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pPoolNode->createInfo.flags)) {
3734 // Can't Free from a NON_FREE pool
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003735 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, (uint64_t)device, __LINE__, DRAWSTATE_CANT_FREE_FROM_NON_FREE_POOL, "DS",
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -06003736 "It is invalid to call vkFreeDescriptorSets() with a pool created without setting VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT.");
Tobin Ehlise735c692015-10-08 13:13:50 -06003737 }
3738 if (skipCall)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003739 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis0b632332015-10-07 09:38:40 -06003740 VkResult result = dev_data->device_dispatch_table->FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets);
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003741 if (VK_SUCCESS == result) {
3742 // For each freed descriptor add it back into the pool as available
3743 for (uint32_t i=0; i<count; ++i) {
Chia-I Wue2fc5522015-10-26 20:04:44 +08003744 SET_NODE* pSet = dev_data->setMap[pDescriptorSets[i]]; // getSetNode() without locking
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003745 LAYOUT_NODE* pLayout = pSet->pLayout;
Chia-I Wu1b99bb22015-10-27 19:25:11 +08003746 uint32_t typeIndex = 0, poolSizeCount = 0;
Chia-I Wud50a7d72015-10-26 20:48:51 +08003747 for (uint32_t j=0; j<pLayout->createInfo.bindingCount; ++j) {
Jon Ashburn6e23c1f2015-12-30 18:01:16 -07003748 typeIndex = static_cast<uint32_t>(pLayout->createInfo.pBindings[j].descriptorType);
3749 poolSizeCount = pLayout->createInfo.pBindings[j].descriptorCount;
Chia-I Wu1b99bb22015-10-27 19:25:11 +08003750 pPoolNode->availableDescriptorTypeCount[typeIndex] += poolSizeCount;
Tobin Ehlisf93f1e32015-10-20 16:16:04 -06003751 }
3752 }
3753 }
3754 // TODO : Any other clean-up or book-keeping to do here?
Tony Barbour34ec6922015-07-10 10:50:45 -06003755 return result;
3756}
3757
Chia-I Wu9ab61502015-11-06 06:42:02 +08003758VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003759{
Tobin Ehlisa1f9b642015-10-27 12:25:35 -06003760 // dsUpdate will return VK_TRUE only if a bailout error occurs, so we want to call down tree when update returns VK_FALSE
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06003761 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wu40cf0ae2015-10-26 17:20:32 +08003762 if (!dsUpdate(dev_data, device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies)) {
3763 dev_data->device_dispatch_table->UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
Jon Ashburn3950e1b2015-05-20 09:00:28 -06003764 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003765}
3766
Chia-I Wu9ab61502015-11-06 06:42:02 +08003767VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo* pCreateInfo, VkCommandBuffer* pCommandBuffer)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003768{
Tobin Ehlis0b632332015-10-07 09:38:40 -06003769 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003770 VkResult result = dev_data->device_dispatch_table->AllocateCommandBuffers(device, pCreateInfo, pCommandBuffer);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06003771 if (VK_SUCCESS == result) {
Courtney Goeltzenleuchter51239472015-12-16 16:06:06 -07003772 for (uint32_t i = 0; i < pCreateInfo->bufferCount; i++) {
Mark Lobodzinski39298632015-11-18 08:38:27 -07003773 // Validate command pool
3774 if (dev_data->commandPoolMap.find(pCreateInfo->commandPool) != dev_data->commandPoolMap.end()) {
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07003775 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07003776 // Add command buffer to its commandPool map
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003777 dev_data->commandPoolMap[pCreateInfo->commandPool].commandBuffers.push_back(pCommandBuffer[i]);
Mark Lobodzinski39298632015-11-18 08:38:27 -07003778 GLOBAL_CB_NODE* pCB = new GLOBAL_CB_NODE;
3779 // Add command buffer to map
3780 dev_data->commandBufferMap[pCommandBuffer[i]] = pCB;
Mark Lobodzinskib8df78c2015-11-20 14:33:48 -07003781 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski39298632015-11-18 08:38:27 -07003782 resetCB(dev_data, pCommandBuffer[i]);
3783 pCB->commandBuffer = pCommandBuffer[i];
3784 pCB->createInfo = *pCreateInfo;
Mark Lobodzinski39298632015-11-18 08:38:27 -07003785 }
3786 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003787 }
3788 return result;
3789}
3790
Chia-I Wu9ab61502015-11-06 06:42:02 +08003791VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003792{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003793 VkBool32 skipCall = false;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003794 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Mark Lobodzinskid9139a62015-08-04 16:24:20 -06003795 // Validate command buffer level
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003796 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Mark Lobodzinskid9139a62015-08-04 16:24:20 -06003797 if (pCB) {
Mark Lobodzinski85881c72015-11-19 13:22:11 -07003798 if (pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
Chia-I Wue2fc5522015-10-26 20:04:44 +08003799 if (pBeginInfo->renderPass || pBeginInfo->framebuffer) {
Mark Lobodzinskid9139a62015-08-04 16:24:20 -06003800 // These should be NULL for a Primary CB
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003801 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
Tobin Ehlis75f6fa92015-12-16 07:17:23 -07003802 "vkBeginCommandBuffer(): Primary Command Buffer (%p) may not specify framebuffer or renderpass parameters.", (void*)commandBuffer);
Mark Lobodzinskid9139a62015-08-04 16:24:20 -06003803 }
Tobin Ehlis75f6fa92015-12-16 07:17:23 -07003804 } else { // Secondary Command Buffer
Tobin Ehlis61b36f32015-12-16 08:19:42 -07003805 // TODO : Add check here from spec "If commandBuffer is a secondary command buffer and either the
3806 // occlusionQueryEnable member of pBeginInfo is VK_FALSE, or the precise occlusion queries feature
3807 // is not enabled, the queryFlags member of pBeginInfo must not contain VK_QUERY_CONTROL_PRECISE_BIT"
Tobin Ehlis651d9b02015-12-16 05:01:22 -07003808 if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) {
3809 if (!pBeginInfo->renderPass) { // renderpass should NOT be null for an Secondary CB
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003810 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
Tobin Ehlis651d9b02015-12-16 05:01:22 -07003811 "vkBeginCommandBuffer(): Secondary Command Buffers (%p) must specify a valid renderpass parameter.", (void*)commandBuffer);
3812 }
3813 if (!pBeginInfo->framebuffer) { // framebuffer may be null for an Secondary CB, but this affects perf
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003814 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERF_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
Tobin Ehlis651d9b02015-12-16 05:01:22 -07003815 "vkBeginCommandBuffer(): Secondary Command Buffers (%p) may perform better if a valid framebuffer parameter is specified.", (void*)commandBuffer);
3816 } else {
3817 string errorString = "";
3818 VkRenderPass fbRP = dev_data->frameBufferMap[pBeginInfo->framebuffer]->renderPass;
3819 if (!verify_renderpass_compatibility(dev_data, fbRP, pBeginInfo->renderPass, errorString)) {
3820 // renderPass that framebuffer was created with must be compatible with local renderPass
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003821 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
Tobin Ehlis651d9b02015-12-16 05:01:22 -07003822 "vkBeginCommandBuffer(): Secondary Command Buffer (%p) renderPass (%#" PRIxLEAST64 ") is incompatible w/ framebuffer (%#" PRIxLEAST64 ") w/ render pass (%#" PRIxLEAST64 ") due to: %s",
3823 (void*)commandBuffer, (uint64_t)pBeginInfo->renderPass, (uint64_t)pBeginInfo->framebuffer, (uint64_t)fbRP, errorString.c_str());
3824 }
3825 }
Mark Lobodzinskid9139a62015-08-04 16:24:20 -06003826 }
3827 }
Tobin Ehlis59278bf2015-08-18 07:10:58 -06003828 pCB->beginInfo = *pBeginInfo;
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003829 if (CB_RECORDING == pCB->state) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003830 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003831 "vkBeginCommandBuffer(): Cannot call Begin on CB (%#" PRIxLEAST64 ") in the RECORDING state. Must first call vkEndCommandBuffer().", (uint64_t)commandBuffer);
3832 } else if (CB_RECORDED == pCB->state) {
3833 VkCommandPool cmdPool = pCB->createInfo.commandPool;
3834 if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & dev_data->commandPoolMap[cmdPool].createFlags)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003835 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer,
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003836 __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER_RESET, "DS",
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003837 "Call to vkBeginCommandBuffer() on command buffer (%#" PRIxLEAST64 ") attempts to implicitly reset cmdBuffer created from command pool (%#" PRIxLEAST64 ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set.",
3838 (uint64_t) commandBuffer, (uint64_t) cmdPool);
3839 }
3840 }
Tobin Ehlis59278bf2015-08-18 07:10:58 -06003841 } else {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003842 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003843 "In vkBeginCommandBuffer() and unable to find CommandBuffer Node for CB %p!", (void*)commandBuffer);
Mark Lobodzinskid9139a62015-08-04 16:24:20 -06003844 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003845 if (skipCall) {
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003846 return VK_ERROR_VALIDATION_FAILED_EXT;
Courtney Goeltzenleuchter5fe086f2015-09-04 15:03:52 -06003847 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003848 VkResult result = dev_data->device_dispatch_table->BeginCommandBuffer(commandBuffer, pBeginInfo);
Mark Lobodzinski29b8d5a2015-11-12 16:14:04 -07003849 if ((VK_SUCCESS == result) && (pCB != NULL)) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07003850 if (CB_RECORDED == pCB->state) { resetCB(dev_data, commandBuffer); } pCB->state = CB_RECORDING; }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003851 return result;
3852}
3853
Chia-I Wu9ab61502015-11-06 06:42:02 +08003854VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer(VkCommandBuffer commandBuffer)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003855{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003856 VkBool32 skipCall = VK_FALSE;
Courtney Goeltzenleuchtered894072015-09-04 13:39:59 -06003857 VkResult result = VK_SUCCESS;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003858 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
3859 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis9c536442015-06-19 13:00:59 -06003860 if (pCB) {
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003861 if (pCB->state != CB_RECORDING) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003862 skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkEndCommandBuffer()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003863 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003864 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003865 if (VK_FALSE == skipCall) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003866 result = dev_data->device_dispatch_table->EndCommandBuffer(commandBuffer);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003867 if (VK_SUCCESS == result) {
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003868 pCB->state = CB_RECORDED;
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003869 // Reset CB status flags
3870 pCB->status = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003871 printCB(dev_data, commandBuffer);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003872 }
3873 } else {
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003874 result = VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003875 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003876 return result;
3877}
3878
Chia-I Wu9ab61502015-11-06 06:42:02 +08003879VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003880{
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003881 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003882 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003883 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
3884 VkCommandPool cmdPool = pCB->createInfo.commandPool;
3885 if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & dev_data->commandPoolMap[cmdPool].createFlags)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003886 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t) commandBuffer,
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003887 __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER_RESET, "DS",
Tobin Ehlisac0ef842015-12-14 13:46:38 -07003888 "Attempt to reset command buffer (%#" PRIxLEAST64 ") created from command pool (%#" PRIxLEAST64 ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set.",
3889 (uint64_t) commandBuffer, (uint64_t) cmdPool);
3890 }
3891 if (skipCall)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07003892 return VK_ERROR_VALIDATION_FAILED_EXT;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003893 VkResult result = dev_data->device_dispatch_table->ResetCommandBuffer(commandBuffer, flags);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06003894 if (VK_SUCCESS == result) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003895 resetCB(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003896 }
3897 return result;
3898}
3899
Chia-I Wu9ab61502015-11-06 06:42:02 +08003900VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003901{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003902 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003903 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
3904 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003905 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07003906 skipCall |= addCmd(dev_data, pCB, CMD_BINDPIPELINE, "vkCmdBindPipeline()");
3907 if ((VK_PIPELINE_BIND_POINT_COMPUTE == pipelineBindPoint) && (pCB->activeRenderPass)) {
3908 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, (uint64_t) pipeline,
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003909 __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS",
Tobin Ehlis61b36f32015-12-16 08:19:42 -07003910 "Incorrectly binding compute pipeline (%#" PRIxLEAST64 ") during active RenderPass (%#" PRIxLEAST64 ")",
3911 (uint64_t) pipeline, (uint64_t) pCB->activeRenderPass);
3912 } else if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) {
3913 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdBindPipeline");
3914 }
3915
3916 PIPELINE_NODE* pPN = getPipeline(dev_data, pipeline);
3917 if (pPN) {
3918 pCB->lastBoundPipeline = pipeline;
3919 loader_platform_thread_lock_mutex(&globalLock);
3920 set_cb_pso_status(pCB, pPN);
3921 loader_platform_thread_unlock_mutex(&globalLock);
3922 skipCall |= validatePipelineState(dev_data, pCB, pipelineBindPoint, pipeline);
Tobin Ehlisce132d82015-06-19 15:07:05 -06003923 } else {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07003924 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07003925 (uint64_t) pipeline, __LINE__, DRAWSTATE_INVALID_PIPELINE, "DS",
Tobin Ehlis61b36f32015-12-16 08:19:42 -07003926 "Attempt to bind Pipeline %#" PRIxLEAST64 " that doesn't exist!", reinterpret_cast<uint64_t>(pipeline));
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003927 }
3928 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003929 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003930 dev_data->device_dispatch_table->CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003931}
3932
Chia-I Wu9ab61502015-11-06 06:42:02 +08003933VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetViewport(
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003934 VkCommandBuffer commandBuffer,
Jon Ashburn19d3bf12015-12-30 14:06:55 -07003935 uint32_t firstViewport,
3936 uint32_t viewportCount,
3937 const VkViewport* pViewports)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003938{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003939 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003940 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
3941 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis9c536442015-06-19 13:00:59 -06003942 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07003943 skipCall |= addCmd(dev_data, pCB, CMD_SETVIEWPORTSTATE, "vkCmdSetViewport()");
3944 loader_platform_thread_lock_mutex(&globalLock);
3945 pCB->status |= CBSTATUS_VIEWPORT_SET;
3946 pCB->viewports.resize(viewportCount);
3947 memcpy(pCB->viewports.data(), pViewports, viewportCount * sizeof(VkViewport));
3948 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehlis9c536442015-06-19 13:00:59 -06003949 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003950 if (VK_FALSE == skipCall)
Jon Ashburn19d3bf12015-12-30 14:06:55 -07003951 dev_data->device_dispatch_table->CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports);
Courtney Goeltzenleuchter078f8172015-09-21 11:44:06 -06003952}
3953
Chia-I Wu9ab61502015-11-06 06:42:02 +08003954VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetScissor(
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003955 VkCommandBuffer commandBuffer,
Jon Ashburn19d3bf12015-12-30 14:06:55 -07003956 uint32_t firstScissor,
3957 uint32_t scissorCount,
3958 const VkRect2D* pScissors)
Courtney Goeltzenleuchter078f8172015-09-21 11:44:06 -06003959{
3960 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003961 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
3962 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Courtney Goeltzenleuchter078f8172015-09-21 11:44:06 -06003963 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07003964 skipCall |= addCmd(dev_data, pCB, CMD_SETSCISSORSTATE, "vkCmdSetScissor()");
3965 loader_platform_thread_lock_mutex(&globalLock);
3966 pCB->status |= CBSTATUS_SCISSOR_SET;
3967 pCB->scissors.resize(scissorCount);
3968 memcpy(pCB->scissors.data(), pScissors, scissorCount * sizeof(VkRect2D));
3969 loader_platform_thread_unlock_mutex(&globalLock);
Courtney Goeltzenleuchter078f8172015-09-21 11:44:06 -06003970 }
3971 if (VK_FALSE == skipCall)
Jon Ashburn19d3bf12015-12-30 14:06:55 -07003972 dev_data->device_dispatch_table->CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06003973}
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06003974
Chia-I Wu9ab61502015-11-06 06:42:02 +08003975VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003976{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003977 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003978 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
3979 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06003980 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07003981 skipCall |= addCmd(dev_data, pCB, CMD_SETLINEWIDTHSTATE, "vkCmdSetLineWidth()");
3982 /* TODO: Do we still need this lock? */
3983 loader_platform_thread_lock_mutex(&globalLock);
3984 pCB->status |= CBSTATUS_LINE_WIDTH_SET;
3985 pCB->lineWidth = lineWidth;
3986 loader_platform_thread_unlock_mutex(&globalLock);
Cody Northrop12365112015-08-17 11:10:49 -06003987 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003988 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003989 dev_data->device_dispatch_table->CmdSetLineWidth(commandBuffer, lineWidth);
Cody Northrop12365112015-08-17 11:10:49 -06003990}
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06003991
Chia-I Wu9ab61502015-11-06 06:42:02 +08003992VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias(
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003993 VkCommandBuffer commandBuffer,
Chia-I Wud8c946a2015-10-26 19:08:09 +08003994 float depthBiasConstantFactor,
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06003995 float depthBiasClamp,
Chia-I Wud8c946a2015-10-26 19:08:09 +08003996 float depthBiasSlopeFactor)
Cody Northrop12365112015-08-17 11:10:49 -06003997{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06003998 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003999 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4000 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Cody Northrop12365112015-08-17 11:10:49 -06004001 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004002 skipCall |= addCmd(dev_data, pCB, CMD_SETDEPTHBIASSTATE, "vkCmdSetDepthBias()");
4003 pCB->status |= CBSTATUS_DEPTH_BIAS_SET;
4004 pCB->depthBiasConstantFactor = depthBiasConstantFactor;
4005 pCB->depthBiasClamp = depthBiasClamp;
4006 pCB->depthBiasSlopeFactor = depthBiasSlopeFactor;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004007 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004008 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004009 dev_data->device_dispatch_table->CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004010}
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004011
Chia-I Wu9ab61502015-11-06 06:42:02 +08004012VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4])
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004013{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004014 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004015 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4016 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004017 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004018 skipCall |= addCmd(dev_data, pCB, CMD_SETBLENDSTATE, "vkCmdSetBlendConstants()");
4019 pCB->status |= CBSTATUS_BLEND_SET;
4020 memcpy(pCB->blendConstants, blendConstants, 4 * sizeof(float));
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004021 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004022 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004023 dev_data->device_dispatch_table->CmdSetBlendConstants(commandBuffer, blendConstants);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004024}
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004025
Chia-I Wu9ab61502015-11-06 06:42:02 +08004026VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBounds(
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004027 VkCommandBuffer commandBuffer,
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004028 float minDepthBounds,
4029 float maxDepthBounds)
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004030{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004031 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004032 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4033 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004034 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004035 skipCall |= addCmd(dev_data, pCB, CMD_SETDEPTHBOUNDSSTATE, "vkCmdSetDepthBounds()");
4036 pCB->status |= CBSTATUS_DEPTH_BOUNDS_SET;
4037 pCB->minDepthBounds = minDepthBounds;
4038 pCB->maxDepthBounds = maxDepthBounds;
Cody Northrop82485a82015-08-18 15:21:16 -06004039 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004040 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004041 dev_data->device_dispatch_table->CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
Cody Northrop82485a82015-08-18 15:21:16 -06004042}
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004043
Chia-I Wu9ab61502015-11-06 06:42:02 +08004044VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilCompareMask(
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004045 VkCommandBuffer commandBuffer,
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004046 VkStencilFaceFlags faceMask,
Chia-I Wu1b99bb22015-10-27 19:25:11 +08004047 uint32_t compareMask)
Cody Northrop82485a82015-08-18 15:21:16 -06004048{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004049 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004050 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4051 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Cody Northrop82485a82015-08-18 15:21:16 -06004052 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004053 skipCall |= addCmd(dev_data, pCB, CMD_SETSTENCILREADMASKSTATE, "vkCmdSetStencilCompareMask()");
4054 if (faceMask & VK_STENCIL_FACE_FRONT_BIT) {
4055 pCB->front.compareMask = compareMask;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004056 }
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004057 if (faceMask & VK_STENCIL_FACE_BACK_BIT) {
4058 pCB->back.compareMask = compareMask;
4059 }
4060 /* TODO: Do we need to track front and back separately? */
4061 /* TODO: We aren't capturing the faceMask, do we need to? */
4062 pCB->status |= CBSTATUS_STENCIL_READ_MASK_SET;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004063 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004064 if (VK_FALSE == skipCall)
Chia-I Wu1b99bb22015-10-27 19:25:11 +08004065 dev_data->device_dispatch_table->CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask);
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06004066}
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004067
Chia-I Wu9ab61502015-11-06 06:42:02 +08004068VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilWriteMask(
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004069 VkCommandBuffer commandBuffer,
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004070 VkStencilFaceFlags faceMask,
Chia-I Wu1b99bb22015-10-27 19:25:11 +08004071 uint32_t writeMask)
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004072{
4073 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004074 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4075 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004076 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004077 skipCall |= addCmd(dev_data, pCB, CMD_SETSTENCILWRITEMASKSTATE, "vkCmdSetStencilWriteMask()");
4078 if (faceMask & VK_STENCIL_FACE_FRONT_BIT) {
4079 pCB->front.writeMask = writeMask;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004080 }
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004081 if (faceMask & VK_STENCIL_FACE_BACK_BIT) {
4082 pCB->back.writeMask = writeMask;
4083 }
4084 pCB->status |= CBSTATUS_STENCIL_WRITE_MASK_SET;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004085 }
4086 if (VK_FALSE == skipCall)
Chia-I Wu1b99bb22015-10-27 19:25:11 +08004087 dev_data->device_dispatch_table->CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask);
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004088}
4089
Chia-I Wu9ab61502015-11-06 06:42:02 +08004090VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilReference(
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004091 VkCommandBuffer commandBuffer,
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004092 VkStencilFaceFlags faceMask,
Chia-I Wu1b99bb22015-10-27 19:25:11 +08004093 uint32_t reference)
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004094{
4095 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004096 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4097 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004098 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004099 skipCall |= addCmd(dev_data, pCB, CMD_SETSTENCILREFERENCESTATE, "vkCmdSetStencilReference()");
4100 if (faceMask & VK_STENCIL_FACE_FRONT_BIT) {
4101 pCB->front.reference = reference;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004102 }
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004103 if (faceMask & VK_STENCIL_FACE_BACK_BIT) {
4104 pCB->back.reference = reference;
4105 }
4106 pCB->status |= CBSTATUS_STENCIL_REFERENCE_SET;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004107 }
4108 if (VK_FALSE == skipCall)
Chia-I Wu1b99bb22015-10-27 19:25:11 +08004109 dev_data->device_dispatch_table->CmdSetStencilReference(commandBuffer, faceMask, reference);
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06004110}
4111
Chia-I Wu9ab61502015-11-06 06:42:02 +08004112VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004113{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004114 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004115 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4116 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004117 if (pCB) {
Tobin Ehlisf6585052015-12-17 11:48:42 -07004118 if (pCB->state == CB_RECORDING) {
4119 if ((VK_PIPELINE_BIND_POINT_COMPUTE == pipelineBindPoint) && (pCB->activeRenderPass)) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004120 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS",
Tobin Ehlisf6585052015-12-17 11:48:42 -07004121 "Incorrectly binding compute DescriptorSets during active RenderPass (%#" PRIxLEAST64 ")", (uint64_t) pCB->activeRenderPass);
4122 } else if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) {
4123 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdBindDescriptorSets");
Mark Lobodzinski74635932015-12-18 15:35:38 -07004124 }
Tobin Ehlisf6585052015-12-17 11:48:42 -07004125 if (VK_FALSE == skipCall) {
4126 // Track total count of dynamic descriptor types to make sure we have an offset for each one
4127 uint32_t totalDynamicDescriptors = 0;
4128 string errorString = "";
4129 uint32_t lastSetIndex = firstSet+setCount-1;
4130 if (lastSetIndex >= pCB->boundDescriptorSets.size())
Tobin Ehlis559c6382015-11-05 09:52:49 -07004131 pCB->boundDescriptorSets.resize(lastSetIndex+1);
Tobin Ehlisf6585052015-12-17 11:48:42 -07004132 VkDescriptorSet oldFinalBoundSet = pCB->boundDescriptorSets[lastSetIndex];
4133 for (uint32_t i=0; i<setCount; i++) {
4134 SET_NODE* pSet = getSetNode(dev_data, pDescriptorSets[i]);
4135 if (pSet) {
4136 loader_platform_thread_lock_mutex(&globalLock);
4137 pCB->lastBoundDescriptorSet = pDescriptorSets[i];
4138 pCB->lastBoundPipelineLayout = layout;
4139 pCB->boundDescriptorSets[i+firstSet] = pDescriptorSets[i];
4140 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004141 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) pDescriptorSets[i], __LINE__, DRAWSTATE_NONE, "DS",
Tobin Ehlisf6585052015-12-17 11:48:42 -07004142 "DS %#" PRIxLEAST64 " bound on pipeline %s", (uint64_t) pDescriptorSets[i], string_VkPipelineBindPoint(pipelineBindPoint));
4143 if (!pSet->pUpdateStructs) {
4144 // TODO: Verify against Valid Usage
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004145 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) pDescriptorSets[i], __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS",
Tobin Ehlisf6585052015-12-17 11:48:42 -07004146 "DS %#" PRIxLEAST64 " bound but it was never updated. You may want to either update it or not bind it.", (uint64_t) pDescriptorSets[i]);
4147 }
4148 // Verify that set being bound is compatible with overlapping setLayout of pipelineLayout
4149 if (!verify_set_layout_compatibility(dev_data, pSet, layout, i+firstSet, errorString)) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004150 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) pDescriptorSets[i], __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS",
Tobin Ehlisf6585052015-12-17 11:48:42 -07004151 "descriptorSet #%u being bound is not compatible with overlapping layout in pipelineLayout due to: %s", i, errorString.c_str());
4152 }
4153 if (pSet->pLayout->dynamicDescriptorCount) {
4154 // First make sure we won't overstep bounds of pDynamicOffsets array
4155 if ((totalDynamicDescriptors + pSet->pLayout->dynamicDescriptorCount) > dynamicOffsetCount) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004156 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) pDescriptorSets[i], __LINE__, DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS",
Tobin Ehlisf6585052015-12-17 11:48:42 -07004157 "descriptorSet #%u (%#" PRIxLEAST64 ") requires %u dynamicOffsets, but only %u dynamicOffsets are left in pDynamicOffsets array. There must be one dynamic offset for each dynamic descriptor being bound.",
4158 i, (uint64_t) pDescriptorSets[i], pSet->pLayout->dynamicDescriptorCount, (dynamicOffsetCount - totalDynamicDescriptors));
4159 } else { // Store dynamic offsets with the set
4160 const uint32_t* pStartDynOffset = pDynamicOffsets + totalDynamicDescriptors;
4161 pSet->dynamicOffsets.assign(pStartDynOffset, pStartDynOffset + pSet->pLayout->dynamicDescriptorCount);
4162 totalDynamicDescriptors += pSet->pLayout->dynamicDescriptorCount;
4163 }
4164 }
4165 } else {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004166 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) pDescriptorSets[i], __LINE__, DRAWSTATE_INVALID_SET, "DS",
Tobin Ehlisf6585052015-12-17 11:48:42 -07004167 "Attempt to bind DS %#" PRIxLEAST64 " that doesn't exist!", (uint64_t) pDescriptorSets[i]);
4168 }
4169 }
4170 skipCall |= addCmd(dev_data, pCB, CMD_BINDDESCRIPTORSETS, "vkCmdBindDescrsiptorSets()");
4171 // For any previously bound sets, need to set them to "invalid" if they were disturbed by this update
4172 if (firstSet > 0) { // Check set #s below the first bound set
4173 for (uint32_t i=0; i<firstSet; ++i) {
4174 if (pCB->boundDescriptorSets[i] && !verify_set_layout_compatibility(dev_data, dev_data->setMap[pCB->boundDescriptorSets[i]], layout, i, errorString)) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004175 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERF_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) pCB->boundDescriptorSets[i], __LINE__, DRAWSTATE_NONE, "DS",
Tobin Ehlisf6585052015-12-17 11:48:42 -07004176 "DescriptorSetDS %#" PRIxLEAST64 " previously bound as set #%u was disturbed by newly bound pipelineLayout (%#" PRIxLEAST64 ")", (uint64_t) pCB->boundDescriptorSets[i], i, (uint64_t) layout);
4177 pCB->boundDescriptorSets[i] = VK_NULL_HANDLE;
4178 }
4179 }
4180 }
4181 // Check if newly last bound set invalidates any remaining bound sets
4182 if ((pCB->boundDescriptorSets.size()-1) > (lastSetIndex)) {
4183 if (oldFinalBoundSet && !verify_set_layout_compatibility(dev_data, dev_data->setMap[oldFinalBoundSet], layout, lastSetIndex, errorString)) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004184 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERF_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t) oldFinalBoundSet, __LINE__, DRAWSTATE_NONE, "DS",
Tobin Ehlisf6585052015-12-17 11:48:42 -07004185 "DescriptorSetDS %#" PRIxLEAST64 " previously bound as set #%u is incompatible with set %#" PRIxLEAST64 " newly bound as set #%u so set #%u and any subsequent sets were disturbed by newly bound pipelineLayout (%#" PRIxLEAST64 ")", (uint64_t) oldFinalBoundSet, lastSetIndex, (uint64_t) pCB->boundDescriptorSets[lastSetIndex], lastSetIndex, lastSetIndex+1, (uint64_t) layout);
4186 pCB->boundDescriptorSets.resize(lastSetIndex+1);
4187 }
4188 }
4189 // dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound
4190 if (totalDynamicDescriptors != dynamicOffsetCount) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004191 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t) commandBuffer, __LINE__, DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS",
Tobin Ehlisf6585052015-12-17 11:48:42 -07004192 "Attempting to bind %u descriptorSets with %u dynamic descriptors, but dynamicOffsetCount is %u. It should exactly match the number of dynamic descriptors.", setCount, totalDynamicDescriptors, dynamicOffsetCount);
Tobin Ehlisda2f0d02015-11-04 12:28:28 -07004193 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004194 }
Tobin Ehlisf6585052015-12-17 11:48:42 -07004195 } else {
4196 skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdBindDescriptorSets()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004197 }
4198 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004199 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004200 dev_data->device_dispatch_table->CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, setCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004201}
4202
Chia-I Wu9ab61502015-11-06 06:42:02 +08004203VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004204{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004205 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004206 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4207 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004208 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004209 skipCall |= addCmd(dev_data, pCB, CMD_BINDINDEXBUFFER, "vkCmdBindIndexBuffer()");
4210 VkDeviceSize offset_align = 0;
4211 switch (indexType) {
4212 case VK_INDEX_TYPE_UINT16:
4213 offset_align = 2;
4214 break;
4215 case VK_INDEX_TYPE_UINT32:
4216 offset_align = 4;
4217 break;
4218 default:
4219 // ParamChecker should catch bad enum, we'll also throw alignment error below if offset_align stays 0
4220 break;
4221 }
4222 if (!offset_align || (offset % offset_align)) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004223 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_VTX_INDEX_ALIGNMENT_ERROR, "DS",
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004224 "vkCmdBindIndexBuffer() offset (%#" PRIxLEAST64 ") does not fall on alignment (%s) boundary.", offset, string_VkIndexType(indexType));
Tobin Ehlis9c536442015-06-19 13:00:59 -06004225 }
Tobin Ehlisc4c23182015-09-17 12:24:13 -06004226 pCB->status |= CBSTATUS_INDEX_BUFFER_BOUND;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004227 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004228 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004229 dev_data->device_dispatch_table->CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004230}
4231
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07004232void updateResourceTracking(GLOBAL_CB_NODE* pCB, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers) {
4233 uint32_t end = firstBinding + bindingCount;
Michael Lentine700b0aa2015-10-30 17:57:32 -07004234 if (pCB->currentDrawData.buffers.size() < end) {
4235 pCB->currentDrawData.buffers.resize(end);
4236 }
4237 for (uint32_t i = 0; i < bindingCount; ++i) {
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07004238 pCB->currentDrawData.buffers[i + firstBinding] = pBuffers[i];
Michael Lentine700b0aa2015-10-30 17:57:32 -07004239 }
4240}
4241
4242void updateResourceTrackingOnDraw(GLOBAL_CB_NODE* pCB) {
4243 pCB->drawData.push_back(pCB->currentDrawData);
4244}
4245
Chia-I Wu9ab61502015-11-06 06:42:02 +08004246VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers(
Mark Lobodzinskidfcd9b62015-12-14 15:14:10 -07004247 VkCommandBuffer commandBuffer,
Jon Ashburn19d3bf12015-12-30 14:06:55 -07004248 uint32_t firstBinding,
Courtney Goeltzenleuchterf68ad722015-04-16 13:38:46 -06004249 uint32_t bindingCount,
Mark Lobodzinskidfcd9b62015-12-14 15:14:10 -07004250 const VkBuffer *pBuffers,
4251 const VkDeviceSize *pOffsets)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004252{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004253 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004254 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4255 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004256 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004257 addCmd(dev_data, pCB, CMD_BINDVERTEXBUFFER, "vkCmdBindVertexBuffer()");
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07004258 pCB->lastVtxBinding = firstBinding + bindingCount - 1;
4259 updateResourceTracking(pCB, firstBinding, bindingCount, pBuffers);
Michael Lentine700b0aa2015-10-30 17:57:32 -07004260 } else {
4261 skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdBindVertexBuffer()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004262 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004263 if (VK_FALSE == skipCall)
Jon Ashburn19d3bf12015-12-30 14:06:55 -07004264 dev_data->device_dispatch_table->CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004265}
4266
Chia-I Wu9ab61502015-11-06 06:42:02 +08004267VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004268{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004269 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004270 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4271 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004272 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004273 skipCall |= addCmd(dev_data, pCB, CMD_DRAW, "vkCmdDraw()");
4274 pCB->drawCount[DRAW]++;
4275 skipCall |= validate_draw_state(dev_data, pCB, VK_FALSE);
4276 // TODO : Need to pass commandBuffer as srcObj here
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004277 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_NONE, "DS",
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004278 "vkCmdDraw() call #%" PRIu64 ", reporting DS state:", g_drawCount[DRAW]++);
4279 skipCall |= synchAndPrintDSConfig(dev_data, commandBuffer);
Michael Lentine700b0aa2015-10-30 17:57:32 -07004280 if (VK_FALSE == skipCall) {
4281 updateResourceTrackingOnDraw(pCB);
4282 }
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004283 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdDraw");
Jon Ashburn3950e1b2015-05-20 09:00:28 -06004284 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004285 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004286 dev_data->device_dispatch_table->CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004287}
4288
Chia-I Wu9ab61502015-11-06 06:42:02 +08004289VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004290{
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004291 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4292 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004293 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004294 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004295 skipCall |= addCmd(dev_data, pCB, CMD_DRAWINDEXED, "vkCmdDrawIndexed()");
4296 pCB->drawCount[DRAW_INDEXED]++;
4297 skipCall |= validate_draw_state(dev_data, pCB, VK_TRUE);
4298 // TODO : Need to pass commandBuffer as srcObj here
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004299 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_NONE, "DS",
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004300 "vkCmdDrawIndexed() call #%" PRIu64 ", reporting DS state:", g_drawCount[DRAW_INDEXED]++);
4301 skipCall |= synchAndPrintDSConfig(dev_data, commandBuffer);
Michael Lentine700b0aa2015-10-30 17:57:32 -07004302 if (VK_FALSE == skipCall) {
4303 updateResourceTrackingOnDraw(pCB);
4304 }
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004305 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdDrawIndexed");
Jon Ashburn3950e1b2015-05-20 09:00:28 -06004306 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004307 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004308 dev_data->device_dispatch_table->CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004309}
4310
Chia-I Wu9ab61502015-11-06 06:42:02 +08004311VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004312{
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004313 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4314 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004315 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004316 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004317 skipCall |= addCmd(dev_data, pCB, CMD_DRAWINDIRECT, "vkCmdDrawIndirect()");
4318 pCB->drawCount[DRAW_INDIRECT]++;
4319 skipCall |= validate_draw_state(dev_data, pCB, VK_FALSE);
4320 // TODO : Need to pass commandBuffer as srcObj here
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004321 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_NONE, "DS",
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004322 "vkCmdDrawIndirect() call #%" PRIu64 ", reporting DS state:", g_drawCount[DRAW_INDIRECT]++);
4323 skipCall |= synchAndPrintDSConfig(dev_data, commandBuffer);
Michael Lentine700b0aa2015-10-30 17:57:32 -07004324 if (VK_FALSE == skipCall) {
4325 updateResourceTrackingOnDraw(pCB);
4326 }
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004327 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdDrawIndirect");
Jon Ashburn3950e1b2015-05-20 09:00:28 -06004328 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004329 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004330 dev_data->device_dispatch_table->CmdDrawIndirect(commandBuffer, buffer, offset, count, stride);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004331}
4332
Chia-I Wu9ab61502015-11-06 06:42:02 +08004333VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004334{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004335 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004336 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4337 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004338 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004339 skipCall |= addCmd(dev_data, pCB, CMD_DRAWINDEXEDINDIRECT, "vkCmdDrawIndexedIndirect()");
4340 pCB->drawCount[DRAW_INDEXED_INDIRECT]++;
4341 skipCall |= validate_draw_state(dev_data, pCB, VK_TRUE);
4342 // TODO : Need to pass commandBuffer as srcObj here
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004343 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFO_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_NONE, "DS",
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004344 "vkCmdDrawIndexedIndirect() call #%" PRIu64 ", reporting DS state:", g_drawCount[DRAW_INDEXED_INDIRECT]++);
4345 skipCall |= synchAndPrintDSConfig(dev_data, commandBuffer);
Michael Lentine700b0aa2015-10-30 17:57:32 -07004346 if (VK_FALSE == skipCall) {
4347 updateResourceTrackingOnDraw(pCB);
4348 }
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004349 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdDrawIndexedIndirect");
Jon Ashburn3950e1b2015-05-20 09:00:28 -06004350 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004351 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004352 dev_data->device_dispatch_table->CmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004353}
4354
Chia-I Wu9ab61502015-11-06 06:42:02 +08004355VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004356{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004357 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004358 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4359 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004360 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004361 skipCall |= addCmd(dev_data, pCB, CMD_DISPATCH, "vkCmdDispatch()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004362 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdDispatch");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004363 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004364 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004365 dev_data->device_dispatch_table->CmdDispatch(commandBuffer, x, y, z);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004366}
4367
Chia-I Wu9ab61502015-11-06 06:42:02 +08004368VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004369{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004370 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004371 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4372 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004373 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004374 skipCall |= addCmd(dev_data, pCB, CMD_DISPATCHINDIRECT, "vkCmdDispatchIndirect()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004375 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdDispatchIndirect");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004376 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004377 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004378 dev_data->device_dispatch_table->CmdDispatchIndirect(commandBuffer, buffer, offset);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004379}
4380
Chia-I Wu9ab61502015-11-06 06:42:02 +08004381VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004382{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004383 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004384 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4385 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004386 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004387 skipCall |= addCmd(dev_data, pCB, CMD_COPYBUFFER, "vkCmdCopyBuffer()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004388 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyBuffer");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004389 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004390 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004391 dev_data->device_dispatch_table->CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004392}
4393
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07004394VkBool32 VerifySourceImageLayout(VkCommandBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout) {
4395 VkBool32 skip_call = false;
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07004396
4397#ifdef DISABLE_IMAGE_LAYOUT_VALIDATION
4398 // TODO: Fix -- initialLayout may have been set in a previous command buffer
4399 return skip_call;
4400#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
4401
Michael Lentineabc5e922015-10-12 11:30:14 -05004402 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
4403 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, cmdBuffer);
4404 auto src_image_element = pCB->imageLayoutMap.find(srcImage);
4405 if (src_image_element == pCB->imageLayoutMap.end()) {
4406 pCB->imageLayoutMap[srcImage].initialLayout = srcImageLayout;
4407 pCB->imageLayoutMap[srcImage].layout = srcImageLayout;
4408 return false;
4409 }
4410 if (src_image_element->second.layout != srcImageLayout) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004411 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05004412 "Cannot copy from an image whose source layout is %d and doesn't match the current layout %d.", srcImageLayout, src_image_element->second.layout);
4413 }
4414 if (srcImageLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) {
4415 if (srcImageLayout == VK_IMAGE_LAYOUT_GENERAL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07004416 // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning.
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004417 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERF_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineecc32b72015-10-16 18:08:09 -05004418 "Layout for input image should be TRANSFER_SRC_OPTIMAL instead of GENERAL.");
Michael Lentineabc5e922015-10-12 11:30:14 -05004419 } else {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004420 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineecc32b72015-10-16 18:08:09 -05004421 "Layout for input image is %d but can only be TRANSFER_SRC_OPTIMAL or GENERAL.", srcImageLayout);
Michael Lentineabc5e922015-10-12 11:30:14 -05004422 }
4423 }
4424 return skip_call;
4425}
4426
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07004427VkBool32 VerifyDestImageLayout(VkCommandBuffer cmdBuffer, VkImage destImage, VkImageLayout destImageLayout) {
4428 VkBool32 skip_call = false;
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07004429
4430#ifdef DISABLE_IMAGE_LAYOUT_VALIDATION
4431 // TODO: Fix -- initialLayout may have been set in a previous command buffer
4432 return skip_call;
4433#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
4434
Michael Lentineabc5e922015-10-12 11:30:14 -05004435 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
4436 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, cmdBuffer);
4437 auto dest_image_element = pCB->imageLayoutMap.find(destImage);
4438 if (dest_image_element == pCB->imageLayoutMap.end()) {
4439 pCB->imageLayoutMap[destImage].initialLayout = destImageLayout;
4440 pCB->imageLayoutMap[destImage].layout = destImageLayout;
4441 return false;
4442 }
4443 if (dest_image_element->second.layout != destImageLayout) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004444 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05004445 "Cannot copy from an image whose dest layout is %d and doesn't match the current layout %d.", destImageLayout, dest_image_element->second.layout);
4446 }
4447 if (destImageLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
4448 if (destImageLayout == VK_IMAGE_LAYOUT_GENERAL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07004449 // LAYOUT_GENERAL is allowed, but may not be performance optimal, flag as perf warning.
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004450 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERF_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05004451 "Layout for output image should be TRANSFER_DST_OPTIMAL instead of GENERAL.");
4452 } else {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004453 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05004454 "Layout for output image is %d but can only be TRANSFER_DST_OPTIMAL or GENERAL.", destImageLayout);
4455 }
4456 }
4457 return skip_call;
4458}
4459
Chia-I Wu9ab61502015-11-06 06:42:02 +08004460VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage(VkCommandBuffer commandBuffer,
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06004461 VkImage srcImage,
4462 VkImageLayout srcImageLayout,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004463 VkImage dstImage,
4464 VkImageLayout dstImageLayout,
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06004465 uint32_t regionCount, const VkImageCopy* pRegions)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004466{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004467 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004468 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4469 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004470 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004471 skipCall |= addCmd(dev_data, pCB, CMD_COPYIMAGE, "vkCmdCopyImage()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004472 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyImage");
Michael Lentineabc5e922015-10-12 11:30:14 -05004473 skipCall |= VerifySourceImageLayout(commandBuffer, srcImage, srcImageLayout);
4474 skipCall |= VerifyDestImageLayout(commandBuffer, dstImage, dstImageLayout);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004475 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004476 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004477 dev_data->device_dispatch_table->CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004478}
4479
Chia-I Wu9ab61502015-11-06 06:42:02 +08004480VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage(VkCommandBuffer commandBuffer,
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06004481 VkImage srcImage, VkImageLayout srcImageLayout,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004482 VkImage dstImage, VkImageLayout dstImageLayout,
Mark Lobodzinskiee5eef12015-05-22 14:43:25 -05004483 uint32_t regionCount, const VkImageBlit* pRegions,
Chia-I Wub99df442015-10-26 16:49:32 +08004484 VkFilter filter)
Courtney Goeltzenleuchter91f9cee2015-04-03 14:42:51 -06004485{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004486 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004487 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4488 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Courtney Goeltzenleuchter91f9cee2015-04-03 14:42:51 -06004489 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004490 skipCall |= addCmd(dev_data, pCB, CMD_BLITIMAGE, "vkCmdBlitImage()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004491 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdBlitImage");
Courtney Goeltzenleuchter91f9cee2015-04-03 14:42:51 -06004492 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004493 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004494 dev_data->device_dispatch_table->CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter);
Courtney Goeltzenleuchter91f9cee2015-04-03 14:42:51 -06004495}
4496
Chia-I Wu9ab61502015-11-06 06:42:02 +08004497VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer,
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06004498 VkBuffer srcBuffer,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004499 VkImage dstImage, VkImageLayout dstImageLayout,
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06004500 uint32_t regionCount, const VkBufferImageCopy* pRegions)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004501{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004502 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004503 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4504 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004505 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004506 skipCall |= addCmd(dev_data, pCB, CMD_COPYBUFFERTOIMAGE, "vkCmdCopyBufferToImage()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004507 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyBufferToImage");
Michael Lentineabc5e922015-10-12 11:30:14 -05004508 skipCall |= VerifyDestImageLayout(commandBuffer, dstImage, dstImageLayout);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004509 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004510 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004511 dev_data->device_dispatch_table->CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004512}
4513
Chia-I Wu9ab61502015-11-06 06:42:02 +08004514VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer,
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06004515 VkImage srcImage, VkImageLayout srcImageLayout,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004516 VkBuffer dstBuffer,
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06004517 uint32_t regionCount, const VkBufferImageCopy* pRegions)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004518{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004519 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004520 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4521 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004522 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004523 skipCall |= addCmd(dev_data, pCB, CMD_COPYIMAGETOBUFFER, "vkCmdCopyImageToBuffer()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004524 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyImageToBuffer");
Michael Lentineabc5e922015-10-12 11:30:14 -05004525 skipCall |= VerifySourceImageLayout(commandBuffer, srcImage, srcImageLayout);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004526 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004527 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004528 dev_data->device_dispatch_table->CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004529}
4530
Chia-I Wu9ab61502015-11-06 06:42:02 +08004531VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint32_t* pData)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004532{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004533 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004534 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4535 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004536 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004537 skipCall |= addCmd(dev_data, pCB, CMD_UPDATEBUFFER, "vkCmdUpdateBuffer()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004538 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyUpdateBuffer");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004539 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004540 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004541 dev_data->device_dispatch_table->CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004542}
4543
Chia-I Wu9ab61502015-11-06 06:42:02 +08004544VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004545{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004546 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004547 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4548 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004549 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004550 skipCall |= addCmd(dev_data, pCB, CMD_FILLBUFFER, "vkCmdFillBuffer()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004551 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyFillBuffer");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004552 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004553 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004554 dev_data->device_dispatch_table->CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004555}
4556
Chia-I Wu9ab61502015-11-06 06:42:02 +08004557VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments(
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004558 VkCommandBuffer commandBuffer,
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06004559 uint32_t attachmentCount,
4560 const VkClearAttachment* pAttachments,
Tobin Ehlis53eddda2015-07-01 16:46:13 -06004561 uint32_t rectCount,
Courtney Goeltzenleuchter4ca43f62015-10-15 18:22:08 -06004562 const VkClearRect* pRects)
Tobin Ehlis53eddda2015-07-01 16:46:13 -06004563{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004564 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004565 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4566 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis53eddda2015-07-01 16:46:13 -06004567 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004568 skipCall |= addCmd(dev_data, pCB, CMD_CLEARATTACHMENTS, "vkCmdClearAttachments()");
4569 // Warn if this is issued prior to Draw Cmd and clearing the entire attachment
4570 if (!hasDrawCmd(pCB) &&
4571 (pCB->activeRenderPassBeginInfo.renderArea.extent.width == pRects[0].rect.extent.width) &&
4572 (pCB->activeRenderPassBeginInfo.renderArea.extent.height == pRects[0].rect.extent.height)) {
4573 // TODO : commandBuffer should be srcObj
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004574 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_CLEAR_CMD_BEFORE_DRAW, "DS",
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004575 "vkCmdClearAttachments() issued on CB object 0x%" PRIxLEAST64 " prior to any Draw Cmds."
4576 " It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw.", reinterpret_cast<uint64_t>(commandBuffer));
Tobin Ehlis53eddda2015-07-01 16:46:13 -06004577 }
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06004578 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdClearAttachments");
4579 }
4580
4581 // Validate that attachment is in reference list of active subpass
4582 if (pCB->activeRenderPass) {
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07004583 const VkRenderPassCreateInfo *pRPCI = dev_data->renderPassMap[pCB->activeRenderPass]->pCreateInfo;
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06004584 const VkSubpassDescription *pSD = &pRPCI->pSubpasses[pCB->activeSubpass];
4585
4586 for (uint32_t attachment_idx = 0; attachment_idx < attachmentCount; attachment_idx++) {
4587 const VkClearAttachment *attachment = &pAttachments[attachment_idx];
4588 if (attachment->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
4589 VkBool32 found = VK_FALSE;
Chia-I Wud50a7d72015-10-26 20:48:51 +08004590 for (uint32_t i = 0; i < pSD->colorAttachmentCount; i++) {
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06004591 if (attachment->colorAttachment == pSD->pColorAttachments[i].attachment) {
4592 found = VK_TRUE;
4593 break;
4594 }
4595 }
4596 if (VK_FALSE == found) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07004597 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004598 (uint64_t)commandBuffer, __LINE__, DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS",
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06004599 "vkCmdClearAttachments() attachment index %d not found in attachment reference array of active subpass %d",
4600 attachment->colorAttachment, pCB->activeSubpass);
4601 }
4602 } else if (attachment->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
Mark Lobodzinskid6e7bff2015-11-17 15:11:24 -07004603 if (!pSD->pDepthStencilAttachment || // Says no DS will be used in active subpass
Mark Lobodzinski2fd355a2015-11-18 08:58:31 -07004604 (pSD->pDepthStencilAttachment->attachment == VK_ATTACHMENT_UNUSED)) { // Says no DS will be used in active subpass
Mark Lobodzinskid6e7bff2015-11-17 15:11:24 -07004605
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07004606 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004607 (uint64_t)commandBuffer, __LINE__, DRAWSTATE_MISSING_ATTACHMENT_REFERENCE, "DS",
Mark Lobodzinskid6e7bff2015-11-17 15:11:24 -07004608 "vkCmdClearAttachments() attachment index %d does not match depthStencilAttachment.attachment (%d) found in active subpass %d",
4609 attachment->colorAttachment,
4610 (pSD->pDepthStencilAttachment) ? pSD->pDepthStencilAttachment->attachment : VK_ATTACHMENT_UNUSED,
4611 pCB->activeSubpass);
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06004612 }
4613 }
4614 }
Tobin Ehlis53eddda2015-07-01 16:46:13 -06004615 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004616 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004617 dev_data->device_dispatch_table->CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
Tobin Ehlis53eddda2015-07-01 16:46:13 -06004618}
4619
Chia-I Wu9ab61502015-11-06 06:42:02 +08004620VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage(
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004621 VkCommandBuffer commandBuffer,
Courtney Goeltzenleuchterd7a5cff2015-04-23 17:49:22 -06004622 VkImage image, VkImageLayout imageLayout,
Chris Forbesf0796e12015-06-24 14:34:53 +12004623 const VkClearColorValue *pColor,
Courtney Goeltzenleuchterd7a5cff2015-04-23 17:49:22 -06004624 uint32_t rangeCount, const VkImageSubresourceRange* pRanges)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004625{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004626 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004627 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4628 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004629 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004630 skipCall |= addCmd(dev_data, pCB, CMD_CLEARCOLORIMAGE, "vkCmdClearColorImage()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004631 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdClearColorImage");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004632 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004633 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004634 dev_data->device_dispatch_table->CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004635}
4636
Chia-I Wu9ab61502015-11-06 06:42:02 +08004637VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearDepthStencilImage(
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004638 VkCommandBuffer commandBuffer,
Courtney Goeltzenleuchter45df9e12015-09-15 18:03:22 -06004639 VkImage image, VkImageLayout imageLayout,
4640 const VkClearDepthStencilValue *pDepthStencil,
4641 uint32_t rangeCount,
4642 const VkImageSubresourceRange* pRanges)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004643{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004644 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004645 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4646 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004647 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004648 skipCall |= addCmd(dev_data, pCB, CMD_CLEARDEPTHSTENCILIMAGE, "vkCmdClearDepthStencilImage()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004649 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdClearDepthStencilImage");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004650 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004651 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004652 dev_data->device_dispatch_table->CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004653}
4654
Chia-I Wu9ab61502015-11-06 06:42:02 +08004655VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage(VkCommandBuffer commandBuffer,
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06004656 VkImage srcImage, VkImageLayout srcImageLayout,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004657 VkImage dstImage, VkImageLayout dstImageLayout,
Tony Barbour6865d4a2015-04-13 15:02:52 -06004658 uint32_t regionCount, const VkImageResolve* pRegions)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004659{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004660 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004661 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4662 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004663 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004664 skipCall |= addCmd(dev_data, pCB, CMD_RESOLVEIMAGE, "vkCmdResolveImage()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004665 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdResolveImage");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004666 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004667 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004668 dev_data->device_dispatch_table->CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004669}
4670
Chia-I Wu9ab61502015-11-06 06:42:02 +08004671VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004672{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004673 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004674 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4675 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004676 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004677 skipCall |= addCmd(dev_data, pCB, CMD_SETEVENT, "vkCmdSetEvent()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004678 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdSetEvent");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004679 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004680 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004681 dev_data->device_dispatch_table->CmdSetEvent(commandBuffer, event, stageMask);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004682}
4683
Chia-I Wu9ab61502015-11-06 06:42:02 +08004684VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004685{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004686 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004687 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4688 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004689 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004690 skipCall |= addCmd(dev_data, pCB, CMD_RESETEVENT, "vkCmdResetEvent()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004691 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdResetEvent");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004692 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004693 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004694 dev_data->device_dispatch_table->CmdResetEvent(commandBuffer, event, stageMask);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004695}
4696
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07004697VkBool32 TransitionImageLayouts(VkCommandBuffer cmdBuffer, uint32_t memBarrierCount, const void* const* ppMemBarriers) {
Michael Lentineabc5e922015-10-12 11:30:14 -05004698 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
4699 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, cmdBuffer);
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07004700 VkBool32 skip = false;
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07004701
4702#ifdef DISABLE_IMAGE_LAYOUT_VALIDATION
4703 // TODO: Fix -- pay attention to image subresource ranges -- not all subresources transition at the same time
4704 return skip;
4705#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
4706
Michael Lentineabc5e922015-10-12 11:30:14 -05004707 for (uint32_t i = 0; i < memBarrierCount; ++i) {
4708 auto mem_barrier = reinterpret_cast<const VkMemoryBarrier*>(ppMemBarriers[i]);
4709 if (mem_barrier && mem_barrier->sType == VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER) {
4710 auto image_mem_barrier = reinterpret_cast<const VkImageMemoryBarrier*>(mem_barrier);
4711 auto image_data = pCB->imageLayoutMap.find(image_mem_barrier->image);
4712 if (image_data == pCB->imageLayoutMap.end()) {
4713 pCB->imageLayoutMap[image_mem_barrier->image].initialLayout = image_mem_barrier->oldLayout;
4714 pCB->imageLayoutMap[image_mem_barrier->image].layout = image_mem_barrier->newLayout;
4715 } else {
4716 if (image_data->second.layout != image_mem_barrier->oldLayout) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004717 skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Courtney Goeltzenleuchterb19042e2015-11-25 11:38:54 -07004718 "You cannot transition the layout from %d when current layout is %d.", image_mem_barrier->oldLayout, image_data->second.layout);
Michael Lentineabc5e922015-10-12 11:30:14 -05004719 }
4720 image_data->second.layout = image_mem_barrier->newLayout;
4721 }
4722 }
4723 }
4724 return skip;
4725}
4726
Mark Lobodzinskia3a86112016-01-05 17:17:55 -07004727// Print readable FlagBits in FlagMask
4728std::string string_VkAccessFlags(VkAccessFlags accessMask)
4729{
4730 std::string result;
4731 std::string separator;
4732
4733 if (accessMask == 0) {
4734 result = "[None]";
4735 } else {
4736 result = "[";
4737 for (auto i = 0; i < 32; i++) {
4738 if (accessMask & (1 << i)) {
4739 result = result + separator + string_VkAccessFlagBits((VkAccessFlagBits)(1 << i));
4740 separator = " | ";
4741 }
4742 }
4743 result = result + "]";
4744 }
4745 return result;
4746}
4747
Michael Lentine97eb7462015-11-20 09:48:52 -08004748// AccessFlags MUST have 'required_bit' set, and may have one or more of 'optional_bits' set.
4749// If required_bit is zero, accessMask must have at least one of 'optional_bits' set
Mark Lobodzinskifd740fc2016-01-06 12:56:29 -07004750// TODO: Add tracking to ensure that at least one barrier has been set for these layout transitions
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004751VkBool32 ValidateMaskBits(const layer_data* my_data, VkCommandBuffer cmdBuffer, const VkAccessFlags& accessMask, const VkImageLayout& layout,
4752 VkAccessFlags required_bit, VkAccessFlags optional_bits, const char* type) {
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07004753 VkBool32 skip_call = false;
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004754
Michael Lentine97eb7462015-11-20 09:48:52 -08004755 if ((accessMask & required_bit) || (!required_bit && (accessMask & optional_bits))) {
4756 if (accessMask & !(required_bit | optional_bits)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07004757 // TODO: Verify against Valid Use
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004758 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004759 "Additional bits in %s accessMask %d %s are specified when layout is %s.",
4760 type, accessMask, string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout));
Michael Lentineecc32b72015-10-16 18:08:09 -05004761 }
4762 } else {
Michael Lentine97eb7462015-11-20 09:48:52 -08004763 if (!required_bit) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004764 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
Mark Lobodzinskifd740fc2016-01-06 12:56:29 -07004765 "%s AccessMask %d %s must contain at least one of access bits %d %s when layout is %s, unless the app has previously added a barrier for this transition.",
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004766 type, accessMask, string_VkAccessFlags(accessMask).c_str(), optional_bits,
4767 string_VkAccessFlags(optional_bits).c_str(), string_VkImageLayout(layout));
Michael Lentine97eb7462015-11-20 09:48:52 -08004768 } else {
Mark Lobodzinskif2cc2a52016-01-05 13:35:29 -07004769 std::string opt_bits;
4770 if (optional_bits != 0) {
4771 opt_bits = "and may have optional bits " + std::to_string(optional_bits) + ' ' + string_VkAccessFlags(optional_bits);
4772 }
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004773 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
Mark Lobodzinskifd740fc2016-01-06 12:56:29 -07004774 "%s AccessMask %d %s must have required access bit %d %s %s when layout is %s, unless the app has previously added a barrier for this transition.",
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004775 type, accessMask, string_VkAccessFlags(accessMask).c_str(),
4776 required_bit, string_VkAccessFlags(required_bit).c_str(),
Mark Lobodzinskif2cc2a52016-01-05 13:35:29 -07004777 opt_bits.c_str(), string_VkImageLayout(layout));
Michael Lentine97eb7462015-11-20 09:48:52 -08004778 }
Michael Lentineecc32b72015-10-16 18:08:09 -05004779 }
4780 return skip_call;
4781}
4782
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004783VkBool32 ValidateMaskBitsFromLayouts(const layer_data* my_data, VkCommandBuffer cmdBuffer, const VkAccessFlags& accessMask, const VkImageLayout& layout, const char* type) {
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07004784 VkBool32 skip_call = false;
Michael Lentine97eb7462015-11-20 09:48:52 -08004785 switch (layout) {
4786 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: {
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004787 skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, type);
Michael Lentine97eb7462015-11-20 09:48:52 -08004788 break;
Michael Lentineecc32b72015-10-16 18:08:09 -05004789 }
Michael Lentine97eb7462015-11-20 09:48:52 -08004790 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: {
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004791 skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, type);
Michael Lentine97eb7462015-11-20 09:48:52 -08004792 break;
Michael Lentineecc32b72015-10-16 18:08:09 -05004793 }
Michael Lentine97eb7462015-11-20 09:48:52 -08004794 case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: {
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004795 skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_WRITE_BIT, 0, type);
Michael Lentine97eb7462015-11-20 09:48:52 -08004796 break;
4797 }
4798 case VK_IMAGE_LAYOUT_PREINITIALIZED: {
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004799 skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_HOST_WRITE_BIT, 0, type);
Michael Lentine97eb7462015-11-20 09:48:52 -08004800 break;
4801 }
4802 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: {
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004803 skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, 0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT, type);
Michael Lentine97eb7462015-11-20 09:48:52 -08004804 break;
4805 }
4806 case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: {
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004807 skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, 0, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT, type);
Michael Lentine97eb7462015-11-20 09:48:52 -08004808 break;
4809 }
4810 case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: {
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004811 skip_call |= ValidateMaskBits(my_data, cmdBuffer, accessMask, layout, VK_ACCESS_TRANSFER_READ_BIT, 0, type);
Michael Lentine97eb7462015-11-20 09:48:52 -08004812 break;
4813 }
4814 case VK_IMAGE_LAYOUT_UNDEFINED: {
4815 if (accessMask != 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07004816 // TODO: Verify against Valid Use section spec
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004817 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004818 "Additional bits in %s accessMask %d %s are specified when layout is %s.", type, accessMask, string_VkAccessFlags(accessMask).c_str(),
4819 string_VkImageLayout(layout));
Michael Lentine97eb7462015-11-20 09:48:52 -08004820 }
4821 break;
4822 }
4823 case VK_IMAGE_LAYOUT_GENERAL:
4824 default: {
4825 break;
4826 }
Michael Lentineecc32b72015-10-16 18:08:09 -05004827 }
4828 return skip_call;
4829}
4830
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07004831VkBool32 ValidateBarriers(VkCommandBuffer cmdBuffer, uint32_t memBarrierCount, const void* const* ppMemBarriers) {
4832 VkBool32 skip_call = false;
Michael Lentine48930b82015-10-15 17:07:00 -05004833 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
4834 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, cmdBuffer);
4835 if (pCB->activeRenderPass && memBarrierCount) {
4836 for (uint32_t i = 0; i < memBarrierCount; ++i) {
4837 auto mem_barrier = reinterpret_cast<const VkMemoryBarrier*>(ppMemBarriers[i]);
4838 if (mem_barrier && mem_barrier->sType != VK_STRUCTURE_TYPE_MEMORY_BARRIER) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004839 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
Michael Lentine48930b82015-10-15 17:07:00 -05004840 "Image or Buffers Barriers cannot be used during a render pass.");
4841 }
4842 }
4843 if (!dev_data->renderPassMap[pCB->activeRenderPass]->hasSelfDependency[pCB->activeSubpass]) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07004844 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
Michael Lentine48930b82015-10-15 17:07:00 -05004845 "Barriers cannot be set during subpass %d with no self dependency specified.", pCB->activeSubpass);
4846 }
4847 }
Mark Lobodzinski73a37ec2015-11-20 09:27:27 -07004848
Michael Lentineecc32b72015-10-16 18:08:09 -05004849 for (uint32_t i = 0; i < memBarrierCount; ++i) {
4850 auto mem_barrier = reinterpret_cast<const VkMemoryBarrier*>(ppMemBarriers[i]);
4851 if (mem_barrier && mem_barrier->sType == VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER) {
4852 auto image_mem_barrier = reinterpret_cast<const VkImageMemoryBarrier*>(mem_barrier);
Mark Lobodzinski882655d2016-01-05 11:32:53 -07004853 skip_call |= ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, image_mem_barrier->srcAccessMask, image_mem_barrier->oldLayout, "Source");
4854 skip_call |= ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, image_mem_barrier->dstAccessMask, image_mem_barrier->newLayout, "Dest");
Michael Lentineecc32b72015-10-16 18:08:09 -05004855 }
4856 }
Mark Lobodzinski3cba24a2015-12-03 15:42:32 -07004857
Michael Lentine48930b82015-10-15 17:07:00 -05004858 return skip_call;
4859}
4860
Chia-I Wu9ab61502015-11-06 06:42:02 +08004861VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags sourceStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const void* const* ppMemoryBarriers)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004862{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004863 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004864 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4865 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004866 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004867 skipCall |= addCmd(dev_data, pCB, CMD_WAITEVENTS, "vkCmdWaitEvents()");
Michael Lentineabc5e922015-10-12 11:30:14 -05004868 skipCall |= TransitionImageLayouts(commandBuffer, memoryBarrierCount, ppMemoryBarriers);
Michael Lentine48930b82015-10-15 17:07:00 -05004869 skipCall |= ValidateBarriers(commandBuffer, memoryBarrierCount, ppMemoryBarriers);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004870 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004871 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004872 dev_data->device_dispatch_table->CmdWaitEvents(commandBuffer, eventCount, pEvents, sourceStageMask, dstStageMask, memoryBarrierCount, ppMemoryBarriers);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004873}
4874
Chia-I Wu9ab61502015-11-06 06:42:02 +08004875VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const void* const* ppMemoryBarriers)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004876{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004877 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004878 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4879 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004880 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004881 skipCall |= addCmd(dev_data, pCB, CMD_PIPELINEBARRIER, "vkCmdPipelineBarrier()");
Michael Lentineabc5e922015-10-12 11:30:14 -05004882 skipCall |= TransitionImageLayouts(commandBuffer, memoryBarrierCount, ppMemoryBarriers);
Michael Lentine48930b82015-10-15 17:07:00 -05004883 skipCall |= ValidateBarriers(commandBuffer, memoryBarrierCount, ppMemoryBarriers);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004884 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004885 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004886 dev_data->device_dispatch_table->CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, ppMemoryBarriers);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004887}
4888
Chia-I Wu9ab61502015-11-06 06:42:02 +08004889VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkFlags flags)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004890{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004891 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004892 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4893 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004894 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004895 skipCall |= addCmd(dev_data, pCB, CMD_BEGINQUERY, "vkCmdBeginQuery()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004896 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004897 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004898 dev_data->device_dispatch_table->CmdBeginQuery(commandBuffer, queryPool, slot, flags);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004899}
4900
Chia-I Wu9ab61502015-11-06 06:42:02 +08004901VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004902{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004903 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004904 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4905 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004906 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004907 skipCall |= addCmd(dev_data, pCB, CMD_ENDQUERY, "vkCmdEndQuery()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004908 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004909 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004910 dev_data->device_dispatch_table->CmdEndQuery(commandBuffer, queryPool, slot);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004911}
4912
Jon Ashburn19d3bf12015-12-30 14:06:55 -07004913VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004914{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004915 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004916 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4917 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004918 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004919 skipCall |= addCmd(dev_data, pCB, CMD_RESETQUERYPOOL, "vkCmdResetQueryPool()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004920 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdQueryPool");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004921 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004922 if (VK_FALSE == skipCall)
Jon Ashburn19d3bf12015-12-30 14:06:55 -07004923 dev_data->device_dispatch_table->CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004924}
4925
Jon Ashburn19d3bf12015-12-30 14:06:55 -07004926VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004927 uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset,
Chia-I Wuccc93a72015-10-26 18:36:20 +08004928 VkDeviceSize stride, VkQueryResultFlags flags)
Mark Lobodzinski5495d132015-09-30 16:19:16 -06004929{
4930 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004931 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4932 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Mark Lobodzinski5495d132015-09-30 16:19:16 -06004933 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004934 skipCall |= addCmd(dev_data, pCB, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()");
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06004935 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdCopyQueryPoolResults");
Mark Lobodzinski5495d132015-09-30 16:19:16 -06004936 }
4937 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004938 dev_data->device_dispatch_table->CmdCopyQueryPoolResults(commandBuffer, queryPool,
Jon Ashburn19d3bf12015-12-30 14:06:55 -07004939 firstQuery, queryCount, dstBuffer, dstOffset, stride, flags);
Mark Lobodzinski5495d132015-09-30 16:19:16 -06004940}
4941
Chia-I Wu9ab61502015-11-06 06:42:02 +08004942VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t slot)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004943{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004944 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004945 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4946 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004947 if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07004948 skipCall |= addCmd(dev_data, pCB, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004949 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06004950 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08004951 dev_data->device_dispatch_table->CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06004952}
4953
Chia-I Wu9ab61502015-11-06 06:42:02 +08004954VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer)
Tobin Ehliseba312c2015-04-01 08:40:34 -06004955{
Tobin Ehlis0b632332015-10-07 09:38:40 -06004956 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +08004957 VkResult result = dev_data->device_dispatch_table->CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06004958 if (VK_SUCCESS == result) {
Tobin Ehliseba312c2015-04-01 08:40:34 -06004959 // Shadow create info and store in map
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06004960 VkFramebufferCreateInfo* localFBCI = new VkFramebufferCreateInfo(*pCreateInfo);
Chia-I Wu08accc62015-07-07 11:50:03 +08004961 if (pCreateInfo->pAttachments) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -06004962 localFBCI->pAttachments = new VkImageView[localFBCI->attachmentCount];
4963 memcpy((void*)localFBCI->pAttachments, pCreateInfo->pAttachments, localFBCI->attachmentCount*sizeof(VkImageView));
Tobin Ehliseba312c2015-04-01 08:40:34 -06004964 }
Chia-I Wue2fc5522015-10-26 20:04:44 +08004965 dev_data->frameBufferMap[*pFramebuffer] = localFBCI;
Tobin Ehliseba312c2015-04-01 08:40:34 -06004966 }
4967 return result;
4968}
4969
Michael Lentineb6986752015-10-06 14:56:18 -07004970// Store the DAG.
4971struct DAGNode {
4972 uint32_t pass;
4973 std::vector<uint32_t> prev;
4974 std::vector<uint32_t> next;
4975};
4976
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -07004977VkBool32 FindDependency(const int index, const int dependent, const std::vector<DAGNode>& subpass_to_node, std::unordered_set<uint32_t>& processed_nodes) {
Michael Lentineb6986752015-10-06 14:56:18 -07004978 // If we have already checked this node we have not found a dependency path so return false.
4979 if (processed_nodes.count(index))
4980 return false;
4981 processed_nodes.insert(index);
4982 const DAGNode& node = subpass_to_node[index];
4983 // Look for a dependency path. If one exists return true else recurse on the previous nodes.
4984 if (std::find(node.prev.begin(), node.prev.end(), dependent) == node.prev.end()) {
4985 for (auto elem : node.prev) {
4986 if (FindDependency(elem, dependent, subpass_to_node, processed_nodes))
4987 return true;
4988 }
4989 } else {
4990 return true;
4991 }
4992 return false;
4993}
4994
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -07004995VkBool32 CheckDependencyExists(const layer_data* my_data, VkDevice device, const int subpass, const std::vector<uint32_t>& dependent_subpasses, const std::vector<DAGNode>& subpass_to_node, VkBool32& skip_call) {
4996 VkBool32 result = true;
Michael Lentineb6986752015-10-06 14:56:18 -07004997 // Loop through all subpasses that share the same attachment and make sure a dependency exists
4998 for (uint32_t k = 0; k < dependent_subpasses.size(); ++k) {
4999 if (subpass == dependent_subpasses[k])
5000 continue;
5001 const DAGNode& node = subpass_to_node[subpass];
5002 // Check for a specified dependency between the two nodes. If one exists we are done.
5003 auto prev_elem = std::find(node.prev.begin(), node.prev.end(), dependent_subpasses[k]);
5004 auto next_elem = std::find(node.next.begin(), node.next.end(), dependent_subpasses[k]);
5005 if (prev_elem == node.prev.end() && next_elem == node.next.end()) {
5006 // If no dependency exits an implicit dependency still might. If so, warn and if not throw an error.
5007 std::unordered_set<uint32_t> processed_nodes;
5008 if (FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) ||
5009 FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07005010 // TODO: Verify against Valid Use section of spec
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005011 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
Michael Lentineb6986752015-10-06 14:56:18 -07005012 "A dependency between subpasses %d and %d must exist but only an implicit one is specified.",
5013 subpass, dependent_subpasses[k]);
5014 } else {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005015 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
Michael Lentineb6986752015-10-06 14:56:18 -07005016 "A dependency between subpasses %d and %d must exist but one is not specified.",
5017 subpass, dependent_subpasses[k]);
5018 result = false;
5019 }
5020 }
5021 }
5022 return result;
5023}
5024
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -07005025VkBool32 CheckPreserved(const layer_data* my_data, VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const int index, const int attachment, const std::vector<DAGNode>& subpass_to_node, int depth, VkBool32& skip_call) {
Michael Lentineb6986752015-10-06 14:56:18 -07005026 const DAGNode& node = subpass_to_node[index];
5027 // If this node writes to the attachment return true as next nodes need to preserve the attachment.
5028 const VkSubpassDescription& subpass = pCreateInfo->pSubpasses[index];
Chia-I Wud50a7d72015-10-26 20:48:51 +08005029 for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
Michael Lentineb6986752015-10-06 14:56:18 -07005030 if (attachment == subpass.pColorAttachments[j].attachment)
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -07005031 return VK_TRUE;
Michael Lentineb6986752015-10-06 14:56:18 -07005032 }
Chia-I Wu1efb7e52015-10-26 17:32:47 +08005033 if (subpass.pDepthStencilAttachment &&
5034 subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
5035 if (attachment == subpass.pDepthStencilAttachment->attachment)
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -07005036 return VK_TRUE;
Michael Lentineb6986752015-10-06 14:56:18 -07005037 }
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -07005038 VkBool32 result = VK_FALSE;
Michael Lentineb6986752015-10-06 14:56:18 -07005039 // Loop through previous nodes and see if any of them write to the attachment.
5040 for (auto elem : node.prev) {
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06005041 result |= CheckPreserved(my_data, device, pCreateInfo, elem, attachment, subpass_to_node, depth + 1, skip_call);
Michael Lentineb6986752015-10-06 14:56:18 -07005042 }
5043 // If the attachment was written to by a previous node than this node needs to preserve it.
5044 if (result && depth > 0) {
5045 const VkSubpassDescription& subpass = pCreateInfo->pSubpasses[index];
Courtney Goeltzenleuchter6ed5dc22015-11-03 15:41:43 -07005046 VkBool32 has_preserved = false;
Chia-I Wud50a7d72015-10-26 20:48:51 +08005047 for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) {
Michael Lentineb6986752015-10-06 14:56:18 -07005048 if (subpass.pPreserveAttachments[j].attachment == attachment) {
5049 has_preserved = true;
5050 break;
5051 }
5052 }
5053 if (!has_preserved) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005054 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
Michael Lentineb6986752015-10-06 14:56:18 -07005055 "Attachment %d is used by a later subpass and must be preserved in subpass %d.", attachment, index);
5056 }
5057 }
5058 return result;
5059}
5060
Michael Lentineb4979492015-12-22 11:36:14 -06005061VkBool32 ValidateDependencies(const layer_data* my_data, VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const std::vector<DAGNode>& subpass_to_node) {
5062 VkBool32 skip_call = false;
Michael Lentineb6986752015-10-06 14:56:18 -07005063 std::vector<std::vector<uint32_t>> output_attachment_to_subpass(pCreateInfo->attachmentCount);
5064 std::vector<std::vector<uint32_t>> input_attachment_to_subpass(pCreateInfo->attachmentCount);
Michael Lentineb6986752015-10-06 14:56:18 -07005065 // Find for each attachment the subpasses that use them.
5066 for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
5067 const VkSubpassDescription& subpass = pCreateInfo->pSubpasses[i];
Chia-I Wud50a7d72015-10-26 20:48:51 +08005068 for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
Michael Lentineb6986752015-10-06 14:56:18 -07005069 input_attachment_to_subpass[subpass.pInputAttachments[j].attachment].push_back(i);
5070 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08005071 for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
Michael Lentineb6986752015-10-06 14:56:18 -07005072 output_attachment_to_subpass[subpass.pColorAttachments[j].attachment].push_back(i);
5073 }
Chia-I Wu1efb7e52015-10-26 17:32:47 +08005074 if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
5075 output_attachment_to_subpass[subpass.pDepthStencilAttachment->attachment].push_back(i);
Michael Lentineb6986752015-10-06 14:56:18 -07005076 }
5077 }
5078 // If there is a dependency needed make sure one exists
5079 for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
5080 const VkSubpassDescription& subpass = pCreateInfo->pSubpasses[i];
5081 // If the attachment is an input then all subpasses that output must have a dependency relationship
Chia-I Wud50a7d72015-10-26 20:48:51 +08005082 for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
Michael Lentineb6986752015-10-06 14:56:18 -07005083 const uint32_t& attachment = subpass.pInputAttachments[j].attachment;
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06005084 CheckDependencyExists(my_data, device, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call);
Michael Lentineb6986752015-10-06 14:56:18 -07005085 }
5086 // If the attachment is an output then all subpasses that use the attachment must have a dependency relationship
Chia-I Wud50a7d72015-10-26 20:48:51 +08005087 for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
Michael Lentineb6986752015-10-06 14:56:18 -07005088 const uint32_t& attachment = subpass.pColorAttachments[j].attachment;
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06005089 CheckDependencyExists(my_data, device, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call);
5090 CheckDependencyExists(my_data, device, i, input_attachment_to_subpass[attachment], subpass_to_node, skip_call);
Michael Lentineb6986752015-10-06 14:56:18 -07005091 }
Chia-I Wu1efb7e52015-10-26 17:32:47 +08005092 if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
5093 const uint32_t& attachment = subpass.pDepthStencilAttachment->attachment;
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06005094 CheckDependencyExists(my_data, device, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call);
5095 CheckDependencyExists(my_data, device, i, input_attachment_to_subpass[attachment], subpass_to_node, skip_call);
Michael Lentineb6986752015-10-06 14:56:18 -07005096 }
5097 }
5098 // Loop through implicit dependencies, if this pass reads make sure the attachment is preserved for all passes after it was written.
5099 for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
5100 const VkSubpassDescription& subpass = pCreateInfo->pSubpasses[i];
Chia-I Wud50a7d72015-10-26 20:48:51 +08005101 for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06005102 CheckPreserved(my_data, device, pCreateInfo, i, subpass.pInputAttachments[j].attachment, subpass_to_node, 0, skip_call);
Michael Lentineb6986752015-10-06 14:56:18 -07005103 }
5104 }
5105 return skip_call;
5106}
5107
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07005108VkBool32 ValidateLayouts(const layer_data* my_data, VkDevice device, const VkRenderPassCreateInfo* pCreateInfo) {
5109 VkBool32 skip = false;
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07005110
5111#ifdef DISABLE_IMAGE_LAYOUT_VALIDATION
5112 return skip;
5113#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
5114
Michael Lentineabc5e922015-10-12 11:30:14 -05005115 for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
5116 const VkSubpassDescription& subpass = pCreateInfo->pSubpasses[i];
5117 for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
5118 if (subpass.pInputAttachments[j].layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
5119 subpass.pInputAttachments[j].layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
5120 if (subpass.pInputAttachments[j].layout == VK_IMAGE_LAYOUT_GENERAL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07005121 // TODO: Verify Valid Use in spec. I believe this is allowed (valid) but may not be optimal performance
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005122 skip |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05005123 "Layout for input attachment is GENERAL but should be READ_ONLY_OPTIMAL.");
5124 } else {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005125 skip |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05005126 "Layout for input attachment is %d but can only be READ_ONLY_OPTIMAL or GENERAL.", subpass.pInputAttachments[j].attachment);
5127 }
5128 }
5129 }
5130 for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
5131 if (subpass.pColorAttachments[j].layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
5132 if (subpass.pColorAttachments[j].layout == VK_IMAGE_LAYOUT_GENERAL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07005133 // TODO: Verify Valid Use in spec. I believe this is allowed (valid) but may not be optimal performance
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005134 skip |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05005135 "Layout for color attachment is GENERAL but should be COLOR_ATTACHMENT_OPTIMAL.");
5136 } else {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005137 skip |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05005138 "Layout for color attachment is %d but can only be COLOR_ATTACHMENT_OPTIMAL or GENERAL.", subpass.pColorAttachments[j].attachment);
5139 }
5140 }
5141 }
Mark Lobodzinski0f30f9e2015-10-28 13:03:56 -06005142 if ((subpass.pDepthStencilAttachment != NULL) &&
5143 (subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)) {
Michael Lentineabc5e922015-10-12 11:30:14 -05005144 if (subpass.pDepthStencilAttachment->layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
5145 if (subpass.pDepthStencilAttachment->layout == VK_IMAGE_LAYOUT_GENERAL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07005146 // TODO: Verify Valid Use in spec. I believe this is allowed (valid) but may not be optimal performance
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005147 skip |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05005148 "Layout for depth attachment is GENERAL but should be DEPTH_STENCIL_ATTACHMENT_OPTIMAL.");
5149 } else {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005150 skip |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05005151 "Layout for depth attachment is %d but can only be DEPTH_STENCIL_ATTACHMENT_OPTIMAL or GENERAL.", subpass.pDepthStencilAttachment->attachment);
5152 }
5153 }
5154 }
5155 }
5156 return skip;
5157}
5158
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07005159VkBool32 CreatePassDAG(const layer_data* my_data, VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, std::vector<DAGNode>& subpass_to_node, std::vector<bool>& has_self_dependency) {
5160 VkBool32 skip_call = false;
Michael Lentineabc5e922015-10-12 11:30:14 -05005161 for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
5162 DAGNode& subpass_node = subpass_to_node[i];
5163 subpass_node.pass = i;
5164 }
5165 for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) {
5166 const VkSubpassDependency& dependency = pCreateInfo->pDependencies[i];
5167 if (dependency.srcSubpass > dependency.dstSubpass) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005168 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05005169 "Depedency graph must be specified such that an earlier pass cannot depend on a later pass.");
Michael Lentine48930b82015-10-15 17:07:00 -05005170 } else if (dependency.srcSubpass == dependency.dstSubpass) {
5171 has_self_dependency[dependency.srcSubpass] = true;
Michael Lentineabc5e922015-10-12 11:30:14 -05005172 }
5173 subpass_to_node[dependency.dstSubpass].prev.push_back(dependency.srcSubpass);
5174 subpass_to_node[dependency.srcSubpass].next.push_back(dependency.dstSubpass);
5175 }
5176 return skip_call;
5177}
Tobin Ehlis8fab6562015-12-01 09:57:09 -07005178// TODOSC : Add intercept of vkCreateShaderModule
Michael Lentineabc5e922015-10-12 11:30:14 -05005179
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07005180VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule(
5181 VkDevice device,
5182 const VkShaderModuleCreateInfo *pCreateInfo,
5183 const VkAllocationCallbacks* pAllocator,
5184 VkShaderModule *pShaderModule)
5185{
5186 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07005187 VkBool32 skip_call = false;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07005188 if (!shader_is_spirv(pCreateInfo)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07005189 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005190 /* dev */ 0, __LINE__, SHADER_CHECKER_NON_SPIRV_SHADER, "SC",
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07005191 "Shader is not SPIR-V");
5192 }
5193
5194 if (skip_call)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005195 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07005196
5197 VkResult res = my_data->device_dispatch_table->CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
5198
5199 if (res == VK_SUCCESS) {
5200 loader_platform_thread_lock_mutex(&globalLock);
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07005201 my_data->shaderModuleMap[*pShaderModule] = new shader_module(pCreateInfo);
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07005202 loader_platform_thread_unlock_mutex(&globalLock);
5203 }
5204 return res;
5205}
5206
Chia-I Wu9ab61502015-11-06 06:42:02 +08005207VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass)
Tobin Ehliseba312c2015-04-01 08:40:34 -06005208{
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07005209 VkBool32 skip_call = false;
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06005210 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Michael Lentineabc5e922015-10-12 11:30:14 -05005211 // Create DAG
Michael Lentine48930b82015-10-15 17:07:00 -05005212 std::vector<bool> has_self_dependency(pCreateInfo->subpassCount);
Michael Lentineabc5e922015-10-12 11:30:14 -05005213 std::vector<DAGNode> subpass_to_node(pCreateInfo->subpassCount);
Michael Lentine48930b82015-10-15 17:07:00 -05005214 skip_call |= CreatePassDAG(dev_data, device, pCreateInfo, subpass_to_node, has_self_dependency);
Michael Lentineabc5e922015-10-12 11:30:14 -05005215 // Validate using DAG
5216 skip_call |= ValidateDependencies(dev_data, device, pCreateInfo, subpass_to_node);
5217 skip_call |= ValidateLayouts(dev_data, device, pCreateInfo);
5218 if (skip_call) {
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005219 return VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentineb6986752015-10-06 14:56:18 -07005220 }
Chia-I Wuf7458c52015-10-26 21:10:41 +08005221 VkResult result = dev_data->device_dispatch_table->CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005222 if (VK_SUCCESS == result) {
Tobin Ehlis8fab6562015-12-01 09:57:09 -07005223 // TODOSC : Merge in tracking of renderpass from ShaderChecker
Tobin Ehliseba312c2015-04-01 08:40:34 -06005224 // Shadow create info and store in map
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06005225 VkRenderPassCreateInfo* localRPCI = new VkRenderPassCreateInfo(*pCreateInfo);
Chia-I Wu08accc62015-07-07 11:50:03 +08005226 if (pCreateInfo->pAttachments) {
5227 localRPCI->pAttachments = new VkAttachmentDescription[localRPCI->attachmentCount];
5228 memcpy((void*)localRPCI->pAttachments, pCreateInfo->pAttachments, localRPCI->attachmentCount*sizeof(VkAttachmentDescription));
Tobin Ehliseba312c2015-04-01 08:40:34 -06005229 }
Chia-I Wu08accc62015-07-07 11:50:03 +08005230 if (pCreateInfo->pSubpasses) {
5231 localRPCI->pSubpasses = new VkSubpassDescription[localRPCI->subpassCount];
5232 memcpy((void*)localRPCI->pSubpasses, pCreateInfo->pSubpasses, localRPCI->subpassCount*sizeof(VkSubpassDescription));
5233
5234 for (uint32_t i = 0; i < localRPCI->subpassCount; i++) {
5235 VkSubpassDescription *subpass = (VkSubpassDescription *) &localRPCI->pSubpasses[i];
Chia-I Wud50a7d72015-10-26 20:48:51 +08005236 const uint32_t attachmentCount = subpass->inputAttachmentCount +
5237 subpass->colorAttachmentCount * (1 + (subpass->pResolveAttachments?1:0)) +
Chia-I Wu1efb7e52015-10-26 17:32:47 +08005238 ((subpass->pDepthStencilAttachment) ? 1 : 0) + subpass->preserveAttachmentCount;
Chia-I Wu08accc62015-07-07 11:50:03 +08005239 VkAttachmentReference *attachments = new VkAttachmentReference[attachmentCount];
5240
Cody Northropa505dda2015-08-04 11:16:41 -06005241 memcpy(attachments, subpass->pInputAttachments,
Chia-I Wud50a7d72015-10-26 20:48:51 +08005242 sizeof(attachments[0]) * subpass->inputAttachmentCount);
Cody Northropa505dda2015-08-04 11:16:41 -06005243 subpass->pInputAttachments = attachments;
Chia-I Wud50a7d72015-10-26 20:48:51 +08005244 attachments += subpass->inputAttachmentCount;
Chia-I Wu08accc62015-07-07 11:50:03 +08005245
Cody Northropa505dda2015-08-04 11:16:41 -06005246 memcpy(attachments, subpass->pColorAttachments,
Chia-I Wud50a7d72015-10-26 20:48:51 +08005247 sizeof(attachments[0]) * subpass->colorAttachmentCount);
Cody Northropa505dda2015-08-04 11:16:41 -06005248 subpass->pColorAttachments = attachments;
Chia-I Wud50a7d72015-10-26 20:48:51 +08005249 attachments += subpass->colorAttachmentCount;
Chia-I Wu08accc62015-07-07 11:50:03 +08005250
Cody Northropa505dda2015-08-04 11:16:41 -06005251 if (subpass->pResolveAttachments) {
5252 memcpy(attachments, subpass->pResolveAttachments,
Chia-I Wud50a7d72015-10-26 20:48:51 +08005253 sizeof(attachments[0]) * subpass->colorAttachmentCount);
Cody Northropa505dda2015-08-04 11:16:41 -06005254 subpass->pResolveAttachments = attachments;
Chia-I Wud50a7d72015-10-26 20:48:51 +08005255 attachments += subpass->colorAttachmentCount;
Chia-I Wu08accc62015-07-07 11:50:03 +08005256 }
5257
Chia-I Wu1efb7e52015-10-26 17:32:47 +08005258 if (subpass->pDepthStencilAttachment) {
5259 memcpy(attachments, subpass->pDepthStencilAttachment,
5260 sizeof(attachments[0]) * 1);
5261 subpass->pDepthStencilAttachment = attachments;
5262 attachments += 1;
5263 }
5264
Cody Northropa505dda2015-08-04 11:16:41 -06005265 memcpy(attachments, subpass->pPreserveAttachments,
Chia-I Wud50a7d72015-10-26 20:48:51 +08005266 sizeof(attachments[0]) * subpass->preserveAttachmentCount);
Cody Northropa505dda2015-08-04 11:16:41 -06005267 subpass->pPreserveAttachments = attachments;
Chia-I Wu08accc62015-07-07 11:50:03 +08005268 }
Tobin Ehliseba312c2015-04-01 08:40:34 -06005269 }
Chia-I Wu08accc62015-07-07 11:50:03 +08005270 if (pCreateInfo->pDependencies) {
5271 localRPCI->pDependencies = new VkSubpassDependency[localRPCI->dependencyCount];
5272 memcpy((void*)localRPCI->pDependencies, pCreateInfo->pDependencies, localRPCI->dependencyCount*sizeof(VkSubpassDependency));
Tobin Ehliseba312c2015-04-01 08:40:34 -06005273 }
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07005274 loader_platform_thread_lock_mutex(&globalLock);
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07005275 dev_data->renderPassMap[*pRenderPass] = new RENDER_PASS_NODE(localRPCI);
Michael Lentine48930b82015-10-15 17:07:00 -05005276 dev_data->renderPassMap[*pRenderPass]->hasSelfDependency = has_self_dependency;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07005277 loader_platform_thread_unlock_mutex(&globalLock);
Tobin Ehliseba312c2015-04-01 08:40:34 -06005278 }
5279 return result;
5280}
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06005281// Free the renderpass shadow
5282static void deleteRenderPasses(layer_data* my_data)
5283{
5284 if (my_data->renderPassMap.size() <= 0)
5285 return;
5286 for (auto ii=my_data->renderPassMap.begin(); ii!=my_data->renderPassMap.end(); ++ii) {
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07005287 const VkRenderPassCreateInfo* pRenderPassInfo = (*ii).second->pCreateInfo;
Michael Lentine48930b82015-10-15 17:07:00 -05005288 if (pRenderPassInfo->pAttachments) {
5289 delete[] pRenderPassInfo->pAttachments;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06005290 }
Michael Lentine48930b82015-10-15 17:07:00 -05005291 if (pRenderPassInfo->pSubpasses) {
5292 for (uint32_t i=0; i<pRenderPassInfo->subpassCount; ++i) {
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06005293 // Attachements are all allocated in a block, so just need to
5294 // find the first non-null one to delete
Michael Lentine48930b82015-10-15 17:07:00 -05005295 if (pRenderPassInfo->pSubpasses[i].pInputAttachments) {
5296 delete[] pRenderPassInfo->pSubpasses[i].pInputAttachments;
5297 } else if (pRenderPassInfo->pSubpasses[i].pColorAttachments) {
5298 delete[] pRenderPassInfo->pSubpasses[i].pColorAttachments;
5299 } else if (pRenderPassInfo->pSubpasses[i].pResolveAttachments) {
5300 delete[] pRenderPassInfo->pSubpasses[i].pResolveAttachments;
5301 } else if (pRenderPassInfo->pSubpasses[i].pPreserveAttachments) {
5302 delete[] pRenderPassInfo->pSubpasses[i].pPreserveAttachments;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06005303 }
5304 }
Michael Lentine48930b82015-10-15 17:07:00 -05005305 delete[] pRenderPassInfo->pSubpasses;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06005306 }
Michael Lentine48930b82015-10-15 17:07:00 -05005307 if (pRenderPassInfo->pDependencies) {
5308 delete[] pRenderPassInfo->pDependencies;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06005309 }
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07005310 delete pRenderPassInfo;
Michael Lentine48930b82015-10-15 17:07:00 -05005311 delete (*ii).second;
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06005312 }
5313 my_data->renderPassMap.clear();
5314}
Michael Lentineabc5e922015-10-12 11:30:14 -05005315
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07005316VkBool32 VerifyFramebufferAndRenderPassLayouts(VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo* pRenderPassBegin) {
5317 VkBool32 skip_call = false;
Michael Lentineabc5e922015-10-12 11:30:14 -05005318 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
5319 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, cmdBuffer);
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07005320 const VkRenderPassCreateInfo* pRenderPassInfo = dev_data->renderPassMap[pRenderPassBegin->renderPass]->pCreateInfo;
Michael Lentineabc5e922015-10-12 11:30:14 -05005321 const VkFramebufferCreateInfo* pFramebufferInfo = dev_data->frameBufferMap[pRenderPassBegin->framebuffer];
5322 if (pRenderPassInfo->attachmentCount != pFramebufferInfo->attachmentCount) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005323 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05005324 "You cannot start a render pass using a framebuffer with a different number of attachments.");
5325 }
5326 for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) {
5327 const VkImageView& image_view = pFramebufferInfo->pAttachments[i];
5328 const VkImage& image = dev_data->imageViewMap[image_view]->image;
5329 auto image_data = pCB->imageLayoutMap.find(image);
5330 if (image_data == pCB->imageLayoutMap.end()) {
5331 pCB->imageLayoutMap[image].initialLayout = pRenderPassInfo->pAttachments[i].initialLayout;
5332 pCB->imageLayoutMap[image].layout = pRenderPassInfo->pAttachments[i].initialLayout;
5333 } else if (pRenderPassInfo->pAttachments[i].initialLayout != image_data->second.layout) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005334 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05005335 "You cannot start a render pass using attachment %i where the intial layout differs from the starting layout.", i);
5336 }
5337 }
5338 return skip_call;
5339}
5340
5341void TransitionSubpassLayouts(VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const int subpass_index) {
5342 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
5343 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, cmdBuffer);
5344 auto render_pass_data = dev_data->renderPassMap.find(pRenderPassBegin->renderPass);
5345 if (render_pass_data == dev_data->renderPassMap.end()) {
5346 return;
5347 }
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07005348 const VkRenderPassCreateInfo* pRenderPassInfo = render_pass_data->second->pCreateInfo;
Michael Lentineabc5e922015-10-12 11:30:14 -05005349 auto framebuffer_data = dev_data->frameBufferMap.find(pRenderPassBegin->framebuffer);
5350 if (framebuffer_data == dev_data->frameBufferMap.end()) {
5351 return;
5352 }
5353 const VkFramebufferCreateInfo* pFramebufferInfo = framebuffer_data->second;
5354 const VkSubpassDescription& subpass = pRenderPassInfo->pSubpasses[subpass_index];
5355 for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
5356 const VkImageView& image_view = pFramebufferInfo->pAttachments[subpass.pInputAttachments[j].attachment];
5357 auto image_view_data = dev_data->imageViewMap.find(image_view);
5358 if (image_view_data != dev_data->imageViewMap.end()) {
5359 auto image_layout = pCB->imageLayoutMap.find(image_view_data->second->image);
5360 if (image_layout != pCB->imageLayoutMap.end()) {
5361 image_layout->second.layout = subpass.pInputAttachments[j].layout;
5362 }
5363 }
5364 }
5365 for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
5366 const VkImageView& image_view = pFramebufferInfo->pAttachments[subpass.pColorAttachments[j].attachment];
5367 auto image_view_data = dev_data->imageViewMap.find(image_view);
5368 if (image_view_data != dev_data->imageViewMap.end()) {
5369 auto image_layout = pCB->imageLayoutMap.find(image_view_data->second->image);
5370 if (image_layout != pCB->imageLayoutMap.end()) {
5371 image_layout->second.layout = subpass.pColorAttachments[j].layout;
5372 }
5373 }
5374 }
Michael Lentine3dea6512015-10-28 15:55:18 -07005375 if ((subpass.pDepthStencilAttachment != NULL) &&
Mark Lobodzinski0f30f9e2015-10-28 13:03:56 -06005376 (subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)) {
Michael Lentineabc5e922015-10-12 11:30:14 -05005377 const VkImageView& image_view = pFramebufferInfo->pAttachments[subpass.pDepthStencilAttachment->attachment];
5378 auto image_view_data = dev_data->imageViewMap.find(image_view);
5379 if (image_view_data != dev_data->imageViewMap.end()) {
5380 auto image_layout = pCB->imageLayoutMap.find(image_view_data->second->image);
5381 if (image_layout != pCB->imageLayoutMap.end()) {
5382 image_layout->second.layout = subpass.pDepthStencilAttachment->layout;
5383 }
5384 }
5385 }
5386}
5387
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07005388VkBool32 validatePrimaryCommandBuffer(const layer_data* my_data, const GLOBAL_CB_NODE* pCB, const std::string& cmd_name) {
5389 VkBool32 skip_call = false;
Michael Lentine3dea6512015-10-28 15:55:18 -07005390 if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005391 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
Michael Lentine3dea6512015-10-28 15:55:18 -07005392 "Cannot execute command %s on a secondary command buffer.", cmd_name.c_str());
5393 }
5394 return skip_call;
5395}
5396
Michael Lentineabc5e922015-10-12 11:30:14 -05005397void TransitionFinalSubpassLayouts(VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo* pRenderPassBegin) {
5398 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
5399 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, cmdBuffer);
5400 auto render_pass_data = dev_data->renderPassMap.find(pRenderPassBegin->renderPass);
5401 if (render_pass_data == dev_data->renderPassMap.end()) {
5402 return;
5403 }
Tobin Ehlis3f5ddbb2015-12-02 13:53:34 -07005404 const VkRenderPassCreateInfo* pRenderPassInfo = render_pass_data->second->pCreateInfo;
Michael Lentineabc5e922015-10-12 11:30:14 -05005405 auto framebuffer_data = dev_data->frameBufferMap.find(pRenderPassBegin->framebuffer);
5406 if (framebuffer_data == dev_data->frameBufferMap.end()) {
5407 return;
5408 }
5409 const VkFramebufferCreateInfo* pFramebufferInfo = framebuffer_data->second;
5410 for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) {
5411 const VkImageView& image_view = pFramebufferInfo->pAttachments[i];
5412 auto image_view_data = dev_data->imageViewMap.find(image_view);
5413 if (image_view_data != dev_data->imageViewMap.end()) {
5414 auto image_layout = pCB->imageLayoutMap.find(image_view_data->second->image);
5415 if (image_layout != pCB->imageLayoutMap.end()) {
5416 image_layout->second.layout = pRenderPassInfo->pAttachments[i].finalLayout;
5417 }
5418 }
5419 }
5420}
5421
Chia-I Wu9ab61502015-11-06 06:42:02 +08005422VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, VkSubpassContents contents)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005423{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005424 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005425 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5426 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005427 if (pCB) {
Tobin Ehlis259730a2015-06-23 16:13:03 -06005428 if (pRenderPassBegin && pRenderPassBegin->renderPass) {
Mark Lobodzinski0f30f9e2015-10-28 13:03:56 -06005429 skipCall |= VerifyFramebufferAndRenderPassLayouts(commandBuffer, pRenderPassBegin);
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06005430 skipCall |= insideRenderPass(dev_data, pCB, "vkCmdBeginRenderPass");
Michael Lentine3dea6512015-10-28 15:55:18 -07005431 skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdBeginRenderPass");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005432 skipCall |= addCmd(dev_data, pCB, CMD_BEGINRENDERPASS, "vkCmdBeginRenderPass()");
Mark Lobodzinski5495d132015-09-30 16:19:16 -06005433 pCB->activeRenderPass = pRenderPassBegin->renderPass;
Michael Lentineabc5e922015-10-12 11:30:14 -05005434 // This is a shallow copy as that is all that is needed for now
5435 pCB->activeRenderPassBeginInfo = *pRenderPassBegin;
Mark Lobodzinski5495d132015-09-30 16:19:16 -06005436 pCB->activeSubpass = 0;
5437 pCB->framebuffer = pRenderPassBegin->framebuffer;
Tobin Ehlis502480b2015-06-24 15:53:07 -06005438 } else {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005439 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
Tobin Ehlis259730a2015-06-23 16:13:03 -06005440 "You cannot use a NULL RenderPass object in vkCmdBeginRenderPass()");
Tony Barbourbadda992015-04-06 11:09:26 -06005441 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005442 }
Mark Lobodzinski0f30f9e2015-10-28 13:03:56 -06005443 if (VK_FALSE == skipCall) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005444 dev_data->device_dispatch_table->CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
Mark Lobodzinski0f30f9e2015-10-28 13:03:56 -06005445 // This is a shallow copy as that is all that is needed for now
5446 dev_data->renderPassBeginInfo = *pRenderPassBegin;
5447 dev_data->currentSubpass = 0;
5448 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005449}
5450
Chia-I Wu9ab61502015-11-06 06:42:02 +08005451VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents)
Chia-I Wu08accc62015-07-07 11:50:03 +08005452{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005453 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005454 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5455 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Michael Lentineabc5e922015-10-12 11:30:14 -05005456 TransitionSubpassLayouts(commandBuffer, &dev_data->renderPassBeginInfo, ++dev_data->currentSubpass);
Chia-I Wu08accc62015-07-07 11:50:03 +08005457 if (pCB) {
Michael Lentine3dea6512015-10-28 15:55:18 -07005458 skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdNextSubpass");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005459 skipCall |= addCmd(dev_data, pCB, CMD_NEXTSUBPASS, "vkCmdNextSubpass()");
Mark Lobodzinski5495d132015-09-30 16:19:16 -06005460 pCB->activeSubpass++;
Tony Barbour6e1b5ba2015-12-15 10:24:45 -07005461 TransitionSubpassLayouts(commandBuffer, &pCB->activeRenderPassBeginInfo, pCB->activeSubpass);
Mark Lobodzinski5495d132015-09-30 16:19:16 -06005462 if (pCB->lastBoundPipeline) {
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06005463 skipCall |= validatePipelineState(dev_data, pCB, VK_PIPELINE_BIND_POINT_GRAPHICS, pCB->lastBoundPipeline);
Chia-I Wu08accc62015-07-07 11:50:03 +08005464 }
Tobin Ehlis432ef5c2015-10-20 17:06:16 -06005465 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdNextSubpass");
Chia-I Wu08accc62015-07-07 11:50:03 +08005466 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005467 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005468 dev_data->device_dispatch_table->CmdNextSubpass(commandBuffer, contents);
Chia-I Wu08accc62015-07-07 11:50:03 +08005469}
5470
Chia-I Wu9ab61502015-11-06 06:42:02 +08005471VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass(VkCommandBuffer commandBuffer)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005472{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005473 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005474 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5475 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Michael Lentineabc5e922015-10-12 11:30:14 -05005476 TransitionFinalSubpassLayouts(commandBuffer, &dev_data->renderPassBeginInfo);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005477 if (pCB) {
Michael Lentine3dea6512015-10-28 15:55:18 -07005478 skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass");
Michael Lentine3dea6512015-10-28 15:55:18 -07005479 skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005480 skipCall |= addCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()");
Michael Lentineabc5e922015-10-12 11:30:14 -05005481 TransitionFinalSubpassLayouts(commandBuffer, &pCB->activeRenderPassBeginInfo);
Mark Lobodzinski5495d132015-09-30 16:19:16 -06005482 pCB->activeRenderPass = 0;
5483 pCB->activeSubpass = 0;
Chia-I Wu0b50a1c2015-06-26 15:34:39 +08005484 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005485 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005486 dev_data->device_dispatch_table->CmdEndRenderPass(commandBuffer);
Chia-I Wu0b50a1c2015-06-26 15:34:39 +08005487}
5488
Chia-I Wu9ab61502015-11-06 06:42:02 +08005489VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount, const VkCommandBuffer* pCommandBuffers)
Chia-I Wu0b50a1c2015-06-26 15:34:39 +08005490{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005491 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005492 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5493 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Chia-I Wu0b50a1c2015-06-26 15:34:39 +08005494 if (pCB) {
Tobin Ehlis651d9b02015-12-16 05:01:22 -07005495 // TODO : If secondary CB was not created w/ *_USAGE_SIMULTANEOUS_USE_BIT it cannot be used more than once in given primary CB
5496 // ALSO if secondary w/o this flag is set in primary, then primary must not be pending execution more than once at a time
5497 // If not w/ SIMULTANEOUS bit, then any other references to those 2ndary CBs are invalidated, should warn on that case
Tobin Ehlis4b34ddc2015-09-17 14:18:16 -06005498 GLOBAL_CB_NODE* pSubCB = NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005499 for (uint32_t i=0; i<commandBuffersCount; i++) {
5500 pSubCB = getCBNode(dev_data, pCommandBuffers[i]);
Tobin Ehlis4b34ddc2015-09-17 14:18:16 -06005501 if (!pSubCB) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005502 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005503 "vkCmdExecuteCommands() called w/ invalid Cmd Buffer %p in element %u of pCommandBuffers array.", (void*)pCommandBuffers[i], i);
5504 } else if (VK_COMMAND_BUFFER_LEVEL_PRIMARY == pSubCB->createInfo.level) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005505 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005506 "vkCmdExecuteCommands() called w/ Primary Cmd Buffer %p in element %u of pCommandBuffers array. All cmd buffers in pCommandBuffers array must be secondary.", (void*)pCommandBuffers[i], i);
Tobin Ehlis651d9b02015-12-16 05:01:22 -07005507 } else if (pCB->activeRenderPass) { // Secondary CB w/i RenderPass must have *CONTINUE_BIT set
5508 if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005509 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)pCommandBuffers[i], __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
Tobin Ehlis651d9b02015-12-16 05:01:22 -07005510 "vkCmdExecuteCommands(): Secondary Command Buffer (%p) executed within render pass (%#" PRIxLEAST64 ") must have had vkBeginCommandBuffer() called w/ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT set.", (void*)pCommandBuffers[i], (uint64_t)pCB->activeRenderPass);
5511 }
5512 string errorString = "";
5513 if (!verify_renderpass_compatibility(dev_data, pCB->activeRenderPass, pSubCB->beginInfo.renderPass, errorString)) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005514 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)pCommandBuffers[i], __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
Tobin Ehlis651d9b02015-12-16 05:01:22 -07005515 "vkCmdExecuteCommands(): Secondary Command Buffer (%p) w/ render pass (%#" PRIxLEAST64 ") is incompatible w/ primary command buffer (%p) w/ render pass (%#" PRIxLEAST64 ") due to: %s",
5516 (void*)pCommandBuffers[i], (uint64_t)pSubCB->beginInfo.renderPass, (void*)commandBuffer, (uint64_t)pCB->activeRenderPass, errorString.c_str());
5517 }
5518 // If framebuffer for secondary CB is not NULL, then it must match FB from vkCmdBeginRenderPass()
5519 // that this CB will be executed in AND framebuffer must have been created w/ RP compatible w/ renderpass
5520 if (pSubCB->beginInfo.framebuffer) {
5521 if (pSubCB->beginInfo.framebuffer != pCB->activeRenderPassBeginInfo.framebuffer) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005522 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)pCommandBuffers[i], __LINE__, DRAWSTATE_FRAMEBUFFER_INCOMPATIBLE, "DS",
Tobin Ehlis651d9b02015-12-16 05:01:22 -07005523 "vkCmdExecuteCommands(): Secondary Command Buffer (%p) references framebuffer (%#" PRIxLEAST64 ") that does not match framebuffer (%#" PRIxLEAST64 ") in active renderpass (%#" PRIxLEAST64 ").",
5524 (void*)pCommandBuffers[i], (uint64_t)pSubCB->beginInfo.framebuffer, (uint64_t)pCB->activeRenderPassBeginInfo.framebuffer, (uint64_t)pCB->activeRenderPass);
5525 }
5526 }
Tobin Ehlis4b34ddc2015-09-17 14:18:16 -06005527 }
5528 }
Michael Lentine3dea6512015-10-28 15:55:18 -07005529 skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdExecuteComands");
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005530 skipCall |= addCmd(dev_data, pCB, CMD_EXECUTECOMMANDS, "vkCmdExecuteComands()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005531 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005532 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005533 dev_data->device_dispatch_table->CmdExecuteCommands(commandBuffer, commandBuffersCount, pCommandBuffers);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005534}
5535
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07005536VkBool32 ValidateMapImageLayouts(VkDevice device, VkDeviceMemory mem) {
5537 VkBool32 skip_call = false;
Michael Lentine7b236262015-10-23 12:41:44 -07005538 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5539 auto mem_data = dev_data->memImageMap.find(mem);
5540 if (mem_data != dev_data->memImageMap.end()) {
5541 auto image_data = dev_data->imageLayoutMap.find(mem_data->second);
5542 if (image_data != dev_data->imageLayoutMap.end()) {
5543 if (image_data->second->layout != VK_IMAGE_LAYOUT_PREINITIALIZED && image_data->second->layout != VK_IMAGE_LAYOUT_GENERAL) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005544 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentine7b236262015-10-23 12:41:44 -07005545 "Cannot map an image with layout %d. Only GENERAL or PREINITIALIZED are supported.", image_data->second->layout);
5546 }
5547 }
5548 }
5549 return skip_call;
5550}
5551
Chia-I Wu9ab61502015-11-06 06:42:02 +08005552VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory(
Michael Lentine7b236262015-10-23 12:41:44 -07005553 VkDevice device,
5554 VkDeviceMemory mem,
5555 VkDeviceSize offset,
5556 VkDeviceSize size,
5557 VkFlags flags,
5558 void **ppData)
5559{
5560 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07005561
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07005562 VkBool32 skip_call = VK_FALSE;
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07005563#ifndef DISABLE_IMAGE_LAYOUT_VALIDATION
5564 skip_call = ValidateMapImageLayouts(device, mem);
5565#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
5566
Michael Lentine7b236262015-10-23 12:41:44 -07005567 if (VK_FALSE == skip_call) {
5568 return dev_data->device_dispatch_table->MapMemory(device, mem, offset, size, flags, ppData);
5569 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005570 return VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentine7b236262015-10-23 12:41:44 -07005571}
5572
Chia-I Wu9ab61502015-11-06 06:42:02 +08005573VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory(
Michael Lentine7b236262015-10-23 12:41:44 -07005574 VkDevice device,
5575 VkImage image,
5576 VkDeviceMemory mem,
5577 VkDeviceSize memOffset)
5578{
5579 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5580 VkResult result = dev_data->device_dispatch_table->BindImageMemory(device, image, mem, memOffset);
5581 loader_platform_thread_lock_mutex(&globalLock);
5582 dev_data->memImageMap[mem] = image;
5583 loader_platform_thread_unlock_mutex(&globalLock);
5584 return result;
5585}
5586
Chia-I Wu9ab61502015-11-06 06:42:02 +08005587VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
Michael Lentineabc5e922015-10-12 11:30:14 -05005588 VkDevice device,
5589 const VkSwapchainCreateInfoKHR *pCreateInfo,
Ian Elliott05846062015-11-20 14:13:17 -07005590 const VkAllocationCallbacks *pAllocator,
Michael Lentineabc5e922015-10-12 11:30:14 -05005591 VkSwapchainKHR *pSwapchain)
5592{
5593 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott05846062015-11-20 14:13:17 -07005594 VkResult result = dev_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
Michael Lentineabc5e922015-10-12 11:30:14 -05005595
5596 if (VK_SUCCESS == result) {
5597 SWAPCHAIN_NODE *swapchain_data = new SWAPCHAIN_NODE;
5598 loader_platform_thread_lock_mutex(&globalLock);
5599 dev_data->device_extensions.swapchainMap[*pSwapchain] = swapchain_data;
5600 loader_platform_thread_unlock_mutex(&globalLock);
5601 }
5602
5603 return result;
5604}
5605
Ian Elliott05846062015-11-20 14:13:17 -07005606VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR(
Michael Lentineabc5e922015-10-12 11:30:14 -05005607 VkDevice device,
Ian Elliott05846062015-11-20 14:13:17 -07005608 VkSwapchainKHR swapchain,
5609 const VkAllocationCallbacks *pAllocator)
Michael Lentineabc5e922015-10-12 11:30:14 -05005610{
5611 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Michael Lentineabc5e922015-10-12 11:30:14 -05005612
5613 loader_platform_thread_lock_mutex(&globalLock);
5614 auto swapchain_data = dev_data->device_extensions.swapchainMap.find(swapchain);
5615 if (swapchain_data != dev_data->device_extensions.swapchainMap.end()) {
5616 if (swapchain_data->second->images.size() > 0) {
5617 for (auto swapchain_image : swapchain_data->second->images) {
5618 auto image_item = dev_data->imageLayoutMap.find(swapchain_image);
5619 if (image_item != dev_data->imageLayoutMap.end())
5620 dev_data->imageLayoutMap.erase(image_item);
5621 }
5622 }
5623 delete swapchain_data->second;
5624 dev_data->device_extensions.swapchainMap.erase(swapchain);
5625 }
5626 loader_platform_thread_unlock_mutex(&globalLock);
Ian Elliott05846062015-11-20 14:13:17 -07005627 return dev_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
Michael Lentineabc5e922015-10-12 11:30:14 -05005628}
5629
Chia-I Wu9ab61502015-11-06 06:42:02 +08005630VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(
Michael Lentineabc5e922015-10-12 11:30:14 -05005631 VkDevice device,
5632 VkSwapchainKHR swapchain,
5633 uint32_t* pCount,
5634 VkImage* pSwapchainImages)
5635{
5636 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
5637 VkResult result = dev_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pCount, pSwapchainImages);
5638
5639 if (result == VK_SUCCESS && pSwapchainImages != NULL) {
5640 // This should never happen and is checked by param checker.
5641 if (!pCount) return result;
5642 for (uint32_t i = 0; i < *pCount; ++i) {
5643 IMAGE_NODE* image_node = new IMAGE_NODE;
5644 image_node->layout = VK_IMAGE_LAYOUT_UNDEFINED;
5645 loader_platform_thread_lock_mutex(&globalLock);
5646 dev_data->device_extensions.swapchainMap[swapchain]->images.push_back(pSwapchainImages[i]);
5647 dev_data->imageLayoutMap[pSwapchainImages[i]] = image_node;
5648 loader_platform_thread_unlock_mutex(&globalLock);
5649 }
5650 }
5651 return result;
5652}
5653
Ian Elliott05846062015-11-20 14:13:17 -07005654VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo)
Michael Lentineabc5e922015-10-12 11:30:14 -05005655{
5656 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Courtney Goeltzenleuchtere6dd8082015-12-16 16:07:01 -07005657 VkBool32 skip_call = false;
Michael Lentineabc5e922015-10-12 11:30:14 -05005658
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07005659#ifndef DISABLE_IMAGE_LAYOUT_VALIDATION
Michael Lentineabc5e922015-10-12 11:30:14 -05005660 if (pPresentInfo) {
5661 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
Ian Elliott05846062015-11-20 14:13:17 -07005662 auto swapchain_data = dev_data->device_extensions.swapchainMap.find(pPresentInfo->pSwapchains[i]);
5663 if (swapchain_data != dev_data->device_extensions.swapchainMap.end() && pPresentInfo->pImageIndices[i] < swapchain_data->second->images.size()) {
5664 VkImage image = swapchain_data->second->images[pPresentInfo->pImageIndices[i]];
Michael Lentineabc5e922015-10-12 11:30:14 -05005665 auto image_data = dev_data->imageLayoutMap.find(image);
5666 if (image_data != dev_data->imageLayoutMap.end()) {
Ian Elliott05846062015-11-20 14:13:17 -07005667 if (image_data->second->layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005668 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, (uint64_t)queue, __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
Michael Lentineabc5e922015-10-12 11:30:14 -05005669 "Images passed to present must be in layout PRESENT_SOURCE_KHR but is in %d", image_data->second->layout);
5670 }
5671 }
5672 }
5673 }
5674 }
Mark Lobodzinski31e5f282015-11-30 16:48:53 -07005675#endif // DISABLE_IMAGE_LAYOUT_VALIDATION
Michael Lentineabc5e922015-10-12 11:30:14 -05005676
5677 if (VK_FALSE == skip_call)
5678 return dev_data->device_dispatch_table->QueuePresentKHR(queue, pPresentInfo);
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07005679 return VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentineabc5e922015-10-12 11:30:14 -05005680}
5681
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07005682VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(
5683 VkInstance instance,
5684 const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
5685 const VkAllocationCallbacks* pAllocator,
5686 VkDebugReportCallbackEXT* pMsgCallback)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005687{
Tobin Ehlis0b632332015-10-07 09:38:40 -06005688 layer_data* my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07005689 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07005690 VkResult res = pTable->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Tobin Ehlisc16c3e92015-06-16 09:04:30 -06005691 if (VK_SUCCESS == res) {
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07005692 res = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
Tobin Ehlisc16c3e92015-06-16 09:04:30 -06005693 }
5694 return res;
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005695}
5696
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07005697VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07005698 VkInstance instance,
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07005699 VkDebugReportCallbackEXT msgCallback,
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07005700 const VkAllocationCallbacks* pAllocator)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005701{
Tobin Ehlis0b632332015-10-07 09:38:40 -06005702 layer_data* my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07005703 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07005704 pTable->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07005705 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005706}
5707
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07005708VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07005709 VkInstance instance,
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07005710 VkDebugReportFlagsEXT flags,
5711 VkDebugReportObjectTypeEXT objType,
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07005712 uint64_t object,
5713 size_t location,
5714 int32_t msgCode,
5715 const char* pLayerPrefix,
5716 const char* pMsg)
5717{
5718 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07005719 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07005720}
5721
Chia-I Wu9ab61502015-11-06 06:42:02 +08005722VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDbgMarkerBegin(VkCommandBuffer commandBuffer, const char* pMarker)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005723{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005724 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005725 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5726 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis0b632332015-10-07 09:38:40 -06005727 if (!dev_data->device_extensions.debug_marker_enabled) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005728 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_EXTENSION, "DS",
Tobin Ehlisa16e8922015-06-16 15:50:44 -06005729 "Attempt to use CmdDbgMarkerBegin but extension disabled!");
Jon Ashburneab34492015-06-01 09:37:38 -06005730 return;
Tobin Ehlisce132d82015-06-19 15:07:05 -06005731 } else if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005732 skipCall |= addCmd(dev_data, pCB, CMD_DBGMARKERBEGIN, "vkCmdDbgMarkerBegin()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005733 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005734 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005735 debug_marker_dispatch_table(commandBuffer)->CmdDbgMarkerBegin(commandBuffer, pMarker);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005736}
5737
Chia-I Wu9ab61502015-11-06 06:42:02 +08005738VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDbgMarkerEnd(VkCommandBuffer commandBuffer)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005739{
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005740 VkBool32 skipCall = VK_FALSE;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005741 layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
5742 GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
Tobin Ehlis0b632332015-10-07 09:38:40 -06005743 if (!dev_data->device_extensions.debug_marker_enabled) {
Mark Lobodzinskib01451b2016-01-04 13:18:10 -07005744 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__, DRAWSTATE_INVALID_EXTENSION, "DS",
Tobin Ehlisa16e8922015-06-16 15:50:44 -06005745 "Attempt to use CmdDbgMarkerEnd but extension disabled!");
Jon Ashburneab34492015-06-01 09:37:38 -06005746 return;
Tobin Ehlisce132d82015-06-19 15:07:05 -06005747 } else if (pCB) {
Tobin Ehlis61b36f32015-12-16 08:19:42 -07005748 skipCall |= addCmd(dev_data, pCB, CMD_DBGMARKEREND, "vkCmdDbgMarkerEnd()");
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005749 }
Tobin Ehlis1cfb30a2015-09-09 11:31:10 -06005750 if (VK_FALSE == skipCall)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005751 debug_marker_dispatch_table(commandBuffer)->CmdDbgMarkerEnd(commandBuffer);
Jon Ashburneab34492015-06-01 09:37:38 -06005752}
5753
Chia-I Wu9ab61502015-11-06 06:42:02 +08005754VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char* funcName)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005755{
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06005756 if (dev == NULL)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005757 return NULL;
Jon Ashburn3950e1b2015-05-20 09:00:28 -06005758
Tobin Ehlis0b632332015-10-07 09:38:40 -06005759 layer_data *dev_data;
Jon Ashburn8fd08252015-05-28 16:25:02 -06005760 /* loader uses this to force layer initialization; device object is wrapped */
5761 if (!strcmp(funcName, "vkGetDeviceProcAddr")) {
Tobin Ehlis0b632332015-10-07 09:38:40 -06005762 VkBaseLayerObject* wrapped_dev = (VkBaseLayerObject*) dev;
5763 dev_data = get_my_data_ptr(get_dispatch_key(wrapped_dev->baseObject), layer_data_map);
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06005764 dev_data->device_dispatch_table = new VkLayerDispatchTable;
5765 layer_initialize_dispatch_table(dev_data->device_dispatch_table, wrapped_dev);
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005766 return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
Jon Ashburn8fd08252015-05-28 16:25:02 -06005767 }
Tobin Ehlis0b632332015-10-07 09:38:40 -06005768 dev_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06005769 if (!strcmp(funcName, "vkCreateDevice"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005770 return (PFN_vkVoidFunction) vkCreateDevice;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005771 if (!strcmp(funcName, "vkDestroyDevice"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005772 return (PFN_vkVoidFunction) vkDestroyDevice;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005773 if (!strcmp(funcName, "vkQueueSubmit"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005774 return (PFN_vkVoidFunction) vkQueueSubmit;
Michael Lentine700b0aa2015-10-30 17:57:32 -07005775 if (!strcmp(funcName, "vkWaitForFences"))
5776 return (PFN_vkVoidFunction) vkWaitForFences;
5777 if (!strcmp(funcName, "vkGetFenceStatus"))
5778 return (PFN_vkVoidFunction) vkGetFenceStatus;
Mark Lobodzinski8da0d1e2016-01-06 14:58:59 -07005779 if (!strcmp(funcName, "vkQueueWaitIdle"))
5780 return (PFN_vkVoidFunction) vkQueueWaitIdle;
5781 if (!strcmp(funcName, "vkDeviceWaitIdle"))
5782 return (PFN_vkVoidFunction) vkDeviceWaitIdle;
Michael Lentine700b0aa2015-10-30 17:57:32 -07005783 if (!strcmp(funcName, "vkGetDeviceQueue"))
5784 return (PFN_vkVoidFunction) vkGetDeviceQueue;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005785 if (!strcmp(funcName, "vkDestroyInstance"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005786 return (PFN_vkVoidFunction) vkDestroyInstance;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005787 if (!strcmp(funcName, "vkDestroyDevice"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005788 return (PFN_vkVoidFunction) vkDestroyDevice;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005789 if (!strcmp(funcName, "vkDestroyFence"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005790 return (PFN_vkVoidFunction) vkDestroyFence;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005791 if (!strcmp(funcName, "vkDestroySemaphore"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005792 return (PFN_vkVoidFunction) vkDestroySemaphore;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005793 if (!strcmp(funcName, "vkDestroyEvent"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005794 return (PFN_vkVoidFunction) vkDestroyEvent;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005795 if (!strcmp(funcName, "vkDestroyQueryPool"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005796 return (PFN_vkVoidFunction) vkDestroyQueryPool;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005797 if (!strcmp(funcName, "vkDestroyBuffer"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005798 return (PFN_vkVoidFunction) vkDestroyBuffer;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005799 if (!strcmp(funcName, "vkDestroyBufferView"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005800 return (PFN_vkVoidFunction) vkDestroyBufferView;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005801 if (!strcmp(funcName, "vkDestroyImage"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005802 return (PFN_vkVoidFunction) vkDestroyImage;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005803 if (!strcmp(funcName, "vkDestroyImageView"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005804 return (PFN_vkVoidFunction) vkDestroyImageView;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005805 if (!strcmp(funcName, "vkDestroyShaderModule"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005806 return (PFN_vkVoidFunction) vkDestroyShaderModule;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005807 if (!strcmp(funcName, "vkDestroyPipeline"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005808 return (PFN_vkVoidFunction) vkDestroyPipeline;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005809 if (!strcmp(funcName, "vkDestroyPipelineLayout"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005810 return (PFN_vkVoidFunction) vkDestroyPipelineLayout;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005811 if (!strcmp(funcName, "vkDestroySampler"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005812 return (PFN_vkVoidFunction) vkDestroySampler;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005813 if (!strcmp(funcName, "vkDestroyDescriptorSetLayout"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005814 return (PFN_vkVoidFunction) vkDestroyDescriptorSetLayout;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005815 if (!strcmp(funcName, "vkDestroyDescriptorPool"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005816 return (PFN_vkVoidFunction) vkDestroyDescriptorPool;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005817 if (!strcmp(funcName, "vkDestroyFramebuffer"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005818 return (PFN_vkVoidFunction) vkDestroyFramebuffer;
Tobin Ehlis60a9b4f2015-07-07 10:42:20 -06005819 if (!strcmp(funcName, "vkDestroyRenderPass"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005820 return (PFN_vkVoidFunction) vkDestroyRenderPass;
Tobin Ehlisa1c28562015-10-23 16:00:08 -06005821 if (!strcmp(funcName, "vkCreateBuffer"))
5822 return (PFN_vkVoidFunction) vkCreateBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005823 if (!strcmp(funcName, "vkCreateBufferView"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005824 return (PFN_vkVoidFunction) vkCreateBufferView;
Tobin Ehlisa1c28562015-10-23 16:00:08 -06005825 if (!strcmp(funcName, "vkCreateImage"))
5826 return (PFN_vkVoidFunction) vkCreateImage;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005827 if (!strcmp(funcName, "vkCreateImageView"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005828 return (PFN_vkVoidFunction) vkCreateImageView;
Jon Ashburnc669cc62015-07-09 15:02:25 -06005829 if (!strcmp(funcName, "CreatePipelineCache"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005830 return (PFN_vkVoidFunction) vkCreatePipelineCache;
Jon Ashburnc669cc62015-07-09 15:02:25 -06005831 if (!strcmp(funcName, "DestroyPipelineCache"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005832 return (PFN_vkVoidFunction) vkDestroyPipelineCache;
Jon Ashburnc669cc62015-07-09 15:02:25 -06005833 if (!strcmp(funcName, "GetPipelineCacheData"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005834 return (PFN_vkVoidFunction) vkGetPipelineCacheData;
Jon Ashburnc669cc62015-07-09 15:02:25 -06005835 if (!strcmp(funcName, "MergePipelineCaches"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005836 return (PFN_vkVoidFunction) vkMergePipelineCaches;
Jon Ashburnc669cc62015-07-09 15:02:25 -06005837 if (!strcmp(funcName, "vkCreateGraphicsPipelines"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005838 return (PFN_vkVoidFunction) vkCreateGraphicsPipelines;
Mark Lobodzinski475a2182015-11-10 15:25:01 -07005839 if (!strcmp(funcName, "vkCreateComputePipelines"))
5840 return (PFN_vkVoidFunction) vkCreateComputePipelines;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005841 if (!strcmp(funcName, "vkCreateSampler"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005842 return (PFN_vkVoidFunction) vkCreateSampler;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005843 if (!strcmp(funcName, "vkCreateDescriptorSetLayout"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005844 return (PFN_vkVoidFunction) vkCreateDescriptorSetLayout;
Mark Lobodzinski0fadf5f2015-04-17 14:11:39 -05005845 if (!strcmp(funcName, "vkCreatePipelineLayout"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005846 return (PFN_vkVoidFunction) vkCreatePipelineLayout;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005847 if (!strcmp(funcName, "vkCreateDescriptorPool"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005848 return (PFN_vkVoidFunction) vkCreateDescriptorPool;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005849 if (!strcmp(funcName, "vkResetDescriptorPool"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005850 return (PFN_vkVoidFunction) vkResetDescriptorPool;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005851 if (!strcmp(funcName, "vkAllocateDescriptorSets"))
5852 return (PFN_vkVoidFunction) vkAllocateDescriptorSets;
Tobin Ehlise735c692015-10-08 13:13:50 -06005853 if (!strcmp(funcName, "vkFreeDescriptorSets"))
5854 return (PFN_vkVoidFunction) vkFreeDescriptorSets;
Chia-I Wu9d00ed72015-05-25 16:27:55 +08005855 if (!strcmp(funcName, "vkUpdateDescriptorSets"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005856 return (PFN_vkVoidFunction) vkUpdateDescriptorSets;
Mark Lobodzinski39298632015-11-18 08:38:27 -07005857 if (!strcmp(funcName, "vkCreateCommandPool"))
5858 return (PFN_vkVoidFunction) vkCreateCommandPool;
5859 if (!strcmp(funcName, "vkDestroyCommandPool"))
5860 return (PFN_vkVoidFunction) vkDestroyCommandPool;
Tobin Ehlisac0ef842015-12-14 13:46:38 -07005861 if (!strcmp(funcName, "vkResetCommandPool"))
5862 return (PFN_vkVoidFunction) vkResetCommandPool;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08005863 if (!strcmp(funcName, "vkAllocateCommandBuffers"))
5864 return (PFN_vkVoidFunction) vkAllocateCommandBuffers;
Mark Lobodzinski39298632015-11-18 08:38:27 -07005865 if (!strcmp(funcName, "vkFreeCommandBuffers"))
5866 return (PFN_vkVoidFunction) vkFreeCommandBuffers;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005867 if (!strcmp(funcName, "vkBeginCommandBuffer"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005868 return (PFN_vkVoidFunction) vkBeginCommandBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005869 if (!strcmp(funcName, "vkEndCommandBuffer"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005870 return (PFN_vkVoidFunction) vkEndCommandBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005871 if (!strcmp(funcName, "vkResetCommandBuffer"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005872 return (PFN_vkVoidFunction) vkResetCommandBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005873 if (!strcmp(funcName, "vkCmdBindPipeline"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005874 return (PFN_vkVoidFunction) vkCmdBindPipeline;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005875 if (!strcmp(funcName, "vkCmdSetViewport"))
5876 return (PFN_vkVoidFunction) vkCmdSetViewport;
Courtney Goeltzenleuchter078f8172015-09-21 11:44:06 -06005877 if (!strcmp(funcName, "vkCmdSetScissor"))
5878 return (PFN_vkVoidFunction) vkCmdSetScissor;
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -06005879 if (!strcmp(funcName, "vkCmdSetLineWidth"))
5880 return (PFN_vkVoidFunction) vkCmdSetLineWidth;
5881 if (!strcmp(funcName, "vkCmdSetDepthBias"))
5882 return (PFN_vkVoidFunction) vkCmdSetDepthBias;
5883 if (!strcmp(funcName, "vkCmdSetBlendConstants"))
5884 return (PFN_vkVoidFunction) vkCmdSetBlendConstants;
5885 if (!strcmp(funcName, "vkCmdSetDepthBounds"))
5886 return (PFN_vkVoidFunction) vkCmdSetDepthBounds;
5887 if (!strcmp(funcName, "vkCmdSetStencilCompareMask"))
5888 return (PFN_vkVoidFunction) vkCmdSetStencilCompareMask;
5889 if (!strcmp(funcName, "vkCmdSetStencilWriteMask"))
5890 return (PFN_vkVoidFunction) vkCmdSetStencilWriteMask;
5891 if (!strcmp(funcName, "vkCmdSetStencilReference"))
5892 return (PFN_vkVoidFunction) vkCmdSetStencilReference;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005893 if (!strcmp(funcName, "vkCmdBindDescriptorSets"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005894 return (PFN_vkVoidFunction) vkCmdBindDescriptorSets;
Courtney Goeltzenleuchterf68ad722015-04-16 13:38:46 -06005895 if (!strcmp(funcName, "vkCmdBindVertexBuffers"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005896 return (PFN_vkVoidFunction) vkCmdBindVertexBuffers;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005897 if (!strcmp(funcName, "vkCmdBindIndexBuffer"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005898 return (PFN_vkVoidFunction) vkCmdBindIndexBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005899 if (!strcmp(funcName, "vkCmdDraw"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005900 return (PFN_vkVoidFunction) vkCmdDraw;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005901 if (!strcmp(funcName, "vkCmdDrawIndexed"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005902 return (PFN_vkVoidFunction) vkCmdDrawIndexed;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005903 if (!strcmp(funcName, "vkCmdDrawIndirect"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005904 return (PFN_vkVoidFunction) vkCmdDrawIndirect;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005905 if (!strcmp(funcName, "vkCmdDrawIndexedIndirect"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005906 return (PFN_vkVoidFunction) vkCmdDrawIndexedIndirect;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005907 if (!strcmp(funcName, "vkCmdDispatch"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005908 return (PFN_vkVoidFunction) vkCmdDispatch;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005909 if (!strcmp(funcName, "vkCmdDispatchIndirect"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005910 return (PFN_vkVoidFunction) vkCmdDispatchIndirect;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005911 if (!strcmp(funcName, "vkCmdCopyBuffer"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005912 return (PFN_vkVoidFunction) vkCmdCopyBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005913 if (!strcmp(funcName, "vkCmdCopyImage"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005914 return (PFN_vkVoidFunction) vkCmdCopyImage;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005915 if (!strcmp(funcName, "vkCmdCopyBufferToImage"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005916 return (PFN_vkVoidFunction) vkCmdCopyBufferToImage;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005917 if (!strcmp(funcName, "vkCmdCopyImageToBuffer"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005918 return (PFN_vkVoidFunction) vkCmdCopyImageToBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005919 if (!strcmp(funcName, "vkCmdUpdateBuffer"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005920 return (PFN_vkVoidFunction) vkCmdUpdateBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005921 if (!strcmp(funcName, "vkCmdFillBuffer"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005922 return (PFN_vkVoidFunction) vkCmdFillBuffer;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005923 if (!strcmp(funcName, "vkCmdClearColorImage"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005924 return (PFN_vkVoidFunction) vkCmdClearColorImage;
Chris Forbesd9be82b2015-06-22 17:21:59 +12005925 if (!strcmp(funcName, "vkCmdClearDepthStencilImage"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005926 return (PFN_vkVoidFunction) vkCmdClearDepthStencilImage;
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06005927 if (!strcmp(funcName, "vkCmdClearAttachments"))
5928 return (PFN_vkVoidFunction) vkCmdClearAttachments;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005929 if (!strcmp(funcName, "vkCmdResolveImage"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005930 return (PFN_vkVoidFunction) vkCmdResolveImage;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005931 if (!strcmp(funcName, "vkCmdSetEvent"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005932 return (PFN_vkVoidFunction) vkCmdSetEvent;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005933 if (!strcmp(funcName, "vkCmdResetEvent"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005934 return (PFN_vkVoidFunction) vkCmdResetEvent;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005935 if (!strcmp(funcName, "vkCmdWaitEvents"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005936 return (PFN_vkVoidFunction) vkCmdWaitEvents;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005937 if (!strcmp(funcName, "vkCmdPipelineBarrier"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005938 return (PFN_vkVoidFunction) vkCmdPipelineBarrier;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005939 if (!strcmp(funcName, "vkCmdBeginQuery"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005940 return (PFN_vkVoidFunction) vkCmdBeginQuery;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005941 if (!strcmp(funcName, "vkCmdEndQuery"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005942 return (PFN_vkVoidFunction) vkCmdEndQuery;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005943 if (!strcmp(funcName, "vkCmdResetQueryPool"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005944 return (PFN_vkVoidFunction) vkCmdResetQueryPool;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005945 if (!strcmp(funcName, "vkCmdWriteTimestamp"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005946 return (PFN_vkVoidFunction) vkCmdWriteTimestamp;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005947 if (!strcmp(funcName, "vkCreateFramebuffer"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005948 return (PFN_vkVoidFunction) vkCreateFramebuffer;
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07005949 if (!strcmp(funcName, "vkCreateShaderModule"))
5950 return (PFN_vkVoidFunction) vkCreateShaderModule;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005951 if (!strcmp(funcName, "vkCreateRenderPass"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005952 return (PFN_vkVoidFunction) vkCreateRenderPass;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005953 if (!strcmp(funcName, "vkCmdBeginRenderPass"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005954 return (PFN_vkVoidFunction) vkCmdBeginRenderPass;
Chia-I Wu08accc62015-07-07 11:50:03 +08005955 if (!strcmp(funcName, "vkCmdNextSubpass"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005956 return (PFN_vkVoidFunction) vkCmdNextSubpass;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06005957 if (!strcmp(funcName, "vkCmdEndRenderPass"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005958 return (PFN_vkVoidFunction) vkCmdEndRenderPass;
Tobin Ehlis4b34ddc2015-09-17 14:18:16 -06005959 if (!strcmp(funcName, "vkCmdExecuteCommands"))
5960 return (PFN_vkVoidFunction) vkCmdExecuteCommands;
Michael Lentine7b236262015-10-23 12:41:44 -07005961 if (!strcmp(funcName, "vkMapMemory"))
5962 return (PFN_vkVoidFunction) vkMapMemory;
Jon Ashburneab34492015-06-01 09:37:38 -06005963
Michael Lentineabc5e922015-10-12 11:30:14 -05005964 if (dev_data->device_extensions.wsi_enabled)
5965 {
5966 if (!strcmp(funcName, "vkCreateSwapchainKHR"))
5967 return (PFN_vkVoidFunction) vkCreateSwapchainKHR;
5968 if (!strcmp(funcName, "vkDestroySwapchainKHR"))
5969 return (PFN_vkVoidFunction) vkDestroySwapchainKHR;
5970 if (!strcmp(funcName, "vkGetSwapchainImagesKHR"))
5971 return (PFN_vkVoidFunction) vkGetSwapchainImagesKHR;
5972 if (!strcmp(funcName, "vkQueuePresentKHR"))
5973 return (PFN_vkVoidFunction) vkQueuePresentKHR;
5974 }
5975
Tobin Ehlis0b632332015-10-07 09:38:40 -06005976 VkLayerDispatchTable* pTable = dev_data->device_dispatch_table;
5977 if (dev_data->device_extensions.debug_marker_enabled)
Jon Ashburn8fd08252015-05-28 16:25:02 -06005978 {
Jon Ashburn747f2b62015-06-18 15:02:58 -06005979 if (!strcmp(funcName, "vkCmdDbgMarkerBegin"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005980 return (PFN_vkVoidFunction) vkCmdDbgMarkerBegin;
Jon Ashburn747f2b62015-06-18 15:02:58 -06005981 if (!strcmp(funcName, "vkCmdDbgMarkerEnd"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005982 return (PFN_vkVoidFunction) vkCmdDbgMarkerEnd;
Jon Ashburneab34492015-06-01 09:37:38 -06005983 }
5984 {
Jon Ashburn8fd08252015-05-28 16:25:02 -06005985 if (pTable->GetDeviceProcAddr == NULL)
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06005986 return NULL;
Jon Ashburn8fd08252015-05-28 16:25:02 -06005987 return pTable->GetDeviceProcAddr(dev, funcName);
Jon Ashburnf6b33db2015-05-05 14:22:52 -06005988 }
5989}
5990
Chia-I Wu9ab61502015-11-06 06:42:02 +08005991VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
Jon Ashburnf6b33db2015-05-05 14:22:52 -06005992{
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06005993 PFN_vkVoidFunction fptr;
Jon Ashburnf6b33db2015-05-05 14:22:52 -06005994 if (instance == NULL)
5995 return NULL;
5996
Tobin Ehlis0b632332015-10-07 09:38:40 -06005997 layer_data* my_data;
Jon Ashburn8fd08252015-05-28 16:25:02 -06005998 /* loader uses this to force layer initialization; instance object is wrapped */
5999 if (!strcmp(funcName, "vkGetInstanceProcAddr")) {
Tobin Ehlis0b632332015-10-07 09:38:40 -06006000 VkBaseLayerObject* wrapped_inst = (VkBaseLayerObject*) instance;
6001 my_data = get_my_data_ptr(get_dispatch_key(wrapped_inst->baseObject), layer_data_map);
Tobin Ehlisb212dfc2015-10-07 15:40:22 -06006002 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
6003 layer_init_instance_dispatch_table(my_data->instance_dispatch_table, wrapped_inst);
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06006004 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
Jon Ashburn8fd08252015-05-28 16:25:02 -06006005 }
Courtney Goeltzenleuchterabc035e2015-06-01 14:29:58 -06006006 if (!strcmp(funcName, "vkCreateInstance"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06006007 return (PFN_vkVoidFunction) vkCreateInstance;
Jon Ashburn3950e1b2015-05-20 09:00:28 -06006008 if (!strcmp(funcName, "vkDestroyInstance"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06006009 return (PFN_vkVoidFunction) vkDestroyInstance;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06006010 if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
6011 return (PFN_vkVoidFunction) vkEnumerateInstanceLayerProperties;
6012 if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
6013 return (PFN_vkVoidFunction) vkEnumerateInstanceExtensionProperties;
6014 if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
6015 return (PFN_vkVoidFunction) vkEnumerateDeviceLayerProperties;
6016 if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
6017 return (PFN_vkVoidFunction) vkEnumerateDeviceExtensionProperties;
Courtney Goeltzenleuchteree562872015-06-01 14:33:14 -06006018
Tobin Ehlis7e2ad752015-12-01 09:48:58 -07006019 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Tobin Ehlisa16e8922015-06-16 15:50:44 -06006020 fptr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
Courtney Goeltzenleuchteree562872015-06-01 14:33:14 -06006021 if (fptr)
6022 return fptr;
6023
Jon Ashburn8fd08252015-05-28 16:25:02 -06006024 {
Tobin Ehlis0b632332015-10-07 09:38:40 -06006025 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
Jon Ashburn8fd08252015-05-28 16:25:02 -06006026 if (pTable->GetInstanceProcAddr == NULL)
Jon Ashburnf6b33db2015-05-05 14:22:52 -06006027 return NULL;
Jon Ashburn8fd08252015-05-28 16:25:02 -06006028 return pTable->GetInstanceProcAddr(instance, funcName);
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006029 }
Tobin Ehlis10ae8c12015-03-17 16:24:32 -06006030}