1from .common.codegen import CodeGen, VulkanWrapperGenerator 2from .common.vulkantypes import \ 3 VulkanAPI, makeVulkanTypeSimple, iterateVulkanType 4from .common.vulkantypes import EXCLUDED_APIS 5from .common.vulkantypes import HANDLE_TYPES 6 7import copy 8import re 9 10RESOURCE_TRACKER_ENTRIES = [ 11 "vkEnumerateInstanceExtensionProperties", 12 "vkEnumerateDeviceExtensionProperties", 13 "vkEnumeratePhysicalDevices", 14 "vkAllocateMemory", 15 "vkFreeMemory", 16 "vkCreateImage", 17 "vkDestroyImage", 18 "vkGetImageMemoryRequirements", 19 "vkGetImageMemoryRequirements2", 20 "vkGetImageMemoryRequirements2KHR", 21 "vkGetImageSubresourceLayout", 22 "vkBindImageMemory", 23 "vkBindImageMemory2", 24 "vkBindImageMemory2KHR", 25 "vkCreateBuffer", 26 "vkDestroyBuffer", 27 "vkGetBufferMemoryRequirements", 28 "vkGetBufferMemoryRequirements2", 29 "vkGetBufferMemoryRequirements2KHR", 30 "vkBindBufferMemory", 31 "vkBindBufferMemory2", 32 "vkBindBufferMemory2KHR", 33 "vkCreateSemaphore", 34 "vkDestroySemaphore", 35 "vkQueueSubmit", 36 "vkQueueSubmit2", 37 "vkQueueWaitIdle", 38 "vkImportSemaphoreFdKHR", 39 "vkGetSemaphoreFdKHR", 40 # Warning: These need to be defined in vk.xml (currently no-op) { 41 "vkGetMemoryFuchsiaHandleKHR", 42 "vkGetMemoryFuchsiaHandlePropertiesKHR", 43 "vkGetSemaphoreFuchsiaHandleKHR", 44 "vkImportSemaphoreFuchsiaHandleKHR", 45 # } end Warning: These need to be defined in vk.xml (currently no-op) 46 "vkGetAndroidHardwareBufferPropertiesANDROID", 47 "vkGetMemoryAndroidHardwareBufferANDROID", 48 "vkGetMemoryFdKHR", 49 "vkGetMemoryFdPropertiesKHR", 50 "vkCreateSamplerYcbcrConversion", 51 "vkDestroySamplerYcbcrConversion", 52 "vkCreateSamplerYcbcrConversionKHR", 53 "vkDestroySamplerYcbcrConversionKHR", 54 "vkUpdateDescriptorSetWithTemplate", 55 "vkUpdateDescriptorSetWithTemplateKHR", 56 "vkGetPhysicalDeviceImageFormatProperties2", 57 "vkGetPhysicalDeviceImageFormatProperties2KHR", 58 "vkBeginCommandBuffer", 59 "vkEndCommandBuffer", 60 "vkResetCommandBuffer", 61 "vkCreateImageView", 62 "vkCreateSampler", 63 "vkGetPhysicalDeviceExternalFenceProperties", 64 "vkGetPhysicalDeviceExternalFencePropertiesKHR", 65 "vkGetPhysicalDeviceExternalBufferProperties", 66 "vkGetPhysicalDeviceExternalBufferPropertiesKHR", 67 "vkCreateFence", 68 "vkResetFences", 69 "vkImportFenceFdKHR", 70 "vkGetFenceFdKHR", 71 "vkGetFenceStatus", 72 "vkWaitForFences", 73 "vkCreateDescriptorPool", 74 "vkDestroyDescriptorPool", 75 "vkResetDescriptorPool", 76 "vkAllocateDescriptorSets", 77 "vkFreeDescriptorSets", 78 "vkCreateDescriptorSetLayout", 79 "vkCmdExecuteCommands", 80 "vkCmdBindDescriptorSets", 81 "vkDestroyDescriptorSetLayout", 82 "vkAllocateCommandBuffers", 83 "vkQueueSignalReleaseImageANDROID", 84 "vkCmdPipelineBarrier", 85 "vkCreateGraphicsPipelines", 86 # Fuchsia 87 "vkGetMemoryZirconHandleFUCHSIA", 88 "vkGetMemoryZirconHandlePropertiesFUCHSIA", 89 "vkGetSemaphoreZirconHandleFUCHSIA", 90 "vkImportSemaphoreZirconHandleFUCHSIA", 91 "vkCreateBufferCollectionFUCHSIA", 92 "vkDestroyBufferCollectionFUCHSIA", 93 "vkSetBufferCollectionImageConstraintsFUCHSIA", 94 "vkSetBufferCollectionBufferConstraintsFUCHSIA", 95 "vkGetBufferCollectionPropertiesFUCHSIA", 96] 97 98SUCCESS_VAL = { 99 "VkResult" : ["VK_SUCCESS"], 100} 101 102HANDWRITTEN_ENTRY_POINTS = [ 103 # Instance/device/physical-device special-handling, dispatch tables, etc.. 104 "vkCreateInstance", 105 "vkDestroyInstance", 106 "vkGetInstanceProcAddr", 107 "vkEnumerateInstanceVersion", 108 "vkEnumerateInstanceLayerProperties", 109 "vkEnumerateInstanceExtensionProperties", 110 "vkEnumerateDeviceExtensionProperties", 111 "vkGetDeviceProcAddr", 112 "vkEnumeratePhysicalDevices", 113 "vkEnumeratePhysicalDeviceGroups", 114 "vkCreateDevice", 115 "vkDestroyDevice", 116 # Manual alloc/free + vk_*_init/free() call w/ special params 117 "vkGetDeviceQueue", 118 "vkGetDeviceQueue2", 119 # Command pool/buffer handling 120 "vkCreateCommandPool", 121 "vkDestroyCommandPool", 122 "vkAllocateCommandBuffers", 123 "vkResetCommandPool", 124 "vkFreeCommandBuffers", 125 "vkResetCommandPool", 126 # Transform feedback 127 "vkCmdBeginTransformFeedbackEXT", 128 # Special cases to handle struct translations in the pNext chain 129 # TODO: Make a codegen module (use deepcopy as reference) to make this more robust 130 "vkAllocateMemory", 131 "vkUpdateDescriptorSets", 132 "vkGetPhysicalDeviceFormatProperties2", 133] 134 135# Handles that need to be translated to/from their corresponding gfxstream object types 136HANDLES_TRANSLATE = { 137 "VkInstance", 138 "VkPhysicalDevice", 139 "VkDevice", 140 "VkQueue", 141 "VkCommandPool", 142 "VkCommandBuffer", 143 "VkFence", 144 "VkSemaphore", 145 # TODO: Still need this translation to avoid descriptorSets crash 146 "VkBuffer", 147} 148 149# Types that have a corresponding method for transforming 150# an input list to its internal counterpart 151TYPES_TRANSFORM_LIST_METHOD = { 152 "VkFence", 153 "VkSemaphore", 154 "VkSemaphoreSubmitInfo", 155} 156 157def is_cmdbuf_dispatch(api): 158 return "VkCommandBuffer" == api.parameters[0].typeName 159 160def is_queue_dispatch(api): 161 return "VkQueue" == api.parameters[0].typeName 162 163def getCreateParam(api): 164 for param in api.parameters: 165 if param.isCreatedBy(api): 166 return param 167 return None 168 169def getDestroyParam(api): 170 for param in api.parameters: 171 if param.isDestroyedBy(api): 172 return param 173 return None 174 175# i.e. VkQueryPool --> vk_query_pool 176def typeNameToMesaType(typeName): 177 vkTypeNameRegex = "(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])" 178 words = re.split(vkTypeNameRegex, typeName) 179 outputType = "vk" 180 for word in words[1:]: 181 outputType += "_" 182 outputType += word.lower() 183 return outputType 184 185def typeNameToBaseName(typeName): 186 return typeNameToMesaType(typeName)[len("vk_"):] 187 188def paramNameToObjectName(paramName): 189 return "gfxstream_%s" % paramName 190 191def typeNameToVkObjectType(typeName): 192 return "VK_OBJECT_TYPE_%s" % typeNameToBaseName(typeName).upper() 193 194def typeNameToObjectType(typeName): 195 return "gfxstream_vk_%s" % typeNameToBaseName(typeName) 196 197def transformListFuncName(typeName): 198 return "transform%sList" % (typeName) 199 200def isAllocatorParam(param): 201 ALLOCATOR_TYPE_NAME = "VkAllocationCallbacks" 202 return (param.pointerIndirectionLevels == 1 203 and param.isConst 204 and param.typeName == ALLOCATOR_TYPE_NAME) 205 206def isArrayParam(param): 207 return (1 == param.pointerIndirectionLevels 208 and param.isConst 209 and "len" in param.attribs) 210 211INTERNAL_OBJECT_NAME = "internal_object" 212 213class VulkanFuncTable(VulkanWrapperGenerator): 214 def __init__(self, module, typeInfo): 215 VulkanWrapperGenerator.__init__(self, module, typeInfo) 216 self.typeInfo = typeInfo 217 self.cgen = CodeGen() 218 self.entries = [] 219 self.entryFeatures = [] 220 self.cmdToFeatureType = {} 221 self.feature = None 222 self.featureType = None 223 224 def onBegin(self,): 225 cgen = self.cgen 226 self.module.appendImpl(cgen.swapCode()) 227 pass 228 229 def onBeginFeature(self, featureName, featureType): 230 self.feature = featureName 231 self.featureType = featureType 232 233 def onEndFeature(self): 234 self.feature = None 235 self.featureType = None 236 237 def onFeatureNewCmd(self, name): 238 self.cmdToFeatureType[name] = self.featureType 239 240 def onGenCmd(self, cmdinfo, name, alias): 241 typeInfo = self.typeInfo 242 cgen = self.cgen 243 api = typeInfo.apis[name] 244 self.entries.append(api) 245 self.entryFeatures.append(self.feature) 246 self.loopVars = ["i", "j", "k", "l", "m", "n"] 247 self.loopVarIndex = 0 248 249 def getNextLoopVar(): 250 if self.loopVarIndex >= len(self.loopVars): 251 raise 252 loopVar = self.loopVars[self.loopVarIndex] 253 self.loopVarIndex += 1 254 return loopVar 255 256 def isCompoundType(typeName): 257 return typeInfo.isCompoundType(typeName) 258 259 def handleTranslationRequired(typeName): 260 return typeName in HANDLE_TYPES and typeName in HANDLES_TRANSLATE 261 262 def translationRequired(typeName): 263 if isCompoundType(typeName): 264 struct = typeInfo.structs[typeName] 265 for member in struct.members: 266 if translationRequired(member.typeName): 267 return True 268 return False 269 else: 270 return handleTranslationRequired(typeName) 271 272 def genDestroyGfxstreamObjects(): 273 destroyParam = getDestroyParam(api) 274 if not destroyParam: 275 return 276 if not translationRequired(destroyParam.typeName): 277 return 278 objectName = paramNameToObjectName(destroyParam.paramName) 279 allocatorParam = "NULL" 280 for p in api.parameters: 281 if isAllocatorParam(p): 282 allocatorParam = p.paramName 283 deviceParam = api.parameters[0] 284 if "VkDevice" != deviceParam.typeName: 285 print("ERROR: Unhandled non-VkDevice parameters[0]: %s (for API: %s)" %(deviceParam.typeName, api.name)) 286 raise 287 # call vk_object_free() directly 288 mesaObjectDestroy = "(void *)%s" % objectName 289 cgen.funcCall( 290 None, 291 "vk_object_free", 292 ["&%s->vk" % paramNameToObjectName(deviceParam.paramName), allocatorParam, mesaObjectDestroy] 293 ) 294 295 def genMesaObjectAlloc(allocCallLhs): 296 deviceParam = api.parameters[0] 297 if "VkDevice" != deviceParam.typeName: 298 print("ERROR: Unhandled non-VkDevice parameters[0]: %s (for API: %s)" %(deviceParam.typeName, api.name)) 299 raise 300 allocatorParam = "NULL" 301 for p in api.parameters: 302 if isAllocatorParam(p): 303 allocatorParam = p.paramName 304 createParam = getCreateParam(api) 305 objectType = typeNameToObjectType(createParam.typeName) 306 # Call vk_object_zalloc directly 307 cgen.funcCall( 308 allocCallLhs, 309 "(%s *)vk_object_zalloc" % objectType, 310 ["&%s->vk" % paramNameToObjectName(deviceParam.paramName), allocatorParam, ("sizeof(%s)" % objectType), typeNameToVkObjectType(createParam.typeName)] 311 ) 312 313 # Alloc/create gfxstream_vk_* object 314 def genCreateGfxstreamObjects(): 315 createParam = getCreateParam(api) 316 if not createParam: 317 return False 318 if not handleTranslationRequired(createParam.typeName): 319 return False 320 objectType = "struct %s" % typeNameToObjectType(createParam.typeName) 321 callLhs = "%s *%s" % (objectType, paramNameToObjectName(createParam.paramName)) 322 genMesaObjectAlloc(callLhs) 323 324 retVar = api.getRetVarExpr() 325 if retVar: 326 retTypeName = api.getRetTypeExpr() 327 # ex: vkCreateBuffer_VkResult_return = gfxstream_buffer ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY; 328 cgen.stmt("%s = %s ? %s : %s" % 329 (retVar, paramNameToObjectName(createParam.paramName), SUCCESS_VAL[retTypeName][0], "VK_ERROR_OUT_OF_HOST_MEMORY")) 330 return True 331 332 def genVkFromHandle(param, fromName): 333 objectName = paramNameToObjectName(param.paramName) 334 cgen.stmt("VK_FROM_HANDLE(%s, %s, %s)" % 335 (typeNameToObjectType(param.typeName), objectName, fromName)) 336 return objectName 337 338 def genGetGfxstreamHandles(): 339 createParam = getCreateParam(api) 340 for param in api.parameters: 341 if not handleTranslationRequired(param.typeName): 342 continue 343 elif isArrayParam(param): 344 continue 345 elif param != createParam: 346 if param.pointerIndirectionLevels > 0: 347 print("ERROR: Unhandled pointerIndirectionLevels > 1 for API %s (param %s)" % (api.name, param.paramName)) 348 raise 349 genVkFromHandle(param, param.paramName) 350 351 def internalNestedParamName(param): 352 parentName = "" 353 if param.parent: 354 parentName = "_%s" % param.parent.typeName 355 return "internal%s_%s" % (parentName, param.paramName) 356 357 def genInternalArrayDeclarations(param, countParamName, nestLevel=0): 358 internalArray = None 359 if 0 == nestLevel: 360 internalArray = "internal_%s" % param.paramName 361 cgen.stmt("std::vector<%s> %s(%s)" % (param.typeName, internalArray, countParamName)) 362 elif 1 == nestLevel or 2 == nestLevel: 363 internalArray = internalNestedParamName(param) 364 if isArrayParam(param): 365 cgen.stmt("std::vector<std::vector<%s>> %s" % (param.typeName, internalArray)) 366 else: 367 cgen.stmt("std::vector<%s> %s" % (param.typeName, internalArray)) 368 else: 369 print("ERROR: nestLevel > 2 not verified.") 370 raise 371 if isCompoundType(param.typeName): 372 for member in typeInfo.structs[param.typeName].members: 373 if translationRequired(member.typeName): 374 if handleTranslationRequired(member.typeName) and not isArrayParam(member): 375 # No declarations for non-array handleType 376 continue 377 genInternalArrayDeclarations(member, countParamName, nestLevel + 1) 378 return internalArray 379 380 def genInternalCompoundType(param, outName, inName, currLoopVar): 381 nextLoopVar = None 382 cgen.stmt("%s = %s" % (outName, inName)) 383 for member in typeInfo.structs[param.typeName].members: 384 if not translationRequired(member.typeName): 385 continue 386 cgen.line("/* %s::%s */" % (param.typeName, member.paramName)) 387 nestedOutName = ("%s[%s]" % (internalNestedParamName(member), currLoopVar)) 388 if isArrayParam(member): 389 countParamName = "%s.%s" % (outName, member.attribs["len"]) 390 inArrayName = "%s.%s" % (outName, member.paramName) 391 cgen.stmt("%s.push_back(std::vector<%s>())" % (internalNestedParamName(member), member.typeName)) 392 if member.typeName in TYPES_TRANSFORM_LIST_METHOD: 393 # Use the corresponding transformList call 394 cgen.funcCall(nestedOutName, transformListFuncName(member.typeName), [inArrayName, countParamName]) 395 cgen.stmt("%s = %s.data()" % (inArrayName, nestedOutName)) 396 cgen.stmt("%s = %s.size()" % (countParamName, nestedOutName)) 397 else: 398 # Standard translation 399 cgen.stmt("%s.resize(%s)" % (nestedOutName, countParamName)) 400 if not nextLoopVar: 401 nextLoopVar = getNextLoopVar() 402 internalArray = genInternalArray(member, countParamName, nestedOutName, inArrayName, nextLoopVar) 403 cgen.stmt("%s = %s" %(inArrayName, internalArray)) 404 elif isCompoundType(member.typeName): 405 memberFullName = "%s.%s" % (outName, member.paramName) 406 if 1 == member.pointerIndirectionLevels: 407 cgen.beginIf(memberFullName) 408 inParamName = "%s[0]" % memberFullName 409 genInternalCompoundType(member, nestedOutName, inParamName, currLoopVar) 410 cgen.stmt("%s.%s = &%s" % (outName, member.paramName, nestedOutName)) 411 else: 412 cgen.beginBlock() 413 genInternalCompoundType(member, nestedOutName, memberFullName, currLoopVar) 414 cgen.stmt("%s.%s = %s" % (outName, member.paramName, nestedOutName)) 415 cgen.endBlock() 416 else: 417 # Replace member with internal object 418 replaceName = "%s.%s" % (outName, member.paramName) 419 if member.isOptional: 420 cgen.beginIf(replaceName) 421 gfxstreamObject = genVkFromHandle(member, replaceName) 422 cgen.stmt("%s = %s->%s" % (replaceName, gfxstreamObject, INTERNAL_OBJECT_NAME)) 423 if member.isOptional: 424 cgen.endIf() 425 426 def genInternalArray(param, countParamName, outArrayName, inArrayName, loopVar): 427 if param.typeName in TYPES_TRANSFORM_LIST_METHOD: 428 # Use the corresponding transformList call 429 cgen.funcCall(outArrayName, transformListFuncName(param.typeName), [inArrayName, countParamName]) 430 cgen.stmt("%s = %s.data()" % (inArrayName, outArrayName)) 431 cgen.stmt("%s = %s.size()" % (countParamName, outArrayName)) 432 else: 433 cgen.beginFor("uint32_t %s = 0" % loopVar, "%s < %s" % (loopVar, countParamName), "++%s" % loopVar) 434 if param.isOptional: 435 cgen.beginIf(inArrayName) 436 if isCompoundType(param.typeName): 437 genInternalCompoundType(param, ("%s[%s]" % (outArrayName, loopVar)), "%s[%s]" % (inArrayName, loopVar), loopVar) 438 else: 439 gfxstreamObject = genVkFromHandle(param, "%s[%s]" % (inArrayName, loopVar)) 440 cgen.stmt("%s[%s] = %s->%s" % (outArrayName, loopVar, gfxstreamObject, INTERNAL_OBJECT_NAME)) 441 if param.isOptional: 442 cgen.endIf() 443 cgen.endFor() 444 return "%s.data()" % outArrayName 445 446 # Translate params into params needed for gfxstream-internal 447 # encoder/resource-tracker calls 448 def getEncoderOrResourceTrackerParams(): 449 createParam = getCreateParam(api) 450 outParams = copy.deepcopy(api.parameters) 451 nextLoopVar = getNextLoopVar() 452 for param in outParams: 453 if not translationRequired(param.typeName): 454 continue 455 elif isArrayParam(param) or isCompoundType(param.typeName): 456 if param.possiblyOutput(): 457 print("ERROR: Unhandled CompoundType / Array output for API %s (param %s)" % (api.name, param.paramName)) 458 raise 459 if 1 != param.pointerIndirectionLevels or not param.isConst: 460 print("ERROR: Compound type / array input is not 'const <type>*' (API: %s, paramName: %s)" % (api.name, param.paramName)) 461 raise 462 countParamName = "1" 463 if "len" in param.attribs: 464 countParamName = param.attribs["len"] 465 internalArrayName = genInternalArrayDeclarations(param, countParamName) 466 param.paramName = genInternalArray(param, countParamName, internalArrayName, param.paramName, nextLoopVar) 467 elif 0 == param.pointerIndirectionLevels: 468 if param.isOptional: 469 param.paramName = ("%s ? %s->%s : VK_NULL_HANDLE" % (paramNameToObjectName(param.paramName), paramNameToObjectName(param.paramName), INTERNAL_OBJECT_NAME)) 470 else: 471 param.paramName = ("%s->%s" % (paramNameToObjectName(param.paramName), INTERNAL_OBJECT_NAME)) 472 elif createParam and param.paramName == createParam.paramName: 473 param.paramName = ("&%s->%s" % (paramNameToObjectName(param.paramName), INTERNAL_OBJECT_NAME)) 474 else: 475 print("ERROR: Unknown handling for param: %s (API: %s)" % (param, api.name)) 476 raise 477 return outParams 478 479 def genEncoderOrResourceTrackerCall(declareResources=True): 480 if is_cmdbuf_dispatch(api): 481 cgen.stmt("auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(%s->%s)" % (paramNameToObjectName(api.parameters[0].paramName), INTERNAL_OBJECT_NAME)) 482 elif is_queue_dispatch(api): 483 cgen.stmt("auto vkEnc = gfxstream::vk::ResourceTracker::getQueueEncoder(%s->%s)" % (paramNameToObjectName(api.parameters[0].paramName), INTERNAL_OBJECT_NAME)) 484 else: 485 cgen.stmt("auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder()") 486 callLhs = None 487 retTypeName = api.getRetTypeExpr() 488 if retTypeName != "void": 489 callLhs = api.getRetVarExpr() 490 491 # Get parameter list modded for gfxstream-internal call 492 parameters = getEncoderOrResourceTrackerParams() 493 if name in RESOURCE_TRACKER_ENTRIES: 494 if declareResources: 495 cgen.stmt("auto resources = gfxstream::vk::ResourceTracker::get()") 496 cgen.funcCall( 497 callLhs, "resources->" + "on_" + api.name, 498 ["vkEnc"] + SUCCESS_VAL.get(retTypeName, []) + \ 499 [p.paramName for p in parameters]) 500 else: 501 cgen.funcCall( 502 callLhs, "vkEnc->" + api.name, [p.paramName for p in parameters] + ["true /* do lock */"]) 503 504 def genReturnExpression(): 505 retTypeName = api.getRetTypeExpr() 506 # Set the createParam output, if applicable 507 createParam = getCreateParam(api) 508 if createParam and handleTranslationRequired(createParam.typeName): 509 if 1 != createParam.pointerIndirectionLevels: 510 print("ERROR: Unhandled pointerIndirectionLevels != 1 in return for API %s (createParam %s)" % api.name, createParam.paramName) 511 raise 512 # ex: *pBuffer = gfxstream_vk_buffer_to_handle(gfxstream_buffer) 513 cgen.funcCall( 514 "*%s" % createParam.paramName, 515 "%s_to_handle" % typeNameToObjectType(createParam.typeName), 516 [paramNameToObjectName(createParam.paramName)] 517 ) 518 519 if retTypeName != "void": 520 cgen.stmt("return %s" % api.getRetVarExpr()) 521 522 def genGfxstreamEntry(declareResources=True): 523 cgen.stmt("MESA_TRACE_SCOPE(\"%s\")" % api.name) 524 # declare returnVar 525 retTypeName = api.getRetTypeExpr() 526 retVar = api.getRetVarExpr() 527 if retVar: 528 cgen.stmt("%s %s = (%s)0" % (retTypeName, retVar, retTypeName)) 529 # Check non-null destroy param for free/destroy calls 530 destroyParam = getDestroyParam(api) 531 if destroyParam: 532 cgen.beginIf("VK_NULL_HANDLE == %s" % destroyParam.paramName) 533 if api.getRetTypeExpr() != "void": 534 cgen.stmt("return %s" % api.getRetVarExpr()) 535 else: 536 cgen.stmt("return") 537 cgen.endIf() 538 # Translate handles 539 genGetGfxstreamHandles() 540 # Translation/creation of objects 541 createdObject = genCreateGfxstreamObjects() 542 # Make encoder/resource-tracker call 543 if retVar and createdObject: 544 cgen.beginIf("%s == %s" % (SUCCESS_VAL[retTypeName][0], retVar)) 545 else: 546 cgen.beginBlock() 547 genEncoderOrResourceTrackerCall() 548 cgen.endBlock() 549 # Destroy gfxstream objects 550 genDestroyGfxstreamObjects() 551 # Set output / return variables 552 genReturnExpression() 553 554 api_entry = api.withModifiedName("gfxstream_vk_" + api.name[2:]) 555 if api.name not in HANDWRITTEN_ENTRY_POINTS: 556 cgen.line(self.cgen.makeFuncProto(api_entry)) 557 cgen.beginBlock() 558 genGfxstreamEntry() 559 cgen.endBlock() 560 self.module.appendImpl(cgen.swapCode()) 561 562 563 def onEnd(self,): 564 pass 565 566 def isDeviceDispatch(self, api): 567 # TODO(230793667): improve the heuristic and just use "cmdToFeatureType" 568 return (len(api.parameters) > 0 and 569 "VkDevice" == api.parameters[0].typeName) or ( 570 "VkCommandBuffer" == api.parameters[0].typeName and 571 self.cmdToFeatureType.get(api.name, "") == "device") 572