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