xref: /aosp_15_r20/external/mesa3d/src/gfxstream/codegen/scripts/cereal/reservedmarshaling.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1# Copyright 2018 Google LLC
2# SPDX-License-Identifier: MIT
3from copy import copy
4
5from .common.codegen import CodeGen, VulkanAPIWrapper
6from .common.vulkantypes import \
7        VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator, Atom, FuncExpr, FuncExprVal, FuncLambda
8
9from .wrapperdefs import VulkanWrapperGenerator
10from .wrapperdefs import VULKAN_STREAM_VAR_NAME
11from .wrapperdefs import ROOT_TYPE_VAR_NAME, ROOT_TYPE_PARAM
12from .wrapperdefs import STREAM_RET_TYPE
13from .wrapperdefs import MARSHAL_INPUT_VAR_NAME
14from .wrapperdefs import UNMARSHAL_INPUT_VAR_NAME
15from .wrapperdefs import PARAMETERS_MARSHALING
16from .wrapperdefs import PARAMETERS_MARSHALING_GUEST
17from .wrapperdefs import STYPE_OVERRIDE
18from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE, EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME
19from .wrapperdefs import API_PREFIX_RESERVEDMARSHAL
20from .wrapperdefs import API_PREFIX_RESERVEDUNMARSHAL
21
22from .marshalingdefs import CUSTOM_MARSHAL_TYPES
23class VulkanReservedMarshalingCodegen(VulkanTypeIterator):
24    def __init__(self,
25                 cgen,
26                 variant,
27                 streamVarName,
28                 rootTypeVarName,
29                 inputVarName,
30                 ptrVarName,
31                 marshalPrefix,
32                 handlemapPrefix,
33                 direction = "write",
34                 forApiOutput = False,
35                 dynAlloc = False,
36                 mapHandles = True,
37                 handleMapOverwrites = False,
38                 doFiltering = True,
39                 stackVar=None,
40                 stackArrSize=None):
41        self.cgen = cgen
42        self.variant = variant
43        self.direction = direction
44        self.processSimple = "write" if self.direction == "write" else "read"
45        self.forApiOutput = forApiOutput
46
47        self.checked = False
48
49        self.streamVarName = streamVarName
50        self.rootTypeVarName = rootTypeVarName
51        self.inputVarName = inputVarName
52        self.ptrVar = ptrVarName
53        self.marshalPrefix = marshalPrefix
54        self.handlemapPrefix = handlemapPrefix
55
56        self.exprAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.inputVarName, asPtr = True)
57        self.exprValueAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.inputVarName, asPtr = False)
58        self.exprPrimitiveValueAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.inputVarName, asPtr = False)
59        self.lenAccessor = lambda t: self.cgen.generalLengthAccess(t, parentVarName = self.inputVarName)
60        self.lenAccessorGuard = lambda t: self.cgen.generalLengthAccessGuard(
61            t, parentVarName=self.inputVarName)
62        self.filterVarAccessor = lambda t: self.cgen.filterVarAccess(t, parentVarName = self.inputVarName)
63
64        self.dynAlloc = dynAlloc
65        self.mapHandles = mapHandles
66        self.handleMapOverwrites = handleMapOverwrites
67        self.doFiltering = doFiltering
68
69        self.stackVar = stackVar
70        self.stackArrSize = stackArrSize
71
72    def getTypeForStreaming(self, vulkanType):
73        res = copy(vulkanType)
74
75        if not vulkanType.accessibleAsPointer():
76            res = res.getForAddressAccess()
77
78        if vulkanType.staticArrExpr:
79            res = res.getForAddressAccess()
80
81        if self.direction == "write":
82            return res
83        else:
84            return res.getForNonConstAccess()
85
86    def makeCastExpr(self, vulkanType):
87        return "(%s)" % (
88            self.cgen.makeCTypeDecl(vulkanType, useParamName=False))
89
90    def genPtrIncr(self, sizeExpr):
91        self.cgen.stmt("*%s += %s" % (self.ptrVar, sizeExpr))
92
93    def genMemcpyAndIncr(self, varname, cast, toStreamExpr, sizeExpr, toBe = False, actualSize = 4):
94        if self.direction == "write":
95            self.cgen.stmt("memcpy(*%s, %s%s, %s)" % (varname, cast, toStreamExpr, sizeExpr))
96        else:
97            self.cgen.stmt("memcpy(%s%s, *%s, %s)" % (cast, toStreamExpr, varname, sizeExpr))
98
99        if toBe:
100            streamPrefix = "to"
101            if "read" == self.direction:
102                streamPrefix = "from"
103
104            streamMethod = streamPrefix
105
106            if 1 == actualSize:
107                streamMethod += "Byte"
108            elif 2 == actualSize:
109                streamMethod += "Be16"
110            elif 4 == actualSize:
111                streamMethod += "Be32"
112            elif 8 == actualSize:
113                streamMethod += "Be64"
114            else:
115                pass
116
117            if self.variant == "guest":
118                streamNamespace = "gfxstream::aemu"
119            else:
120                streamNamespace = "android::base"
121            if self.direction == "write":
122                self.cgen.stmt("%s::Stream::%s((uint8_t*)*%s)" % (streamNamespace, streamMethod, varname))
123            else:
124                self.cgen.stmt("%s::Stream::%s((uint8_t*)%s)" % (streamNamespace, streamMethod, toStreamExpr))
125
126        self.genPtrIncr(sizeExpr)
127
128    def genStreamCall(self, vulkanType, toStreamExpr, sizeExpr):
129        varname = self.ptrVar
130        cast = self.makeCastExpr(self.getTypeForStreaming(vulkanType))
131        self.genMemcpyAndIncr(varname, cast, toStreamExpr, sizeExpr)
132
133    def genPrimitiveStreamCall(self, vulkanType, access):
134        varname = self.ptrVar
135        self.cgen.memcpyPrimitive(
136            self.typeInfo,
137            "(*" + varname + ")",
138            access,
139            vulkanType,
140            self.variant,
141            direction=self.direction)
142        self.genPtrIncr(str(self.cgen.countPrimitive(
143            self.typeInfo,
144            vulkanType)))
145
146    def genHandleMappingCall(self, vulkanType, access, lenAccess, lenAccessGuard):
147
148        if lenAccess is None:
149            lenAccess = "1"
150            handle64Bytes = "8"
151        else:
152            handle64Bytes = "%s * 8" % lenAccess
153
154        handle64Var = self.cgen.var()
155        if lenAccess != "1":
156            self.cgen.beginIf(lenAccess)
157            self.cgen.stmt("uint8_t* %s_ptr = (uint8_t*)(*%s)" % (handle64Var, self.ptrVar))
158            handle64VarAccess = handle64Var
159            handle64VarType = \
160                makeVulkanTypeSimple(False, "uint64_t", 1, paramName=handle64Var)
161        else:
162            self.cgen.stmt("uint64_t %s" % handle64Var)
163            handle64VarAccess = "&%s" % handle64Var
164            handle64VarType = \
165                makeVulkanTypeSimple(False, "uint64_t", 0, paramName=handle64Var)
166
167        if "" == self.handlemapPrefix:
168            mapFunc = ("(%s)" % vulkanType.typeName)
169            mapFunc64 = ("(%s)" % "uint64_t")
170        else:
171            mapFunc = self.handlemapPrefix + vulkanType.typeName
172            mapFunc64 = mapFunc
173
174        if self.direction == "write":
175            if self.handleMapOverwrites:
176                self.cgen.stmt(
177                    "static_assert(8 == sizeof(%s), \"handle map overwrite requres %s to be 8 bytes long\")" % \
178                            (vulkanType.typeName, vulkanType.typeName))
179                if "1" == lenAccess:
180                    self.cgen.stmt("*%s = (%s)%s(*%s)" % (access, vulkanType.typeName, mapFunc, access))
181                    self.genStreamCall(vulkanType, access, "8 * %s" % lenAccess)
182                else:
183                    if lenAccessGuard is not None:
184                        self.cgen.beginIf(lenAccessGuard)
185                    self.cgen.beginFor("uint32_t k = 0", "k < %s" % lenAccess, "++k")
186                    self.cgen.stmt("%s[k] = (%s)%s(%s[k])" % (access, vulkanType.typeName, mapFunc, access))
187                    self.cgen.endFor()
188                    if lenAccessGuard is not None:
189                        self.cgen.endIf()
190                    self.genPtrIncr("8 * %s" % lenAccess)
191            else:
192                if "1" == lenAccess:
193                    self.cgen.stmt("*%s = %s((*%s))" % (handle64VarAccess, mapFunc64, access))
194                    self.genStreamCall(handle64VarType, handle64VarAccess, handle64Bytes)
195                else:
196                    if lenAccessGuard is not None:
197                        self.cgen.beginIf(lenAccessGuard)
198                    self.cgen.beginFor("uint32_t k = 0", "k < %s" % lenAccess, "++k")
199                    self.cgen.stmt("uint64_t tmpval = %s(%s[k])" % (mapFunc64, access))
200                    self.cgen.stmt("memcpy(%s_ptr + k * 8, &tmpval, sizeof(uint64_t))" % (handle64Var))
201                    self.cgen.endFor()
202                    if lenAccessGuard is not None:
203                        self.cgen.endIf()
204                    self.genPtrIncr("8 * %s" % lenAccess)
205        else:
206            if "1" == lenAccess:
207                self.genStreamCall(handle64VarType, handle64VarAccess, handle64Bytes)
208                self.cgen.stmt("*%s%s = (%s)%s((%s)(*%s))" % (
209                    self.makeCastExpr(vulkanType.getForNonConstAccess()), access,
210                    vulkanType.typeName, mapFunc, vulkanType.typeName, handle64VarAccess))
211            else:
212                self.genPtrIncr("8 * %s" % lenAccess)
213                if lenAccessGuard is not None:
214                    self.cgen.beginIf(lenAccessGuard)
215                self.cgen.beginFor("uint32_t k = 0", "k < %s" % lenAccess, "++k")
216                self.cgen.stmt("uint64_t tmpval; memcpy(&tmpval, %s_ptr + k * 8, sizeof(uint64_t))" % handle64Var)
217                self.cgen.stmt("*((%s%s) + k) = tmpval ? (%s)%s((%s)tmpval) : VK_NULL_HANDLE" % (
218                    self.makeCastExpr(vulkanType.getForNonConstAccess()), access,
219                    vulkanType.typeName, mapFunc, vulkanType.typeName))
220                if lenAccessGuard is not None:
221                    self.cgen.endIf()
222                self.cgen.endFor()
223
224        if lenAccess != "1":
225            self.cgen.endIf()
226
227    def doAllocSpace(self, vulkanType):
228        if self.dynAlloc and self.direction == "read":
229            access = self.exprAccessor(vulkanType)
230            lenAccess = self.lenAccessor(vulkanType)
231            sizeof = self.cgen.sizeofExpr(vulkanType.getForValueAccess())
232            if lenAccess:
233                bytesExpr = "%s * %s" % (lenAccess, sizeof)
234            else:
235                bytesExpr = sizeof
236                lenAccess = "1"
237
238            if self.stackVar:
239                if self.stackArrSize != lenAccess:
240                    self.cgen.beginIf("%s <= %s" % (lenAccess, self.stackArrSize))
241
242                self.cgen.stmt(
243                        "%s = %s%s" % (access, self.makeCastExpr(vulkanType.getForNonConstAccess()), self.stackVar))
244
245                if self.stackArrSize != lenAccess:
246                    self.cgen.endIf()
247                    self.cgen.beginElse()
248
249                if self.stackArrSize != lenAccess:
250                    self.cgen.stmt(
251                            "%s->alloc((void**)&%s, %s)" %
252                            (self.streamVarName,
253                                access, bytesExpr))
254
255                if self.stackArrSize != lenAccess:
256                    self.cgen.endIf()
257            else:
258                self.cgen.stmt(
259                        "%s->alloc((void**)&%s, %s)" %
260                        (self.streamVarName,
261                            access, bytesExpr))
262
263    def getOptionalStringFeatureExpr(self, vulkanType):
264        streamFeature = vulkanType.getProtectStreamFeature()
265        if streamFeature is None:
266            return None
267        return "%s->getFeatureBits() & %s" % (self.streamVarName, streamFeature)
268
269    def onCheck(self, vulkanType):
270        if self.forApiOutput:
271            return
272
273        featureExpr = self.getOptionalStringFeatureExpr(vulkanType)
274        self.checked = True
275        access = self.exprAccessor(vulkanType)
276        needConsistencyCheck = False
277
278        self.cgen.line("// WARNING PTR CHECK")
279        if (self.dynAlloc and self.direction == "read") or self.direction == "write":
280            checkAccess = self.exprAccessor(vulkanType)
281            addrExpr = "&" + checkAccess
282            sizeExpr = self.cgen.sizeofExpr(vulkanType)
283        else:
284            checkName = "check_%s" % vulkanType.paramName
285            self.cgen.stmt("%s %s" % (
286                self.cgen.makeCTypeDecl(vulkanType, useParamName = False), checkName))
287            checkAccess = checkName
288            addrExpr = "&" + checkAccess
289            sizeExpr = self.cgen.sizeofExpr(vulkanType)
290            needConsistencyCheck = True
291
292        if featureExpr is not None:
293            self.cgen.beginIf(featureExpr)
294
295        self.genPrimitiveStreamCall(
296            vulkanType,
297            checkAccess)
298
299        if featureExpr is not None:
300            self.cgen.endIf()
301
302        if featureExpr is not None:
303            self.cgen.beginIf("(!(%s) || %s)" % (featureExpr, access))
304        else:
305            self.cgen.beginIf(access)
306
307        if needConsistencyCheck and featureExpr is None:
308            self.cgen.beginIf("!(%s)" % checkName)
309            self.cgen.stmt(
310                "fprintf(stderr, \"fatal: %s inconsistent between guest and host\\n\")" % (access))
311            self.cgen.endIf()
312
313    def onCheckWithNullOptionalStringFeature(self, vulkanType):
314        self.cgen.beginIf("%s->getFeatureBits() & VULKAN_STREAM_FEATURE_NULL_OPTIONAL_STRINGS_BIT" % self.streamVarName)
315        self.onCheck(vulkanType)
316
317    def endCheckWithNullOptionalStringFeature(self, vulkanType):
318        self.endCheck(vulkanType)
319        self.cgen.endIf()
320        self.cgen.beginElse()
321
322    def finalCheckWithNullOptionalStringFeature(self, vulkanType):
323        self.cgen.endElse()
324
325    def endCheck(self, vulkanType):
326
327        if self.checked:
328            self.cgen.endIf()
329            self.checked = False
330
331    def genFilterFunc(self, filterfunc, env):
332
333        def loop(expr, lambdaEnv={}):
334            def do_func(expr):
335                fnamestr = expr.name.name
336                if "not" == fnamestr:
337                    return "!(%s)" % (loop(expr.args[0], lambdaEnv))
338                if "eq" == fnamestr:
339                    return "(%s == %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
340                if "and" == fnamestr:
341                    return "(%s && %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
342                if "or" == fnamestr:
343                    return "(%s || %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
344                if "bitwise_and" == fnamestr:
345                    return "(%s & %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
346                if "getfield" == fnamestr:
347                    ptrlevels = get_ptrlevels(expr.args[0].val.name)
348                    if ptrlevels == 0:
349                        return "%s.%s" % (loop(expr.args[0], lambdaEnv), expr.args[1].val)
350                    else:
351                        return "(%s(%s)).%s" % ("*" * ptrlevels, loop(expr.args[0], lambdaEnv), expr.args[1].val)
352
353                if "if" == fnamestr:
354                    return "((%s) ? (%s) : (%s))" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv), loop(expr.args[2], lambdaEnv))
355
356                return "%s(%s)" % (fnamestr, ", ".join(map(lambda e: loop(e, lambdaEnv), expr.args)))
357
358            def do_expratom(atomname, lambdaEnv= {}):
359                if lambdaEnv.get(atomname, None) is not None:
360                    return atomname
361
362                enventry = env.get(atomname, None)
363                if None != enventry:
364                    return self.getEnvAccessExpr(atomname)
365                return atomname
366
367            def get_ptrlevels(atomname, lambdaEnv= {}):
368                if lambdaEnv.get(atomname, None) is not None:
369                    return 0
370
371                enventry = env.get(atomname, None)
372                if None != enventry:
373                    return self.getPointerIndirectionLevels(atomname)
374
375                return 0
376
377            def do_exprval(expr, lambdaEnv= {}):
378                expratom = expr.val
379
380                if Atom == type(expratom):
381                    return do_expratom(expratom.name, lambdaEnv)
382
383                return "%s" % expratom
384
385            def do_lambda(expr, lambdaEnv= {}):
386                params = expr.vs
387                body = expr.body
388                newEnv = {}
389
390                for (k, v) in lambdaEnv.items():
391                    newEnv[k] = v
392
393                for p in params:
394                    newEnv[p.name] = p.typ
395
396                return "[](%s) { return %s; }" % (", ".join(list(map(lambda p: "%s %s" % (p.typ, p.name), params))), loop(body, lambdaEnv=newEnv))
397
398            if FuncExpr == type(expr):
399                return do_func(expr)
400            if FuncLambda == type(expr):
401                return do_lambda(expr)
402            elif FuncExprVal == type(expr):
403                return do_exprval(expr)
404
405        return loop(filterfunc)
406
407    def beginFilterGuard(self, vulkanType):
408        if vulkanType.filterVar == None:
409            return
410
411        if self.doFiltering == False:
412            return
413
414        filterVarAccess = self.getEnvAccessExpr(vulkanType.filterVar)
415
416        filterValsExpr = None
417        filterFuncExpr = None
418        filterExpr = None
419
420        filterFeature = "%s->getFeatureBits() & VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT" % self.streamVarName
421
422        if None != vulkanType.filterVals:
423            filterValsExpr = " || ".join(map(lambda filterval: "(%s == %s)" % (filterval, filterVarAccess), vulkanType.filterVals))
424
425        if None != vulkanType.filterFunc:
426            filterFuncExpr = self.genFilterFunc(vulkanType.filterFunc, self.currentStructInfo.environment)
427
428        if None != filterValsExpr and None != filterFuncExpr:
429            filterExpr = "%s || %s" % (filterValsExpr, filterFuncExpr)
430        elif None == filterValsExpr and None == filterFuncExpr:
431            # Assume is bool
432            self.cgen.beginIf(filterVarAccess)
433        elif None != filterValsExpr:
434            self.cgen.beginIf("(!(%s) || (%s))" % (filterFeature, filterValsExpr))
435        elif None != filterFuncExpr:
436            self.cgen.beginIf("(!(%s) || (%s))" % (filterFeature, filterFuncExpr))
437
438    def endFilterGuard(self, vulkanType, cleanupExpr=None):
439        if vulkanType.filterVar == None:
440            return
441
442        if self.doFiltering == False:
443            return
444
445        if cleanupExpr == None:
446            self.cgen.endIf()
447        else:
448            self.cgen.endIf()
449            self.cgen.beginElse()
450            self.cgen.stmt(cleanupExpr)
451            self.cgen.endElse()
452
453    def getEnvAccessExpr(self, varName):
454        parentEnvEntry = self.currentStructInfo.environment.get(varName, None)
455
456        if parentEnvEntry != None:
457            isParentMember = parentEnvEntry["structmember"]
458
459            if isParentMember:
460                envAccess = self.exprValueAccessor(list(filter(lambda member: member.paramName == varName, self.currentStructInfo.members))[0])
461            else:
462                envAccess = varName
463            return envAccess
464
465        return None
466
467    def getPointerIndirectionLevels(self, varName):
468        parentEnvEntry = self.currentStructInfo.environment.get(varName, None)
469
470        if parentEnvEntry != None:
471            isParentMember = parentEnvEntry["structmember"]
472
473            if isParentMember:
474                return list(filter(lambda member: member.paramName == varName, self.currentStructInfo.members))[0].pointerIndirectionLevels
475            else:
476                return 0
477            return 0
478
479        return 0
480
481
482    def onCompoundType(self, vulkanType):
483
484        access = self.exprAccessor(vulkanType)
485        lenAccess = self.lenAccessor(vulkanType)
486
487        self.beginFilterGuard(vulkanType)
488
489        if vulkanType.pointerIndirectionLevels > 0:
490            self.doAllocSpace(vulkanType)
491
492        if lenAccess is not None:
493            loopVar = "i"
494            access = "%s + %s" % (access, loopVar)
495            forInit = "uint32_t %s = 0" % loopVar
496            forCond = "%s < (uint32_t)%s" % (loopVar, lenAccess)
497            forIncr = "++%s" % loopVar
498            self.cgen.beginFor(forInit, forCond, forIncr)
499
500        accessWithCast = "%s(%s)" % (self.makeCastExpr(
501            self.getTypeForStreaming(vulkanType)), access)
502
503        callParams = [self.streamVarName, self.rootTypeVarName, accessWithCast, self.ptrVar]
504
505        for (bindName, localName) in vulkanType.binds.items():
506            callParams.append(self.getEnvAccessExpr(localName))
507
508        self.cgen.funcCall(None, self.marshalPrefix + vulkanType.typeName,
509                           callParams)
510
511        if lenAccess is not None:
512            self.cgen.endFor()
513
514        if self.direction == "read":
515            self.endFilterGuard(vulkanType, "%s = 0" % self.exprAccessor(vulkanType))
516        else:
517            self.endFilterGuard(vulkanType)
518
519    def onString(self, vulkanType):
520        access = self.exprAccessor(vulkanType)
521
522        if self.direction == "write":
523            self.cgen.beginBlock()
524            self.cgen.stmt("uint32_t l = %s ? strlen(%s): 0" % (access, access))
525            self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)" ,"&l", "sizeof(uint32_t)", toBe = True, actualSize = 4)
526            self.genMemcpyAndIncr(self.ptrVar, "(char*)", access, "l")
527            self.cgen.endBlock()
528        else:
529            castExpr = \
530                self.makeCastExpr( \
531                    self.getTypeForStreaming( \
532                        vulkanType.getForAddressAccess()))
533            self.cgen.stmt( \
534                "%s->loadStringInPlaceWithStreamPtr(%s&%s, %s)" % (self.streamVarName, castExpr, access, self.ptrVar))
535
536    def onStringArray(self, vulkanType):
537        access = self.exprAccessor(vulkanType)
538        lenAccess = self.lenAccessor(vulkanType)
539        lenAccessGuard = self.lenAccessorGuard(vulkanType)
540
541        if self.direction == "write":
542            self.cgen.beginBlock()
543
544            self.cgen.stmt("uint32_t c = 0")
545            if lenAccessGuard is not None:
546                self.cgen.beginIf(lenAccessGuard)
547            self.cgen.stmt("c = %s" % (lenAccess))
548            if lenAccessGuard is not None:
549                self.cgen.endIf()
550            self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)" ,"&c", "sizeof(uint32_t)", toBe = True, actualSize = 4)
551
552            self.cgen.beginFor("uint32_t i = 0", "i < c", "++i")
553            self.cgen.stmt("uint32_t l = %s ? strlen(%s[i]): 0" % (access, access))
554            self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)" ,"&l", "sizeof(uint32_t)", toBe = True, actualSize = 4)
555            self.cgen.beginIf("l")
556            self.genMemcpyAndIncr(self.ptrVar, "(char*)", "(%s[i])" % access, "l")
557            self.cgen.endIf()
558            self.cgen.endFor()
559
560            self.cgen.endBlock()
561        else:
562            castExpr = \
563                self.makeCastExpr( \
564                    self.getTypeForStreaming( \
565                        vulkanType.getForAddressAccess()))
566
567            self.cgen.stmt("%s->loadStringArrayInPlaceWithStreamPtr(%s&%s, %s)" % (self.streamVarName, castExpr, access, self.ptrVar))
568
569    def onStaticArr(self, vulkanType):
570        access = self.exprValueAccessor(vulkanType)
571        lenAccess = self.lenAccessor(vulkanType)
572        finalLenExpr = "%s * %s" % (lenAccess, self.cgen.sizeofExpr(vulkanType))
573        self.genStreamCall(vulkanType, access, finalLenExpr)
574
575    # Old version VkEncoder may have some sType values conflict with VkDecoder
576    # of new versions. For host decoder, it should not carry the incorrect old
577    # sType values to the |forUnmarshaling| struct. Instead it should overwrite
578    # the sType value.
579    def overwriteSType(self, vulkanType):
580        if self.direction == "read":
581            sTypeParam = copy(vulkanType)
582            sTypeParam.paramName = "sType"
583            sTypeAccess = self.exprAccessor(sTypeParam)
584
585            typeName = vulkanType.parent.typeName
586            if typeName in STYPE_OVERRIDE:
587                self.cgen.stmt("%s = %s" %
588                               (sTypeAccess, STYPE_OVERRIDE[typeName]))
589
590    def onStructExtension(self, vulkanType):
591        self.overwriteSType(vulkanType)
592
593        sTypeParam = copy(vulkanType)
594        sTypeParam.paramName = "sType"
595
596        access = self.exprAccessor(vulkanType)
597        sizeVar = "%s_size" % vulkanType.paramName
598
599        if self.direction == "read":
600            castedAccessExpr = "(%s)(%s)" % ("void*", access)
601        else:
602            castedAccessExpr = access
603
604        sTypeAccess = self.exprAccessor(sTypeParam)
605        self.cgen.beginIf("%s == VK_STRUCTURE_TYPE_MAX_ENUM" % self.rootTypeVarName)
606        self.cgen.stmt("%s = %s" % (self.rootTypeVarName, sTypeAccess))
607        self.cgen.endIf()
608
609        if self.direction == "read" and self.dynAlloc:
610            self.cgen.stmt("uint32_t %s" % sizeVar)
611
612            self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)", "&" + sizeVar, "sizeof(uint32_t)", toBe = True, actualSize = 4)
613
614            self.cgen.stmt("%s = nullptr" % access)
615            self.cgen.beginIf(sizeVar)
616            self.cgen.stmt( \
617                    "%s->alloc((void**)&%s, sizeof(VkStructureType))" %
618                    (self.streamVarName, access))
619
620            self.genStreamCall(vulkanType, access, "sizeof(VkStructureType)")
621            self.cgen.stmt("VkStructureType extType = *(VkStructureType*)(%s)" % access)
622            self.cgen.stmt( \
623                    "%s->alloc((void**)&%s, %s(%s->getFeatureBits(), %s, %s))" %
624                    (self.streamVarName, access, EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME, self.streamVarName, self.rootTypeVarName, access))
625            self.cgen.stmt("*(VkStructureType*)%s = extType" % access)
626
627            self.cgen.funcCall(None, self.marshalPrefix + "extension_struct",
628                [self.streamVarName, self.rootTypeVarName, castedAccessExpr, self.ptrVar])
629            self.cgen.endIf()
630        else:
631
632            self.cgen.funcCall(None, self.marshalPrefix + "extension_struct",
633                [self.streamVarName, self.rootTypeVarName, castedAccessExpr, self.ptrVar])
634
635    def onPointer(self, vulkanType):
636        access = self.exprAccessor(vulkanType)
637
638        lenAccess = self.lenAccessor(vulkanType)
639        lenAccessGuard = self.lenAccessorGuard(vulkanType)
640
641        self.beginFilterGuard(vulkanType)
642        self.doAllocSpace(vulkanType)
643
644        if vulkanType.isHandleType() and self.mapHandles:
645            self.genHandleMappingCall(
646                vulkanType, access, lenAccess, lenAccessGuard)
647        else:
648            if self.typeInfo.isNonAbiPortableType(vulkanType.typeName):
649                if lenAccess is not None:
650                    if lenAccessGuard is not None:
651                        self.cgen.beginIf(lenAccessGuard)
652                    self.cgen.beginFor("uint32_t i = 0", "i < (uint32_t)%s" % lenAccess, "++i")
653                    self.genPrimitiveStreamCall(vulkanType.getForValueAccess(), "%s[i]" % access)
654                    self.cgen.endFor()
655                    if lenAccessGuard is not None:
656                        self.cgen.endIf()
657                else:
658                    self.genPrimitiveStreamCall(vulkanType.getForValueAccess(), "(*%s)" % access)
659            else:
660                if lenAccess is not None:
661                    finalLenExpr = "%s * %s" % (
662                        lenAccess, self.cgen.sizeofExpr(vulkanType.getForValueAccess()))
663                else:
664                    finalLenExpr = "%s" % (
665                        self.cgen.sizeofExpr(vulkanType.getForValueAccess()))
666                self.genStreamCall(vulkanType, access, finalLenExpr)
667
668        if self.direction == "read":
669            self.endFilterGuard(vulkanType, "%s = 0" % access)
670        else:
671            self.endFilterGuard(vulkanType)
672
673    def onValue(self, vulkanType):
674        self.beginFilterGuard(vulkanType)
675
676        if vulkanType.isHandleType() and self.mapHandles:
677            access = self.exprAccessor(vulkanType)
678            self.genHandleMappingCall(
679                vulkanType.getForAddressAccess(), access, "1", None)
680        elif self.typeInfo.isNonAbiPortableType(vulkanType.typeName):
681            access = self.exprPrimitiveValueAccessor(vulkanType)
682            self.genPrimitiveStreamCall(vulkanType, access)
683        else:
684            access = self.exprAccessor(vulkanType)
685            self.genStreamCall(vulkanType, access, self.cgen.sizeofExpr(vulkanType))
686
687        self.endFilterGuard(vulkanType)
688
689    def streamLetParameter(self, structInfo, letParamInfo):
690        filterFeature = "%s->getFeatureBits() & VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT" % self.streamVarName
691        self.cgen.stmt("%s %s = 1" % (letParamInfo.typeName, letParamInfo.paramName))
692
693        self.cgen.beginIf(filterFeature)
694
695        if self.direction == "write":
696            bodyExpr = self.currentStructInfo.environment[letParamInfo.paramName]["body"]
697            self.cgen.stmt("%s = %s" % (letParamInfo.paramName, self.genFilterFunc(bodyExpr, self.currentStructInfo.environment)))
698
699        self.genPrimitiveStreamCall(letParamInfo, letParamInfo.paramName)
700
701        self.cgen.endIf()
702
703class VulkanReservedMarshaling(VulkanWrapperGenerator):
704
705    def __init__(self, module, typeInfo, variant="host"):
706        VulkanWrapperGenerator.__init__(self, module, typeInfo)
707
708        self.cgenHeader = CodeGen()
709        self.cgenImpl = CodeGen()
710
711        self.variant = variant
712
713        self.currentFeature = None
714        self.apiOpcodes = {}
715        self.dynAlloc = self.variant != "guest"
716        self.ptrVarName = "ptr"
717        self.ptrVarType = makeVulkanTypeSimple(False, "uint8_t", 2, self.ptrVarName)
718        self.ptrVarTypeUnmarshal = makeVulkanTypeSimple(False, "uint8_t", 2, self.ptrVarName)
719
720        if self.variant == "guest":
721            self.marshalingParams = PARAMETERS_MARSHALING_GUEST
722        else:
723            self.marshalingParams = PARAMETERS_MARSHALING
724
725        self.writeCodegen = \
726            VulkanReservedMarshalingCodegen(
727                None,
728                self.variant,
729                VULKAN_STREAM_VAR_NAME,
730                ROOT_TYPE_VAR_NAME,
731                MARSHAL_INPUT_VAR_NAME,
732                self.ptrVarName,
733                API_PREFIX_RESERVEDMARSHAL,
734                "get_host_u64_" if "guest" == self.variant else "",
735                direction = "write")
736
737        self.readCodegen = \
738            VulkanReservedMarshalingCodegen(
739                None,
740                self.variant,
741                VULKAN_STREAM_VAR_NAME,
742                ROOT_TYPE_VAR_NAME,
743                UNMARSHAL_INPUT_VAR_NAME,
744                self.ptrVarName,
745                API_PREFIX_RESERVEDUNMARSHAL,
746                "unbox_" if "host" == self.variant else "",
747                direction = "read",
748                dynAlloc=self.dynAlloc)
749
750        self.knownDefs = {}
751
752        self.extensionMarshalPrototype = \
753            VulkanAPI(API_PREFIX_RESERVEDMARSHAL + "extension_struct",
754                      STREAM_RET_TYPE,
755                      self.marshalingParams +
756                      [STRUCT_EXTENSION_PARAM, self.ptrVarType])
757
758        self.extensionUnmarshalPrototype = \
759            VulkanAPI(API_PREFIX_RESERVEDUNMARSHAL + "extension_struct",
760                      STREAM_RET_TYPE,
761                      self.marshalingParams +
762                      [STRUCT_EXTENSION_PARAM_FOR_WRITE, self.ptrVarTypeUnmarshal])
763
764    def onBegin(self,):
765        VulkanWrapperGenerator.onBegin(self)
766        self.module.appendImpl(self.cgenImpl.makeFuncDecl(self.extensionMarshalPrototype))
767        self.module.appendImpl(self.cgenImpl.makeFuncDecl(self.extensionUnmarshalPrototype))
768
769    def onBeginFeature(self, featureName, featureType):
770        VulkanWrapperGenerator.onBeginFeature(self, featureName, featureType)
771        self.currentFeature = featureName
772
773    def onGenType(self, typeXml, name, alias):
774        VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)
775
776        if name in self.knownDefs:
777            return
778
779        category = self.typeInfo.categoryOf(name)
780
781        if category in ["struct", "union"] and alias:
782            if self.variant != "host":
783                self.module.appendHeader(
784                    self.cgenHeader.makeFuncAlias(API_PREFIX_RESERVEDMARSHAL + name,
785                                                  API_PREFIX_RESERVEDMARSHAL + alias))
786            if self.variant != "guest":
787                self.module.appendHeader(
788                    self.cgenHeader.makeFuncAlias(API_PREFIX_RESERVEDUNMARSHAL + name,
789                                                  API_PREFIX_RESERVEDUNMARSHAL + alias))
790
791        if category in ["struct", "union"] and not alias:
792
793            structInfo = self.typeInfo.structs[name]
794
795            marshalParams = self.marshalingParams + \
796                [makeVulkanTypeSimple(True, name, 1, MARSHAL_INPUT_VAR_NAME),
797                        self.ptrVarType]
798
799            freeParams = []
800            letParams = []
801
802            for (envname, bindingInfo) in list(sorted(structInfo.environment.items(), key = lambda kv: kv[0])):
803                if None == bindingInfo["binding"]:
804                    freeParams.append(makeVulkanTypeSimple(True, bindingInfo["type"], 0, envname))
805                else:
806                    if not bindingInfo["structmember"]:
807                        letParams.append(makeVulkanTypeSimple(True, bindingInfo["type"], 0, envname))
808
809            marshalPrototype = \
810                VulkanAPI(API_PREFIX_RESERVEDMARSHAL + name,
811                          STREAM_RET_TYPE,
812                          marshalParams + freeParams)
813
814            marshalPrototypeNoFilter = \
815                VulkanAPI(API_PREFIX_RESERVEDMARSHAL + name,
816                          STREAM_RET_TYPE,
817                          marshalParams)
818
819            def structMarshalingCustom(cgen):
820                self.writeCodegen.cgen = cgen
821                self.writeCodegen.currentStructInfo = structInfo
822                marshalingCode = \
823                    CUSTOM_MARSHAL_TYPES[name]["common"] + \
824                    CUSTOM_MARSHAL_TYPES[name]["reservedmarshaling"].format(
825                        streamVarName=self.writeCodegen.streamVarName,
826                        rootTypeVarName=self.writeCodegen.rootTypeVarName,
827                        inputVarName=self.writeCodegen.inputVarName,
828                        newInputVarName=self.writeCodegen.inputVarName + "_new")
829                for line in marshalingCode.split('\n'):
830                    cgen.line(line)
831
832            def structMarshalingDef(cgen):
833                self.writeCodegen.cgen = cgen
834                self.writeCodegen.currentStructInfo = structInfo
835                self.writeCodegen.cgen.stmt("(void)%s" % VULKAN_STREAM_VAR_NAME)
836                self.writeCodegen.cgen.stmt("(void)%s" % ROOT_TYPE_VAR_NAME)
837
838                if category == "struct":
839                    # marshal 'let' parameters first
840                    for letp in letParams:
841                        self.writeCodegen.streamLetParameter(self.typeInfo, letp)
842
843                    for member in structInfo.members:
844                        iterateVulkanType(self.typeInfo, member, self.writeCodegen)
845                if category == "union":
846                    iterateVulkanType(self.typeInfo, structInfo.members[0], self.writeCodegen)
847
848            def structMarshalingDefNoFilter(cgen):
849                self.writeCodegen.cgen = cgen
850                self.writeCodegen.currentStructInfo = structInfo
851                self.writeCodegen.doFiltering = False
852                self.writeCodegen.cgen.stmt("(void)%s" % VULKAN_STREAM_VAR_NAME)
853                self.writeCodegen.cgen.stmt("(void)%s" % ROOT_TYPE_VAR_NAME)
854
855                if category == "struct":
856                    # marshal 'let' parameters first
857                    for letp in letParams:
858                        self.writeCodegen.streamLetParameter(self.typeInfo, letp)
859
860                    for member in structInfo.members:
861                        iterateVulkanType(self.typeInfo, member, self.writeCodegen)
862                if category == "union":
863                    iterateVulkanType(self.typeInfo, structInfo.members[0], self.writeCodegen)
864                self.writeCodegen.doFiltering = True
865
866            if self.variant != "host":
867                self.module.appendHeader(
868                    self.cgenHeader.makeFuncDecl(marshalPrototype))
869
870                if name in CUSTOM_MARSHAL_TYPES and CUSTOM_MARSHAL_TYPES[name].get("reservedmarshaling"):
871                    self.module.appendImpl(
872                        self.cgenImpl.makeFuncImpl(
873                            marshalPrototype, structMarshalingCustom))
874                else:
875                    self.module.appendImpl(
876                        self.cgenImpl.makeFuncImpl(
877                            marshalPrototype, structMarshalingDef))
878
879                if freeParams != []:
880                    self.module.appendHeader(
881                        self.cgenHeader.makeFuncDecl(marshalPrototypeNoFilter))
882                    self.module.appendImpl(
883                        self.cgenImpl.makeFuncImpl(
884                            marshalPrototypeNoFilter, structMarshalingDefNoFilter))
885
886            unmarshalPrototype = \
887                VulkanAPI(API_PREFIX_RESERVEDUNMARSHAL + name,
888                          STREAM_RET_TYPE,
889                          self.marshalingParams + [makeVulkanTypeSimple(False, name, 1, UNMARSHAL_INPUT_VAR_NAME), self.ptrVarTypeUnmarshal] + freeParams)
890
891            unmarshalPrototypeNoFilter = \
892                VulkanAPI(API_PREFIX_RESERVEDUNMARSHAL + name,
893                          STREAM_RET_TYPE,
894                          self.marshalingParams + [makeVulkanTypeSimple(False, name, 1, UNMARSHAL_INPUT_VAR_NAME), self.ptrVarTypeUnmarshal])
895
896            def structUnmarshalingCustom(cgen):
897                self.readCodegen.cgen = cgen
898                self.readCodegen.currentStructInfo = structInfo
899                unmarshalingCode = \
900                    CUSTOM_MARSHAL_TYPES[name]["common"] + \
901                    CUSTOM_MARSHAL_TYPES[name]["reservedunmarshaling"].format(
902                        streamVarName=self.readCodegen.streamVarName,
903                        rootTypeVarName=self.readCodegen.rootTypeVarName,
904                        inputVarName=self.readCodegen.inputVarName,
905                        newInputVarName=self.readCodegen.inputVarName + "_new")
906                for line in unmarshalingCode.split('\n'):
907                    cgen.line(line)
908
909            def structUnmarshalingDef(cgen):
910                self.readCodegen.cgen = cgen
911                self.readCodegen.currentStructInfo = structInfo
912                if category == "struct":
913                    # unmarshal 'let' parameters first
914                    for letp in letParams:
915                        self.readCodegen.streamLetParameter(self.typeInfo, letp)
916
917                    for member in structInfo.members:
918                        iterateVulkanType(self.typeInfo, member, self.readCodegen)
919                if category == "union":
920                    iterateVulkanType(self.typeInfo, structInfo.members[0], self.readCodegen)
921
922            def structUnmarshalingDefNoFilter(cgen):
923                self.readCodegen.cgen = cgen
924                self.readCodegen.currentStructInfo = structInfo
925                self.readCodegen.doFiltering = False
926                if category == "struct":
927                    # unmarshal 'let' parameters first
928                    for letp in letParams:
929                        iterateVulkanType(self.typeInfo, letp, self.readCodegen)
930                    for member in structInfo.members:
931                        iterateVulkanType(self.typeInfo, member, self.readCodegen)
932                if category == "union":
933                    iterateVulkanType(self.typeInfo, structInfo.members[0], self.readCodegen)
934                self.readCodegen.doFiltering = True
935
936            if self.variant != "guest":
937                self.module.appendHeader(
938                    self.cgenHeader.makeFuncDecl(unmarshalPrototype))
939
940                if name in CUSTOM_MARSHAL_TYPES and CUSTOM_MARSHAL_TYPES[name].get("reservedunmarshaling"):
941                    self.module.appendImpl(
942                        self.cgenImpl.makeFuncImpl(
943                            unmarshalPrototype, structUnmarshalingCustom))
944                else:
945                    self.module.appendImpl(
946                        self.cgenImpl.makeFuncImpl(
947                            unmarshalPrototype, structUnmarshalingDef))
948
949                if freeParams != []:
950                    self.module.appendHeader(
951                        self.cgenHeader.makeFuncDecl(unmarshalPrototypeNoFilter))
952                    self.module.appendImpl(
953                        self.cgenImpl.makeFuncImpl(
954                            unmarshalPrototypeNoFilter, structUnmarshalingDefNoFilter))
955
956    def onGenCmd(self, cmdinfo, name, alias):
957        VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
958
959    def doExtensionStructMarshalingCodegen(self, cgen, retType, extParam, forEach, funcproto, direction):
960        accessVar = "structAccess"
961        sizeVar = "currExtSize"
962        cgen.stmt("VkInstanceCreateInfo* %s = (VkInstanceCreateInfo*)(%s)" % (accessVar, extParam.paramName))
963        cgen.stmt("uint32_t %s = %s(%s->getFeatureBits(), %s, %s)" % (sizeVar, EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME, VULKAN_STREAM_VAR_NAME, ROOT_TYPE_VAR_NAME, extParam.paramName))
964
965        cgen.beginIf("!%s && %s" % (sizeVar, extParam.paramName))
966
967        cgen.line("// unknown struct extension; skip and call on its pNext field");
968        cgen.funcCall(None, funcproto.name, ["vkStream", ROOT_TYPE_VAR_NAME, "(void*)%s->pNext" % accessVar, self.ptrVarName])
969        cgen.stmt("return")
970
971        cgen.endIf()
972        cgen.beginElse()
973
974        cgen.line("// known or null extension struct")
975
976        if self.variant == "guest":
977            streamNamespace = "gfxstream::aemu"
978        else:
979            streamNamespace = "android::base"
980
981        if direction == "write":
982            cgen.stmt("memcpy(*%s, &%s, sizeof(uint32_t));" % (self.ptrVarName, sizeVar))
983            cgen.stmt("%s::Stream::toBe32((uint8_t*)*%s); *%s += sizeof(uint32_t)" % (streamNamespace, self.ptrVarName, self.ptrVarName))
984        elif not self.dynAlloc:
985            cgen.stmt("memcpy(&%s, *%s, sizeof(uint32_t));" % (sizeVar, self.ptrVarName))
986            cgen.stmt("%s::Stream::fromBe32((uint8_t*)&%s); *%s += sizeof(uint32_t)" % (streamNamespace, sizeVar, self.ptrVarName))
987
988        cgen.beginIf("!%s" % (sizeVar))
989        cgen.line("// exit if this was a null extension struct (size == 0 in this branch)")
990        cgen.stmt("return")
991        cgen.endIf()
992
993        cgen.endIf()
994
995        # Now we can do stream stuff
996        if direction == "write":
997            cgen.stmt("memcpy(*%s, %s, sizeof(VkStructureType)); *%s += sizeof(VkStructureType)" % (self.ptrVarName, extParam.paramName, self.ptrVarName))
998        elif not self.dynAlloc:
999            cgen.stmt("uint64_t pNext_placeholder")
1000            placeholderAccess = "(&pNext_placeholder)"
1001            cgen.stmt("memcpy(%s, *%s, sizeof(VkStructureType)); *%s += sizeof(VkStructureType)" % (placeholderAccess, self.ptrVarName, self.ptrVarName))
1002            cgen.stmt("(void)pNext_placeholder")
1003
1004        def fatalDefault(cgen):
1005            cgen.line("// fatal; the switch is only taken if the extension struct is known")
1006            if self.variant != "guest":
1007                cgen.stmt("fprintf(stderr, \" %s, Unhandled Vulkan structure type %s [%d], aborting.\\n\", __func__, string_VkStructureType(VkStructureType(structType)), structType)")
1008            cgen.stmt("abort()")
1009            pass
1010
1011        self.emitForEachStructExtension(
1012            cgen,
1013            retType,
1014            extParam,
1015            forEach,
1016            defaultEmit=fatalDefault,
1017            rootTypeVar=ROOT_TYPE_PARAM)
1018
1019    def onEnd(self,):
1020        VulkanWrapperGenerator.onEnd(self)
1021
1022        def forEachExtensionMarshal(ext, castedAccess, cgen):
1023            cgen.funcCall(None, API_PREFIX_RESERVEDMARSHAL + ext.name,
1024                          [VULKAN_STREAM_VAR_NAME, ROOT_TYPE_VAR_NAME, castedAccess, self.ptrVarName])
1025
1026        def forEachExtensionUnmarshal(ext, castedAccess, cgen):
1027            cgen.funcCall(None, API_PREFIX_RESERVEDUNMARSHAL + ext.name,
1028                          [VULKAN_STREAM_VAR_NAME, ROOT_TYPE_VAR_NAME, castedAccess, self.ptrVarName])
1029
1030        if self.variant != "host":
1031            self.module.appendImpl(
1032                self.cgenImpl.makeFuncImpl(
1033                    self.extensionMarshalPrototype,
1034                    lambda cgen: self.doExtensionStructMarshalingCodegen(
1035                        cgen,
1036                        STREAM_RET_TYPE,
1037                        STRUCT_EXTENSION_PARAM,
1038                        forEachExtensionMarshal,
1039                        self.extensionMarshalPrototype,
1040                        "write")))
1041
1042        if self.variant != "guest":
1043            self.module.appendImpl(
1044                self.cgenImpl.makeFuncImpl(
1045                    self.extensionUnmarshalPrototype,
1046                    lambda cgen: self.doExtensionStructMarshalingCodegen(
1047                        cgen,
1048                        STREAM_RET_TYPE,
1049                        STRUCT_EXTENSION_PARAM_FOR_WRITE,
1050                        forEachExtensionUnmarshal,
1051                        self.extensionUnmarshalPrototype,
1052                        "read")))
1053