zink: add support to device info for macro guards and just VkPhysicalDevice*Features with out the have_.

Extends the flexability of the device info script.
Allows #if defined()/#endif guards around particular data, for platform or version specific structures.
Allows for feature structures to be retreved without having to have a have_ variable as well. Helps if there is more than one feature in the structure.

These changes help towards allowing the use of the portability set extensions.

Reviewed-by: Hoe Hao Cheng <haochengho12907@gmail.com>
Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7457>
diff --git a/src/gallium/drivers/zink/zink_device_info.py b/src/gallium/drivers/zink/zink_device_info.py
index 159502b..7e334c5 100644
--- a/src/gallium/drivers/zink/zink_device_info.py
+++ b/src/gallium/drivers/zink/zink_device_info.py
@@ -28,7 +28,7 @@
 import re
 import sys
 
-# constructor: Extensions(name, alias="", required=False, properties=False, feature=None)
+# constructor: Extensions(name, alias="", required=False, properties=False, features=False, have_feature=None, guard=False)
 # The attributes:
 #  - required: the generated code debug_prints "ZINK: {name} required!" and
 #              returns NULL if the extension is unavailable.
@@ -40,30 +40,37 @@
 #                Example: the properties for `VK_EXT_transform_feedback`, is stored in
 #                `VkPhysicalDeviceTransformFeedbackPropertiesEXT tf_props`.
 #
-#  - feature: enable the fine-grained detection of extension features in a
+#  - have_feature: enable the fine-grained detection of extension features in a
 #             device. Similar to `properties`, this stores the features
 #             struct inside `zink_device_info.{alias}_feats`.
 #             It sets `zink_device_info.have_{name} = true` only if
-#             `{alias}_feats.{feature}` is true. 
-#             If feature is None, `have_{extension_name}` is true when the extensions
+#             `{alias}_feats.{has_feature}` is true. 
+#             If have_feature is None, `have_{extension_name}` is true when the extensions
 #             given by vkEnumerateDeviceExtensionProperties() include the extension.
 #             Furthermore, `zink_device_info.{extension_alias}_feats` is unavailable.
+#
+#  - features: enable the getting extension features in a
+#              device. Similar to `have_feature`, this stores the features
+#              struct inside `zink_device_info.{alias}_feats`.
+#              Unlike `have_feature` it does not create a `have_` member.
+#
+#  - guard: adds a #if defined(`extension_name`)/#endif guard around the code generated for this Extension.
 def EXTENSIONS():
     return [
         Extension("VK_KHR_maintenance1",             required=True),
         Extension("VK_KHR_external_memory",          required=True),
         Extension("VK_KHR_external_memory_fd"),
         Extension("VK_KHR_vulkan_memory_model"),
-        Extension("VK_EXT_conditional_rendering",    alias="cond_render", feature="conditionalRendering"),
-        Extension("VK_EXT_transform_feedback",       alias="tf", properties=True, feature="transformFeedback"),
-        Extension("VK_EXT_index_type_uint8",         alias="index_uint8", feature="indexTypeUint8"),
-        Extension("VK_EXT_robustness2",              alias="rb2", properties=True, feature="nullDescriptor"),
-        Extension("VK_EXT_vertex_attribute_divisor", alias="vdiv", properties=True, feature="vertexAttributeInstanceRateDivisor"),
+        Extension("VK_EXT_conditional_rendering",    alias="cond_render", have_feature="conditionalRendering"),
+        Extension("VK_EXT_transform_feedback",       alias="tf", properties=True, have_feature="transformFeedback"),
+        Extension("VK_EXT_index_type_uint8",         alias="index_uint8", have_feature="indexTypeUint8"),
+        Extension("VK_EXT_robustness2",              alias="rb2", properties=True, have_feature="nullDescriptor"),
+        Extension("VK_EXT_vertex_attribute_divisor", alias="vdiv", properties=True, have_feature="vertexAttributeInstanceRateDivisor"),
         Extension("VK_EXT_calibrated_timestamps"),
-        Extension("VK_EXT_custom_border_color",      alias="border_color", properties=True, feature="customBorderColors"),
+        Extension("VK_EXT_custom_border_color",      alias="border_color", properties=True, have_feature="customBorderColors"),
         Extension("VK_EXT_blend_operation_advanced", alias="blend", properties=True),
-        Extension("VK_EXT_extended_dynamic_state",   alias="dynamic_state", feature="extendedDynamicState"),
-        Extension("VK_EXT_pipeline_creation_cache_control",   alias="pipeline_cache_control", feature="pipelineCreationCacheControl"),
+        Extension("VK_EXT_extended_dynamic_state",   alias="dynamic_state", have_feature="extendedDynamicState"),
+        Extension("VK_EXT_pipeline_creation_cache_control",   alias="pipeline_cache_control", have_feature="pipelineCreationCacheControl"),
         Extension("VK_EXT_shader_stencil_export",    alias="stencil_export"),
     ]
 
@@ -87,7 +94,9 @@
 
 struct zink_device_info {
 %for ext in extensions:
+   ${ext.guard_start()}
    bool have_${ext.name_with_vendor()};
+   ${ext.guard_end()}
 %endfor
 
    VkPhysicalDeviceFeatures2 feats;
@@ -95,12 +104,14 @@
    VkPhysicalDeviceMemoryProperties mem_props;
 
 %for ext in extensions:
-%if ext.feature_field is not None:
+   ${ext.guard_start()}
+%if ext.feature_field is not None or ext.has_features:
    VkPhysicalDevice${ext.name_in_camel_case()}Features${ext.vendor()} ${ext.field("feats")};
 %endif
 %if ext.has_properties:
    VkPhysicalDevice${ext.name_in_camel_case()}Properties${ext.vendor()} ${ext.field("props")};
 %endif
+   ${ext.guard_end()}
 %endfor
 
     const char *extensions[${len(extensions)}];
@@ -123,7 +134,9 @@
 {
    struct zink_device_info *info = &screen->info;
 %for ext in extensions:
+   ${ext.guard_start()}
    bool support_${ext.name_with_vendor()} = false;
+   ${ext.guard_end()}
 %endfor
    uint32_t num_extensions = 0;
 
@@ -138,9 +151,11 @@
 
          for (uint32_t i = 0; i < num_extensions; ++i) {
          %for ext in extensions:
+            ${ext.guard_start()}
             if (!strcmp(extensions[i].extensionName, "${ext.name}")) {
                support_${ext.name_with_vendor()} = true;
             }
+            ${ext.guard_end()}
          %endfor
          }
 
@@ -152,18 +167,21 @@
    info->feats.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
 
 %for ext in extensions:
-%if ext.feature_field is not None:
+%if ext.feature_field is not None or ext.has_features:
+   ${ext.guard_start()}
    if (support_${ext.name_with_vendor()}) {
       info->${ext.field("feats")}.sType = ${ext.stype("FEATURES")};
       info->${ext.field("feats")}.pNext = info->feats.pNext;
       info->feats.pNext = &info->${ext.field("feats")};
    }
+   ${ext.guard_end()}
 %endif
 %endfor
 
    vkGetPhysicalDeviceFeatures2(screen->pdev, &info->feats);
 
 %for ext in extensions:
+   ${ext.guard_start()}
 %if ext.feature_field is None:
    info->have_${ext.name_with_vendor()} = support_${ext.name_with_vendor()};
 %else:
@@ -171,6 +189,7 @@
       info->have_${ext.name_with_vendor()} = true;
    }
 %endif
+   ${ext.guard_end()}
 %endfor
 
    // check for device properties
@@ -179,11 +198,13 @@
 
 %for ext in extensions:
 %if ext.has_properties:
+   ${ext.guard_start()}
    if (info->have_${ext.name_with_vendor()}) {
       info->${ext.field("props")}.sType = ${ext.stype("PROPERTIES")};
       info->${ext.field("props")}.pNext = props.pNext;
       props.pNext = &info->${ext.field("props")};
    }
+   ${ext.guard_end()}
 %endif
 %endfor
 
@@ -194,6 +215,7 @@
    num_extensions = 0;
 
 %for ext in extensions:
+   ${ext.guard_start()}
    if (info->have_${ext.name_with_vendor()}) {
        info->extensions[num_extensions++] = "${ext.name}";
 %if ext.is_required:
@@ -202,6 +224,7 @@
        goto fail;
 %endif
    }
+   ${ext.guard_end()}
 %endfor
 
    info->num_extensions = num_extensions;
@@ -218,16 +241,20 @@
     alias          : str  = None
     is_required    : bool = False
     has_properties : bool = False
-    feature_field : str  = None
+    has_features   : bool = False
+    feature_field  : str  = None
+    guard          : bool = False
 
-    def __init__(self, name, alias="", required=False, properties=False, feature=None):
+    def __init__(self, name, alias="", required=False, properties=False, features=False, have_feature=None, guard=False):
         self.name = name
         self.alias = alias
         self.is_required = required
         self.has_properties = properties
-        self.feature_field = feature
+        self.has_features = features
+        self.feature_field = have_feature
+        self.guard = guard
 
-        if alias == "" and (properties == True or feature is not None):
+        if alias == "" and (properties == True or have_feature is not None):
             raise RuntimeError("alias must be available when properties/feature is used")
 
     # e.g.: "VK_EXT_robustness2" -> "robustness2"
@@ -272,6 +299,21 @@
     def vendor(self):
         return self.name.split('_')[1]
 
+    # e.g. #if defined(VK_EXT_robustness2)
+    def guard_start(self):
+        if self.guard == False:
+            return ""
+        return ("#if defined("
+                + self.extension_name()
+                + ")")
+
+    # e.g. #endif // VK_EXT_robustness2
+    def guard_end(self):
+        if self.guard == False:
+            return ""
+        return ("#endif //"
+                + self.extension_name())
+
 
 def replace_code(code: str, replacement: dict):
     for (k, v) in replacement.items():