|
26 | 26 | import re |
27 | 27 | import os |
28 | 28 | from base_generator import BaseGenerator |
| 29 | +from vulkan_object import Version |
29 | 30 |
|
30 | 31 | WSI_EXT_NAMES = ['VK_KHR_surface', |
31 | 32 | 'VK_KHR_display', |
|
103 | 104 | 'vkEnumerateInstanceLayerProperties', |
104 | 105 | 'vkEnumerateInstanceVersion'] |
105 | 106 |
|
| 107 | +# This class is a container for any source code, data, or other behavior that is necessary to |
| 108 | +# customize the generator script for a specific target API variant (e.g. Vulkan SC). As such, |
| 109 | +# all of these API-specific interfaces and their use in the generator script are part of the |
| 110 | +# contract between this repository and its downstream users. Changing or removing any of these |
| 111 | +# interfaces or their use in the generator script will have downstream effects and thus |
| 112 | +# should be avoided unless absolutely necessary. |
| 113 | +class APISpecific: |
| 114 | + @staticmethod |
| 115 | + def getApiVersionDisplayName(targetApiName: str, name: str) -> str: |
| 116 | + match targetApiName: |
| 117 | + case 'vulkan': |
| 118 | + api_name = 'Vulkan' |
| 119 | + |
| 120 | + version_number = name[name.find('_VERSION_') + len('_VERSION_'):].replace('_', '.') |
| 121 | + return f'{api_name} {version_number}' |
| 122 | + |
| 123 | + @staticmethod |
| 124 | + def getFirstVersionName(targetApiName: str) -> str: |
| 125 | + match targetApiName: |
| 126 | + case 'vulkan': |
| 127 | + return 'VK_VERSION_1_0' |
| 128 | + |
| 129 | + # This handles the dependency across versions of APIs, even across API variants |
| 130 | + # (e.g. maps VK_VERSION_1_2 to VKSC_VERSION_1_0 for Vulkan SC). |
| 131 | + # This handles the lack of proper support for the "depends" attribute of <feature> tags in the XML. |
| 132 | + @staticmethod |
| 133 | + def getEffectiveVersionName(targetApiName: str, version: Version) -> str: |
| 134 | + if version is None: |
| 135 | + return APISpecific.getFirstVersionName(targetApiName) |
| 136 | + |
| 137 | + match targetApiName: |
| 138 | + case 'vulkan': |
| 139 | + return version.name |
| 140 | + |
| 141 | + |
106 | 142 | class LoaderExtensionGenerator(BaseGenerator): |
107 | 143 | def __init__(self): |
108 | 144 | BaseGenerator.__init__(self) |
@@ -224,14 +260,13 @@ def ConvertDependencyExpression(expr, replace_func): |
224 | 260 | return expr |
225 | 261 |
|
226 | 262 | def DescribeBlock(self, command, current_block, out, custom_commands_string = ' commands', indent = ' '): |
227 | | - if command.extensions != current_block and command.version != current_block: |
228 | | - if command.version is None and len(command.extensions) == 0: # special case for 1.0 |
229 | | - out.append(f'\n{indent}// ---- Core Vulkan 1.0{custom_commands_string}\n') |
230 | | - return None |
231 | | - elif command.version is not None: |
232 | | - if command.version != current_block: |
233 | | - out.append(f"\n{indent}// ---- Core Vulkan 1.{command.version.name.split('_')[-1]}{custom_commands_string}\n") |
234 | | - return command.version |
| 263 | + effective_version_name = APISpecific.getEffectiveVersionName(self.targetApiName, command.version) |
| 264 | + if command.extensions != current_block and effective_version_name != current_block: |
| 265 | + if effective_version_name and len(command.extensions) == 0: |
| 266 | + # Entry points that have an effective version in the target API |
| 267 | + api_version_display_name = APISpecific.getApiVersionDisplayName(self.targetApiName, effective_version_name) |
| 268 | + out.append(f"\n{indent}// ---- Core {api_version_display_name}{custom_commands_string}\n") |
| 269 | + return effective_version_name |
235 | 270 | else: |
236 | 271 | # don't repeat unless the first extension is different (while rest can vary) |
237 | 272 | if not isinstance(current_block, list) or current_block[0] != command.extensions[0]: |
@@ -503,7 +538,8 @@ def OutputIcdDispatchTableInit(self, out): |
503 | 538 | if command.protect is not None: |
504 | 539 | out.append( f'#if defined({command.protect})\n') |
505 | 540 |
|
506 | | - if command.version is None and len(command.extensions) == 0: |
| 541 | + effective_version_name = APISpecific.getEffectiveVersionName(self.targetApiName, command.version) |
| 542 | + if effective_version_name == APISpecific.getFirstVersionName(self.targetApiName) and len(command.extensions) == 0: |
507 | 543 | # The Core Vulkan code will be wrapped in a feature called VK_VERSION_#_# |
508 | 544 | # For example: VK_VERSION_1_0 wraps the core 1.0 Vulkan functionality |
509 | 545 | out.append(f' LOOKUP_REQUIRED_GIPA({command.name[2:]});\n') |
@@ -711,7 +747,9 @@ def OutputLoaderLookupFunc(self, out): |
711 | 747 | current_block = self.DescribeBlock(command, current_block, out) |
712 | 748 | if len(command.extensions) == 0: |
713 | 749 | if cur_type == 'device': |
714 | | - version_check = f" if (dev->should_ignore_device_commands_from_newer_version && api_version < {command.version.nameApi if command.version else 'VK_API_VERSION_1_0'}) return NULL;\n" |
| 750 | + effective_version_name = APISpecific.getEffectiveVersionName(self.targetApiName, command.version) |
| 751 | + api_version = effective_version_name.replace('_VERSION_', '_API_VERSION_') |
| 752 | + version_check = f" if (dev->should_ignore_device_commands_from_newer_version && api_version < {api_version}) return NULL;\n" |
715 | 753 | else: |
716 | 754 | version_check = '' |
717 | 755 |
|
|
0 commit comments