xref: /aosp_15_r20/external/mesa3d/src/gfxstream/codegen/scripts/cereal/functable.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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