shader_checker: Only continue with pipeline config if no errors
The driver may crash in these cases.
Signed-off-by: Chris Forbes <chrisf@ijw.co.nz>
Reviewed-by: Tobin Ehlis <tobin@lunarg.com>
diff --git a/layers/shader_checker.cpp b/layers/shader_checker.cpp
index 40dad1b..3121349 100644
--- a/layers/shader_checker.cpp
+++ b/layers/shader_checker.cpp
@@ -482,7 +482,7 @@
}
-static void
+static bool
validate_interface_between_stages(shader_source const *producer, char const *producer_name,
shader_source const *consumer, char const *consumer_name)
{
@@ -493,6 +493,7 @@
std::map<uint32_t, interface_var> builtin_inputs;
char str[1024];
+ bool pass = true;
collect_interface_by_location(producer, spv::StorageClassOutput, outputs, builtin_outputs);
collect_interface_by_location(consumer, spv::StorageClassInput, inputs, builtin_inputs);
@@ -517,6 +518,7 @@
sprintf(str, "%s consumes input location %d which is not written by %s\n",
consumer_name, b_first, producer_name);
layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", str);
+ pass = false;
b_it++;
}
else {
@@ -532,11 +534,14 @@
sprintf(str, "Type mismatch on location %d: '%s' vs '%s'\n", a_it->first,
producer_type, consumer_type);
layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", str);
+ pass = false;
}
a_it++;
b_it++;
}
}
+
+ return pass;
}
@@ -625,7 +630,7 @@
}
-static void
+static bool
validate_vi_against_vs_inputs(VkPipelineVertexInputCreateInfo const *vi, shader_source const *vs)
{
std::map<uint32_t, interface_var> inputs;
@@ -634,6 +639,7 @@
*/
std::map<uint32_t, interface_var> builtin_inputs;
char str[1024];
+ bool pass = true;
collect_interface_by_location(vs, spv::StorageClassInput, inputs, builtin_inputs);
@@ -658,6 +664,7 @@
else if (a_at_end || b_first < a_first) {
sprintf(str, "VS consumes input at location %d but not provided", b_first);
layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", str);
+ pass = false;
it_b++;
}
else {
@@ -671,6 +678,7 @@
sprintf(str, "Attribute type of `%s` at location %d does not match VS input type of `%s`",
string_VkFormat(it_a->second->format), a_first, vs_type);
layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", str);
+ pass = false;
}
/* OK! */
@@ -678,15 +686,18 @@
it_b++;
}
}
+
+ return pass;
}
-static void
+static bool
validate_fs_outputs_against_cb(shader_source const *fs, VkPipelineCbStateCreateInfo const *cb)
{
std::map<uint32_t, interface_var> outputs;
std::map<uint32_t, interface_var> builtin_outputs;
char str[1024];
+ bool pass = true;
/* TODO: dual source blend index (spv::DecIndex, zero if not provided) */
@@ -696,11 +707,10 @@
* and all color attachment should be UNORM/SNORM/FLOAT.
*/
if (builtin_outputs.find(spv::BuiltInFragColor) != builtin_outputs.end()) {
- bool broadcast_err = false;
if (outputs.size()) {
layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_FS_MIXED_BROADCAST, "SC",
"Should not have user-defined FS outputs when using broadcast");
- broadcast_err = true;
+ pass = false;
}
for (unsigned i = 0; i < cb->attachmentCount; i++) {
@@ -708,11 +718,11 @@
if (attachmentType == FORMAT_TYPE_SINT || attachmentType == FORMAT_TYPE_UINT) {
layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC",
"CB format should not be SINT or UINT when using broadcast");
- broadcast_err = true;
+ pass = false;
}
}
- return;
+ return pass;
}
auto it = outputs.begin();
@@ -732,6 +742,7 @@
sprintf(str, "Attachment %d not written by FS", attachment);
layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", str);
attachment++;
+ pass = false;
}
else {
unsigned output_type = get_fundamental_type(fs, it->second.type_id);
@@ -744,6 +755,7 @@
sprintf(str, "Attachment %d of type `%s` does not match FS output type of `%s`",
attachment, string_VkFormat(cb->pAttachments[attachment].format), fs_type);
layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", str);
+ pass = false;
}
/* OK! */
@@ -751,6 +763,8 @@
attachment++;
}
}
+
+ return pass;
}
@@ -768,6 +782,7 @@
VkPipelineCbStateCreateInfo const *cb = 0;
VkPipelineVertexInputCreateInfo const *vi = 0;
char str[1024];
+ bool pass = true;
loader_platform_thread_lock_mutex(&globalLock);
@@ -798,23 +813,31 @@
layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_NONE, "SC", str);
if (vi && vs_source) {
- validate_vi_against_vs_inputs(vi, vs_source);
+ pass = validate_vi_against_vs_inputs(vi, vs_source) && pass;
}
if (vs_source && fs_source) {
- validate_interface_between_stages(vs_source, "vertex shader",
- fs_source, "fragment shader");
+ pass = validate_interface_between_stages(vs_source, "vertex shader",
+ fs_source, "fragment shader") && pass;
}
if (fs_source && cb) {
- validate_fs_outputs_against_cb(fs_source, cb);
+ pass = validate_fs_outputs_against_cb(fs_source, cb) && pass;
}
VkLayerDispatchTable *pTable = tableMap[(VkBaseLayerObject *)device];
- VkResult res = pTable->CreateGraphicsPipeline(device, pCreateInfo, pPipeline);
loader_platform_thread_unlock_mutex(&globalLock);
- return res;
+
+ if (pass) {
+ /* The driver is allowed to crash if passed junk. Only actually create the
+ * pipeline if we didn't run into any showstoppers above.
+ */
+ return pTable->CreateGraphicsPipeline(device, pCreateInfo, pPipeline);
+ }
+ else {
+ return VK_ERROR_UNKNOWN;
+ }
}