Layers: Add code-gen'd calls to val exts

Modified PV code gen to insert and make calls to validate
extension dependencies.

Change-Id: I90103b16d36fb868b32df796b1dae7741dfcba34
diff --git a/layers/parameter_validation.cpp b/layers/parameter_validation.cpp
index 7070535..7e74d1e 100644
--- a/layers/parameter_validation.cpp
+++ b/layers/parameter_validation.cpp
@@ -81,7 +81,7 @@
     VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos = nullptr;
     VkDebugReportCallbackEXT *tmp_callbacks = nullptr;
     InstanceExtensions extensions = {};
-
+    std::unordered_set<std::string> enabled_extensions;
     VkLayerInstanceDispatchTable dispatch_table = {};
 };
 
@@ -94,6 +94,7 @@
     VkPhysicalDevice physical_device = VK_NULL_HANDLE;
     VkDevice device = VK_NULL_HANDLE;
     DeviceExtensions enables;
+    std::unordered_set<std::string> enabled_extensions;
 
     VkLayerDispatchTable dispatch_table = {};
 };
@@ -109,6 +110,8 @@
     layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_parameter_validation");
 }
 
+
+
 VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
                                                             const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
                                                             const VkAllocationCallbacks *pAllocator,
@@ -144,6 +147,16 @@
     "VK_LAYER_LUNARG_parameter_validation", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
 };
 
+bool ValidateRequiredExtensions(std::string api_name, const std::vector<std::string> required_extensions) {
+    bool skip = false;
+
+    for (auto reqd_ext = required_extensions.begin(); reqd_ext != required_extensions.end(); reqd_ext++) {
+        // Insert depency checks here
+    }
+
+    return skip;
+}
+
 static const int MaxParamCheckerStringLength = 256;
 
 static bool validate_string(debug_report_data *report_data, const char *apiName, const ParameterName &stringName,
@@ -248,6 +261,11 @@
         auto my_instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), instance_layer_data_map);
         assert(my_instance_data != nullptr);
 
+        // Save enabled instance extension names for validation extension APIs
+        for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+            my_instance_data->enabled_extensions.emplace(pCreateInfo->ppEnabledExtensionNames[i]);
+        }
+
         layer_init_instance_dispatch_table(*pInstance, &my_instance_data->dispatch_table, fpGetInstanceProcAddr);
         my_instance_data->instance = *pInstance;
         my_instance_data->report_data =
@@ -607,6 +625,11 @@
             my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
             layer_init_device_dispatch_table(*pDevice, &my_device_data->dispatch_table, fpGetDeviceProcAddr);
 
+            // Save enabled instance extension names for validation extension APIs
+            for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+                my_instance_data->enabled_extensions.emplace(pCreateInfo->ppEnabledExtensionNames[i]);
+            }
+
             my_device_data->enables.InitFromDeviceCreateInfo(pCreateInfo);
 
             storeCreateDeviceData(*pDevice, pCreateInfo);
diff --git a/layers/parameter_validation_utils.h b/layers/parameter_validation_utils.h
index d5497cb..791a7a1 100644
--- a/layers/parameter_validation_utils.h
+++ b/layers/parameter_validation_utils.h
@@ -86,6 +86,9 @@
 // The value of all VK_xxx_MAX_ENUM tokens
 const uint32_t MaxEnumValue = 0x7FFFFFFF;
 
+// Forward declaration
+bool ValidateRequiredExtensions(std::string api_name, const std::vector<std::string> required_extensions);
+
 template <typename T>
 bool is_extension_added_token(T value) {
     return (value != MaxEnumValue) && (static_cast<uint32_t>(std::abs(static_cast<int32_t>(value))) >= ExtEnumBaseValue);
diff --git a/scripts/parameter_validation_generator.py b/scripts/parameter_validation_generator.py
index 1c5a4e4..330e532 100644
--- a/scripts/parameter_validation_generator.py
+++ b/scripts/parameter_validation_generator.py
@@ -18,6 +18,7 @@
 # limitations under the License.
 #
 # Author: Dustin Graves <dustin@lunarg.com>
+# Author: Mark Lobodzinski <mark@lunarg.com>
 
 import os,re,sys
 import xml.etree.ElementTree as etree
@@ -155,6 +156,7 @@
         self.flags = set()                                # Map of flags typenames
         self.flagBits = dict()                            # Map of flag bits typename to list of values
         self.newFlags = set()                             # Map of flags typenames /defined in the current feature/
+        self.required_extensions = []                     # List of required extensions for the current extension
         # Named tuples to store struct and command data
         self.StructType = namedtuple('StructType', ['name', 'value'])
         self.CommandParam = namedtuple('CommandParam', ['type', 'name', 'ispointer', 'isstaticarray', 'isbool', 'israngedenum',
@@ -241,6 +243,13 @@
         self.commands = []
         self.structMembers = []
         self.newFlags = set()
+        # Save list of required extensions for this extension
+        self.required_extensions = []
+        if self.featureName != "VK_VERSION_1_0":
+            self.required_extensions.append(self.featureName)
+        required_extensions = interface.get('requires')
+        if required_extensions is not None:
+            self.required_extensions.extend(required_extensions.split(','))
     def endFeature(self):
         # C-specific
         # Actually write the interface to the output file.
@@ -631,7 +640,10 @@
         # argument is a handle (not vkCreateInstance)
         reportData = '    debug_report_data*'.ljust(self.genOpts.alignFuncParam) + 'report_data,'
         if cmd.name != 'vkCreateInstance':
-            lines[1] = reportData
+            if len(lines) < 3:   # Terminate correctly if single parameter
+                lines[1] = reportData[:-1] + ')'
+            else:
+                lines[1] = reportData
         else:
             lines.insert(1, reportData)
         return '\n'.join(lines)
@@ -1010,7 +1022,17 @@
         for command in self.commands:
             # Skip first parameter if it is a dispatch handle (everything except vkCreateInstance)
             startIndex = 0 if command.name == 'vkCreateInstance' else 1
+            if command.name == 'vkCmdDebugMarkerEndEXT':
+                stop = 'here'
             lines, unused = self.genFuncBody(command.name, command.params[startIndex:], '', '', None)
+            if self.required_extensions:
+                def_line = 'std::vector<std::string> required_extensions = {'
+                for ext in self.required_extensions:
+                    def_line += '"%s", ' % ext
+                def_line = def_line[:-2] + '};'
+                ext_call = 'skipCall |= ValidateRequiredExtensions("%s", required_extensions);\n' % command.name
+                lines.insert(0, ext_call)
+                lines.insert(0, def_line)
             if lines:
                 cmdDef = self.getCmdDef(command) + '\n'
                 cmdDef += '{\n'
@@ -1023,6 +1045,7 @@
                     if len(unused) > 0:
                         cmdDef += '\n'
                 cmdDef += indent + 'bool skipCall = false;\n'
+
                 for line in lines:
                     cmdDef += '\n'
                     if type(line) is list: