1// 2// Copyright (C) 2024 The Android Open Source Project 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15// 16 17package vulkan_xml 18 19import ( 20 "berberis/cpp_types" 21 "fmt" 22 "testing" 23) 24 25func TestUnmarshallNameAsString(t *testing.T) { 26 registry, err := Unmarshal([]byte(` 27 <?xml version="1.0" encoding="UTF-8"?> 28 <registry> 29 <types> 30 <type>This type is <name>int</name></type> 31 <type category="test">Here is <name>type_name</name></type> 32 </types> 33 </registry>`)) 34 if err != nil { 35 t.Error("Failed to parse test XML") 36 return 37 } 38 if registry.Types[0].Name != "int" { 39 t.Error("Name of type improperly parsed") 40 } 41 if registry.Types[1].Name != "type_name" { 42 t.Error("Name of type improperly parsed") 43 } 44} 45 46func TestUnknownType(t *testing.T) { 47 _, err := Unmarshal([]byte(` 48 <?xml version="1.0" encoding="UTF-8"?> 49 <registry> 50 <types> 51 <type name="Foo"/> 52 </types> 53 </registry>`)) 54 if err == nil { 55 t.Error("XML was errorneously accepted") 56 return 57 } 58 if err.Error() != "Unknown type without category: \"Foo\"" { 59 t.Error("Unexpected error: \"" + err.Error() + "\"") 60 } 61} 62 63func TestStructType(t *testing.T) { 64 registry, err := Unmarshal([]byte(` 65 <?xml version="1.0" encoding="UTF-8"?> 66 <registry> 67 <types> 68 <type category="union" name="Union"> 69 <member><type>float</type> <name>float32</name>[4]</member> 70 <member>const <type>int32_t</type> <name>int32</name>[4]</member> 71 </type> 72 </types> 73 </registry>`)) 74 if err != nil { 75 t.Error("Failed to parse test XML") 76 return 77 } 78 if registry.Types[0].Members[0].Name != "float32" { 79 t.Error("Name of member improperly parsed") 80 } 81 if registry.Types[0].Members[1].Name != "int32" { 82 t.Error("Name of member improperly parsed") 83 } 84 85} 86 87func TestEnumWarts(t *testing.T) { 88 registry, err := Unmarshal([]byte(` 89 <?xml version="1.0" encoding="UTF-8"?> 90 <registry> 91 <enums name="API Constants"> 92 <enum value="1000.0f" 93 name="VK_LOD_CLAMP_NONE" 94 comment="We don't care about this enum value but our parser shouldn't choke on it"/> 95 <enum value="0" 96 name="VK_FALSE" 97 comment="We don't care about thus enum value but our parser shouldn't choke on it"/> 98 </enums> 99 <feature api="vulkan" name="VK_VERSION_1_0" number="1.0"> 100 <require comment="API constants"> 101 <enum name="VK_FALSE"/> 102 </require> 103 </feature> 104 </registry>`)) 105 if err != nil { 106 t.Error("Failed to parse test XML") 107 return 108 } 109 _, _, _, _, _, err = VulkanTypesfromXML(registry) 110 if err != nil { 111 t.Error("Failed to parse test XML") 112 return 113 } 114} 115 116func TestEnumExtend(t *testing.T) { 117 registry, err := Unmarshal([]byte(` 118 <?xml version="1.0" encoding="UTF-8"?> 119 <registry> 120 <types> 121 <type name="VkStructureType" category="enum"/> 122 </types> 123 <feature api="vulkan" name="VK_VERSION_1_1" number="1.1"> 124 <require> 125 <enum extends="VkStructureType" extnumber="158" offset="1" name="VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO"/> 126 </require> 127 </feature> 128 <extensions> 129 <extension name="VK_KHR_swapchain" number="2"> 130 <require> 131 <enum value="70" name="VK_KHR_SWAPCHAIN_SPEC_VERSION"/> 132 <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PRESENT_INFO_KHR"/> 133 </require> 134 </extension> 135 </extensions> 136 </registry>`)) 137 if err != nil { 138 t.Error("Failed to parse test XML") 139 return 140 } 141 _, types, _, _, extensions, err := VulkanTypesfromXML(registry) 142 if err != nil { 143 t.Error("Failed to parse test XML") 144 return 145 } 146 if extension_spec, ok := extensions["VK_KHR_swapchain"]; ok { 147 if extension_spec != 70 { 148 t.Error("VK_KHR_swapchain spec is not 70") 149 } 150 } else { 151 t.Error("VK_KHR_swapchain extension not found") 152 } 153 if typе, ok := types["VkStructureType"]; ok { 154 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 155 if typе.Kind(arch) != cpp_types.Enum { 156 t.Error("VkStructureType is not enum") 157 } 158 if typе.Elem(arch).Kind(arch) != cpp_types.Int32T { 159 t.Error("VkStructureType is not std::int32_t-based enum") 160 } 161 if typе.NumField(arch) != 2 { 162 t.Error("VkStructureType is supposed to have two fields") 163 } 164 enumerator := typе.Field(0, arch).(cpp_types.EnumFieldInfo) 165 if enumerator.Name() != "VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO" { 166 t.Error("VkStructureType's first element is not VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO") 167 } 168 if enumerator.Value() != 1000157001 { 169 t.Error("VkStructureType's first element is not 1000157001") 170 } 171 enumerator = typе.Field(1, arch).(cpp_types.EnumFieldInfo) 172 if enumerator.Name() != "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR" { 173 t.Error("VkStructureType's first element is not VK_STRUCTURE_TYPE_PRESENT_INFO_KHR") 174 } 175 if enumerator.Value() != 1000001001 { 176 t.Error("VkStructureType's first element is not 1000001001") 177 } 178 } 179 return 180 } 181 t.Error("VkStructureType type wasn't parsed") 182} 183 184func TestEnumUInt32(t *testing.T) { 185 registry, err := Unmarshal([]byte(` 186 <?xml version="1.0" encoding="UTF-8"?> 187 <registry> 188 <types> 189 <type name="VkImageCreateFlagBits" category="enum"/> 190 </types> 191 <enums name="VkImageCreateFlagBits" type="enum"> 192 <enum bitpos="31" 193 name="VK_IMAGE_RESERVED_31_BIT" 194 comment="Note: that value doesn't fit into int32_t but does fit into uint32_t"/> 195 </enums> 196 </registry>`)) 197 if err != nil { 198 t.Error("Failed to parse test XML") 199 return 200 } 201 _, types, _, _, _, err := VulkanTypesfromXML(registry) 202 if err != nil { 203 t.Error("Failed to parse test XML") 204 return 205 } 206 if typе, ok := types["VkImageCreateFlagBits"]; ok { 207 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 208 if typе.Kind(arch) != cpp_types.Enum { 209 t.Error("VkImageCreateFlagBits is not enum") 210 } 211 if typе.Elem(arch).Kind(arch) != cpp_types.UInt32T { 212 t.Error("VkImageCreateFlagBits is not std::uint32_t-based enum") 213 } 214 if typе.NumField(arch) != 1 { 215 t.Error("VkImageCreateFlagBits is supposed to have two fields") 216 } 217 enumerator := typе.Field(0, arch).(cpp_types.EnumFieldInfo) 218 if enumerator.Name() != "VK_IMAGE_RESERVED_31_BIT" { 219 t.Error("VkImageCreateFlagBits's first element is not VK_IMAGE_RESERVED_31_BIT") 220 } 221 if enumerator.Value() != 0x80000000 { 222 t.Error("VkImageCreateFlagBits's first element is not 0x80000000") 223 } 224 } 225 return 226 } 227 t.Error("VkImageCreateFlagBits type wasn't parsed") 228} 229 230func TestEnum64bit(t *testing.T) { 231 registry, err := Unmarshal([]byte(` 232 <?xml version="1.0" encoding="UTF-8"?> 233 <registry> 234 <types> 235 <type name="Vk64BitEnum" category="enum"/> 236 </types> 237 <enums name="Vk64BitEnum" type="enum"> 238 <enum value="0x100000000" name="VK_64_BIT_ENUM_TEST_VALUE"/> 239 </enums> 240 </registry>`)) 241 if err != nil { 242 t.Error("Failed to parse test XML") 243 return 244 } 245 _, types, _, _, _, err := VulkanTypesfromXML(registry) 246 if err != nil { 247 t.Error("Failed to parse test XML") 248 return 249 } 250 if typе, ok := types["Vk64BitEnum"]; ok { 251 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 252 if typе.Kind(arch) != cpp_types.Enum { 253 t.Error("Vk64BitEnum is not enum") 254 } 255 if typе.Elem(arch).Kind(arch) != cpp_types.Int64T { 256 t.Error("Vk64BitEnum is not std::int64_t-based enum") 257 } 258 if typе.NumField(arch) != 1 { 259 t.Error("Vk64BitEnum is supposed to have one field") 260 } 261 enumerator := typе.Field(0, arch).(cpp_types.EnumFieldInfo) 262 if enumerator.Name() != "VK_64_BIT_ENUM_TEST_VALUE" { 263 t.Error("Vk64BitEnum's first element is not VK_64_BIT_ENUM_TEST_VALUE") 264 } 265 if enumerator.Value() != 0x100000000 { 266 t.Error("Vk64BitEnum's first element is not 0x100000000") 267 } 268 } 269 return 270 } 271 t.Error("Vk64BitEnum type wasn't parsed") 272} 273 274func TestHandle(t *testing.T) { 275 registry, err := Unmarshal([]byte(` 276 <?xml version="1.0" encoding="UTF-8"?> 277 <registry> 278 <types> 279 <type category="handle"><type>VK_DEFINE_HANDLE</type>(<name>VkInstance</name>)</type> 280 </types> 281 </registry>`)) 282 if err != nil { 283 t.Error("Failed to parse test XML") 284 return 285 } 286 _, types, _, _, _, err := VulkanTypesfromXML(registry) 287 if err != nil { 288 t.Error("Failed to parse test XML") 289 return 290 } 291 if typе, ok := types["VkInstance"]; ok { 292 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 293 if typе.Kind(arch) != cpp_types.Alias { 294 t.Error("vkInstance is not alias") 295 continue 296 } 297 if typе.Elem(arch).Kind(arch) != cpp_types.Ptr { 298 t.Error("vkInstance is not pointer alias") 299 continue 300 } 301 if typе.Elem(arch).Elem(arch).Kind(arch) != cpp_types.Opaque { 302 t.Error("vkInstance is not pointer alias to opaque type") 303 continue 304 } 305 } 306 return 307 } 308 t.Error("vkInstance type wasn't parsed") 309} 310 311func TestNondispatchableHandle(t *testing.T) { 312 registry, err := Unmarshal([]byte(` 313 <?xml version="1.0" encoding="UTF-8"?> 314 <registry> 315 <types> 316 <type category="handle"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkFence</name>)</type> 317 </types> 318 </registry>`)) 319 if err != nil { 320 t.Error("Failed to parse test XML") 321 return 322 } 323 _, types, _, _, _, err := VulkanTypesfromXML(registry) 324 if err != nil { 325 t.Error("Failed to parse test XML") 326 return 327 } 328 if typе, ok := types["VkFence"]; ok { 329 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 330 if typе.Kind(arch) != cpp_types.Alias { 331 t.Error("VkFence is not alias") 332 continue 333 } 334 if arch%2 == 0 { 335 if typе.Elem(arch) != cpp_types.UInt64TType { 336 t.Error("VkFence is not uint64_t alias") 337 continue 338 } 339 } else { 340 if typе.Elem(arch).Kind(arch) != cpp_types.Ptr { 341 t.Error("VkFence is not pointer alias") 342 continue 343 } 344 if typе.Elem(arch).Elem(arch).Kind(arch) != cpp_types.Opaque { 345 t.Error("VkFence is not pointer alias to opaque type") 346 continue 347 } 348 } 349 } 350 return 351 } 352 t.Error("VkFence type wasn't parsed") 353} 354 355func TestFuncPtr(t *testing.T) { 356 registry, err := Unmarshal([]byte(` 357 <?xml version="1.0" encoding="UTF-8"?> 358 <registry> 359 <types> 360 <type category="funcpointer">typedef void (VKAPI_PTR *<name>PFN_vkVoidFunction</name>)(void);</type> 361 <type category="funcpointer" requires="VkDebugUtilsMessengerCallbackDataEXT"> 362 typedef uint32_t (VKAPI_PTR *<name>PFN_vkDebugUtilsMessengerCallbackEXT</name>)( 363 <type>uint8_t</type> pIndex, 364 const <type>VkDebugUtilsMessengerCallbackDataEXT</type>* pCallbackData, 365 <type>void</type>* pUserData); 366 </type> 367 </types> 368 </registry>`)) 369 if err != nil { 370 t.Error("Failed to parse test XML") 371 return 372 } 373 _, types, _, _, _, err := VulkanTypesfromXML(registry) 374 if err != nil { 375 t.Error("Failed to parse test XML") 376 return 377 } 378 if typе, ok := types["PFN_vkVoidFunction"]; ok { 379 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 380 if typе.Kind(arch) != cpp_types.Ptr || 381 typе.Elem(arch).Kind(arch) != cpp_types.Func { 382 t.Error("PFN_vkVoidFunction is not function pointer") 383 continue 384 } 385 if typе.Elem(arch).Elem(arch).Kind(arch) != cpp_types.Void { 386 t.Error("PFN_vkVoidFunction return type is not void") 387 } 388 if typе.Elem(arch).NumField(arch) != 0 { 389 t.Error("PFN_vkVoidFunction is not zero-argument function") 390 } 391 } 392 } else { 393 t.Error("PFN_vkVoidFunction type wasn't parsed") 394 } 395 if typе, ok := types["PFN_vkDebugUtilsMessengerCallbackEXT"]; ok { 396 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 397 if typе.Kind(arch) != cpp_types.Ptr || 398 typе.Elem(arch).Kind(arch) != cpp_types.Func { 399 t.Error("VkDebugUtilsMessengerCallbackDataEXT is not function pointer") 400 continue 401 } 402 if typе.Elem(arch).Elem(arch).Kind(arch) != cpp_types.UInt32T { 403 t.Error("VkDebugUtilsMessengerCallbackDataEXT return type is not uint32_t") 404 } 405 if typе.Elem(arch).NumField(arch) != 3 { 406 t.Error("VkDebugUtilsMessengerCallbackDataEXT is not two-argument function") 407 } 408 field0 := typе.Elem(arch).Field(0, arch) 409 if field0.Name() != "pIndex" { 410 t.Error("First argument of VkDebugUtilsMessengerCallbackDataEXT is not pIndex") 411 } 412 if field0.Type().Kind(arch) != cpp_types.UInt8T { 413 t.Error("First argument of VkDebugUtilsMessengerCallbackDataEXT has wrong type") 414 } 415 field1 := typе.Elem(arch).Field(1, arch) 416 if field1.Name() != "pCallbackData" { 417 t.Error("Second argument of VkDebugUtilsMessengerCallbackDataEXT is not pCallbackData") 418 } 419 if field1.Type().Kind(arch) != cpp_types.Ptr || 420 field1.Type().Elem(arch).Kind(arch) != cpp_types.Const || 421 field1.Type().Elem(arch).Elem(arch).Kind(arch) != cpp_types.Opaque || 422 field1.Type().Elem(arch).Elem(arch).Name(arch) != "VkDebugUtilsMessengerCallbackDataEXT" { 423 t.Error("Second argument of VkDebugUtilsMessengerCallbackDataEXT has wrong type") 424 } 425 field2 := typе.Elem(arch).Field(2, arch) 426 if field2.Name() != "pUserData" { 427 t.Error("Third argument of VkDebugUtilsMessengerCallbackDataEXT is not pUserData") 428 } 429 if field2.Type().Kind(arch) != cpp_types.Ptr || 430 field2.Type().Elem(arch).Kind(arch) != cpp_types.Void { 431 t.Error("Third argument of VkDebugUtilsMessengerCallbackDataEXT has wrong type") 432 } 433 } 434 } else { 435 t.Error("PFN_vkDebugUtilsMessengerCallbackEXT type wasn't parsed") 436 } 437} 438 439func TestStruct(t *testing.T) { 440 registry, err := Unmarshal([]byte(` 441 <?xml version="1.0" encoding="UTF-8"?> 442 <registry> 443 <types> 444 <type category="basetype">typedef <type>uint32_t</type> <name>VkFlags</name>;</type> 445 <type name="VkStructureType" category="enum"/> 446 <type requires="VkGeometryInstanceFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkGeometryInstanceFlagsKHR</name>;</type> 447 <type category="struct" name="VkBaseOutStructure"> 448 <member><type>VkStructureType</type> <name>sType</name></member> 449 <member>struct <type>VkBaseOutStructure</type>* <name>pNext</name></member> 450 </type> 451 <type category="struct" name="VkBaseInStructure"> 452 <member><type>VkStructureType</type> <name>sType</name></member> 453 <member>const struct <type>VkBaseInStructure</type>* <name>pNext</name></member> 454 </type> 455 <type category="struct" name="VkAccelerationStructureInstanceKHR"> 456 <comment>The bitfields in this structure are non-normative since bitfield ordering is implementation-defined in C. The specification defines the normative layout.</comment> 457 <member><type>VkTransformMatrixKHR</type> <name>transform</name></member> 458 <member><type>uint32_t</type> <name>instanceCustomIndex</name>:24</member> 459 <member><type>uint32_t</type> <name>mask</name>:8</member> 460 <member><type>uint32_t</type> <name>instanceShaderBindingTableRecordOffset</name>:24</member> 461 <member optional="true"><type>VkGeometryInstanceFlagsKHR</type> <name>flags</name>:8</member> 462 <member><type>uint64_t</type> <name>accelerationStructureReference</name></member> 463 </type> 464 <type category="struct" name="VkTransformMatrixKHR"> 465 <member><type>float</type> <name>matrix</name>[3][4]</member> 466 </type> 467 </types> 468 </registry>`)) 469 if err != nil { 470 t.Error("Failed to parse test XML") 471 return 472 } 473 _, types, _, _, _, err := VulkanTypesfromXML(registry) 474 if err != nil { 475 t.Error("Failed to parse test XML") 476 return 477 } 478 if typе, ok := types["VkBaseOutStructure"]; ok { 479 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 480 if typе.Kind(arch) != cpp_types.Struct { 481 t.Error("VkBaseOutStructure is not a struct") 482 continue 483 } 484 if typе.NumField(arch) != 2 { 485 t.Error("VkBaseOutStructure is not two-field struct") 486 continue 487 } 488 field0 := typе.Field(0, arch) 489 if field0.Name() != "sType" { 490 t.Error("First field of VkBaseOutStructure is not sType") 491 } 492 if field0.Type().Kind(arch) != cpp_types.Enum || 493 field0.Type().Elem(arch).Kind(arch) != cpp_types.Int32T { 494 t.Error("First field of VkBaseOutStructure has wrong type") 495 } 496 field1 := typе.Field(1, arch) 497 if field1.Name() != "pNext" { 498 t.Error("Second field of VkBaseOutStructure is not pNext") 499 } 500 if field1.Type().Kind(arch) != cpp_types.Ptr || 501 field1.Type().Elem(arch).Kind(arch) != cpp_types.Struct { 502 t.Error("Second field of VkBaseOutStructure has wrong type") 503 } 504 } 505 } else { 506 t.Error("VkBaseOutStructure type wasn't parsed") 507 } 508 if typе, ok := types["VkBaseInStructure"]; ok { 509 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 510 if typе.Kind(arch) != cpp_types.Struct { 511 t.Error("VkBaseInStructure is not a struct") 512 continue 513 } 514 if typе.NumField(arch) != 2 { 515 t.Error("VkBaseInStructure is not two-field struct") 516 } 517 field0 := typе.Field(0, arch) 518 if field0.Name() != "sType" { 519 t.Error("First field of VkBaseInStructure is not sType") 520 } 521 if field0.Type().Kind(arch) != cpp_types.Enum || 522 field0.Type().Elem(arch).Kind(arch) != cpp_types.Int32T { 523 t.Error("First field of VkBaseInStructure has wrong type") 524 } 525 field1 := typе.Field(1, arch) 526 if field1.Name() != "pNext" { 527 t.Error("Second field of VkBaseInStructuree is not pNext") 528 } 529 if field1.Type().Kind(arch) != cpp_types.Ptr || 530 field1.Type().Elem(arch).Kind(arch) != cpp_types.Const || 531 field1.Type().Elem(arch).Elem(arch).Kind(arch) != cpp_types.Struct { 532 t.Error("Second field of VkBaseInStructure has wrong type") 533 } 534 } 535 } else { 536 t.Error("VkBaseInStructure type wasn't parsed") 537 } 538 if typе, ok := types["VkTransformMatrixKHR"]; ok { 539 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 540 if typе.Kind(arch) != cpp_types.Struct { 541 t.Error("VkTransformMatrixKHR is not a struct") 542 continue 543 } 544 if typе.NumField(arch) != 1 { 545 t.Error("VkTransformMatrixKHR is not one-field struct") 546 } 547 field0 := typе.Field(0, arch) 548 if field0.Name() != "matrix" { 549 t.Error("First field of VkTransformMatrixKHR is not matrix") 550 } 551 if field0.Type().Kind(arch) != cpp_types.Array || 552 field0.Type().NumField(arch) != 4 || 553 field0.Type().Elem(arch).Kind(arch) != cpp_types.Array || 554 field0.Type().Elem(arch).NumField(arch) != 3 || 555 field0.Type().Elem(arch).Elem(arch).Kind(arch) != cpp_types.Float32 { 556 t.Error("First field of VkTransformMatrixKHR has wrong type") 557 } 558 } 559 } else { 560 t.Error("PFN_vkDebugUtilsMessengerCallbackEXT type wasn't parsed") 561 } 562 if typе, ok := types["VkAccelerationStructureInstanceKHR"]; ok { 563 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 564 if typе.Kind(arch) != cpp_types.Struct { 565 t.Error("VkAccelerationStructureInstanceKHR is not a struct") 566 continue 567 } 568 if typе.NumField(arch) != 6 { 569 t.Error("VkAccelerationStructureInstanceKHR is not six-field struct") 570 } 571 assertLayout := func(t *testing.T, field_no uint, field cpp_types.FieldInfo, field_name string, size, offset uint) { 572 if field.Name() != field_name { 573 t.Error(fmt.Sprintf("Field %d of VkAccelerationStructureInstanceKHR is not %s", field_no, field_name)) 574 } 575 if field.Type().Bits(arch) != size { 576 t.Error(fmt.Sprintf("Field %d of VkAccelerationStructureInstanceKHR size is not %d bit", field_no, size)) 577 } 578 if field.(cpp_types.StructFieldInfo).Offset() != offset { 579 t.Error(fmt.Sprintf("Field %d of VkAccelerationStructureInstanceKHR offset is not %d bit", field_no, offset)) 580 } 581 } 582 field0 := typе.Field(0, arch) 583 assertLayout(t, 1, field0, "transform", 384, 0) 584 if field0.Type().Kind(arch) != cpp_types.Struct || 585 field0.Type().Name(arch) != "struct VkTransformMatrixKHR" { 586 t.Error("First field of VkAccelerationStructureInstanceKHR has wrong type") 587 } 588 // Note: bitfields maybe represented differently but we don't care as long as 589 // size and offsets match our expectations. 590 field1 := typе.Field(1, arch) 591 assertLayout(t, 2, field1, "instanceCustomIndex", 24, 384) 592 field2 := typе.Field(2, arch) 593 assertLayout(t, 3, field2, "mask", 8, 408) 594 field3 := typе.Field(3, arch) 595 assertLayout(t, 4, field3, "instanceShaderBindingTableRecordOffset", 24, 416) 596 field4 := typе.Field(4, arch) 597 assertLayout(t, 5, field4, "flags", 8, 440) 598 field5 := typе.Field(5, arch) 599 assertLayout(t, 6, field5, "accelerationStructureReference", 64, 448) 600 if field5.Type().Kind(arch) != cpp_types.UInt64T { 601 t.Error("Sixth field of VkAccelerationStructureInstanceKHR wrong type") 602 } 603 } 604 } else { 605 t.Error("PFN_vkDebugUtilsMessengerCallbackEXT type wasn't parsed") 606 } 607} 608 609func TestCommand(t *testing.T) { 610 registry, err := Unmarshal([]byte(` 611 <?xml version="1.0" encoding="UTF-8"?> 612 <registry> 613 <types> 614 <type category="define"> 615#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* object;</type> 616 <type category="handle" parent="VkCommandPool"><type>VK_DEFINE_HANDLE</type>(<name>VkCommandBuffer</name>)</type> 617 </types> 618 <commands> 619 <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary"> 620 <proto><type>void</type> <name>vkCmdSetBlendConstants</name></proto> 621 <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param> 622 <param><type>uint32_t</type> <name>blendConstantsLen</name></param> 623 <param len="blendConstantsLen">const <type>float</type> <name>blendConstants</name>[4]</param> 624 </command> 625 </commands> 626 </registry>`)) 627 if err != nil { 628 t.Error("Failed to parse test XML") 629 return 630 } 631 _, _, _, commands, _, err := VulkanTypesfromXML(registry) 632 if err != nil { 633 t.Error("Failed to parse test XML") 634 return 635 } 636 if command, ok := commands["vkCmdSetBlendConstants"]; ok { 637 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 638 if command.Kind(arch) != cpp_types.Func { 639 t.Error("vkCmdSetBlendConstants is not a function") 640 continue 641 } 642 if command.Elem(arch).Kind(arch) != cpp_types.Void { 643 t.Error("vkCmdSetBlendConstants is not a void function") 644 } 645 if command.NumField(arch) != 3 { 646 t.Error("vkCmdSetBlendConstants is not three-argument function") 647 continue 648 } 649 field0 := command.Field(0, arch) 650 if field0.Name() != "commandBuffer" { 651 t.Error("First argument of vkCmdSetBlendConstants is not commandBuffer") 652 } 653 if field0.Type().Kind(arch) != cpp_types.Alias || 654 field0.Type().Elem(arch).Kind(arch) != cpp_types.Ptr || 655 field0.Type().Elem(arch).Elem(arch).Kind(arch) != cpp_types.Opaque || 656 field0.Type().Elem(arch).Elem(arch).Name(arch) != "struct VkCommandBuffer_T" { 657 t.Error("First field of vkCmdSetBlendConstants has wrong type") 658 } 659 field1 := command.Field(1, arch) 660 if field1.Name() != "blendConstantsLen" { 661 t.Error("Second argument of vkCmdSetBlendConstants is not blendConstants") 662 } 663 if field1.Type().Kind(arch) != cpp_types.UInt32T { 664 t.Error("Second field of vkCmdSetBlendConstants has wrong type") 665 } 666 field2 := command.Field(2, arch) 667 if field2.Name() != "blendConstants" { 668 t.Error("Third argument of vkCmdSetBlendConstants is not blendConstants") 669 } 670 if field2.Type().Kind(arch) != cpp_types.Ptr || 671 field2.Type().Elem(arch).Kind(arch) != cpp_types.Const || 672 field2.Type().Elem(arch).Elem(arch).Kind(arch) != cpp_types.Float32 || 673 field2.BaseFieldInfo().(ExtendedFieldInfo).Length().Name() != field1.Name() || 674 field2.BaseFieldInfo().(ExtendedFieldInfo).Length().Type() != field1.Type() { 675 t.Error("Third field of vkCmdSetBlendConstants has wrong type") 676 } 677 } 678 } else { 679 t.Error("vkCmdSetBlendConstants command wasn't parsed") 680 } 681} 682 683func TestCommandWithComplexLen(t *testing.T) { 684 registry, err := Unmarshal([]byte(` 685 <?xml version="1.0" encoding="UTF-8"?> 686 <registry> 687 <types> 688 <type category="define"> 689#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* object;</type> 690 <type category="handle"><type>VK_DEFINE_HANDLE</type>(<name>VkDescriptorPool</name>)</type> 691 <type category="handle"><type>VK_DEFINE_HANDLE</type>(<name>VkDescriptorSet</name>)</type> 692 <type category="handle"><type>VK_DEFINE_HANDLE</type>(<name>VkDescriptorSetLayout</name>)</type> 693 <type category="handle"><type>VK_DEFINE_HANDLE</type>(<name>VkDevice</name>)</type> 694 <type category="handle"><type>VK_DEFINE_HANDLE</type>(<name>VkStructureType</name>)</type> 695 <type category="struct" name="VkDescriptorSetAllocateInfo"> 696 <member values="VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO"><type>VkStructureType</type> <name>sType</name></member> 697 <member optional="true">const <type>void</type>* <name>pNext</name></member> 698 <member><type>VkDescriptorPool</type> <name>descriptorPool</name></member> 699 <member><type>uint32_t</type> <name>descriptorSetCount</name></member> 700 <member len="descriptorSetCount">const <type>VkDescriptorSetLayout</type>* <name>pSetLayouts</name></member> 701 </type> 702 </types> 703 <commands> 704 <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_FRAGMENTED_POOL,VK_ERROR_OUT_OF_POOL_MEMORY"> 705 <proto><type>void</type> <name>vkAllocateDescriptorSets</name></proto> 706 <param><type>VkDevice</type> <name>device</name></param> 707 <param externsync="pAllocateInfo->descriptorPool">const <type>VkDescriptorSetAllocateInfo</type>* <name>pAllocateInfo</name></param> 708 <param len="pAllocateInfo->descriptorSetCount"><type>VkDescriptorSet</type>* <name>pDescriptorSets</name></param> 709 </command> 710 </commands> 711 </registry>`)) 712 if err != nil { 713 t.Error("Failed to parse test XML" + err.Error()) 714 return 715 } 716 _, types, _, commands, _, err := VulkanTypesfromXML(registry) 717 if err != nil { 718 t.Error("Failed to parse test XML") 719 return 720 } 721 if command, ok := commands["vkAllocateDescriptorSets"]; ok { 722 for arch := cpp_types.FirstArch; arch <= cpp_types.LastArch; arch++ { 723 if command.Kind(arch) != cpp_types.Func { 724 t.Error("vkAllocateDescriptorSets is not a function") 725 continue 726 } 727 if command.Elem(arch).Kind(arch) != cpp_types.Void { 728 t.Error("vkAllocateDescriptorSets is not a void function") 729 } 730 if command.NumField(arch) != 3 { 731 t.Error("vkAllocateDescriptorSets is not three-argument function") 732 continue 733 } 734 field0 := command.Field(0, arch) 735 if field0.Name() != "device" { 736 t.Error("First argument of vkAllocateDescriptorSets is not device") 737 } 738 if field0.Type().Kind(arch) != cpp_types.Alias || 739 field0.Type().Elem(arch).Kind(arch) != cpp_types.Ptr || 740 field0.Type().Elem(arch).Elem(arch).Kind(arch) != cpp_types.Opaque || 741 field0.Type().Elem(arch).Elem(arch).Name(arch) != "struct VkDevice_T" { 742 t.Error("First field of vkAllocateDescriptorSets has wrong type") 743 } 744 field1 := command.Field(1, arch) 745 if field1.Name() != "pAllocateInfo" { 746 t.Error("Second argument of vkAllocateDescriptorSets is not pAllocateInfo") 747 } 748 if field1.Type().Kind(arch) != cpp_types.Ptr || 749 field1.Type().Elem(arch).Kind(arch) != cpp_types.Const || 750 field1.Type().Elem(arch).Elem(arch).Kind(arch) != cpp_types.Struct || 751 field1.Type().Elem(arch).Elem(arch).Name(arch) != "struct VkDescriptorSetAllocateInfo" { 752 t.Error("First field of vkAllocateDescriptorSets has wrong type") 753 } 754 field2 := command.Field(2, arch) 755 if field2.Name() != "pDescriptorSets" { 756 t.Error("Third argument of vkAllocateDescriptorSets is not pDescriptorSets") 757 } 758 field1_3 := types["VkDescriptorSetAllocateInfo"].Field(3, arch) 759 if field2.Type().Kind(arch) != cpp_types.Ptr || 760 field2.Type().Elem(arch).Kind(arch) != cpp_types.Alias || 761 field2.Type().Elem(arch).Elem(arch).Kind(arch) != cpp_types.Ptr || 762 field2.Type().Elem(arch).Elem(arch).Elem(arch).Kind(arch) != cpp_types.Opaque || 763 field2.Type().Elem(arch).Elem(arch).Elem(arch).Name(arch) != "struct VkDescriptorSet_T" || 764 field2.BaseFieldInfo().(ExtendedFieldInfo).Length().Name() != field1.Name() || 765 field2.BaseFieldInfo().(ExtendedFieldInfo).Length().Type() != field1.Type() || 766 field2.BaseFieldInfo().(ExtendedFieldInfo).NestedField().Name() != field1_3.Name() || 767 field2.BaseFieldInfo().(ExtendedFieldInfo).NestedField().Type() != field1_3.Type() { 768 t.Error("Third field of vkAllocateDescriptorSets has wrong type") 769 } 770 } 771 } else { 772 t.Error("vkCmdSetBlendConstants command wasn't parsed") 773 } 774} 775