| COPYRIGHT=u""" |
| /* Copyright 2024 Valve Corporation |
| * Copyright 2021 Intel Corporation |
| * SPDX-License-Identifier: MIT |
| */ |
| """ |
| |
| import argparse |
| from vk_physical_device_features_gen import get_renamed_feature, str_removeprefix |
| import os |
| import sys |
| import xml.etree.ElementTree as et |
| |
| import mako |
| from mako.template import Template |
| |
| TEMPLATE_C = Template(COPYRIGHT + """ |
| /* This file generated from ${filename}, don't edit directly. */ |
| |
| #include "vk_physical_device.h" |
| #include "vk_instance.h" |
| #include "vk_shader.h" |
| |
| /* for spirv_supported_capabilities */ |
| #include "compiler/spirv/spirv_info.h" |
| |
| struct spirv_capabilities |
| vk_physical_device_get_spirv_capabilities(const struct vk_physical_device *pdev) |
| { |
| const struct vk_features *f = &pdev->supported_features; |
| const struct vk_device_extension_table *e = &pdev->supported_extensions; |
| const struct vk_properties *p = &pdev->properties; |
| uint32_t api_version = pdev->instance->app_info.api_version; |
| |
| struct spirv_capabilities caps = { false, }; |
| |
| /* We |= for everything because some caps have multiple names but the |
| * same enum value and they sometimes have different enables in the |
| * Vulkan spec. To handle this, we just | all the enables together. |
| */ |
| % for cap in caps: |
| caps.${cap} |= ${' | '.join(caps[cap])}; |
| % endfor |
| |
| return caps; |
| } |
| """) |
| |
| # These don't exist in the SPIR-V headers for one reason or another. |
| NON_EXISTANT_CAPS = [ |
| # This isn't a cap, it's an execution mode. |
| # |
| # https://gitlab.khronos.org/vulkan/vulkan/-/merge_requests/6618 |
| 'MaximallyReconvergesKHR', |
| |
| # This extension got published but never got merged to SPIRV-Headers |
| # |
| # https://gitlab.khronos.org/spirv/spirv-extensions/-/merge_requests/238 |
| 'ClusterCullingShadingHUAWEI', |
| |
| # Exclude the one beta cap. |
| 'ShaderEnqueueAMDX', |
| ] |
| |
| def process_enable(enab): |
| attrib = enab.attrib |
| |
| if 'property' in attrib: |
| if attrib['value'] == 'VK_TRUE': |
| return f"p->{attrib['member']}" |
| else: |
| return f"(p->{attrib['member']} & {attrib['value']})" |
| elif 'extension' in attrib: |
| return f"e->{str_removeprefix(attrib['extension'], 'VK_')}" |
| elif 'feature' in attrib: |
| feat = get_renamed_feature(attrib['struct'], attrib['feature']) |
| return f"f->{feat}" |
| else: |
| version = attrib['version'] |
| return f"(api_version >= VK_API_{str_removeprefix(version, 'VK_')})" |
| |
| def get_capabilities(doc, beta): |
| caps = {} |
| |
| for cap in doc.findall('./spirvcapabilities/spirvcapability'): |
| name = cap.attrib['name'] |
| if name in NON_EXISTANT_CAPS: |
| continue |
| |
| enables = cap.findall('enable') |
| lst = caps.setdefault(name, []) |
| lst += [process_enable(x) for x in enables] |
| |
| # Remove duplicates |
| for cap in caps: |
| caps[cap] = list(dict.fromkeys(caps[cap])) |
| |
| return caps |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser() |
| parser.add_argument('--out-c', required=True, help='Output C file.') |
| parser.add_argument('--beta', required=True, help='Enable beta extensions.') |
| parser.add_argument('--xml', required=True, help='Vulkan API XML file.') |
| args = parser.parse_args() |
| |
| environment = { |
| 'filename': os.path.basename(__file__), |
| 'caps': get_capabilities(et.parse(args.xml), args.beta), |
| } |
| |
| try: |
| with open(args.out_c, 'w', encoding='utf-8') as f: |
| f.write(TEMPLATE_C.render(**environment)) |
| except Exception: |
| # In the event there's an error, this uses some helpers from mako |
| # to print a useful stack trace and prints it, then exits with |
| # status 1, if python is run with debug; otherwise it just raises |
| # the exception |
| print(mako.exceptions.text_error_template().render(), file=sys.stderr) |
| sys.exit(1) |
| |
| if __name__ == '__main__': |
| main() |