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