blob: aa0153f362df505ae776a3c7bbee7e0d5d42e1cc [file] [log] [blame]
Chris Forbesaab9d112015-04-02 13:22:31 +13001/*
2 * Vulkan
3 *
4 * Copyright (C) 2015 LunarG, Inc.
5 *
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.
23 */
24#include <string.h>
25#include <stdlib.h>
26#include <assert.h>
Chris Forbes67cc36f2015-04-13 12:14:52 +120027#include <map>
Chris Forbesaab9d112015-04-02 13:22:31 +130028#include <unordered_map>
Chris Forbesbb164b62015-04-08 10:19:16 +120029#include <map>
Chris Forbes4396ff52015-04-08 10:11:59 +120030#include <vector>
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -060031#include <string>
Tobin Ehlis7a51d902015-07-03 10:34:49 -060032#include "vk_loader_platform.h"
Chris Forbesaab9d112015-04-02 13:22:31 +130033#include "vk_dispatch_table_helper.h"
Tobin Ehlis2d1d9702015-07-03 09:42:57 -060034#include "vk_layer.h"
Tobin Ehlis56d204a2015-07-03 10:15:26 -060035#include "vk_layer_config.h"
36#include "vk_layer_msg.h"
37#include "vk_layer_table.h"
Chris Forbes3317b382015-05-04 14:04:24 +120038#include "vk_enum_string_helper.h"
Chris Forbes5c75afe2015-04-17 10:13:28 +120039#include "shader_checker.h"
Chris Forbesaab9d112015-04-02 13:22:31 +130040// The following is #included again to catch certain OS-specific functions
41// being used:
Tobin Ehlis7a51d902015-07-03 10:34:49 -060042#include "vk_loader_platform.h"
Courtney Goeltzenleuchter7abf8e52015-07-07 10:05:05 -060043#include "vk_layer_extension_utils.h"
Chris Forbesaab9d112015-04-02 13:22:31 +130044
Chris Forbes32e3b462015-05-09 10:31:21 +120045#include "spirv/spirv.h"
Chris Forbesaab9d112015-04-02 13:22:31 +130046
Chris Forbesaab9d112015-04-02 13:22:31 +130047
Chris Forbes1b466bd2015-04-15 06:59:41 +120048static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(g_initOnce);
Chris Forbes1ed0f982015-05-29 14:55:18 +120049// TODO : This can be much smarter, using separate locks for separate global data
50static int globalLockInitialized = 0;
51static loader_platform_thread_mutex globalLock;
Chris Forbes4396ff52015-04-08 10:11:59 +120052
Chris Forbes1bb5a2e2015-04-10 11:41:20 +120053
54static void
55build_type_def_index(std::vector<unsigned> const &words, std::unordered_map<unsigned, unsigned> &type_def_index)
56{
57 unsigned int const *code = (unsigned int const *)&words[0];
58 size_t size = words.size();
59
60 unsigned word = 5;
61 while (word < size) {
62 unsigned opcode = code[word] & 0x0ffffu;
63 unsigned oplen = (code[word] & 0xffff0000u) >> 16;
64
65 switch (opcode) {
66 case spv::OpTypeVoid:
67 case spv::OpTypeBool:
68 case spv::OpTypeInt:
69 case spv::OpTypeFloat:
70 case spv::OpTypeVector:
71 case spv::OpTypeMatrix:
72 case spv::OpTypeSampler:
73 case spv::OpTypeFilter:
74 case spv::OpTypeArray:
75 case spv::OpTypeRuntimeArray:
76 case spv::OpTypeStruct:
77 case spv::OpTypeOpaque:
78 case spv::OpTypePointer:
79 case spv::OpTypeFunction:
80 case spv::OpTypeEvent:
81 case spv::OpTypeDeviceEvent:
82 case spv::OpTypeReserveId:
83 case spv::OpTypeQueue:
84 case spv::OpTypePipe:
85 type_def_index[code[word+1]] = word;
86 break;
87
88 default:
89 /* We only care about type definitions */
90 break;
91 }
92
93 word += oplen;
94 }
95}
96
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -060097struct shader_module {
Chris Forbes1bb5a2e2015-04-10 11:41:20 +120098 /* the spirv image itself */
Chris Forbes4396ff52015-04-08 10:11:59 +120099 std::vector<uint32_t> words;
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200100 /* a mapping of <id> to the first word of its def. this is useful because walking type
101 * trees requires jumping all over the instruction stream.
102 */
103 std::unordered_map<unsigned, unsigned> type_def_index;
Chris Forbes4453c772015-06-05 15:01:08 +1200104 bool is_spirv;
Chris Forbes4396ff52015-04-08 10:11:59 +1200105
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600106 shader_module(VkShaderModuleCreateInfo const *pCreateInfo) :
Chris Forbes4453c772015-06-05 15:01:08 +1200107 words((uint32_t *)pCreateInfo->pCode, (uint32_t *)pCreateInfo->pCode + pCreateInfo->codeSize / sizeof(uint32_t)),
108 type_def_index(),
109 is_spirv(true) {
110
111 if (words.size() < 5 || words[0] != spv::MagicNumber || words[1] != spv::Version) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600112 layerCbMsg(VK_DBG_REPORT_WARN_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_NON_SPIRV_SHADER, "SC",
Chris Forbes4453c772015-06-05 15:01:08 +1200113 "Shader is not SPIR-V, most checks will not be possible");
114 is_spirv = false;
115 return;
116 }
117
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200118
119 build_type_def_index(words, type_def_index);
Chris Forbes4396ff52015-04-08 10:11:59 +1200120 }
121};
122
123
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600124static std::unordered_map<void *, shader_module *> shader_module_map;
125
126struct shader_object {
127 std::string name;
128 struct shader_module *module;
129
130 shader_object(VkShaderCreateInfo const *pCreateInfo)
131 {
132 module = shader_module_map[pCreateInfo->module];
133 name = pCreateInfo->pName;
134 }
135};
136static std::unordered_map<void *, shader_object *> shader_object_map;
Chris Forbes4396ff52015-04-08 10:11:59 +1200137
138
Chris Forbes1b466bd2015-04-15 06:59:41 +1200139static void
140initLayer()
141{
142 const char *strOpt;
143 // initialize ShaderChecker options
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600144 getLayerOptionEnum("ShaderCheckerReportLevel", (uint32_t *) &g_reportFlags);
Chris Forbes1b466bd2015-04-15 06:59:41 +1200145 g_actionIsDefault = getLayerOptionEnum("ShaderCheckerDebugAction", (uint32_t *) &g_debugAction);
146
147 if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG)
148 {
149 strOpt = getLayerOption("ShaderCheckerLogFilename");
150 if (strOpt)
151 {
152 g_logFile = fopen(strOpt, "w");
153 }
154 if (g_logFile == NULL)
155 g_logFile = stdout;
156 }
157}
158
Courtney Goeltzenleuchter7abf8e52015-07-07 10:05:05 -0600159static const VkLayerProperties shader_checker_global_layers[] = {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600160 {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600161 "ShaderChecker",
Courtney Goeltzenleuchter7abf8e52015-07-07 10:05:05 -0600162 VK_API_VERSION,
163 VK_MAKE_VERSION(0, 1, 0),
164 "Validation layer: ShaderChecker",
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600165 }
Chris Forbesaab9d112015-04-02 13:22:31 +1300166};
167
Tony Barbour426b9052015-06-24 16:06:58 -0600168VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalExtensionProperties(
Courtney Goeltzenleuchter7abf8e52015-07-07 10:05:05 -0600169 const char *pLayerName,
170 uint32_t *pCount,
171 VkExtensionProperties* pProperties)
Chris Forbesaab9d112015-04-02 13:22:31 +1300172{
Courtney Goeltzenleuchter7abf8e52015-07-07 10:05:05 -0600173 /* shader checker does not have any global extensions */
174 return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Chris Forbesaab9d112015-04-02 13:22:31 +1300175}
176
Courtney Goeltzenleuchter7abf8e52015-07-07 10:05:05 -0600177VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalLayerProperties(
178 uint32_t *pCount,
179 VkLayerProperties* pProperties)
Tony Barbour426b9052015-06-24 16:06:58 -0600180{
Courtney Goeltzenleuchter7abf8e52015-07-07 10:05:05 -0600181 return util_GetLayerProperties(ARRAY_SIZE(shader_checker_global_layers),
182 shader_checker_global_layers,
183 pCount, pProperties);
Tony Barbour426b9052015-06-24 16:06:58 -0600184}
185
186VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionProperties(
Courtney Goeltzenleuchter7abf8e52015-07-07 10:05:05 -0600187 VkPhysicalDevice physicalDevice,
188 const char* pLayerName,
189 uint32_t* pCount,
190 VkExtensionProperties* pProperties)
Jon Ashburnade3bee2015-06-10 16:43:31 -0600191{
Courtney Goeltzenleuchter7abf8e52015-07-07 10:05:05 -0600192 /* Shader checker does not have any physical device extensions */
193 return util_GetExtensionProperties(0, NULL, pCount, pProperties);
194}
Jon Ashburnade3bee2015-06-10 16:43:31 -0600195
Courtney Goeltzenleuchter7abf8e52015-07-07 10:05:05 -0600196VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceLayerProperties(
197 VkPhysicalDevice physicalDevice,
198 uint32_t* pCount,
199 VkLayerProperties* pProperties)
200{
201 /* Shader checker physical device layers are the same as global */
202 return util_GetLayerProperties(ARRAY_SIZE(shader_checker_global_layers),
203 shader_checker_global_layers,
204 pCount, pProperties);
Jon Ashburnade3bee2015-06-10 16:43:31 -0600205}
Chris Forbesaab9d112015-04-02 13:22:31 +1300206
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200207static char const *
208storage_class_name(unsigned sc)
209{
210 switch (sc) {
Cody Northrop812b4612015-04-20 14:09:40 -0600211 case spv::StorageClassInput: return "input";
212 case spv::StorageClassOutput: return "output";
213 case spv::StorageClassUniformConstant: return "const uniform";
214 case spv::StorageClassUniform: return "uniform";
215 case spv::StorageClassWorkgroupLocal: return "workgroup local";
216 case spv::StorageClassWorkgroupGlobal: return "workgroup global";
217 case spv::StorageClassPrivateGlobal: return "private global";
218 case spv::StorageClassFunction: return "function";
219 case spv::StorageClassGeneric: return "generic";
220 case spv::StorageClassPrivate: return "private";
221 case spv::StorageClassAtomicCounter: return "atomic counter";
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200222 default: return "unknown";
223 }
224}
225
226
227/* returns ptr to null terminator */
228static char *
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600229describe_type(char *dst, shader_module const *src, unsigned type)
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200230{
231 auto type_def_it = src->type_def_index.find(type);
232
233 if (type_def_it == src->type_def_index.end()) {
234 return dst + sprintf(dst, "undef");
235 }
236
237 unsigned int const *code = (unsigned int const *)&src->words[type_def_it->second];
238 unsigned opcode = code[0] & 0x0ffffu;
239 switch (opcode) {
240 case spv::OpTypeBool:
241 return dst + sprintf(dst, "bool");
242 case spv::OpTypeInt:
243 return dst + sprintf(dst, "%cint%d", code[3] ? 's' : 'u', code[2]);
244 case spv::OpTypeFloat:
245 return dst + sprintf(dst, "float%d", code[2]);
246 case spv::OpTypeVector:
247 dst += sprintf(dst, "vec%d of ", code[3]);
248 return describe_type(dst, src, code[2]);
249 case spv::OpTypeMatrix:
250 dst += sprintf(dst, "mat%d of ", code[3]);
251 return describe_type(dst, src, code[2]);
252 case spv::OpTypeArray:
253 dst += sprintf(dst, "arr[%d] of ", code[3]);
254 return describe_type(dst, src, code[2]);
255 case spv::OpTypePointer:
256 dst += sprintf(dst, "ptr to %s ", storage_class_name(code[2]));
257 return describe_type(dst, src, code[3]);
258 case spv::OpTypeStruct:
259 {
260 unsigned oplen = code[0] >> 16;
261 dst += sprintf(dst, "struct of (");
Ian Elliottf21f14b2015-04-17 11:05:04 -0600262 for (unsigned i = 2; i < oplen; i++) {
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200263 dst = describe_type(dst, src, code[i]);
264 dst += sprintf(dst, i == oplen-1 ? ")" : ", ");
265 }
266 return dst;
267 }
268 default:
269 return dst + sprintf(dst, "oddtype");
270 }
271}
272
273
274static bool
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600275types_match(shader_module const *a, shader_module const *b, unsigned a_type, unsigned b_type, bool b_arrayed)
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200276{
277 auto a_type_def_it = a->type_def_index.find(a_type);
278 auto b_type_def_it = b->type_def_index.find(b_type);
279
280 if (a_type_def_it == a->type_def_index.end()) {
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200281 return false;
282 }
283
284 if (b_type_def_it == b->type_def_index.end()) {
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200285 return false;
286 }
287
288 /* walk two type trees together, and complain about differences */
289 unsigned int const *a_code = (unsigned int const *)&a->words[a_type_def_it->second];
290 unsigned int const *b_code = (unsigned int const *)&b->words[b_type_def_it->second];
291
292 unsigned a_opcode = a_code[0] & 0x0ffffu;
293 unsigned b_opcode = b_code[0] & 0x0ffffu;
294
Chris Forbes0a94a372015-06-05 14:57:05 +1200295 if (b_arrayed && b_opcode == spv::OpTypeArray) {
296 /* we probably just found the extra level of arrayness in b_type: compare the type inside it to a_type */
297 return types_match(a, b, a_type, b_code[2], false);
298 }
299
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200300 if (a_opcode != b_opcode) {
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200301 return false;
302 }
303
304 switch (a_opcode) {
Chris Forbes0a94a372015-06-05 14:57:05 +1200305 /* if b_arrayed and we hit a leaf type, then we can't match -- there's nowhere for the extra OpTypeArray to be! */
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200306 case spv::OpTypeBool:
Chris Forbes0a94a372015-06-05 14:57:05 +1200307 return true && !b_arrayed;
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200308 case spv::OpTypeInt:
309 /* match on width, signedness */
Chris Forbes0a94a372015-06-05 14:57:05 +1200310 return a_code[2] == b_code[2] && a_code[3] == b_code[3] && !b_arrayed;
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200311 case spv::OpTypeFloat:
312 /* match on width */
Chris Forbes0a94a372015-06-05 14:57:05 +1200313 return a_code[2] == b_code[2] && !b_arrayed;
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200314 case spv::OpTypeVector:
315 case spv::OpTypeMatrix:
316 case spv::OpTypeArray:
Chris Forbes0a94a372015-06-05 14:57:05 +1200317 /* match on element type, count. these all have the same layout. we don't get here if
318 * b_arrayed -- that is handled above. */
319 return !b_arrayed && types_match(a, b, a_code[2], b_code[2], b_arrayed) && a_code[3] == b_code[3];
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200320 case spv::OpTypeStruct:
321 /* match on all element types */
322 {
Chris Forbes0a94a372015-06-05 14:57:05 +1200323 if (b_arrayed) {
324 /* for the purposes of matching different levels of arrayness, structs are leaves. */
325 return false;
326 }
327
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200328 unsigned a_len = a_code[0] >> 16;
329 unsigned b_len = b_code[0] >> 16;
330
331 if (a_len != b_len) {
332 return false; /* structs cannot match if member counts differ */
333 }
334
Ian Elliottf21f14b2015-04-17 11:05:04 -0600335 for (unsigned i = 2; i < a_len; i++) {
Chris Forbes0a94a372015-06-05 14:57:05 +1200336 if (!types_match(a, b, a_code[i], b_code[i], b_arrayed)) {
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200337 return false;
338 }
339 }
340
341 return true;
342 }
343 case spv::OpTypePointer:
344 /* match on pointee type. storage class is expected to differ */
Chris Forbes0a94a372015-06-05 14:57:05 +1200345 return types_match(a, b, a_code[3], b_code[3], b_arrayed);
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200346
347 default:
348 /* remaining types are CLisms, or may not appear in the interfaces we
349 * are interested in. Just claim no match.
350 */
351 return false;
352
353 }
354}
355
356
Chris Forbes67cc36f2015-04-13 12:14:52 +1200357static int
358value_or_default(std::unordered_map<unsigned, unsigned> const &map, unsigned id, int def)
359{
360 auto it = map.find(id);
361 if (it == map.end())
362 return def;
363 else
364 return it->second;
365}
366
367
368struct interface_var {
369 uint32_t id;
370 uint32_t type_id;
371 /* TODO: collect the name, too? Isn't required to be present. */
372};
373
374
375static void
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600376collect_interface_by_location(shader_module const *src, spv::StorageClass sinterface,
Chris Forbes67cc36f2015-04-13 12:14:52 +1200377 std::map<uint32_t, interface_var> &out,
378 std::map<uint32_t, interface_var> &builtins_out)
379{
380 unsigned int const *code = (unsigned int const *)&src->words[0];
381 size_t size = src->words.size();
382
Chris Forbes67cc36f2015-04-13 12:14:52 +1200383 std::unordered_map<unsigned, unsigned> var_locations;
384 std::unordered_map<unsigned, unsigned> var_builtins;
385
386 unsigned word = 5;
387 while (word < size) {
388
389 unsigned opcode = code[word] & 0x0ffffu;
390 unsigned oplen = (code[word] & 0xffff0000u) >> 16;
391
392 /* We consider two interface models: SSO rendezvous-by-location, and
393 * builtins. Complain about anything that fits neither model.
394 */
395 if (opcode == spv::OpDecorate) {
Cody Northrop812b4612015-04-20 14:09:40 -0600396 if (code[word+2] == spv::DecorationLocation) {
Chris Forbes67cc36f2015-04-13 12:14:52 +1200397 var_locations[code[word+1]] = code[word+3];
398 }
399
Cody Northrop812b4612015-04-20 14:09:40 -0600400 if (code[word+2] == spv::DecorationBuiltIn) {
Chris Forbes67cc36f2015-04-13 12:14:52 +1200401 var_builtins[code[word+1]] = code[word+3];
402 }
403 }
404
405 /* TODO: handle grouped decorations */
406 /* TODO: handle index=1 dual source outputs from FS -- two vars will
407 * have the same location, and we DONT want to clobber. */
408
Ian Elliottf21f14b2015-04-17 11:05:04 -0600409 if (opcode == spv::OpVariable && code[word+3] == sinterface) {
Chris Forbes67cc36f2015-04-13 12:14:52 +1200410 int location = value_or_default(var_locations, code[word+2], -1);
411 int builtin = value_or_default(var_builtins, code[word+2], -1);
412
413 if (location == -1 && builtin == -1) {
414 /* No location defined, and not bound to an API builtin.
415 * The spec says nothing about how this case works (or doesn't)
416 * for interface matching.
417 */
Chris Forbes5c75afe2015-04-17 10:13:28 +1200418 char str[1024];
419 sprintf(str, "var %d (type %d) in %s interface has no Location or Builtin decoration\n",
Ian Elliottf21f14b2015-04-17 11:05:04 -0600420 code[word+2], code[word+1], storage_class_name(sinterface));
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600421 layerCbMsg(VK_DBG_REPORT_WARN_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_INCONSISTENT_SPIRV, "SC", str);
Chris Forbes67cc36f2015-04-13 12:14:52 +1200422 }
423 else if (location != -1) {
424 /* A user-defined interface variable, with a location. */
425 interface_var v;
426 v.id = code[word+2];
427 v.type_id = code[word+1];
428 out[location] = v;
429 }
430 else {
431 /* A builtin interface variable */
432 interface_var v;
433 v.id = code[word+2];
434 v.type_id = code[word+1];
435 builtins_out[builtin] = v;
436 }
437 }
438
439 word += oplen;
440 }
441}
442
443
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600444VK_LAYER_EXPORT VkResult VKAPI vkCreateShaderModule(
445 VkDevice device,
446 const VkShaderModuleCreateInfo *pCreateInfo,
447 VkShaderModule *pShaderModule)
Chris Forbesaab9d112015-04-02 13:22:31 +1300448{
Chris Forbes1ed0f982015-05-29 14:55:18 +1200449 loader_platform_thread_lock_mutex(&globalLock);
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600450 VkResult res = device_dispatch_table(device)->CreateShaderModule(device, pCreateInfo, pShaderModule);
Chris Forbes4396ff52015-04-08 10:11:59 +1200451
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600452 shader_module_map[(VkBaseLayerObject *) *pShaderModule] = new shader_module(pCreateInfo);
Chris Forbes1ed0f982015-05-29 14:55:18 +1200453 loader_platform_thread_unlock_mutex(&globalLock);
Chris Forbesaab9d112015-04-02 13:22:31 +1300454 return res;
455}
456
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600457VK_LAYER_EXPORT VkResult VKAPI vkCreateShader(
458 VkDevice device,
459 const VkShaderCreateInfo *pCreateInfo,
460 VkShader *pShader)
461{
462 loader_platform_thread_lock_mutex(&globalLock);
463 VkResult res = device_dispatch_table(device)->CreateShader(device, pCreateInfo, pShader);
464
465 shader_object_map[(VkBaseLayerObject *) *pShader] = new shader_object(pCreateInfo);
466 loader_platform_thread_unlock_mutex(&globalLock);
467 return res;
468}
Chris Forbesaab9d112015-04-02 13:22:31 +1300469
Chris Forbes5f362d02015-05-25 11:13:22 +1200470static bool
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600471validate_interface_between_stages(shader_module const *producer, char const *producer_name,
472 shader_module const *consumer, char const *consumer_name,
Chris Forbes4453c772015-06-05 15:01:08 +1200473 bool consumer_arrayed_input)
Chris Forbesbb164b62015-04-08 10:19:16 +1200474{
475 std::map<uint32_t, interface_var> outputs;
476 std::map<uint32_t, interface_var> inputs;
477
478 std::map<uint32_t, interface_var> builtin_outputs;
479 std::map<uint32_t, interface_var> builtin_inputs;
480
Chris Forbes5c75afe2015-04-17 10:13:28 +1200481 char str[1024];
Chris Forbes5f362d02015-05-25 11:13:22 +1200482 bool pass = true;
Chris Forbesbb164b62015-04-08 10:19:16 +1200483
Cody Northrop812b4612015-04-20 14:09:40 -0600484 collect_interface_by_location(producer, spv::StorageClassOutput, outputs, builtin_outputs);
485 collect_interface_by_location(consumer, spv::StorageClassInput, inputs, builtin_inputs);
Chris Forbesbb164b62015-04-08 10:19:16 +1200486
487 auto a_it = outputs.begin();
488 auto b_it = inputs.begin();
489
490 /* maps sorted by key (location); walk them together to find mismatches */
David Pinedof5997ab2015-04-27 16:36:17 -0600491 while ((outputs.size() > 0 && a_it != outputs.end()) || ( inputs.size() && b_it != inputs.end())) {
492 bool a_at_end = outputs.size() == 0 || a_it == outputs.end();
493 bool b_at_end = inputs.size() == 0 || b_it == inputs.end();
Chris Forbes4cb97672015-06-10 08:37:27 +1200494 auto a_first = a_at_end ? 0 : a_it->first;
495 auto b_first = b_at_end ? 0 : b_it->first;
David Pinedof5997ab2015-04-27 16:36:17 -0600496
497 if (b_at_end || a_first < b_first) {
Chris Forbes5c75afe2015-04-17 10:13:28 +1200498 sprintf(str, "%s writes to output location %d which is not consumed by %s\n",
David Pinedof5997ab2015-04-27 16:36:17 -0600499 producer_name, a_first, consumer_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600500 layerCbMsg(VK_DBG_REPORT_WARN_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", str);
Chris Forbesbb164b62015-04-08 10:19:16 +1200501 a_it++;
502 }
David Pinedof5997ab2015-04-27 16:36:17 -0600503 else if (a_at_end || a_first > b_first) {
Chris Forbes5c75afe2015-04-17 10:13:28 +1200504 sprintf(str, "%s consumes input location %d which is not written by %s\n",
David Pinedof5997ab2015-04-27 16:36:17 -0600505 consumer_name, b_first, producer_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600506 layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", str);
Chris Forbes5f362d02015-05-25 11:13:22 +1200507 pass = false;
Chris Forbesbb164b62015-04-08 10:19:16 +1200508 b_it++;
509 }
510 else {
Chris Forbes4453c772015-06-05 15:01:08 +1200511 if (types_match(producer, consumer, a_it->second.type_id, b_it->second.type_id, consumer_arrayed_input)) {
Chris Forbes5c75afe2015-04-17 10:13:28 +1200512 /* OK! */
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200513 }
514 else {
515 char producer_type[1024];
516 char consumer_type[1024];
517 describe_type(producer_type, producer, a_it->second.type_id);
518 describe_type(consumer_type, consumer, b_it->second.type_id);
519
Chris Forbes5c75afe2015-04-17 10:13:28 +1200520 sprintf(str, "Type mismatch on location %d: '%s' vs '%s'\n", a_it->first,
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200521 producer_type, consumer_type);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600522 layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", str);
Chris Forbes5f362d02015-05-25 11:13:22 +1200523 pass = false;
Chris Forbes1bb5a2e2015-04-10 11:41:20 +1200524 }
Chris Forbesbb164b62015-04-08 10:19:16 +1200525 a_it++;
526 b_it++;
527 }
528 }
Chris Forbes5f362d02015-05-25 11:13:22 +1200529
530 return pass;
Chris Forbesbb164b62015-04-08 10:19:16 +1200531}
532
533
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200534enum FORMAT_TYPE {
535 FORMAT_TYPE_UNDEFINED,
536 FORMAT_TYPE_FLOAT, /* UNORM, SNORM, FLOAT, USCALED, SSCALED, SRGB -- anything we consider float in the shader */
537 FORMAT_TYPE_SINT,
538 FORMAT_TYPE_UINT,
539};
540
541
542static unsigned
543get_format_type(VkFormat fmt) {
544 switch (fmt) {
Chia-I Wu6097f3a2015-04-17 02:00:54 +0800545 case VK_FORMAT_UNDEFINED:
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200546 return FORMAT_TYPE_UNDEFINED;
Chia-I Wu6097f3a2015-04-17 02:00:54 +0800547 case VK_FORMAT_R8_SINT:
548 case VK_FORMAT_R8G8_SINT:
549 case VK_FORMAT_R8G8B8_SINT:
550 case VK_FORMAT_R8G8B8A8_SINT:
551 case VK_FORMAT_R16_SINT:
552 case VK_FORMAT_R16G16_SINT:
553 case VK_FORMAT_R16G16B16_SINT:
554 case VK_FORMAT_R16G16B16A16_SINT:
555 case VK_FORMAT_R32_SINT:
556 case VK_FORMAT_R32G32_SINT:
557 case VK_FORMAT_R32G32B32_SINT:
558 case VK_FORMAT_R32G32B32A32_SINT:
559 case VK_FORMAT_B8G8R8_SINT:
560 case VK_FORMAT_B8G8R8A8_SINT:
561 case VK_FORMAT_R10G10B10A2_SINT:
562 case VK_FORMAT_B10G10R10A2_SINT:
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200563 return FORMAT_TYPE_SINT;
Chia-I Wu6097f3a2015-04-17 02:00:54 +0800564 case VK_FORMAT_R8_UINT:
565 case VK_FORMAT_R8G8_UINT:
566 case VK_FORMAT_R8G8B8_UINT:
567 case VK_FORMAT_R8G8B8A8_UINT:
568 case VK_FORMAT_R16_UINT:
569 case VK_FORMAT_R16G16_UINT:
570 case VK_FORMAT_R16G16B16_UINT:
571 case VK_FORMAT_R16G16B16A16_UINT:
572 case VK_FORMAT_R32_UINT:
573 case VK_FORMAT_R32G32_UINT:
574 case VK_FORMAT_R32G32B32_UINT:
575 case VK_FORMAT_R32G32B32A32_UINT:
576 case VK_FORMAT_B8G8R8_UINT:
577 case VK_FORMAT_B8G8R8A8_UINT:
578 case VK_FORMAT_R10G10B10A2_UINT:
579 case VK_FORMAT_B10G10R10A2_UINT:
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200580 return FORMAT_TYPE_UINT;
581 default:
582 return FORMAT_TYPE_FLOAT;
583 }
584}
585
586
Chris Forbes28c50882015-05-04 14:04:06 +1200587/* characterizes a SPIR-V type appearing in an interface to a FF stage,
588 * for comparison to a VkFormat's characterization above. */
589static unsigned
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600590get_fundamental_type(shader_module const *src, unsigned type)
Chris Forbes28c50882015-05-04 14:04:06 +1200591{
592 auto type_def_it = src->type_def_index.find(type);
593
594 if (type_def_it == src->type_def_index.end()) {
595 return FORMAT_TYPE_UNDEFINED;
596 }
597
598 unsigned int const *code = (unsigned int const *)&src->words[type_def_it->second];
599 unsigned opcode = code[0] & 0x0ffffu;
600 switch (opcode) {
601 case spv::OpTypeInt:
602 return code[3] ? FORMAT_TYPE_SINT : FORMAT_TYPE_UINT;
603 case spv::OpTypeFloat:
604 return FORMAT_TYPE_FLOAT;
605 case spv::OpTypeVector:
606 return get_fundamental_type(src, code[2]);
607 case spv::OpTypeMatrix:
608 return get_fundamental_type(src, code[2]);
609 case spv::OpTypeArray:
610 return get_fundamental_type(src, code[2]);
611 case spv::OpTypePointer:
612 return get_fundamental_type(src, code[3]);
613 default:
614 return FORMAT_TYPE_UNDEFINED;
615 }
616}
617
618
Chris Forbes5f362d02015-05-25 11:13:22 +1200619static bool
Mark Lobodzinski0e0fb5c2015-06-23 15:11:57 -0600620validate_vi_consistency(VkPipelineVertexInputStateCreateInfo const *vi)
Chris Forbes0bf8fe12015-06-12 11:16:41 +1200621{
622 /* walk the binding descriptions, which describe the step rate and stride of each vertex buffer.
623 * each binding should be specified only once.
624 */
625 std::unordered_map<uint32_t, VkVertexInputBindingDescription const *> bindings;
626 char str[1024];
627 bool pass = true;
628
629 for (unsigned i = 0; i < vi->bindingCount; i++) {
630 auto desc = &vi->pVertexBindingDescriptions[i];
631 auto & binding = bindings[desc->binding];
632 if (binding) {
633 sprintf(str, "Duplicate vertex input binding descriptions for binding %d", desc->binding);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600634 layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_INCONSISTENT_VI, "SC", str);
Chris Forbes0bf8fe12015-06-12 11:16:41 +1200635 pass = false;
636 }
637 else {
638 binding = desc;
639 }
640 }
641
642 return pass;
643}
644
645
646static bool
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600647validate_vi_against_vs_inputs(VkPipelineVertexInputStateCreateInfo const *vi, shader_module const *vs)
Chris Forbesfcd05f12015-04-08 10:36:37 +1200648{
649 std::map<uint32_t, interface_var> inputs;
650 /* we collect builtin inputs, but they will never appear in the VI state --
651 * the vs builtin inputs are generated in the pipeline, not sourced from buffers (VertexID, etc)
652 */
653 std::map<uint32_t, interface_var> builtin_inputs;
Chris Forbes5c75afe2015-04-17 10:13:28 +1200654 char str[1024];
Chris Forbes5f362d02015-05-25 11:13:22 +1200655 bool pass = true;
Chris Forbesfcd05f12015-04-08 10:36:37 +1200656
Cody Northrop812b4612015-04-20 14:09:40 -0600657 collect_interface_by_location(vs, spv::StorageClassInput, inputs, builtin_inputs);
Chris Forbesfcd05f12015-04-08 10:36:37 +1200658
659 /* Build index by location */
660 std::map<uint32_t, VkVertexInputAttributeDescription const *> attribs;
Chris Forbes6f2ab982015-05-25 11:13:24 +1200661 if (vi) {
662 for (unsigned i = 0; i < vi->attributeCount; i++)
663 attribs[vi->pVertexAttributeDescriptions[i].location] = &vi->pVertexAttributeDescriptions[i];
664 }
Chris Forbesfcd05f12015-04-08 10:36:37 +1200665
666 auto it_a = attribs.begin();
667 auto it_b = inputs.begin();
668
David Pinedof5997ab2015-04-27 16:36:17 -0600669 while ((attribs.size() > 0 && it_a != attribs.end()) || (inputs.size() > 0 && it_b != inputs.end())) {
670 bool a_at_end = attribs.size() == 0 || it_a == attribs.end();
671 bool b_at_end = inputs.size() == 0 || it_b == inputs.end();
Chris Forbes4cb97672015-06-10 08:37:27 +1200672 auto a_first = a_at_end ? 0 : it_a->first;
673 auto b_first = b_at_end ? 0 : it_b->first;
David Pinedof5997ab2015-04-27 16:36:17 -0600674 if (b_at_end || a_first < b_first) {
675 sprintf(str, "Vertex attribute at location %d not consumed by VS", a_first);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600676 layerCbMsg(VK_DBG_REPORT_WARN_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", str);
Chris Forbesfcd05f12015-04-08 10:36:37 +1200677 it_a++;
678 }
David Pinedof5997ab2015-04-27 16:36:17 -0600679 else if (a_at_end || b_first < a_first) {
680 sprintf(str, "VS consumes input at location %d but not provided", b_first);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600681 layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", str);
Chris Forbes5f362d02015-05-25 11:13:22 +1200682 pass = false;
Chris Forbesfcd05f12015-04-08 10:36:37 +1200683 it_b++;
684 }
685 else {
Chris Forbes3317b382015-05-04 14:04:24 +1200686 unsigned attrib_type = get_format_type(it_a->second->format);
687 unsigned input_type = get_fundamental_type(vs, it_b->second.type_id);
688
689 /* type checking */
690 if (attrib_type != FORMAT_TYPE_UNDEFINED && input_type != FORMAT_TYPE_UNDEFINED && attrib_type != input_type) {
691 char vs_type[1024];
692 describe_type(vs_type, vs, it_b->second.type_id);
693 sprintf(str, "Attribute type of `%s` at location %d does not match VS input type of `%s`",
694 string_VkFormat(it_a->second->format), a_first, vs_type);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600695 layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", str);
Chris Forbes5f362d02015-05-25 11:13:22 +1200696 pass = false;
Chris Forbes3317b382015-05-04 14:04:24 +1200697 }
698
Chris Forbes5c75afe2015-04-17 10:13:28 +1200699 /* OK! */
Chris Forbesfcd05f12015-04-08 10:36:37 +1200700 it_a++;
701 it_b++;
702 }
703 }
Chris Forbes5f362d02015-05-25 11:13:22 +1200704
705 return pass;
Chris Forbesfcd05f12015-04-08 10:36:37 +1200706}
707
708
Chris Forbes5f362d02015-05-25 11:13:22 +1200709static bool
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600710validate_fs_outputs_against_cb(shader_module const *fs, VkPipelineCbStateCreateInfo const *cb)
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200711{
712 std::map<uint32_t, interface_var> outputs;
713 std::map<uint32_t, interface_var> builtin_outputs;
Chris Forbes5c75afe2015-04-17 10:13:28 +1200714 char str[1024];
Chris Forbes5f362d02015-05-25 11:13:22 +1200715 bool pass = true;
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200716
717 /* TODO: dual source blend index (spv::DecIndex, zero if not provided) */
718
Cody Northrop812b4612015-04-20 14:09:40 -0600719 collect_interface_by_location(fs, spv::StorageClassOutput, outputs, builtin_outputs);
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200720
721 /* Check for legacy gl_FragColor broadcast: In this case, we should have no user-defined outputs,
722 * and all color attachment should be UNORM/SNORM/FLOAT.
723 */
724 if (builtin_outputs.find(spv::BuiltInFragColor) != builtin_outputs.end()) {
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200725 if (outputs.size()) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600726 layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_FS_MIXED_BROADCAST, "SC",
Chris Forbes5c75afe2015-04-17 10:13:28 +1200727 "Should not have user-defined FS outputs when using broadcast");
Chris Forbes5f362d02015-05-25 11:13:22 +1200728 pass = false;
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200729 }
730
Ian Elliottf21f14b2015-04-17 11:05:04 -0600731 for (unsigned i = 0; i < cb->attachmentCount; i++) {
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200732 unsigned attachmentType = get_format_type(cb->pAttachments[i].format);
733 if (attachmentType == FORMAT_TYPE_SINT || attachmentType == FORMAT_TYPE_UINT) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600734 layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC",
Chris Forbes5c75afe2015-04-17 10:13:28 +1200735 "CB format should not be SINT or UINT when using broadcast");
Chris Forbes5f362d02015-05-25 11:13:22 +1200736 pass = false;
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200737 }
738 }
739
Chris Forbes5f362d02015-05-25 11:13:22 +1200740 return pass;
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200741 }
742
743 auto it = outputs.begin();
744 uint32_t attachment = 0;
745
746 /* Walk attachment list and outputs together -- this is a little overpowered since attachments
747 * are currently dense, but the parallel with matching between shader stages is nice.
748 */
749
Chris Forbes8802c992015-05-05 11:34:14 +1200750 while ((outputs.size() > 0 && it != outputs.end()) || attachment < cb->attachmentCount) {
scygan7a62cbe2015-06-01 19:48:11 +0200751 if (attachment == cb->attachmentCount || ( it != outputs.end() && it->first < attachment)) {
Chris Forbes5c75afe2015-04-17 10:13:28 +1200752 sprintf(str, "FS writes to output location %d with no matching attachment", it->first);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600753 layerCbMsg(VK_DBG_REPORT_WARN_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", str);
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200754 it++;
755 }
756 else if (it == outputs.end() || it->first > attachment) {
Chris Forbes5c75afe2015-04-17 10:13:28 +1200757 sprintf(str, "Attachment %d not written by FS", attachment);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600758 layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", str);
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200759 attachment++;
Chris Forbes5f362d02015-05-25 11:13:22 +1200760 pass = false;
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200761 }
762 else {
Chris Forbes4b009002015-05-04 14:20:10 +1200763 unsigned output_type = get_fundamental_type(fs, it->second.type_id);
764 unsigned att_type = get_format_type(cb->pAttachments[attachment].format);
765
766 /* type checking */
767 if (att_type != FORMAT_TYPE_UNDEFINED && output_type != FORMAT_TYPE_UNDEFINED && att_type != output_type) {
768 char fs_type[1024];
769 describe_type(fs_type, fs, it->second.type_id);
770 sprintf(str, "Attachment %d of type `%s` does not match FS output type of `%s`",
771 attachment, string_VkFormat(cb->pAttachments[attachment].format), fs_type);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600772 layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", str);
Chris Forbes5f362d02015-05-25 11:13:22 +1200773 pass = false;
Chris Forbes4b009002015-05-04 14:20:10 +1200774 }
775
Chris Forbes5c75afe2015-04-17 10:13:28 +1200776 /* OK! */
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200777 it++;
778 attachment++;
779 }
780 }
Chris Forbes5f362d02015-05-25 11:13:22 +1200781
782 return pass;
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200783}
784
785
Chris Forbes4453c772015-06-05 15:01:08 +1200786struct shader_stage_attributes {
787 char const * const name;
788 bool arrayed_input;
789};
790
791
792static shader_stage_attributes
793shader_stage_attribs[VK_SHADER_STAGE_FRAGMENT + 1] = {
794 { "vertex shader", false },
795 { "tessellation control shader", true },
796 { "tessellation evaluation shader", false },
797 { "geometry shader", true },
798 { "fragment shader", false },
799};
800
801
Chris Forbesf1060ca2015-06-04 20:23:00 +1200802static bool
803validate_graphics_pipeline(VkGraphicsPipelineCreateInfo const *pCreateInfo)
Chris Forbes60540932015-04-08 10:15:35 +1200804{
Chris Forbes8f600932015-04-08 10:16:45 +1200805 /* We seem to allow pipeline stages to be specified out of order, so collect and identify them
806 * before trying to do anything more: */
807
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600808 shader_module const *shaders[VK_SHADER_STAGE_FRAGMENT + 1]; /* exclude CS */
Chris Forbes4453c772015-06-05 15:01:08 +1200809 memset(shaders, 0, sizeof(shaders));
Chris Forbes8f600932015-04-08 10:16:45 +1200810 VkPipelineCbStateCreateInfo const *cb = 0;
Mark Lobodzinski0e0fb5c2015-06-23 15:11:57 -0600811 VkPipelineVertexInputStateCreateInfo const *vi = 0;
Chris Forbes5c75afe2015-04-17 10:13:28 +1200812 char str[1024];
Chris Forbes5f362d02015-05-25 11:13:22 +1200813 bool pass = true;
Chris Forbes8f600932015-04-08 10:16:45 +1200814
Chris Forbes1ed0f982015-05-29 14:55:18 +1200815 loader_platform_thread_lock_mutex(&globalLock);
816
Mark Lobodzinski0e0fb5c2015-06-23 15:11:57 -0600817 for (auto i = 0; i < pCreateInfo->stageCount; i++) {
818 VkPipelineShaderStageCreateInfo const *pStage = &pCreateInfo->pStages[i];
819 if (pStage->sType == VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO) {
Chris Forbes8f600932015-04-08 10:16:45 +1200820
Mark Lobodzinski0e0fb5c2015-06-23 15:11:57 -0600821 if (pStage->stage < VK_SHADER_STAGE_VERTEX || pStage->stage > VK_SHADER_STAGE_FRAGMENT) {
822 sprintf(str, "Unknown shader stage %d\n", pStage->stage);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600823 layerCbMsg(VK_DBG_REPORT_WARN_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_UNKNOWN_STAGE, "SC", str);
Chris Forbes5c75afe2015-04-17 10:13:28 +1200824 }
Chris Forbes4453c772015-06-05 15:01:08 +1200825 else {
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600826 struct shader_object *shader = shader_object_map[(void *) pStage->shader];
827 shaders[pStage->stage] = shader->module;
Chris Forbes4453c772015-06-05 15:01:08 +1200828 }
Chris Forbes8f600932015-04-08 10:16:45 +1200829 }
Chris Forbes8f600932015-04-08 10:16:45 +1200830 }
831
Mark Lobodzinski0e0fb5c2015-06-23 15:11:57 -0600832 cb = pCreateInfo->pCbState;
833 vi = pCreateInfo->pVertexInputState;
834
Chris Forbes0bf8fe12015-06-12 11:16:41 +1200835 if (vi) {
836 pass = validate_vi_consistency(vi) && pass;
837 }
838
Chris Forbes4453c772015-06-05 15:01:08 +1200839 if (shaders[VK_SHADER_STAGE_VERTEX] && shaders[VK_SHADER_STAGE_VERTEX]->is_spirv) {
840 pass = validate_vi_against_vs_inputs(vi, shaders[VK_SHADER_STAGE_VERTEX]) && pass;
Chris Forbesfcd05f12015-04-08 10:36:37 +1200841 }
842
Chris Forbes4453c772015-06-05 15:01:08 +1200843 /* TODO: enforce rules about present combinations of shaders */
844 int producer = VK_SHADER_STAGE_VERTEX;
845 int consumer = VK_SHADER_STAGE_GEOMETRY;
846
847 while (!shaders[producer] && producer != VK_SHADER_STAGE_FRAGMENT) {
848 producer++;
849 consumer++;
Chris Forbesbb164b62015-04-08 10:19:16 +1200850 }
851
Tony Barbour4eb3cd12015-06-11 15:04:25 -0600852 for (; producer != VK_SHADER_STAGE_FRAGMENT && consumer <= VK_SHADER_STAGE_FRAGMENT; consumer++) {
Chris Forbes4453c772015-06-05 15:01:08 +1200853 assert(shaders[producer]);
854 if (shaders[consumer]) {
855 if (shaders[producer]->is_spirv && shaders[consumer]->is_spirv) {
856 pass = validate_interface_between_stages(shaders[producer], shader_stage_attribs[producer].name,
857 shaders[consumer], shader_stage_attribs[consumer].name,
858 shader_stage_attribs[consumer].arrayed_input) && pass;
859 }
860
861 producer = consumer;
862 }
863 }
864
865 if (shaders[VK_SHADER_STAGE_FRAGMENT] && shaders[VK_SHADER_STAGE_FRAGMENT]->is_spirv && cb) {
866 pass = validate_fs_outputs_against_cb(shaders[VK_SHADER_STAGE_FRAGMENT], cb) && pass;
Chris Forbes9b9f5fe2015-04-08 10:37:20 +1200867 }
868
Chris Forbes1ed0f982015-05-29 14:55:18 +1200869 loader_platform_thread_unlock_mutex(&globalLock);
Chris Forbesf1060ca2015-06-04 20:23:00 +1200870 return pass;
871}
872
873
Chris Forbesd0f7f7c2015-06-04 20:27:09 +1200874VK_LAYER_EXPORT VkResult VKAPI
875vkCreateGraphicsPipeline(VkDevice device,
876 const VkGraphicsPipelineCreateInfo *pCreateInfo,
877 VkPipeline *pPipeline)
Chris Forbesf1060ca2015-06-04 20:23:00 +1200878{
879 bool pass = validate_graphics_pipeline(pCreateInfo);
Chris Forbes5f362d02015-05-25 11:13:22 +1200880
881 if (pass) {
882 /* The driver is allowed to crash if passed junk. Only actually create the
883 * pipeline if we didn't run into any showstoppers above.
884 */
Jon Ashburn5a10d212015-06-01 10:02:09 -0600885 return device_dispatch_table(device)->CreateGraphicsPipeline(device, pCreateInfo, pPipeline);
Chris Forbes5f362d02015-05-25 11:13:22 +1200886 }
887 else {
888 return VK_ERROR_UNKNOWN;
889 }
Chris Forbes60540932015-04-08 10:15:35 +1200890}
891
892
Chris Forbesd0f7f7c2015-06-04 20:27:09 +1200893VK_LAYER_EXPORT VkResult VKAPI
894vkCreateGraphicsPipelineDerivative(VkDevice device,
895 const VkGraphicsPipelineCreateInfo *pCreateInfo,
896 VkPipeline basePipeline,
897 VkPipeline *pPipeline)
898{
899 bool pass = validate_graphics_pipeline(pCreateInfo);
900
901 if (pass) {
902 /* The driver is allowed to crash if passed junk. Only actually create the
903 * pipeline if we didn't run into any showstoppers above.
904 */
Jon Ashburn5a10d212015-06-01 10:02:09 -0600905 return device_dispatch_table(device)->CreateGraphicsPipelineDerivative(device, pCreateInfo, basePipeline, pPipeline);
Chris Forbesd0f7f7c2015-06-04 20:27:09 +1200906 }
907 else {
908 return VK_ERROR_UNKNOWN;
909 }
910}
911
912
Jon Ashburn17f37372015-05-19 16:34:53 -0600913/* hook DextroyDevice to remove tableMap entry */
914VK_LAYER_EXPORT VkResult VKAPI vkDestroyDevice(VkDevice device)
915{
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -0600916 dispatch_key key = get_dispatch_key(device);
Jon Ashburn5a10d212015-06-01 10:02:09 -0600917 VkResult res = device_dispatch_table(device)->DestroyDevice(device);
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -0600918 destroy_device_dispatch_table(key);
Jon Ashburn17f37372015-05-19 16:34:53 -0600919 return res;
920}
921
Courtney Goeltzenleuchter6c813dc2015-06-01 14:46:33 -0600922VkResult VKAPI vkCreateInstance(
923 const VkInstanceCreateInfo* pCreateInfo,
924 VkInstance* pInstance)
925{
926
927 loader_platform_thread_once(&g_initOnce, initLayer);
928 /*
929 * For layers, the pInstance has already been filled out
930 * by the loader so that dispatch table is available.
931 */
Jon Ashburnade3bee2015-06-10 16:43:31 -0600932 VkLayerInstanceDispatchTable *pTable = instance_dispatch_table(*pInstance);
Courtney Goeltzenleuchter6c813dc2015-06-01 14:46:33 -0600933
934 VkResult result = pTable->CreateInstance(pCreateInfo, pInstance);
935
936 if (result == VK_SUCCESS) {
Courtney Goeltzenleuchter7abf8e52015-07-07 10:05:05 -0600937 enable_debug_report(pCreateInfo->extensionCount, pCreateInfo->ppEnabledExtensionNames);
Courtney Goeltzenleuchterf4a2eba2015-06-08 14:58:39 -0600938
939 debug_report_init_instance_extension_dispatch_table(
940 pTable,
941 pTable->GetInstanceProcAddr,
942 *pInstance);
Courtney Goeltzenleuchter6c813dc2015-06-01 14:46:33 -0600943 }
944 return result;
945}
946
Jon Ashburn17f37372015-05-19 16:34:53 -0600947/* hook DestroyInstance to remove tableInstanceMap entry */
948VK_LAYER_EXPORT VkResult VKAPI vkDestroyInstance(VkInstance instance)
949{
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -0600950 dispatch_key key = get_dispatch_key(instance);
Jon Ashburn5a10d212015-06-01 10:02:09 -0600951 VkResult res = instance_dispatch_table(instance)->DestroyInstance(instance);
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -0600952 destroy_instance_dispatch_table(key);
Jon Ashburn17f37372015-05-19 16:34:53 -0600953 return res;
954}
Chris Forbesb65ba352015-05-25 11:12:59 +1200955
Courtney Goeltzenleuchter6c813dc2015-06-01 14:46:33 -0600956VK_LAYER_EXPORT VkResult VKAPI vkDbgCreateMsgCallback(
957 VkInstance instance,
958 VkFlags msgFlags,
959 const PFN_vkDbgMsgCallback pfnMsgCallback,
960 void* pUserData,
961 VkDbgMsgCallback* pMsgCallback)
962{
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -0600963 VkLayerInstanceDispatchTable *pTable = instance_dispatch_table(instance);
Courtney Goeltzenleuchter6c813dc2015-06-01 14:46:33 -0600964 return layer_create_msg_callback(instance, pTable, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
965}
966
967VK_LAYER_EXPORT VkResult VKAPI vkDbgDestroyMsgCallback(
968 VkInstance instance,
969 VkDbgMsgCallback msgCallback)
970{
Courtney Goeltzenleuchter9f171942015-06-13 21:22:12 -0600971 VkLayerInstanceDispatchTable *pTable = instance_dispatch_table(instance);
Courtney Goeltzenleuchter6c813dc2015-06-01 14:46:33 -0600972 return layer_destroy_msg_callback(instance, pTable, msgCallback);
973}
974
Jon Ashburn1245cec2015-05-18 13:20:15 -0600975VK_LAYER_EXPORT void * VKAPI vkGetDeviceProcAddr(VkDevice device, const char* pName)
Chris Forbesaab9d112015-04-02 13:22:31 +1300976{
Jon Ashburn1245cec2015-05-18 13:20:15 -0600977 if (device == NULL)
Chris Forbesaab9d112015-04-02 13:22:31 +1300978 return NULL;
979
Chris Forbes1b466bd2015-04-15 06:59:41 +1200980 loader_platform_thread_once(&g_initOnce, initLayer);
981
Jon Ashburn4f2575f2015-05-28 16:25:02 -0600982 /* loader uses this to force layer initialization; device object is wrapped */
983 if (!strcmp("vkGetDeviceProcAddr", pName)) {
Jon Ashburn5a10d212015-06-01 10:02:09 -0600984 initDeviceTable((const VkBaseLayerObject *) device);
Jon Ashburn4f2575f2015-05-28 16:25:02 -0600985 return (void *) vkGetDeviceProcAddr;
986 }
987
Chris Forbesaab9d112015-04-02 13:22:31 +1300988#define ADD_HOOK(fn) \
989 if (!strncmp(#fn, pName, sizeof(#fn))) \
990 return (void *) fn
991
Courtney Goeltzenleuchter2d034fd2015-06-28 13:01:17 -0600992 ADD_HOOK(vkCreateShaderModule);
Chris Forbesaab9d112015-04-02 13:22:31 +1300993 ADD_HOOK(vkCreateShader);
Jon Ashburn17f37372015-05-19 16:34:53 -0600994 ADD_HOOK(vkDestroyDevice);
Chris Forbes60540932015-04-08 10:15:35 +1200995 ADD_HOOK(vkCreateGraphicsPipeline);
Chris Forbesd0f7f7c2015-06-04 20:27:09 +1200996 ADD_HOOK(vkCreateGraphicsPipelineDerivative);
Jon Ashburn8198fd02015-05-18 09:08:41 -0600997#undef ADD_HOOK
Jon Ashburn5a10d212015-06-01 10:02:09 -0600998 VkLayerDispatchTable* pTable = device_dispatch_table(device);
Jon Ashburn4f2575f2015-05-28 16:25:02 -0600999 if (pTable->GetDeviceProcAddr == NULL)
Chris Forbesaab9d112015-04-02 13:22:31 +13001000 return NULL;
Jon Ashburn4f2575f2015-05-28 16:25:02 -06001001 return pTable->GetDeviceProcAddr(device, pName);
Jon Ashburn79b78ac2015-05-05 14:22:52 -06001002}
1003
1004VK_LAYER_EXPORT void * VKAPI vkGetInstanceProcAddr(VkInstance inst, const char* pName)
1005{
Courtney Goeltzenleuchter6c813dc2015-06-01 14:46:33 -06001006 void *fptr;
1007
Jon Ashburn79b78ac2015-05-05 14:22:52 -06001008 if (inst == NULL)
1009 return NULL;
1010
Jon Ashburnd9564002015-05-07 10:27:37 -06001011 loader_platform_thread_once(&g_initOnce, initLayer);
Jon Ashburn79b78ac2015-05-05 14:22:52 -06001012
Jon Ashburn4f2575f2015-05-28 16:25:02 -06001013 if (!strcmp("vkGetInstanceProcAddr", pName)) {
Jon Ashburn5a10d212015-06-01 10:02:09 -06001014 initInstanceTable((const VkBaseLayerObject *) inst);
Jon Ashburn4f2575f2015-05-28 16:25:02 -06001015 return (void *) vkGetInstanceProcAddr;
1016 }
Jon Ashburn79b78ac2015-05-05 14:22:52 -06001017#define ADD_HOOK(fn) \
1018 if (!strncmp(#fn, pName, sizeof(#fn))) \
1019 return (void *) fn
1020
Courtney Goeltzenleuchter6c813dc2015-06-01 14:46:33 -06001021 ADD_HOOK(vkCreateInstance);
Jon Ashburn17f37372015-05-19 16:34:53 -06001022 ADD_HOOK(vkDestroyInstance);
Tony Barbour426b9052015-06-24 16:06:58 -06001023 ADD_HOOK(vkGetGlobalExtensionProperties);
Tony Barbour426b9052015-06-24 16:06:58 -06001024 ADD_HOOK(vkGetPhysicalDeviceExtensionProperties);
Courtney Goeltzenleuchter7abf8e52015-07-07 10:05:05 -06001025 ADD_HOOK(vkGetGlobalLayerProperties);
1026 ADD_HOOK(vkGetPhysicalDeviceLayerProperties);
Jon Ashburn8198fd02015-05-18 09:08:41 -06001027#undef ADD_HOOK
Jon Ashburn79b78ac2015-05-05 14:22:52 -06001028
Courtney Goeltzenleuchter6c813dc2015-06-01 14:46:33 -06001029 fptr = msg_callback_get_proc_addr(pName);
1030 if (fptr)
1031 return fptr;
1032
Jon Ashburn5a10d212015-06-01 10:02:09 -06001033 VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(inst);
Jon Ashburn4f2575f2015-05-28 16:25:02 -06001034 if (pTable->GetInstanceProcAddr == NULL)
Jon Ashburn79b78ac2015-05-05 14:22:52 -06001035 return NULL;
Jon Ashburn4f2575f2015-05-28 16:25:02 -06001036 return pTable->GetInstanceProcAddr(inst, pName);
Chris Forbesaab9d112015-04-02 13:22:31 +13001037}