From: Chris Forbes Date: Thu, 16 Apr 2015 22:13:28 +0000 (+1200) Subject: shader_checker: convert printf to debug output X-Git-Tag: upstream/1.1.92~5727 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cc5bb6aded0ae0c2e74199369e26787d7cf1c3e9;p=platform%2Fupstream%2FVulkan-Tools.git shader_checker: convert printf to debug output --- diff --git a/layers/shader_checker.cpp b/layers/shader_checker.cpp index 835a334..bffcf20 100644 --- a/layers/shader_checker.cpp +++ b/layers/shader_checker.cpp @@ -33,6 +33,7 @@ #include "vkLayer.h" #include "layers_config.h" #include "layers_msg.h" +#include "shader_checker.h" // The following is #included again to catch certain OS-specific functions // being used: #include "loader_platform.h" @@ -397,7 +398,8 @@ collect_interface_by_location(shader_source const *src, spv::StorageClass interf size_t size = src->words.size(); if (code[0] != spv::MagicNumber) { - printf("Invalid magic.\n"); + layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_NON_SPIRV_SHADER, "SC", + "Shader is not SPIR-V, unable to extract interface"); return; } @@ -436,8 +438,10 @@ collect_interface_by_location(shader_source const *src, spv::StorageClass interf * The spec says nothing about how this case works (or doesn't) * for interface matching. */ - printf("WARN: var %d (type %d) in %s interface has no Location or Builtin decoration\n", - code[word+2], code[word+1], interface == spv::StorageInput ? "input" : "output"); + char str[1024]; + sprintf(str, "var %d (type %d) in %s interface has no Location or Builtin decoration\n", + code[word+2], code[word+1], storage_class_name(interface)); + layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_INCONSISTENT_SPIRV, "SC", str); } else if (location != -1) { /* A user-defined interface variable, with a location. */ @@ -481,8 +485,7 @@ validate_interface_between_stages(shader_source const *producer, char const *pro std::map builtin_outputs; std::map builtin_inputs; - printf("Begin validate_interface_between_stages %s -> %s\n", - producer_name, consumer_name); + char str[1024]; collect_interface_by_location(producer, spv::StorageOutput, outputs, builtin_outputs); collect_interface_by_location(consumer, spv::StorageInput, inputs, builtin_inputs); @@ -493,18 +496,20 @@ validate_interface_between_stages(shader_source const *producer, char const *pro /* maps sorted by key (location); walk them together to find mismatches */ while (a_it != outputs.end() || b_it != inputs.end()) { if (b_it == inputs.end() || a_it->first < b_it->first) { - printf(" WARN: %s writes to output location %d which is not consumed by %s\n", + sprintf(str, "%s writes to output location %d which is not consumed by %s\n", producer_name, a_it->first, consumer_name); + layerCbMsg(VK_DBG_MSG_WARNING, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", str); a_it++; } else if (a_it == outputs.end() || a_it->first > b_it->first) { - printf(" ERR: %s consumes input location %d which is not written by %s\n", + sprintf(str, "%s consumes input location %d which is not written by %s\n", consumer_name, b_it->first, producer_name); + layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", str); b_it++; } else { if (types_match(producer, consumer, a_it->second.type_id, b_it->second.type_id)) { - printf(" OK: match on location %d\n", a_it->first); + /* OK! */ } else { char producer_type[1024]; @@ -512,15 +517,14 @@ validate_interface_between_stages(shader_source const *producer, char const *pro describe_type(producer_type, producer, a_it->second.type_id); describe_type(consumer_type, consumer, b_it->second.type_id); - printf(" ERR: type mismatch on location %d: '%s' vs '%s'\n", a_it->first, + 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); } a_it++; b_it++; } } - - printf("End validate_interface_between_stages\n"); } @@ -585,8 +589,7 @@ validate_vi_against_vs_inputs(VkPipelineVertexInputCreateInfo const *vi, shader_ * the vs builtin inputs are generated in the pipeline, not sourced from buffers (VertexID, etc) */ std::map builtin_inputs; - - printf("Begin validate_vi_against_vs_inputs\n"); + char str[1024]; collect_interface_by_location(vs, spv::StorageInput, inputs, builtin_inputs); @@ -600,25 +603,22 @@ validate_vi_against_vs_inputs(VkPipelineVertexInputCreateInfo const *vi, shader_ while (it_a != attribs.end() || it_b != inputs.end()) { if (it_b == inputs.end() || it_a->first < it_b->first) { - printf(" WARN: attribute at location %d not consumed by the vertex shader\n", - it_a->first); + sprintf(str, "Vertex attribute at location %d not consumed by VS", it_a->first); + layerCbMsg(VK_DBG_MSG_WARNING, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", str); it_a++; } else if (it_a == attribs.end() || it_b->first < it_a->first) { - printf(" ERR: vertex shader consumes input at location %d but not provided\n", - it_b->first); + sprintf(str, "VS consumes input at location %d but not provided", it_b->first); + layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", str); it_b++; } else { /* TODO: type check */ - printf(" OK: match on attribute location %d\n", - it_a->first); + /* OK! */ it_a++; it_b++; } } - - printf("End validate_vi_against_vs_inputs\n"); } @@ -627,8 +627,7 @@ validate_fs_outputs_against_cb(shader_source const *fs, VkPipelineCbStateCreateI { std::map outputs; std::map builtin_outputs; - - printf("Begin validate_fs_outputs_against_cb\n"); + char str[1024]; /* TODO: dual source blend index (spv::DecIndex, zero if not provided) */ @@ -640,23 +639,20 @@ validate_fs_outputs_against_cb(shader_source const *fs, VkPipelineCbStateCreateI if (builtin_outputs.find(spv::BuiltInFragColor) != builtin_outputs.end()) { bool broadcast_err = false; if (outputs.size()) { - printf(" ERR: should not have user-defined FS outputs when using broadcast\n"); + 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; } for (int i = 0; i < cb->attachmentCount; i++) { unsigned attachmentType = get_format_type(cb->pAttachments[i].format); if (attachmentType == FORMAT_TYPE_SINT || attachmentType == FORMAT_TYPE_UINT) { - printf(" ERR: CB fomat should not be SINT or UINT when using broadcast\n"); + 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; } } - if (!broadcast_err) - printf(" OK: FS broadcast to all color attachments\n"); - - /* Skip the usual matching -- all attachments are considered written to. */ - printf("End validate_fs_outputs_against_cb\n"); return; } @@ -669,25 +665,22 @@ validate_fs_outputs_against_cb(shader_source const *fs, VkPipelineCbStateCreateI while (it != outputs.end() || attachment < cb->attachmentCount) { if (attachment == cb->attachmentCount || it->first < attachment) { - printf(" ERR: fragment shader writes to output location %d with no matching attachment\n", - it->first); + sprintf(str, "FS writes to output location %d with no matching attachment", it->first); + layerCbMsg(VK_DBG_MSG_WARNING, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", str); it++; } else if (it == outputs.end() || it->first > attachment) { - printf(" ERR: attachment %d not written by fragment shader\n", - attachment); + 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++; } else { - printf(" OK: match on attachment index %d\n", - it->first); + /* OK! */ /* TODO: typecheck */ it++; attachment++; } } - - printf("End validate_fs_outputs_against_cb\n"); } @@ -695,8 +688,7 @@ VK_LAYER_EXPORT VkResult VKAPI vkCreateGraphicsPipeline(VkDevice device, const VkGraphicsPipelineCreateInfo *pCreateInfo, VkPipeline *pPipeline) { - /* TODO: run cross-stage validation */ - /* - Support GS, TCS, TES stages */ + /* TODO: run cross-stage validation for GS, TCS, TES stages */ /* We seem to allow pipeline stages to be specified out of order, so collect and identify them * before trying to do anything more: */ @@ -705,17 +697,22 @@ VK_LAYER_EXPORT VkResult VKAPI vkCreateGraphicsPipeline(VkDevice device, shader_source const *fs_source = 0; VkPipelineCbStateCreateInfo const *cb = 0; VkPipelineVertexInputCreateInfo const *vi = 0; + char str[1024]; for (auto stage = pCreateInfo; stage; stage = (decltype(stage))stage->pNext) { if (stage->sType == VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO) { auto shader_stage = (VkPipelineShaderStageCreateInfo const *)stage; - if (shader_stage->shader.stage == VK_SHADER_STAGE_VERTEX) + if (shader_stage->shader.stage == VK_SHADER_STAGE_VERTEX) { vs_source = shader_map[(void *)(shader_stage->shader.shader)]; - else if (shader_stage->shader.stage == VK_SHADER_STAGE_FRAGMENT) + } + else if (shader_stage->shader.stage == VK_SHADER_STAGE_FRAGMENT) { fs_source = shader_map[(void *)(shader_stage->shader.shader)]; - else - printf("Unknown shader stage %d\n", shader_stage->shader.stage); + } + else { + sprintf(str, "Unknown shader stage %d\n", shader_stage->shader.stage); + layerCbMsg(VK_DBG_MSG_WARNING, VK_VALIDATION_LEVEL_0, NULL, 0, SHADER_CHECKER_UNKNOWN_STAGE, "SC", str); + } } else if (stage->sType == VK_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO) { cb = (VkPipelineCbStateCreateInfo const *)stage; @@ -725,7 +722,8 @@ VK_LAYER_EXPORT VkResult VKAPI vkCreateGraphicsPipeline(VkDevice device, } } - printf("Pipeline: vi=%p vs=%p fs=%p cb=%p\n", vi, vs_source, fs_source, cb); + sprintf(str, "Pipeline: vi=%p vs=%p fs=%p cb=%p\n", vi, vs_source, fs_source, cb); + 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); diff --git a/layers/shader_checker.h b/layers/shader_checker.h new file mode 100644 index 0000000..17692fb --- /dev/null +++ b/layers/shader_checker.h @@ -0,0 +1,38 @@ +/* + * Vulkan + * + * Copyright (C) 2014 LunarG, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#include "vkLayer.h" + + +/* Shader checker error codes */ +typedef enum _SHADER_CHECKER_ERROR +{ + SHADER_CHECKER_NONE, + SHADER_CHECKER_FS_MIXED_BROADCAST, /* FS writes broadcast output AND custom outputs */ + SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, /* Type mismatch between shader stages or shader and pipeline */ + SHADER_CHECKER_OUTPUT_NOT_CONSUMED, /* Entry appears in output interface, but missing in input */ + SHADER_CHECKER_INPUT_NOT_PRODUCED, /* Entry appears in input interface, but missing in output */ + SHADER_CHECKER_NON_SPIRV_SHADER, /* Shader image is not SPIR-V */ + SHADER_CHECKER_INCONSISTENT_SPIRV, /* General inconsistency within a SPIR-V module */ + SHADER_CHECKER_UNKNOWN_STAGE, /* Stage is not supported by analysis */ +} SHADER_CHECKER_ERROR;