build: API parameterization
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0034fcd..5680158 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,6 +19,10 @@
 set(CMAKE_C_VISIBILITY_PRESET "hidden")
 set(CMAKE_VISIBILITY_INLINES_HIDDEN "YES")
 
+# This variable enables downstream users to customize the target API
+# variant (e.g. Vulkan SC)
+set(API_TYPE "vulkan")
+
 add_subdirectory(scripts)
 
 find_package(VulkanHeaders CONFIG QUIET)
@@ -35,7 +39,7 @@
 
     include(GNUInstallDirs)
 
-    install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/vulkan" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+    install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/${API_TYPE}/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/vulkan")
 
     set_target_properties(VulkanLayerSettings PROPERTIES EXPORT_NAME "LayerSettings")
     set_target_properties(VulkanUtilityHeaders PROPERTIES EXPORT_NAME "UtilityHeaders")
diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt
index 3b8c9d4..2f782a7 100644
--- a/scripts/CMakeLists.txt
+++ b/scripts/CMakeLists.txt
@@ -40,6 +40,8 @@
     endif()
     list(APPEND update_dep_command "--config")
     list(APPEND update_dep_command "${_build_type}")
+    list(APPEND update_dep_command "--api")
+    list(APPEND update_dep_command "${API_TYPE}")
 
     set(UPDATE_DEPS_DIR_SUFFIX "${_build_type}")
     if (ANDROID)
diff --git a/scripts/generate_source.py b/scripts/generate_source.py
index f3825a9..21b8d50 100755
--- a/scripts/generate_source.py
+++ b/scripts/generate_source.py
@@ -27,23 +27,32 @@
     from generators.format_utils_generator import FormatUtilsOutputGenerator
     from generators.struct_helper_generator import StructHelperOutputGenerator
 
+    # These set fields that are needed by both OutputGenerator and BaseGenerator,
+    # but are uniform and don't need to be set at a per-generated file level
+    from generators.base_generator import (SetTargetApiName, SetMergedApiNames)
+    SetTargetApiName(api)
+
     # Build up a list of all generators and custom options
     generators = {
         'vk_dispatch_table.h' : {
            'generator' : DispatchTableOutputGenerator,
-           'directory' : 'include/vulkan/utility',
+           'genCombined': True,
+           'directory' : f'include/{api}/utility',
         },
         'vk_enum_string_helper.h' : {
             'generator' : EnumStringHelperOutputGenerator,
-            'directory' : 'include/vulkan',
+            'genCombined': True,
+            'directory' : f'include/{api}',
         },
         'vk_format_utils.h' : {
             'generator' : FormatUtilsOutputGenerator,
-            'directory' : 'include/vulkan/utility',
+            'genCombined': True,
+            'directory' : f'include/{api}/utility',
         },
         'vk_struct_helper.hpp' : {
             'generator' : StructHelperOutputGenerator,
-            'directory' : 'include/vulkan/utility',
+            'genCombined': True,
+            'directory' : f'include/{api}/utility',
         },
     }
 
@@ -61,11 +70,21 @@
         generator = generators[target]['generator']
         gen = generator()
 
+        # This code and the 'genCombined' generator metadata is used by downstream
+        # users to generate code with all Vulkan APIs merged into the target API variant
+        # (e.g. Vulkan SC) when needed. The constructed apiList is also used to filter
+        # out non-applicable extensions later below.
+        apiList = [api]
+        if api != 'vulkan' and generators[target]['genCombined']:
+            SetMergedApiNames('vulkan')
+            apiList.append('vulkan')
+        else:
+            SetMergedApiNames(None)
+
         outDirectory = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', generators[target]['directory']))
         options = BaseGeneratorOptions(
             customFileName  = target,
-            customDirectory = outDirectory,
-            customApiName   = 'vulkan')
+            customDirectory = outDirectory)
 
         # Create the registry object with the specified generator and generator
         # options. The options are set before XML loading as they may affect it.
diff --git a/scripts/generators/base_generator.py b/scripts/generators/base_generator.py
index bd013ea..b402bb5 100644
--- a/scripts/generators/base_generator.py
+++ b/scripts/generators/base_generator.py
@@ -66,6 +66,30 @@
     global globalApiName
     globalApiName = apiname
 
+def SetMergedApiNames(names: str) -> None:
+    global mergedApiNames
+    mergedApiNames = names
+
+
+# This class is a container for any source code, data, or other behavior that is necessary to
+# customize the generator script for a specific target API variant (e.g. Vulkan SC). As such,
+# all of these API-specific interfaces and their use in the generator script are part of the
+# contract between this repository and its downstream users. Changing or removing any of these
+# interfaces or their use in the generator script will have downstream effects and thus
+# should be avoided unless absolutely necessary.
+class APISpecific:
+    # Version object factory method
+    @staticmethod
+    def createApiVersion(targetApiName: str, name: str, number: str) -> Version:
+        match targetApiName:
+
+            # Vulkan specific API version creation
+            case 'vulkan':
+                nameApi = name.replace('VK_', 'VK_API_')
+                nameString = f'"{name}"'
+                return Version(name, nameString, nameApi, number)
+
+
 # This Generator Option is used across all generators.
 # After years of use, it has shown that most the options are unified across each generator (file)
 # as it is easier to modifiy things per-file that need the difference
@@ -79,7 +103,7 @@
                 filename = customFileName if customFileName else globalFileName,
                 directory = customDirectory if customDirectory else globalDirectory,
                 apiname = customApiName if customApiName else globalApiName,
-                mergeApiNames = None,
+                mergeApiNames = mergedApiNames,
                 defaultExtensions = customApiName if customApiName else globalApiName,
                 emitExtensions = '.*',
                 emitSpirv = '.*',
@@ -97,6 +121,7 @@
     def __init__(self):
         OutputGenerator.__init__(self, None, None, None)
         self.vk = VulkanObject()
+        self.targetApiName = globalApiName
 
         # reg.py has a `self.featureName` but this is nicer because
         # it will be either the Version or Extension object
@@ -163,6 +188,15 @@
             #  one or more extension and/or core version names
             for required in dict:
                 for commandName in dict[required]:
+                    # Skip commands removed in the target API
+                    # This check is needed because parts of the base generator code bypass the
+                    # dependency resolution logic in the registry tooling and thus the generator
+                    # may attempt to generate code for commands which are not supported in the
+                    # target API variant, thus this check needs to happen even if any specific
+                    # target API variant may not specifically need it
+                    if not commandName in self.vk.commands:
+                        continue
+
                     command = self.vk.commands[commandName]
                     # Make sure list is unique
                     command.extensions.extend([extension] if extension not in command.extensions else [])
@@ -308,9 +342,7 @@
         else: # version
             number = interface.get('number')
             if number != '1.0':
-                nameApi = name.replace('VK_', 'VK_API_')
-                nameString = f'"{name}"'
-                self.currentVersion = Version(name, nameString, nameApi, number)
+                self.currentVersion = APISpecific.createApiVersion(self.targetApiName, name, number)
                 self.vk.versions[name] = self.currentVersion
 
     def endFeature(self):
@@ -639,8 +671,10 @@
             equivalent = SyncEquivalent(stages, accesses, False)
 
         flagName = syncElem.get('name')
-        flag = [x for x in self.vk.bitmasks['VkPipelineStageFlagBits2'].flags if x.name == flagName][0]
-        self.vk.syncStage.append(SyncStage(flag, support, equivalent))
+        flag = [x for x in self.vk.bitmasks['VkPipelineStageFlagBits2'].flags if x.name == flagName]
+        # This check is needed because not all API variants have VK_KHR_synchronization2
+        if flag:
+            self.vk.syncStage.append(SyncStage(flag[0], support, equivalent))
 
     def genSyncAccess(self, sync):
         OutputGenerator.genSyncAccess(self, sync)
@@ -664,8 +698,10 @@
             equivalent = SyncEquivalent(stages, accesses, False)
 
         flagName = syncElem.get('name')
-        flag = [x for x in self.vk.bitmasks['VkAccessFlagBits2'].flags if x.name == flagName][0]
-        self.vk.syncAccess.append(SyncAccess(flag, support, equivalent))
+        flag = [x for x in self.vk.bitmasks['VkAccessFlagBits2'].flags if x.name == flagName]
+        # This check is needed because not all API variants have VK_KHR_synchronization2
+        if flag:
+            self.vk.syncAccess.append(SyncAccess(flag[0], support, equivalent))
 
     def genSyncPipeline(self, sync):
         OutputGenerator.genSyncPipeline(self, sync)
diff --git a/scripts/known_good.json b/scripts/known_good.json
index 2f10c63..851bb0d 100644
--- a/scripts/known_good.json
+++ b/scripts/known_good.json
@@ -2,6 +2,7 @@
     "repos": [
         {
             "name": "Vulkan-Headers",
+            "api": "vulkan",
             "url": "https://github.com/KhronosGroup/Vulkan-Headers.git",
             "sub_dir": "Vulkan-Headers",
             "build_dir": "Vulkan-Headers/build",