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