#! /usr/bin/awk -f # Copyright 2019-2020 Mark Callow # SPDX-License-Identifier: Apache-2.0 # This script creates 3 files from vulkan/vulkan_core.h: # # - vkformat_enum.h, the VkFormat enum declaration for those who don't # want to include vulkan_core.h. # - vkformat_str.c, a switch statement for converting VkFormat enums to # to strings corresponding to the format names. # - vkformat_check.c, 2 functions: 1 to checking if a format is prohibited in # KTX2 and the other to see if a format is valid. # KTX2. BEGIN { vulkan_core = "vulkan_core.h" processing_core_formats = 0 processing_extension_formats = 0 # Range pattern matches 2nd line to avoid other comments so need # comment opening. copyright = "/*\n" banner = "" format_decl = "" core_formats = "" extension_formats = "" end_range = "" max_std_format_enum = 0 prohibited = "#include \n#include \n\n" prohibited = prohibited "#include \"vkformat_enum.h\"\n\n" prohibited = prohibited "bool\nisProhibitedFormat(VkFormat format)\n{\n" prohibited = prohibited " switch (format) {\n"; valid = "bool\nisValidFormat(VkFormat format)\n{\n" valid = valid " if (format <= VK_FORMAT_MAX_STANDARD_ENUM)\n" valid = valid " return true;\n else switch(format) {\n" if (ARGC == 2) { output_dir = ARGV[1] "/"; } format_hdr = output_dir "vkformat_enum.h" format_strings = output_dir "vkformat_str.c" format_check = output_dir "vkformat_check.c" # Use local vulkan_core.h until ASTC 3D texture extension is released. # if (ENVIRON["Vulkan_INCLUDE_DIR"]) { # vulkan_include_dir = ENVIRON["Vulkan_INCLUDE_DIR"]; # } else { # vulkan_include_dir = "/usr/include"; # } # ARGV[1] = vulkan_include_dir"/vulkan/"vulkan_core; ARGC = 2 ARGV[1] = "lib/dfdutils/vulkan/"vulkan_core; ARGC = 2 } # A range pattern to extract the copyright message. /\*\* Copyright*/,/\*\// { copyright = copyright $0 "\n" } $2 == "VK_HEADER_VERSION" { banner = "\n" banner = banner "/***************************** Do not edit. *****************************\n" banner = banner " Automatically generated from " vulkan_core " version " $3 " by mkvkformatfiles.\n" banner = banner " *************************************************************************/\n" } # Extract VkFlags definition. /typedef .* VkFlags/ { format_decl = format_decl "#if defined(_MSC_VER) && _MSC_VER < 1900 // Older than VS 2015.\n" format_decl = format_decl "typedef unsigned __int32 VkFlags;\n#else\n" format_decl = format_decl "#include \n" format_decl = format_decl $0 "\n#endif\n\n" } # A range pattern to extract the VkFormat declaration. /^typedef enum VkFormat {/,/^} VkFormat;/ { if ($3 !~ /VK_FORMAT_.*/) { # Avoid values defined as existing values. format_decl = format_decl $0 "\n" if ($1 ~ /VK_FORMAT/ && $1 !~ /.*MAX_ENUM/ && $3 !~ /1000....../) { # I don't understand why but if I apply the sub to $3 here, it # breaks extraction of VK_FORMAT token names below. It is like # this $3 becomes the $3 seen down there. enum_val = $3; sub(/,$/, "", enum_val); if (enum_val+0 > max_std_format_enum) { max_std_format_enum = enum_val+0; } } } if ($1 ~ /}/) { end_range = "#define VK_FORMAT_MAX_STANDARD_ENUM " max_std_format_enum "\n"; } } /.*SCALED|A8B8G8R8_.*_PACK32/ { prohibited = prohibited " case " $1 ":\n"; } #/A8B8G8R8_.*_PACK32/ { prohibited = prohibited " case " $1 ":\n"; } # Multiplane formats. /VK_FORMAT_[^F]/ && (/PLANE/ || /422/ || /420/) { # Avoid values defined as existing values and avoid the MAX_ENUM value. if ($3 !~ /VK_FORMAT_.*/ && $1 !~ /.*MAX_ENUM/) { prohibited = prohibited " case " $1 ":\n"; } } # Extract valid formats with values > VK_FORMAT_END_RANGE. /VK_FORMAT_[^F].* = 1000/ && ! /PLANE/ && ! /422/ && !/420/ { valid = valid " case " $1 ":\n"; } # Extract VK_FORMAT token names. [^F] avoids the VK_FORMAT_FEATURE* tokens. / VK_FORMAT_[^F]/ { # Avoid values defined as existing values and avoid the MAX_ENUM value. if ($3 !~ /VK_FORMAT_.*/ && $1 !~ /.*MAX_ENUM/) { switch_body = switch_body " case " $1 ":\n return \"" $1 "\";\n" } } function write_header_file(guard1, guard2, body, filename) { if (guard2) { print "#if !defined("guard1") && !defined("guard2")" > filename } else { print "#ifndef "guard1 > filename } print "#define "guard1 > filename print banner > filename print copyright > filename print body > filename print "#endif /* "guard1" */" > filename } function write_source_file(body, filename) { print banner > filename print copyright > filename print body > filename } END { # vkformat_enum.h write_header_file("_VKFORMAT_ENUM_H_", "VULKAN_CORE_H_", format_decl "\n" end_range, format_hdr); # vkformat_prohibited.c prohibited = prohibited " return true;\n" prohibited = prohibited " default:\n return false;\n }\n}\n"; valid = valid " return true;\n" valid = valid " default:\n return false;\n }\n}\n"; write_source_file(prohibited "\n" valid, format_check) # vkformat_str.c prelude = "\n"; prelude = prelude "#include \n\n"; prelude = prelude "#include \"vkformat_enum.h\"\n\n"; prelude = prelude "const char*\nvkFormatString(VkFormat format)\n{\n"; prelude = prelude " switch (format) {\n"; postscript = " default:\n return \"VK_UNKNOWN_FORMAT\";\n"; postscript = postscript " }\n"; postscript = postscript "}\n"; write_source_file(prelude switch_body postscript, format_strings); } # vim:ai:ts=4:sts=4:sw=2:expandtab:textwidth=70