layers: Require pipeline layout to contain all referenced descriptors
authorChris Forbes <chrisf@ijw.co.nz>
Fri, 14 Aug 2015 00:04:59 +0000 (12:04 +1200)
committerChris Forbes <chrisf@ijw.co.nz>
Fri, 18 Sep 2015 00:09:18 +0000 (12:09 +1200)
If the SPIRV image uses a descriptor (for constant buffer, image, etc)
we must declare it in the pipeline layout.

We won't complain about unused junk in the pipeline layout, but not
declaring something that *is* used is an error.

Signed-off-by: Chris Forbes <chrisf@ijw.co.nz>
Reviewed-by: Courtney Goeltzenleuchter <courtney@lunarg.com>
layers/shader_checker.cpp
layers/shader_checker.h

index 1d5b08a57b13585dccd9f5e46878fb18ff0f9143..b4d1a59c9a4b9f6d858c3c9e052fbea7e1073991 100644 (file)
@@ -991,6 +991,25 @@ shader_stage_attribs[VK_SHADER_STAGE_FRAGMENT + 1] = {
 };
 
 
+static VkDescriptorSetLayoutBinding *
+find_descriptor_binding(std::vector<std::vector<VkDescriptorSetLayoutBinding>*>* layout,
+                        std::pair<unsigned, unsigned> slot)
+{
+    if (!layout)
+        return nullptr;
+
+    if (slot.first >= layout->size())
+        return nullptr;
+
+    auto set = (*layout)[slot.first];
+
+    if (slot.second >= set->size())
+        return nullptr;
+
+    return &(*set)[slot.second];
+}
+
+
 static bool
 validate_graphics_pipeline(VkDevice dev, VkGraphicsPipelineCreateInfo const *pCreateInfo)
 {
@@ -1016,6 +1035,33 @@ validate_graphics_pipeline(VkDevice dev, VkGraphicsPipelineCreateInfo const *pCr
             else {
                 struct shader_object *shader = shader_object_map[pStage->shader.handle];
                 shaders[pStage->stage] = shader->module;
+
+                /* validate descriptor set layout against what the spirv module actually uses */
+                if (shader->module->is_spirv) {
+                    std::map<std::pair<unsigned, unsigned>, interface_var> descriptor_uses;
+                    collect_interface_by_descriptor_slot(dev, shader->module, spv::StorageClassUniform,
+                            descriptor_uses);
+
+                    auto layout = pCreateInfo->layout.handle ?
+                        pipeline_layout_map[pCreateInfo->layout.handle] : nullptr;
+
+                    for (auto it = descriptor_uses.begin(); it != descriptor_uses.end(); it++) {
+
+                        /* find the matching binding */
+                        auto binding = find_descriptor_binding(layout, it->first);
+
+                        if (binding == nullptr) {
+                            char type_name[1024];
+                            describe_type(type_name, shader->module, it->second.type_id);
+                            log_msg(mdd(dev), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_DEVICE, /*dev*/0, 0,
+                                    SHADER_CHECKER_MISSING_DESCRIPTOR, "SC",
+                                    "Shader uses descriptor slot %u.%u (used as type `%s`) but not declared in pipeline layout",
+                                    it->first.first, it->first.second, type_name);
+                            pass = false;
+                        }
+
+                    }
+                }
             }
         }
     }
index 4e7eddf0f6c328122518058dbcdec93fb12ee4ff..2c3868b42ca51ec6319db181982bbeb2acb2e15a 100644 (file)
@@ -37,4 +37,5 @@ typedef enum _SHADER_CHECKER_ERROR
     SHADER_CHECKER_INCONSISTENT_SPIRV,      /* General inconsistency within a SPIR-V module */
     SHADER_CHECKER_UNKNOWN_STAGE,           /* Stage is not supported by analysis */
     SHADER_CHECKER_INCONSISTENT_VI,         /* VI state contains conflicting binding or attrib descriptions */
+    SHADER_CHECKER_MISSING_DESCRIPTOR,      /* Shader attempts to use a descriptor binding not declared in the layout */
 } SHADER_CHECKER_ERROR;