1# Copyright © 2020 Hoe Hao Cheng 2# 3# Permission is hereby granted, free of charge, to any person obtaining a 4# copy of this software and associated documentation files (the "Software"), 5# to deal in the Software without restriction, including without limitation 6# the rights to use, copy, modify, merge, publish, distribute, sublicense, 7# and/or sell copies of the Software, and to permit persons to whom the 8# Software is furnished to do so, subject to the following conditions: 9# 10# The above copyright notice and this permission notice (including the next 11# paragraph) shall be included in all copies or substantial portions of the 12# Software. 13# 14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20# IN THE SOFTWARE. 21# 22# Authors: 23# Hoe Hao Cheng <haochengho12907@gmail.com> 24# 25 26from mako.template import Template 27from mako.lookup import TemplateLookup 28from os import path 29from zink_extensions import Extension,ExtensionRegistry,Version 30import sys 31 32# constructor: 33# Extension(name, alias="", required=False, properties=False, features=False, conditions=None, guard=False) 34# The attributes: 35# - required: the generated code debug_prints "ZINK: {name} required!" and 36# returns NULL if the extension is unavailable. 37# 38# - properties: enable the detection of extension properties in a physical 39# device in the generated code using vkGetPhysicalDeviceProperties2(), 40# and store the returned properties struct inside 41# `zink_device_info.{alias}_props`. 42# Example: the properties for `VK_EXT_transform_feedback`, is stored in 43# `VkPhysicalDeviceTransformFeedbackPropertiesEXT tf_props`. 44# 45# - features: enable the getting extension features in a 46# device. Similar to `properties`, this stores the features 47# struct inside `zink_device_info.{alias}_feats`. 48# 49# - conditions: criteria for enabling an extension. This is an array of strings, 50# where each string is a condition, and all conditions have to be true 51# for `zink_device_info.have_{name}` to be true. 52# 53# The code generator will replace "$feats" and "$props" with the 54# respective variables, e.g. "$feats.nullDescriptor" becomes 55# "info->rb2_feats.nullDescriptor" in the final code for VK_EXT_robustness2. 56# 57# When empty or None, the extension is enabled when the extensions 58# given by vkEnumerateDeviceExtensionProperties() include the extension. 59# 60# - guard: adds a #if defined(`extension_name`)/#endif guard around the code generated for this Extension. 61EXTENSIONS = [ 62 Extension("VK_KHR_maintenance1", 63 required=True), 64 Extension("VK_KHR_maintenance2"), 65 Extension("VK_KHR_maintenance3"), 66 Extension("VK_KHR_maintenance4", 67 alias="maint4", 68 features=True), 69 Extension("VK_KHR_maintenance5", 70 alias="maint5", 71 features=True, properties=True), 72 Extension("VK_KHR_maintenance6", 73 alias="maint6", 74 features=True, properties=True), 75 Extension("VK_KHR_maintenance7", 76 alias="maint7", 77 features=True, properties=True), 78 Extension("VK_KHR_maintenance8", 79 alias="maint8", 80 features=True), 81 Extension("VK_KHR_external_memory"), 82 Extension("VK_KHR_external_memory_fd"), 83 Extension("VK_KHR_vulkan_memory_model"), 84 Extension("VK_KHR_workgroup_memory_explicit_layout", alias="explicit_layout", features=True), 85 Extension("VK_KHR_pipeline_executable_properties", 86 alias="pipestats", 87 features=True), 88 Extension("VK_KHR_external_semaphore_fd"), 89 Extension("VK_KHR_create_renderpass2", 90 required=True), 91 Extension("VK_KHR_synchronization2", 92 alias="sync2", 93 features=True), 94 Extension("VK_KHR_external_memory_win32"), 95 Extension("VK_KHR_external_semaphore_win32"), 96 Extension("VK_EXT_external_memory_dma_buf"), 97 Extension("VK_KHR_buffer_device_address", 98 alias="bda", 99 features=True), 100 Extension("VK_EXT_external_memory_host", alias="ext_host_mem", properties=True), 101 Extension("VK_EXT_queue_family_foreign"), 102 Extension("VK_KHR_swapchain_mutable_format"), 103 Extension("VK_KHR_incremental_present"), 104 Extension("VK_EXT_provoking_vertex", 105 alias="pv", 106 features=True, 107 properties=True, 108 conditions=["$feats.provokingVertexLast"]), 109 Extension("VK_EXT_shader_viewport_index_layer"), 110 Extension("VK_KHR_get_memory_requirements2"), 111 Extension("VK_EXT_post_depth_coverage"), 112 Extension("VK_EXT_depth_clip_control", 113 alias="clip_control", 114 features=True), 115 Extension("VK_EXT_depth_clamp_zero_one", 116 alias="clamp_01", 117 features=True), 118 Extension("VK_EXT_shader_subgroup_ballot"), 119 Extension("VK_EXT_shader_subgroup_vote"), 120 Extension("VK_EXT_legacy_vertex_attributes", alias="legacyverts", features=True, properties=True), 121 Extension("VK_EXT_shader_atomic_float", 122 alias="atomic_float", 123 features=True), 124 Extension("VK_KHR_shader_atomic_int64", 125 alias="atomic_int", 126 features=True), 127 Extension("VK_KHR_8bit_storage", 128 alias="storage_8bit", 129 features=True, 130 conditions=["$feats.storageBuffer8BitAccess"]), 131 Extension("VK_KHR_16bit_storage", 132 alias="storage_16bit", 133 features=True, 134 conditions=["$feats.storageBuffer16BitAccess"]), 135 Extension("VK_EXT_image_2d_view_of_3d", 136 alias="view2d", 137 features=True), 138 Extension("VK_KHR_driver_properties", 139 alias="driver", 140 properties=True), 141 Extension("VK_EXT_memory_budget"), 142 Extension("VK_EXT_memory_priority", alias="memprio", features=True), 143 Extension("VK_EXT_pageable_device_local_memory", alias="mempage", features=True), 144 Extension("VK_KHR_draw_indirect_count"), 145 Extension("VK_EXT_dynamic_rendering_unused_attachments", alias="unused", features=True), 146 Extension("VK_EXT_shader_object", alias="shobj", features=True, properties=True), 147 Extension("VK_EXT_attachment_feedback_loop_layout", 148 alias="feedback_loop", 149 features=True), 150 Extension("VK_EXT_attachment_feedback_loop_dynamic_state", alias="feedback_dyn", features=True), 151 Extension("VK_EXT_fragment_shader_interlock", 152 alias="interlock", 153 features=True, 154 conditions=["$feats.fragmentShaderSampleInterlock", "$feats.fragmentShaderPixelInterlock"]), 155 Extension("VK_EXT_sample_locations", 156 alias="sample_locations", 157 properties=True), 158 Extension("VK_KHR_shader_draw_parameters"), 159 Extension("VK_KHR_sampler_mirror_clamp_to_edge"), 160 Extension("VK_EXT_descriptor_buffer", alias="db", features=True, properties=True), 161 Extension("VK_EXT_conditional_rendering", 162 alias="cond_render", 163 features=True, 164 conditions=["$feats.conditionalRendering"]), 165 Extension("VK_EXT_transform_feedback", 166 alias="tf", 167 properties=True, 168 features=True, 169 conditions=["$feats.transformFeedback"]), 170 Extension("VK_EXT_index_type_uint8", 171 alias="index_uint8", 172 features=True, 173 conditions=["$feats.indexTypeUint8"]), 174 Extension("VK_KHR_image_format_list"), 175 Extension("VK_KHR_sampler_ycbcr_conversion"), 176 Extension("VK_KHR_imageless_framebuffer", 177 alias="imgless", 178 features=True, 179 required=True), 180 Extension("VK_EXT_robustness2", 181 alias="rb2", 182 properties=True, 183 features=True, 184 conditions=["$feats.nullDescriptor"]), 185 Extension("VK_EXT_image_robustness", 186 alias="rb_image", 187 features=True), 188 Extension("VK_EXT_image_drm_format_modifier"), 189 Extension("VK_EXT_vertex_attribute_divisor", 190 alias="vdiv", 191 properties=True, 192 features=True, 193 conditions=["$feats.vertexAttributeInstanceRateDivisor"]), 194 Extension("VK_EXT_calibrated_timestamps"), 195 Extension("VK_NV_linear_color_attachment", 196 alias="linear_color", 197 features=True), 198 Extension("VK_KHR_dynamic_rendering", 199 alias="dynamic_render", 200 features=True), 201 Extension("VK_KHR_dynamic_rendering_local_read", 202 alias="drlr", 203 features=True), 204 Extension("VK_EXT_multisampled_render_to_single_sampled", 205 alias="msrtss", 206 features=True), 207 Extension("VK_KHR_shader_clock", 208 alias="shader_clock", 209 features=True, 210 conditions=["$feats.shaderSubgroupClock"]), 211 Extension("VK_INTEL_shader_integer_functions2", 212 alias="shader_int_fns2", 213 features=True, 214 conditions=["$feats.shaderIntegerFunctions2"]), 215 Extension("VK_EXT_sampler_filter_minmax", 216 alias="reduction", 217 properties=True, 218 conditions=["$props.filterMinmaxSingleComponentFormats"]), 219 Extension("VK_EXT_custom_border_color", 220 alias="border_color", 221 properties=True, 222 features=True, 223 conditions=["$feats.customBorderColors"]), 224 Extension("VK_EXT_non_seamless_cube_map", 225 alias="nonseamless", 226 features=True), 227 Extension("VK_EXT_border_color_swizzle", 228 alias="border_swizzle", 229 features=True), 230 Extension("VK_EXT_blend_operation_advanced", 231 alias="blend", 232 properties=True, 233 # TODO: we can probably support non-premul here with some work? 234 conditions=["$props.advancedBlendNonPremultipliedSrcColor", "$props.advancedBlendNonPremultipliedDstColor"]), 235 Extension("VK_EXT_extended_dynamic_state", 236 alias="dynamic_state", 237 features=True, 238 conditions=["$feats.extendedDynamicState"]), 239 Extension("VK_EXT_extended_dynamic_state2", 240 alias="dynamic_state2", 241 features=True, 242 conditions=["$feats.extendedDynamicState2"]), 243 Extension("VK_EXT_extended_dynamic_state3", 244 alias="dynamic_state3", 245 properties=True, 246 features=True), 247 Extension("VK_EXT_pipeline_creation_cache_control", 248 alias="pipeline_cache_control", 249 features=True, 250 conditions=["$feats.pipelineCreationCacheControl"]), 251 Extension("VK_EXT_shader_stencil_export", 252 alias="stencil_export"), 253 Extension("VK_KHR_portability_subset", 254 alias="portability_subset", 255 features=True, 256 guard=True), 257 Extension("VK_NV_compute_shader_derivatives", 258 alias="shader_derivs", 259 features=True, 260 conditions=["$feats.computeDerivativeGroupQuads", "$feats.computeDerivativeGroupLinear"]), 261 Extension("VK_KHR_timeline_semaphore", 262 alias="timeline", 263 features=True), 264 Extension("VK_EXT_color_write_enable", 265 alias="cwrite", 266 features=True), 267 Extension("VK_EXT_4444_formats", 268 alias="format_4444", 269 features=True), 270 Extension("VK_EXT_host_image_copy", 271 alias="hic", 272 features=True, 273 properties=True), 274 Extension("VK_EXT_scalar_block_layout", 275 alias="scalar_block_layout", 276 features=True, 277 conditions=["$feats.scalarBlockLayout"]), 278 Extension("VK_KHR_swapchain"), 279 Extension("VK_EXT_rasterization_order_attachment_access", 280 alias="rast_order_access", 281 features=True, 282 conditions=["$feats.rasterizationOrderColorAttachmentAccess"]), 283 Extension("VK_KHR_shader_float16_int8", 284 alias="shader_float16_int8", 285 features=True), 286 Extension("VK_EXT_multi_draw", 287 alias="multidraw", 288 features=True, 289 properties=True, 290 conditions=["$feats.multiDraw"]), 291 Extension("VK_EXT_primitives_generated_query", 292 alias="primgen", 293 features=True), 294 Extension("VK_KHR_pipeline_library"), 295 Extension("VK_EXT_graphics_pipeline_library", 296 alias="gpl", 297 features=True, 298 properties=True), 299 Extension("VK_KHR_push_descriptor", 300 alias="push", 301 properties=True), 302 Extension("VK_KHR_descriptor_update_template", 303 alias="template", required=True), 304 Extension("VK_EXT_line_rasterization", 305 alias="line_rast", 306 properties=True, 307 features=True), 308 Extension("VK_EXT_vertex_input_dynamic_state", 309 alias="vertex_input", 310 features=True, 311 conditions=["$feats.vertexInputDynamicState"]), 312 Extension("VK_EXT_primitive_topology_list_restart", 313 alias="list_restart", 314 features=True, 315 conditions=["$feats.primitiveTopologyListRestart"]), 316 Extension("VK_KHR_dedicated_allocation", 317 alias="dedicated"), 318 Extension("VK_EXT_descriptor_indexing", 319 alias="desc_indexing", 320 features=True, 321 properties=True, 322 conditions=["$feats.descriptorBindingPartiallyBound"]), 323 Extension("VK_EXT_depth_clip_enable", 324 alias="depth_clip_enable", 325 features=True), 326 Extension("VK_EXT_shader_demote_to_helper_invocation", 327 alias="demote", 328 features=True, 329 conditions=["$feats.shaderDemoteToHelperInvocation"]), 330 Extension("VK_KHR_shader_float_controls", 331 alias="float_controls"), 332 Extension("VK_KHR_format_feature_flags2"), 333] 334 335# constructor: Versions(device_version(major, minor, patch), struct_version(major, minor)) 336# The attributes: 337# - device_version: Vulkan version, as tuple, to use with 338# VK_MAKE_VERSION(version_major, version_minor, version_patch) 339# 340# - struct_version: Vulkan version, as tuple, to use with structures and macros 341VERSIONS = [ 342 Version((1,1,0), (1,1)), 343 Version((1,2,0), (1,2)), 344 Version((1,3,0), (1,3)), 345] 346 347# There exists some inconsistencies regarding the enum constants, fix them. 348# This is basically generated_code.replace(key, value). 349REPLACEMENTS = { 350 "PROPERTIES_PROPERTIES": "PROPERTIES", 351} 352 353 354# This template provides helper functions for the other templates. 355# Right now, the following functions are defined: 356# - guard(ext) : surrounds the body with an if-def guard according to 357# `ext.extension_name()` if `ext.guard` is True. 358include_template = """ 359<%def name="guard_(ext, body)"> 360%if ext.guard: 361#ifdef ${ext.extension_name()} 362%endif 363 ${capture(body)|trim} 364%if ext.guard: 365#endif 366%endif 367</%def> 368 369## This ugliness is here to prevent mako from adding tons of excessive whitespace 370<%def name="guard(ext)">${capture(guard_, ext, body=caller.body).strip('\\r\\n')}</%def> 371""" 372 373header_code = """ 374<%namespace name="helpers" file="helpers"/> 375 376#ifndef ZINK_DEVICE_INFO_H 377#define ZINK_DEVICE_INFO_H 378 379#include "util/u_memory.h" 380 381#include <vulkan/vulkan_core.h> 382 383#ifdef VK_ENABLE_BETA_EXTENSIONS 384#include <vulkan/vulkan_beta.h> 385#endif 386 387#ifdef _WIN32 388#include <windows.h> 389#include <vulkan/vulkan_win32.h> 390#endif 391 392struct zink_screen; 393 394struct zink_device_info { 395 uint32_t device_version; 396 397%for ext in extensions: 398<%helpers:guard ext="${ext}"> 399 bool have_${ext.name_with_vendor()}; 400</%helpers:guard> 401%endfor 402%for version in versions: 403 bool have_vulkan${version.struct()}; 404%endfor 405 406 VkPhysicalDeviceFeatures2 feats; 407 VkPhysicalDeviceSubgroupProperties subgroup; 408%for version in versions: 409 VkPhysicalDeviceVulkan${version.struct()}Features feats${version.struct()}; 410%endfor 411 412 VkPhysicalDeviceProperties props; 413 VkPhysicalDeviceProperties vk_layered_props; 414 VkPhysicalDeviceLayeredApiPropertiesKHR layered_props; 415 VkPhysicalDeviceDriverPropertiesKHR vk_layered_driver_props; 416%for version in versions: 417 VkPhysicalDeviceVulkan${version.struct()}Properties props${version.struct()}; 418%endfor 419 420 VkPhysicalDeviceMemoryProperties mem_props; 421 VkPhysicalDeviceIDProperties deviceid_props; 422 423%for ext in extensions: 424<%helpers:guard ext="${ext}"> 425%if ext.has_features: 426 ${ext.physical_device_struct("Features")} ${ext.field("feats")}; 427%endif 428%if ext.has_properties: 429 ${ext.physical_device_struct("Properties")} ${ext.field("props")}; 430%endif 431</%helpers:guard> 432%endfor 433 434 const char *extensions[${len(extensions)}]; 435 uint32_t num_extensions; 436}; 437 438bool 439zink_get_physical_device_info(struct zink_screen *screen); 440 441void 442zink_verify_device_extensions(struct zink_screen *screen); 443 444/* stub functions that get inserted into the dispatch table if they are not 445 * properly loaded. 446 */ 447%for ext in extensions: 448%if registry.in_registry(ext.name): 449%for cmd in registry.get_registry_entry(ext.name).device_commands: 450void VKAPI_PTR zink_stub_${cmd.lstrip("vk")}(void); 451%endfor 452%endif 453%endfor 454 455#endif 456""" 457 458 459impl_code = """ 460<%namespace name="helpers" file="helpers"/> 461 462#include "vk_enum_to_str.h" 463#include "zink_device_info.h" 464#include "zink_screen.h" 465 466bool 467zink_get_physical_device_info(struct zink_screen *screen) 468{ 469 struct zink_device_info *info = &screen->info; 470%for ext in extensions: 471<%helpers:guard ext="${ext}"> 472 bool support_${ext.name_with_vendor()} = false; 473</%helpers:guard> 474%endfor 475 uint32_t num_extensions = 0; 476 477 // get device memory properties 478 screen->vk.GetPhysicalDeviceMemoryProperties(screen->pdev, &info->mem_props); 479 480 // enumerate device supported extensions 481 VkResult result = screen->vk.EnumerateDeviceExtensionProperties(screen->pdev, NULL, &num_extensions, NULL); 482 if (result != VK_SUCCESS) { 483 if (!screen->driver_name_is_inferred) 484 mesa_loge("ZINK: vkEnumerateDeviceExtensionProperties failed (%s)", vk_Result_to_str(result)); 485 } else { 486 if (num_extensions > 0) { 487 VkExtensionProperties *extensions = MALLOC(sizeof(VkExtensionProperties) * num_extensions); 488 if (!extensions) goto fail; 489 result = screen->vk.EnumerateDeviceExtensionProperties(screen->pdev, NULL, &num_extensions, extensions); 490 if (result != VK_SUCCESS) { 491 if (!screen->driver_name_is_inferred) 492 mesa_loge("ZINK: vkEnumerateDeviceExtensionProperties failed (%s)", vk_Result_to_str(result)); 493 } 494 495 for (uint32_t i = 0; i < num_extensions; ++i) { 496 %for ext in extensions: 497 <%helpers:guard ext="${ext}"> 498 if (!strcmp(extensions[i].extensionName, "${ext.name}")) { 499 %if not (ext.has_features or ext.has_properties): 500 info->have_${ext.name_with_vendor()} = true; 501 %else: 502 support_${ext.name_with_vendor()} = true; 503 %endif 504 } 505 </%helpers:guard> 506 %endfor 507 } 508 509 FREE(extensions); 510 } 511 } 512 513 // get device features 514 if (screen->vk.GetPhysicalDeviceFeatures2) { 515 // check for device extension features 516 info->feats.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; 517 518%for version in versions: 519%if version.device_version < (1,2,0): 520 if (VK_MAKE_VERSION(1,2,0) <= screen->vk_version) { 521 /* VkPhysicalDeviceVulkan11Features was added in 1.2, not 1.1 as one would think */ 522%else: 523 if (${version.version()} <= screen->vk_version) { 524%endif 525 info->feats${version.struct()}.sType = ${version.stype("FEATURES")}; 526 info->feats${version.struct()}.pNext = info->feats.pNext; 527 info->feats.pNext = &info->feats${version.struct()}; 528 info->have_vulkan${version.struct()} = true; 529 } 530%endfor 531 532%for ext in extensions: 533%if ext.has_features: 534<%helpers:guard ext="${ext}"> 535%if ext.features_promoted: 536 if (support_${ext.name_with_vendor()} && !info->have_vulkan${ext.core_since.struct()}) { 537%else: 538 if (support_${ext.name_with_vendor()}) { 539%endif 540 info->${ext.field("feats")}.sType = ${ext.stype("FEATURES")}; 541 info->${ext.field("feats")}.pNext = info->feats.pNext; 542 info->feats.pNext = &info->${ext.field("feats")}; 543 } 544</%helpers:guard> 545%endif 546%endfor 547 548 screen->vk.GetPhysicalDeviceFeatures2(screen->pdev, &info->feats); 549 } else { 550 screen->vk.GetPhysicalDeviceFeatures(screen->pdev, &info->feats.features); 551 } 552 553 // check for device properties 554 bool copy_layered_props = false; 555 if (screen->vk.GetPhysicalDeviceProperties2) { 556 VkPhysicalDeviceProperties2 props = {0}; 557 props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; 558 559%for version in versions: 560%if version.device_version < (1,2,0): 561 if (VK_MAKE_VERSION(1,2,0) <= screen->vk_version) { 562 /* VkPhysicalDeviceVulkan11Properties was added in 1.2, not 1.1 as one would think */ 563%else: 564 if (${version.version()} <= screen->vk_version) { 565%endif 566 info->props${version.struct()}.sType = ${version.stype("PROPERTIES")}; 567 info->props${version.struct()}.pNext = props.pNext; 568 props.pNext = &info->props${version.struct()}; 569 } 570%endfor 571 572%for ext in extensions: 573%if ext.has_properties: 574<%helpers:guard ext="${ext}"> 575%if ext.properties_promoted: 576 if (support_${ext.name_with_vendor()} && !info->have_vulkan${ext.core_since.struct()}) { 577%else: 578 if (support_${ext.name_with_vendor()}) { 579%endif 580 info->${ext.field("props")}.sType = ${ext.stype("PROPERTIES")}; 581 info->${ext.field("props")}.pNext = props.pNext; 582 props.pNext = &info->${ext.field("props")}; 583 } 584</%helpers:guard> 585%endif 586%endfor 587 588 if (screen->vk_version < VK_MAKE_VERSION(1,2,0) && screen->instance_info.have_KHR_external_memory_capabilities) { 589 info->deviceid_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES; 590 info->deviceid_props.pNext = props.pNext; 591 props.pNext = &info->deviceid_props; 592 } 593 594 if (screen->vk_version >= VK_MAKE_VERSION(1,1,0)) { 595 info->subgroup.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; 596 info->subgroup.pNext = props.pNext; 597 props.pNext = &info->subgroup; 598 } 599 600 /* set up structs to capture underlying driver info */ 601 VkPhysicalDeviceLayeredApiVulkanPropertiesKHR vk_layered_props = { 602 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_API_VULKAN_PROPERTIES_KHR, 603 }; 604 vk_layered_props.properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; 605 info->vk_layered_driver_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; 606 if (support_KHR_driver_properties || info->have_vulkan12) 607 vk_layered_props.properties.pNext = &info->vk_layered_driver_props; 608 info->layered_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_API_PROPERTIES_KHR; 609 info->layered_props.pNext = &vk_layered_props; 610 VkPhysicalDeviceLayeredApiPropertiesListKHR layered_props_list = { 611 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_API_PROPERTIES_LIST_KHR, 612 props.pNext, 613 1, 614 &info->layered_props 615 }; 616 if (support_KHR_maintenance7) 617 props.pNext = &layered_props_list; 618 619 // note: setting up local VkPhysicalDeviceProperties2. 620 screen->vk.GetPhysicalDeviceProperties2(screen->pdev, &props); 621 622 if (support_KHR_maintenance7 && layered_props_list.layeredApiCount) { 623 info->vk_layered_props = vk_layered_props.properties.properties; 624 } else { 625 info->vk_layered_props = info->props; 626 copy_layered_props = true; 627 } 628 } 629 630 /* We re-apply the fields from VkPhysicalDeviceVulkanXYFeatures struct 631 * onto their respective fields in the VkPhysicalDeviceExtensionNameFeatures 632 * struct if the former is provided by the VK implementation. 633 * 634 * As for why this is done: the spec mentions that once an extension is 635 * promoted to core and its feature fields are added in VulkanXYFeatures, 636 * including both ExtensionNameFeatures and VulkanXYFeatures at the same 637 * time is prohibited when using vkGetPhysicalDeviceFeatures2. 638 */ 639%for ext in extensions: 640%if ext.features_promoted: 641 if (info->have_vulkan${ext.core_since.struct()}) { 642 %for field in registry.get_registry_entry(ext.name).features_fields: 643 info->${ext.field("feats")}.${field} = info->feats${ext.core_since.struct()}.${field}; 644 %endfor 645 } 646%endif 647%endfor 648 649 /* See above, but for VulkanXYProperties. 650 * Unlike VulkanXYFeatures with all the booleans, VulkanXYProperties can 651 * contain different types of data, including arrays. The C language hates us 652 * when we assign an array to another array, therefore we use an memcpy here. 653 */ 654%for ext in extensions: 655%if ext.properties_promoted: 656 if (info->have_vulkan${ext.core_since.struct()}) { 657 %for field in registry.get_registry_entry(ext.name).properties_fields: 658 memcpy(&info->${ext.field("props")}.${field}, 659 &info->props${ext.core_since.struct()}.${field}, 660 sizeof(info->${ext.field("props")}.${field})); 661 %endfor 662 } 663%endif 664%endfor 665 666 if (copy_layered_props) 667 info->vk_layered_driver_props = info->driver_props; 668 669 // enable the extensions if they match the conditions given by ext.enable_conds 670 if (screen->vk.GetPhysicalDeviceProperties2) { 671 %for ext in extensions: 672<%helpers:guard ext="${ext}"> 673<% 674 conditions = "" 675 if ext.enable_conds: 676 for cond in ext.enable_conds: 677 cond = cond.replace("$feats", "info->" + ext.field("feats")) 678 cond = cond.replace("$props", "info->" + ext.field("props")) 679 conditions += "&& (" + cond + ")\\n" 680 conditions = conditions.strip() 681%>\ 682 info->have_${ext.name_with_vendor()} |= support_${ext.name_with_vendor()} 683 ${conditions}; 684</%helpers:guard> 685 %endfor 686 } 687 688 // generate extension list 689 num_extensions = 0; 690 691%for ext in extensions: 692<%helpers:guard ext="${ext}"> 693 if (info->have_${ext.name_with_vendor()}) { 694 info->extensions[num_extensions++] = "${ext.name}"; 695%if ext.is_required: 696 } else { 697 debug_printf("ZINK: ${ext.name} required!\\n"); 698 goto fail; 699%endif 700 } 701</%helpers:guard> 702%endfor 703 704 info->num_extensions = num_extensions; 705 706 info->feats.pNext = NULL; 707 708%for version in versions: 709%if version.device_version < (1,2,0): 710 if (VK_MAKE_VERSION(1,2,0) <= screen->vk_version) { 711 /* VkPhysicalDeviceVulkan11Features was added in 1.2, not 1.1 as one would think */ 712%else: 713 if (${version.version()} <= screen->vk_version) { 714%endif 715 info->feats${version.struct()}.pNext = info->feats.pNext; 716 info->feats.pNext = &info->feats${version.struct()}; 717 } 718%endfor 719 720%for ext in extensions: 721%if ext.has_features: 722<%helpers:guard ext="${ext}"> 723%if ext.features_promoted: 724 if (info->have_${ext.name_with_vendor()} && !info->have_vulkan${ext.core_since.struct()}) { 725%else: 726 if (info->have_${ext.name_with_vendor()}) { 727%endif 728 info->${ext.field("feats")}.sType = ${ext.stype("FEATURES")}; 729 info->${ext.field("feats")}.pNext = info->feats.pNext; 730 info->feats.pNext = &info->${ext.field("feats")}; 731 } 732</%helpers:guard> 733%endif 734%endfor 735 736 return true; 737 738fail: 739 return false; 740} 741 742void 743zink_verify_device_extensions(struct zink_screen *screen) 744{ 745%for ext in extensions: 746%if registry.in_registry(ext.name): 747<%helpers:guard ext="${ext}"> 748 if (screen->info.have_${ext.name_with_vendor()}) { 749%for cmd in registry.get_registry_entry(ext.name).device_commands: 750%if cmd.find("win32"): 751#ifdef _WIN32 752%endif 753 if (!screen->vk.${cmd.lstrip("vk")}) { 754#ifndef NDEBUG 755 screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_${cmd.lstrip("vk")}; 756#else 757 screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_function_not_loaded; 758#endif 759 } 760%if cmd.find("win32"): 761#endif 762%endif 763%endfor 764 } 765</%helpers:guard> 766%endif 767%endfor 768} 769 770#ifndef NDEBUG 771/* generated stub functions */ 772## remember the stub functions that are already generated 773<% generated_funcs = set() %> 774 775%for ext in extensions: 776%if registry.in_registry(ext.name): 777%for cmd in registry.get_registry_entry(ext.name).device_commands: 778## 779## some functions are added by multiple extensions, which creates duplication 780## and thus redefinition of stubs (eg. vkCmdPushDescriptorSetWithTemplateKHR) 781## 782%if cmd in generated_funcs: 783 <% continue %> 784%else: 785 <% generated_funcs.add(cmd) %> 786%endif 787void VKAPI_PTR 788zink_stub_${cmd.lstrip("vk")}() 789{ 790 mesa_loge("ZINK: ${cmd} is not loaded properly!"); 791 abort(); 792} 793%endfor 794%endif 795%endfor 796#endif 797""" 798 799 800def replace_code(code: str, replacement: dict): 801 for (k, v) in replacement.items(): 802 code = code.replace(k, v) 803 804 return code 805 806 807if __name__ == "__main__": 808 try: 809 header_path = sys.argv[1] 810 impl_path = sys.argv[2] 811 vkxml_path = sys.argv[3] 812 813 header_path = path.abspath(header_path) 814 impl_path = path.abspath(impl_path) 815 vkxml_path = path.abspath(vkxml_path) 816 except: 817 print("usage: %s <path to .h> <path to .c> <path to vk.xml>" % sys.argv[0]) 818 exit(1) 819 820 registry = ExtensionRegistry(vkxml_path) 821 822 extensions = EXTENSIONS 823 versions = VERSIONS 824 replacement = REPLACEMENTS 825 826 # Perform extension validation and set core_since for the extension if available 827 error_count = 0 828 for ext in extensions: 829 if not registry.in_registry(ext.name): 830 # disable validation for nonstandard extensions 831 if ext.is_nonstandard: 832 continue 833 834 error_count += 1 835 print("The extension {} is not registered in vk.xml - a typo?".format(ext.name)) 836 continue 837 838 entry = registry.get_registry_entry(ext.name) 839 840 if entry.ext_type != "device": 841 error_count += 1 842 print("The extension {} is {} extension - expected a device extension.".format(ext.name, entry.ext_type)) 843 continue 844 845 if ext.has_features: 846 if not (entry.features_struct and ext.physical_device_struct("Features") == entry.features_struct): 847 error_count += 1 848 print("The extension {} does not provide a features struct.".format(ext.name)) 849 ext.features_promoted = entry.features_promoted 850 851 if ext.has_properties: 852 if not (entry.properties_struct and ext.physical_device_struct("Properties") == entry.properties_struct): 853 error_count += 1 854 print("The extension {} does not provide a properties struct.".format(ext.name)) 855 ext.properties_promoted = entry.properties_promoted 856 857 if entry.promoted_in and entry.promoted_in <= versions[-1].struct_version: 858 ext.core_since = Version((*entry.promoted_in, 0)) 859 else: 860 # even if the ext is promoted in a newer VK version, consider it 861 # unpromoted until there's an entry for that VK version in VERSIONS 862 ext.features_promoted = False 863 ext.properties_promoted = False 864 865 if error_count > 0: 866 print("zink_device_info.py: Found {} error(s) in total. Quitting.".format(error_count)) 867 exit(1) 868 869 lookup = TemplateLookup() 870 lookup.put_string("helpers", include_template) 871 872 with open(header_path, "w", encoding='utf-8') as header_file: 873 header = Template(header_code, lookup=lookup).render(extensions=extensions, versions=versions, registry=registry).strip() 874 header = replace_code(header, replacement) 875 print(header, file=header_file) 876 877 with open(impl_path, "w", encoding='utf-8') as impl_file: 878 impl = Template(impl_code, lookup=lookup).render(extensions=extensions, versions=versions, registry=registry).strip() 879 impl = replace_code(impl, replacement) 880 print(impl, file=impl_file) 881