summaryrefslogtreecommitdiff
path: root/codegen/vulkan/scripts/cereal/reservedmarshaling.py
diff options
context:
space:
mode:
Diffstat (limited to 'codegen/vulkan/scripts/cereal/reservedmarshaling.py')
-rw-r--r--codegen/vulkan/scripts/cereal/reservedmarshaling.py1055
1 files changed, 1055 insertions, 0 deletions
diff --git a/codegen/vulkan/scripts/cereal/reservedmarshaling.py b/codegen/vulkan/scripts/cereal/reservedmarshaling.py
new file mode 100644
index 00000000..23ace9d3
--- /dev/null
+++ b/codegen/vulkan/scripts/cereal/reservedmarshaling.py
@@ -0,0 +1,1055 @@
+# Copyright (c) 2018 The Android Open Source Project
+# Copyright (c) 2018 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from copy import copy
+
+from .common.codegen import CodeGen, VulkanAPIWrapper
+from .common.vulkantypes import \
+ VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator, Atom, FuncExpr, FuncExprVal, FuncLambda
+
+from .wrapperdefs import VulkanWrapperGenerator
+from .wrapperdefs import VULKAN_STREAM_VAR_NAME
+from .wrapperdefs import ROOT_TYPE_VAR_NAME, ROOT_TYPE_PARAM
+from .wrapperdefs import STREAM_RET_TYPE
+from .wrapperdefs import MARSHAL_INPUT_VAR_NAME
+from .wrapperdefs import UNMARSHAL_INPUT_VAR_NAME
+from .wrapperdefs import PARAMETERS_MARSHALING
+from .wrapperdefs import PARAMETERS_MARSHALING_GUEST
+from .wrapperdefs import STYPE_OVERRIDE
+from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE, EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME
+from .wrapperdefs import API_PREFIX_RESERVEDMARSHAL
+from .wrapperdefs import API_PREFIX_RESERVEDUNMARSHAL
+
+from .marshalingdefs import CUSTOM_MARSHAL_TYPES
+class VulkanReservedMarshalingCodegen(VulkanTypeIterator):
+ def __init__(self,
+ cgen,
+ streamVarName,
+ rootTypeVarName,
+ inputVarName,
+ ptrVarName,
+ marshalPrefix,
+ handlemapPrefix,
+ direction = "write",
+ forApiOutput = False,
+ dynAlloc = False,
+ mapHandles = True,
+ handleMapOverwrites = False,
+ doFiltering = True,
+ stackVar=None,
+ stackArrSize=None):
+ self.cgen = cgen
+ self.direction = direction
+ self.processSimple = "write" if self.direction == "write" else "read"
+ self.forApiOutput = forApiOutput
+
+ self.checked = False
+
+ self.streamVarName = streamVarName
+ self.rootTypeVarName = rootTypeVarName
+ self.inputVarName = inputVarName
+ self.ptrVar = ptrVarName
+ self.marshalPrefix = marshalPrefix
+ self.handlemapPrefix = handlemapPrefix
+
+ self.exprAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.inputVarName, asPtr = True)
+ self.exprValueAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.inputVarName, asPtr = False)
+ self.exprPrimitiveValueAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.inputVarName, asPtr = False)
+ self.lenAccessor = lambda t: self.cgen.generalLengthAccess(t, parentVarName = self.inputVarName)
+ self.lenAccessorGuard = lambda t: self.cgen.generalLengthAccessGuard(
+ t, parentVarName=self.inputVarName)
+ self.filterVarAccessor = lambda t: self.cgen.filterVarAccess(t, parentVarName = self.inputVarName)
+
+ self.dynAlloc = dynAlloc
+ self.mapHandles = mapHandles
+ self.handleMapOverwrites = handleMapOverwrites
+ self.doFiltering = doFiltering
+
+ self.stackVar = stackVar
+ self.stackArrSize = stackArrSize
+
+ def getTypeForStreaming(self, vulkanType):
+ res = copy(vulkanType)
+
+ if not vulkanType.accessibleAsPointer():
+ res = res.getForAddressAccess()
+
+ if vulkanType.staticArrExpr:
+ res = res.getForAddressAccess()
+
+ if self.direction == "write":
+ return res
+ else:
+ return res.getForNonConstAccess()
+
+ def makeCastExpr(self, vulkanType):
+ return "(%s)" % (
+ self.cgen.makeCTypeDecl(vulkanType, useParamName=False))
+
+ def genPtrIncr(self, sizeExpr):
+ self.cgen.stmt("*%s += %s" % (self.ptrVar, sizeExpr))
+
+ def genMemcpyAndIncr(self, varname, cast, toStreamExpr, sizeExpr, toBe = False, actualSize = 4):
+ if self.direction == "write":
+ self.cgen.stmt("memcpy(*%s, %s%s, %s)" % (varname, cast, toStreamExpr, sizeExpr))
+ else:
+ self.cgen.stmt("memcpy(%s%s, *%s, %s)" % (cast, toStreamExpr, varname, sizeExpr))
+
+ if toBe:
+ streamPrefix = "to"
+ if "read" == self.direction:
+ streamPrefix = "from"
+
+ streamMethod = streamPrefix
+
+ if 1 == actualSize:
+ streamMethod += "Byte"
+ elif 2 == actualSize:
+ streamMethod += "Be16"
+ elif 4 == actualSize:
+ streamMethod += "Be32"
+ elif 8 == actualSize:
+ streamMethod += "Be64"
+ else:
+ pass
+
+ if self.direction == "write":
+ self.cgen.stmt("android::base::Stream::%s((uint8_t*)*%s)" % (streamMethod, varname))
+ else:
+ self.cgen.stmt("android::base::Stream::%s((uint8_t*)%s)" % (streamMethod, toStreamExpr))
+
+ self.genPtrIncr(sizeExpr)
+
+ def genStreamCall(self, vulkanType, toStreamExpr, sizeExpr):
+ varname = self.ptrVar
+ cast = self.makeCastExpr(self.getTypeForStreaming(vulkanType))
+ self.genMemcpyAndIncr(varname, cast, toStreamExpr, sizeExpr)
+
+ def genPrimitiveStreamCall(self, vulkanType, access):
+ varname = self.ptrVar
+ self.cgen.memcpyPrimitive(
+ self.typeInfo,
+ "(*" + varname + ")",
+ access,
+ vulkanType,
+ direction=self.direction)
+ self.genPtrIncr(str(self.cgen.countPrimitive(
+ self.typeInfo,
+ vulkanType)))
+
+ def genHandleMappingCall(self, vulkanType, access, lenAccess, lenAccessGuard):
+
+ if lenAccess is None:
+ lenAccess = "1"
+ handle64Bytes = "8"
+ else:
+ handle64Bytes = "%s * 8" % lenAccess
+
+ handle64Var = self.cgen.var()
+ if lenAccess != "1":
+ self.cgen.beginIf(lenAccess)
+ self.cgen.stmt("uint8_t* %s_ptr = (uint8_t*)(*%s)" % (handle64Var, self.ptrVar))
+ handle64VarAccess = handle64Var
+ handle64VarType = \
+ makeVulkanTypeSimple(False, "uint64_t", 1, paramName=handle64Var)
+ else:
+ self.cgen.stmt("uint64_t %s" % handle64Var)
+ handle64VarAccess = "&%s" % handle64Var
+ handle64VarType = \
+ makeVulkanTypeSimple(False, "uint64_t", 0, paramName=handle64Var)
+
+ if "" == self.handlemapPrefix:
+ mapFunc = ("(%s)" % vulkanType.typeName)
+ mapFunc64 = ("(%s)" % "uint64_t")
+ else:
+ mapFunc = self.handlemapPrefix + vulkanType.typeName
+ mapFunc64 = mapFunc
+
+ if self.direction == "write":
+ if self.handleMapOverwrites:
+ self.cgen.stmt(
+ "static_assert(8 == sizeof(%s), \"handle map overwrite requres %s to be 8 bytes long\")" % \
+ (vulkanType.typeName, vulkanType.typeName))
+ if "1" == lenAccess:
+ self.cgen.stmt("*%s = (%s)%s(*%s)" % (access, vulkanType.typeName, mapFunc, access))
+ self.genStreamCall(vulkanType, access, "8 * %s" % lenAccess)
+ else:
+ if lenAccessGuard is not None:
+ self.cgen.beginIf(lenAccessGuard)
+ self.cgen.beginFor("uint32_t k = 0", "k < %s" % lenAccess, "++k")
+ self.cgen.stmt("%s[k] = (%s)%s(%s[k])" % (access, vulkanType.typeName, mapFunc, access))
+ self.cgen.endFor()
+ if lenAccessGuard is not None:
+ self.cgen.endIf()
+ self.genPtrIncr("8 * %s" % lenAccess)
+ else:
+ if "1" == lenAccess:
+ self.cgen.stmt("*%s = %s((*%s))" % (handle64VarAccess, mapFunc64, access))
+ self.genStreamCall(handle64VarType, handle64VarAccess, handle64Bytes)
+ else:
+ if lenAccessGuard is not None:
+ self.cgen.beginIf(lenAccessGuard)
+ self.cgen.beginFor("uint32_t k = 0", "k < %s" % lenAccess, "++k")
+ self.cgen.stmt("uint64_t tmpval = %s(%s[k])" % (mapFunc64, access))
+ self.cgen.stmt("memcpy(%s_ptr + k * 8, &tmpval, sizeof(uint64_t))" % (handle64Var))
+ self.cgen.endFor()
+ if lenAccessGuard is not None:
+ self.cgen.endIf()
+ self.genPtrIncr("8 * %s" % lenAccess)
+ else:
+ if "1" == lenAccess:
+ self.genStreamCall(handle64VarType, handle64VarAccess, handle64Bytes)
+ self.cgen.stmt("*%s%s = (%s)%s((%s)(*%s))" % (
+ self.makeCastExpr(vulkanType.getForNonConstAccess()), access,
+ vulkanType.typeName, mapFunc, vulkanType.typeName, handle64VarAccess))
+ else:
+ self.genPtrIncr("8 * %s" % lenAccess)
+ if lenAccessGuard is not None:
+ self.cgen.beginIf(lenAccessGuard)
+ self.cgen.beginFor("uint32_t k = 0", "k < %s" % lenAccess, "++k")
+ self.cgen.stmt("uint64_t tmpval; memcpy(&tmpval, %s_ptr + k * 8, sizeof(uint64_t))" % handle64Var)
+ self.cgen.stmt("*((%s%s) + k) = (%s)%s((%s)tmpval)" % (
+ self.makeCastExpr(vulkanType.getForNonConstAccess()), access,
+ vulkanType.typeName, mapFunc, vulkanType.typeName))
+ if lenAccessGuard is not None:
+ self.cgen.endIf()
+ self.cgen.endFor()
+
+ if lenAccess != "1":
+ self.cgen.endIf()
+
+ def doAllocSpace(self, vulkanType):
+ if self.dynAlloc and self.direction == "read":
+ access = self.exprAccessor(vulkanType)
+ lenAccess = self.lenAccessor(vulkanType)
+ sizeof = self.cgen.sizeofExpr(vulkanType.getForValueAccess())
+ if lenAccess:
+ bytesExpr = "%s * %s" % (lenAccess, sizeof)
+ else:
+ bytesExpr = sizeof
+ lenAccess = "1"
+
+ if self.stackVar:
+ if self.stackArrSize != lenAccess:
+ self.cgen.beginIf("%s <= %s" % (lenAccess, self.stackArrSize))
+
+ self.cgen.stmt(
+ "%s = %s%s" % (access, self.makeCastExpr(vulkanType.getForNonConstAccess()), self.stackVar))
+
+ if self.stackArrSize != lenAccess:
+ self.cgen.endIf()
+ self.cgen.beginElse()
+
+ if self.stackArrSize != lenAccess:
+ self.cgen.stmt(
+ "%s->alloc((void**)&%s, %s)" %
+ (self.streamVarName,
+ access, bytesExpr))
+
+ if self.stackArrSize != lenAccess:
+ self.cgen.endIf()
+ else:
+ self.cgen.stmt(
+ "%s->alloc((void**)&%s, %s)" %
+ (self.streamVarName,
+ access, bytesExpr))
+
+ def getOptionalStringFeatureExpr(self, vulkanType):
+ if vulkanType.optionalStr is not None:
+ if vulkanType.optionalStr.startswith("streamFeature:"):
+ splitted = vulkanType.optionalStr.split(":")
+ featureExpr = "%s->getFeatureBits() & %s" % (self.streamVarName, splitted[1])
+ return featureExpr
+ return None
+
+ def onCheck(self, vulkanType):
+ if self.forApiOutput:
+ return
+
+ featureExpr = self.getOptionalStringFeatureExpr(vulkanType)
+ self.checked = True
+ access = self.exprAccessor(vulkanType)
+ needConsistencyCheck = False
+
+ self.cgen.line("// WARNING PTR CHECK")
+ if (self.dynAlloc and self.direction == "read") or self.direction == "write":
+ checkAccess = self.exprAccessor(vulkanType)
+ addrExpr = "&" + checkAccess
+ sizeExpr = self.cgen.sizeofExpr(vulkanType)
+ else:
+ checkName = "check_%s" % vulkanType.paramName
+ self.cgen.stmt("%s %s" % (
+ self.cgen.makeCTypeDecl(vulkanType, useParamName = False), checkName))
+ checkAccess = checkName
+ addrExpr = "&" + checkAccess
+ sizeExpr = self.cgen.sizeofExpr(vulkanType)
+ needConsistencyCheck = True
+
+ if featureExpr is not None:
+ self.cgen.beginIf(featureExpr)
+
+ self.genPrimitiveStreamCall(
+ vulkanType,
+ checkAccess)
+
+ if featureExpr is not None:
+ self.cgen.endIf()
+
+ if featureExpr is not None:
+ self.cgen.beginIf("(!(%s) || %s)" % (featureExpr, access))
+ else:
+ self.cgen.beginIf(access)
+
+ if needConsistencyCheck and featureExpr is None:
+ self.cgen.beginIf("!(%s)" % checkName)
+ self.cgen.stmt(
+ "fprintf(stderr, \"fatal: %s inconsistent between guest and host\\n\")" % (access))
+ self.cgen.endIf()
+
+ def onCheckWithNullOptionalStringFeature(self, vulkanType):
+ self.cgen.beginIf("%s->getFeatureBits() & VULKAN_STREAM_FEATURE_NULL_OPTIONAL_STRINGS_BIT" % self.streamVarName)
+ self.onCheck(vulkanType)
+
+ def endCheckWithNullOptionalStringFeature(self, vulkanType):
+ self.endCheck(vulkanType)
+ self.cgen.endIf()
+ self.cgen.beginElse()
+
+ def finalCheckWithNullOptionalStringFeature(self, vulkanType):
+ self.cgen.endElse()
+
+ def endCheck(self, vulkanType):
+
+ if self.checked:
+ self.cgen.endIf()
+ self.checked = False
+
+ def genFilterFunc(self, filterfunc, env):
+
+ def loop(expr, lambdaEnv={}):
+ def do_func(expr):
+ fnamestr = expr.name.name
+ if "not" == fnamestr:
+ return "!(%s)" % (loop(expr.args[0], lambdaEnv))
+ if "eq" == fnamestr:
+ return "(%s == %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
+ if "and" == fnamestr:
+ return "(%s && %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
+ if "or" == fnamestr:
+ return "(%s || %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
+ if "bitwise_and" == fnamestr:
+ return "(%s & %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
+ if "getfield" == fnamestr:
+ ptrlevels = get_ptrlevels(expr.args[0].val.name)
+ if ptrlevels == 0:
+ return "%s.%s" % (loop(expr.args[0], lambdaEnv), expr.args[1].val)
+ else:
+ return "(%s(%s)).%s" % ("*" * ptrlevels, loop(expr.args[0], lambdaEnv), expr.args[1].val)
+
+ if "if" == fnamestr:
+ return "((%s) ? (%s) : (%s))" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv), loop(expr.args[2], lambdaEnv))
+
+ return "%s(%s)" % (fnamestr, ", ".join(map(lambda e: loop(e, lambdaEnv), expr.args)))
+
+ def do_expratom(atomname, lambdaEnv= {}):
+ if lambdaEnv.get(atomname, None) is not None:
+ return atomname
+
+ enventry = env.get(atomname, None)
+ if None != enventry:
+ return self.getEnvAccessExpr(atomname)
+ return atomname
+
+ def get_ptrlevels(atomname, lambdaEnv= {}):
+ if lambdaEnv.get(atomname, None) is not None:
+ return 0
+
+ enventry = env.get(atomname, None)
+ if None != enventry:
+ return self.getPointerIndirectionLevels(atomname)
+
+ return 0
+
+ def do_exprval(expr, lambdaEnv= {}):
+ expratom = expr.val
+
+ if Atom == type(expratom):
+ return do_expratom(expratom.name, lambdaEnv)
+
+ return "%s" % expratom
+
+ def do_lambda(expr, lambdaEnv= {}):
+ params = expr.vs
+ body = expr.body
+ newEnv = {}
+
+ for (k, v) in lambdaEnv.items():
+ newEnv[k] = v
+
+ for p in params:
+ newEnv[p.name] = p.typ
+
+ return "[](%s) { return %s; }" % (", ".join(list(map(lambda p: "%s %s" % (p.typ, p.name), params))), loop(body, lambdaEnv=newEnv))
+
+ if FuncExpr == type(expr):
+ return do_func(expr)
+ if FuncLambda == type(expr):
+ return do_lambda(expr)
+ elif FuncExprVal == type(expr):
+ return do_exprval(expr)
+
+ return loop(filterfunc)
+
+ def beginFilterGuard(self, vulkanType):
+ if vulkanType.filterVar == None:
+ return
+
+ if self.doFiltering == False:
+ return
+
+ filterVarAccess = self.getEnvAccessExpr(vulkanType.filterVar)
+
+ filterValsExpr = None
+ filterFuncExpr = None
+ filterExpr = None
+
+ filterFeature = "%s->getFeatureBits() & VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT" % self.streamVarName
+
+ if None != vulkanType.filterVals:
+ filterValsExpr = " || ".join(map(lambda filterval: "(%s == %s)" % (filterval, filterVarAccess), vulkanType.filterVals))
+
+ if None != vulkanType.filterFunc:
+ filterFuncExpr = self.genFilterFunc(vulkanType.filterFunc, self.currentStructInfo.environment)
+
+ if None != filterValsExpr and None != filterFuncExpr:
+ filterExpr = "%s || %s" % (filterValsExpr, filterFuncExpr)
+ elif None == filterValsExpr and None == filterFuncExpr:
+ # Assume is bool
+ self.cgen.beginIf(filterVarAccess)
+ elif None != filterValsExpr:
+ self.cgen.beginIf("(!(%s) || (%s))" % (filterFeature, filterValsExpr))
+ elif None != filterFuncExpr:
+ self.cgen.beginIf("(!(%s) || (%s))" % (filterFeature, filterFuncExpr))
+
+ def endFilterGuard(self, vulkanType, cleanupExpr=None):
+ if vulkanType.filterVar == None:
+ return
+
+ if self.doFiltering == False:
+ return
+
+ if cleanupExpr == None:
+ self.cgen.endIf()
+ else:
+ self.cgen.endIf()
+ self.cgen.beginElse()
+ self.cgen.stmt(cleanupExpr)
+ self.cgen.endElse()
+
+ def getEnvAccessExpr(self, varName):
+ parentEnvEntry = self.currentStructInfo.environment.get(varName, None)
+
+ if parentEnvEntry != None:
+ isParentMember = parentEnvEntry["structmember"]
+
+ if isParentMember:
+ envAccess = self.exprValueAccessor(list(filter(lambda member: member.paramName == varName, self.currentStructInfo.members))[0])
+ else:
+ envAccess = varName
+ return envAccess
+
+ return None
+
+ def getPointerIndirectionLevels(self, varName):
+ parentEnvEntry = self.currentStructInfo.environment.get(varName, None)
+
+ if parentEnvEntry != None:
+ isParentMember = parentEnvEntry["structmember"]
+
+ if isParentMember:
+ return list(filter(lambda member: member.paramName == varName, self.currentStructInfo.members))[0].pointerIndirectionLevels
+ else:
+ return 0
+ return 0
+
+ return 0
+
+
+ def onCompoundType(self, vulkanType):
+
+ access = self.exprAccessor(vulkanType)
+ lenAccess = self.lenAccessor(vulkanType)
+
+ self.beginFilterGuard(vulkanType)
+
+ if vulkanType.pointerIndirectionLevels > 0:
+ self.doAllocSpace(vulkanType)
+
+ if lenAccess is not None:
+ loopVar = "i"
+ access = "%s + %s" % (access, loopVar)
+ forInit = "uint32_t %s = 0" % loopVar
+ forCond = "%s < (uint32_t)%s" % (loopVar, lenAccess)
+ forIncr = "++%s" % loopVar
+ self.cgen.beginFor(forInit, forCond, forIncr)
+
+ accessWithCast = "%s(%s)" % (self.makeCastExpr(
+ self.getTypeForStreaming(vulkanType)), access)
+
+ callParams = [self.streamVarName, self.rootTypeVarName, accessWithCast, self.ptrVar]
+
+ for (bindName, localName) in vulkanType.binds.items():
+ callParams.append(self.getEnvAccessExpr(localName))
+
+ self.cgen.funcCall(None, self.marshalPrefix + vulkanType.typeName,
+ callParams)
+
+ if lenAccess is not None:
+ self.cgen.endFor()
+
+ if self.direction == "read":
+ self.endFilterGuard(vulkanType, "%s = 0" % self.exprAccessor(vulkanType))
+ else:
+ self.endFilterGuard(vulkanType)
+
+ def onString(self, vulkanType):
+ access = self.exprAccessor(vulkanType)
+
+ if self.direction == "write":
+ self.cgen.beginBlock()
+ self.cgen.stmt("uint32_t l = %s ? strlen(%s): 0" % (access, access))
+ self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)" ,"&l", "sizeof(uint32_t)", toBe = True, actualSize = 4)
+ self.genMemcpyAndIncr(self.ptrVar, "(char*)", access, "l")
+ self.cgen.endBlock()
+ else:
+ castExpr = \
+ self.makeCastExpr( \
+ self.getTypeForStreaming( \
+ vulkanType.getForAddressAccess()))
+ self.cgen.stmt( \
+ "%s->loadStringInPlaceWithStreamPtr(%s&%s, %s)" % (self.streamVarName, castExpr, access, self.ptrVar))
+
+ def onStringArray(self, vulkanType):
+ access = self.exprAccessor(vulkanType)
+ lenAccess = self.lenAccessor(vulkanType)
+ lenAccessGuard = self.lenAccessorGuard(vulkanType)
+
+ if self.direction == "write":
+ self.cgen.beginBlock()
+
+ self.cgen.stmt("uint32_t c = 0")
+ if lenAccessGuard is not None:
+ self.cgen.beginIf(lenAccessGuard)
+ self.cgen.stmt("c = %s" % (lenAccess))
+ if lenAccessGuard is not None:
+ self.cgen.endIf()
+ self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)" ,"&c", "sizeof(uint32_t)", toBe = True, actualSize = 4)
+
+ self.cgen.beginFor("uint32_t i = 0", "i < c", "++i")
+ self.cgen.stmt("uint32_t l = %s ? strlen(%s[i]): 0" % (access, access))
+ self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)" ,"&l", "sizeof(uint32_t)", toBe = True, actualSize = 4)
+ self.cgen.beginIf("l")
+ self.genMemcpyAndIncr(self.ptrVar, "(char*)", "(%s[i])" % access, "l")
+ self.cgen.endIf()
+ self.cgen.endFor()
+
+ self.cgen.endBlock()
+ else:
+ castExpr = \
+ self.makeCastExpr( \
+ self.getTypeForStreaming( \
+ vulkanType.getForAddressAccess()))
+
+ self.cgen.stmt("%s->loadStringArrayInPlaceWithStreamPtr(%s&%s, %s)" % (self.streamVarName, castExpr, access, self.ptrVar))
+
+ def onStaticArr(self, vulkanType):
+ access = self.exprValueAccessor(vulkanType)
+ lenAccess = self.lenAccessor(vulkanType)
+ finalLenExpr = "%s * %s" % (lenAccess, self.cgen.sizeofExpr(vulkanType))
+ self.genStreamCall(vulkanType, access, finalLenExpr)
+
+ # Old version VkEncoder may have some sType values conflict with VkDecoder
+ # of new versions. For host decoder, it should not carry the incorrect old
+ # sType values to the |forUnmarshaling| struct. Instead it should overwrite
+ # the sType value.
+ def overwriteSType(self, vulkanType):
+ if self.direction == "read":
+ sTypeParam = copy(vulkanType)
+ sTypeParam.paramName = "sType"
+ sTypeAccess = self.exprAccessor(sTypeParam)
+
+ typeName = vulkanType.parent.typeName
+ if typeName in STYPE_OVERRIDE:
+ self.cgen.stmt("%s = %s" %
+ (sTypeAccess, STYPE_OVERRIDE[typeName]))
+
+ def onStructExtension(self, vulkanType):
+ self.overwriteSType(vulkanType)
+
+ sTypeParam = copy(vulkanType)
+ sTypeParam.paramName = "sType"
+
+ access = self.exprAccessor(vulkanType)
+ sizeVar = "%s_size" % vulkanType.paramName
+
+ if self.direction == "read":
+ castedAccessExpr = "(%s)(%s)" % ("void*", access)
+ else:
+ castedAccessExpr = access
+
+ sTypeAccess = self.exprAccessor(sTypeParam)
+ self.cgen.beginIf("%s == VK_STRUCTURE_TYPE_MAX_ENUM" % self.rootTypeVarName)
+ self.cgen.stmt("%s = %s" % (self.rootTypeVarName, sTypeAccess))
+ self.cgen.endIf()
+
+ if self.direction == "read" and self.dynAlloc:
+ self.cgen.stmt("uint32_t %s" % sizeVar)
+
+ self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)", "&" + sizeVar, "sizeof(uint32_t)", toBe = True, actualSize = 4)
+
+ self.cgen.stmt("%s = nullptr" % access)
+ self.cgen.beginIf(sizeVar)
+ self.cgen.stmt( \
+ "%s->alloc((void**)&%s, sizeof(VkStructureType))" %
+ (self.streamVarName, access))
+
+ self.genStreamCall(vulkanType, access, "sizeof(VkStructureType)")
+ self.cgen.stmt("VkStructureType extType = *(VkStructureType*)(%s)" % access)
+ self.cgen.stmt( \
+ "%s->alloc((void**)&%s, %s(%s->getFeatureBits(), %s, %s))" %
+ (self.streamVarName, access, EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME, self.streamVarName, self.rootTypeVarName, access))
+ self.cgen.stmt("*(VkStructureType*)%s = extType" % access)
+
+ self.cgen.funcCall(None, self.marshalPrefix + "extension_struct",
+ [self.streamVarName, self.rootTypeVarName, castedAccessExpr, self.ptrVar])
+ self.cgen.endIf()
+ else:
+
+ self.cgen.funcCall(None, self.marshalPrefix + "extension_struct",
+ [self.streamVarName, self.rootTypeVarName, castedAccessExpr, self.ptrVar])
+
+ def onPointer(self, vulkanType):
+ access = self.exprAccessor(vulkanType)
+
+ lenAccess = self.lenAccessor(vulkanType)
+ lenAccessGuard = self.lenAccessorGuard(vulkanType)
+
+ self.beginFilterGuard(vulkanType)
+ self.doAllocSpace(vulkanType)
+
+ if vulkanType.filterVar != None:
+ print("onPointer Needs filter: %s filterVar %s" % (access, vulkanType.filterVar))
+
+ if vulkanType.isHandleType() and self.mapHandles:
+ self.genHandleMappingCall(
+ vulkanType, access, lenAccess, lenAccessGuard)
+ else:
+ if self.typeInfo.isNonAbiPortableType(vulkanType.typeName):
+ if lenAccess is not None:
+ if lenAccessGuard is not None:
+ self.cgen.beginIf(lenAccessGuard)
+ self.cgen.beginFor("uint32_t i = 0", "i < (uint32_t)%s" % lenAccess, "++i")
+ self.genPrimitiveStreamCall(vulkanType.getForValueAccess(), "%s[i]" % access)
+ self.cgen.endFor()
+ if lenAccessGuard is not None:
+ self.cgen.endIf()
+ else:
+ self.genPrimitiveStreamCall(vulkanType.getForValueAccess(), "(*%s)" % access)
+ else:
+ if lenAccess is not None:
+ finalLenExpr = "%s * %s" % (
+ lenAccess, self.cgen.sizeofExpr(vulkanType.getForValueAccess()))
+ else:
+ finalLenExpr = "%s" % (
+ self.cgen.sizeofExpr(vulkanType.getForValueAccess()))
+ self.genStreamCall(vulkanType, access, finalLenExpr)
+
+ if self.direction == "read":
+ self.endFilterGuard(vulkanType, "%s = 0" % access)
+ else:
+ self.endFilterGuard(vulkanType)
+
+ def onValue(self, vulkanType):
+ self.beginFilterGuard(vulkanType)
+
+ if vulkanType.isHandleType() and self.mapHandles:
+ access = self.exprAccessor(vulkanType)
+ if vulkanType.filterVar != None:
+ print("onValue Needs filter: %s filterVar %s" % (access, vulkanType.filterVar))
+ self.genHandleMappingCall(
+ vulkanType.getForAddressAccess(), access, "1", None)
+ elif self.typeInfo.isNonAbiPortableType(vulkanType.typeName):
+ access = self.exprPrimitiveValueAccessor(vulkanType)
+ self.genPrimitiveStreamCall(vulkanType, access)
+ else:
+ access = self.exprAccessor(vulkanType)
+ self.genStreamCall(vulkanType, access, self.cgen.sizeofExpr(vulkanType))
+
+ self.endFilterGuard(vulkanType)
+
+ def streamLetParameter(self, structInfo, letParamInfo):
+ filterFeature = "%s->getFeatureBits() & VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT" % self.streamVarName
+ self.cgen.stmt("%s %s = 1" % (letParamInfo.typeName, letParamInfo.paramName))
+
+ self.cgen.beginIf(filterFeature)
+
+ if self.direction == "write":
+ bodyExpr = self.currentStructInfo.environment[letParamInfo.paramName]["body"]
+ self.cgen.stmt("%s = %s" % (letParamInfo.paramName, self.genFilterFunc(bodyExpr, self.currentStructInfo.environment)))
+
+ self.genPrimitiveStreamCall(letParamInfo, letParamInfo.paramName)
+
+ self.cgen.endIf()
+
+class VulkanReservedMarshaling(VulkanWrapperGenerator):
+
+ def __init__(self, module, typeInfo, variant="host"):
+ VulkanWrapperGenerator.__init__(self, module, typeInfo)
+
+ self.cgenHeader = CodeGen()
+ self.cgenImpl = CodeGen()
+
+ self.variant = variant
+
+ self.currentFeature = None
+ self.apiOpcodes = {}
+ self.dynAlloc = self.variant != "guest"
+ self.ptrVarName = "ptr"
+ self.ptrVarType = makeVulkanTypeSimple(False, "uint8_t", 2, self.ptrVarName)
+ self.ptrVarTypeUnmarshal = makeVulkanTypeSimple(False, "uint8_t", 2, self.ptrVarName)
+
+ if self.variant == "guest":
+ self.marshalingParams = PARAMETERS_MARSHALING_GUEST
+ else:
+ self.marshalingParams = PARAMETERS_MARSHALING
+
+ self.writeCodegen = \
+ VulkanReservedMarshalingCodegen(
+ None,
+ VULKAN_STREAM_VAR_NAME,
+ ROOT_TYPE_VAR_NAME,
+ MARSHAL_INPUT_VAR_NAME,
+ self.ptrVarName,
+ API_PREFIX_RESERVEDMARSHAL,
+ "get_host_u64_" if "guest" == self.variant else "",
+ direction = "write")
+
+ self.readCodegen = \
+ VulkanReservedMarshalingCodegen(
+ None,
+ VULKAN_STREAM_VAR_NAME,
+ ROOT_TYPE_VAR_NAME,
+ UNMARSHAL_INPUT_VAR_NAME,
+ self.ptrVarName,
+ API_PREFIX_RESERVEDUNMARSHAL,
+ "unbox_" if "host" == self.variant else "",
+ direction = "read",
+ dynAlloc=self.dynAlloc)
+
+ self.knownDefs = {}
+
+ self.extensionMarshalPrototype = \
+ VulkanAPI(API_PREFIX_RESERVEDMARSHAL + "extension_struct",
+ STREAM_RET_TYPE,
+ self.marshalingParams +
+ [STRUCT_EXTENSION_PARAM, self.ptrVarType])
+
+ self.extensionUnmarshalPrototype = \
+ VulkanAPI(API_PREFIX_RESERVEDUNMARSHAL + "extension_struct",
+ STREAM_RET_TYPE,
+ self.marshalingParams +
+ [STRUCT_EXTENSION_PARAM_FOR_WRITE, self.ptrVarTypeUnmarshal])
+
+ def onBegin(self,):
+ VulkanWrapperGenerator.onBegin(self)
+ self.module.appendImpl(self.cgenImpl.makeFuncDecl(self.extensionMarshalPrototype))
+ self.module.appendImpl(self.cgenImpl.makeFuncDecl(self.extensionUnmarshalPrototype))
+
+ def onBeginFeature(self, featureName, featureType):
+ VulkanWrapperGenerator.onBeginFeature(self, featureName, featureType)
+ self.currentFeature = featureName
+
+ def onGenType(self, typeXml, name, alias):
+ VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)
+
+ if name in self.knownDefs:
+ return
+
+ category = self.typeInfo.categoryOf(name)
+
+ if category in ["struct", "union"] and alias:
+ if self.variant != "host":
+ self.module.appendHeader(
+ self.cgenHeader.makeFuncAlias(API_PREFIX_RESERVEDMARSHAL + name,
+ API_PREFIX_RESERVEDMARSHAL + alias))
+ if self.variant != "guest":
+ self.module.appendHeader(
+ self.cgenHeader.makeFuncAlias(API_PREFIX_RESERVEDUNMARSHAL + name,
+ API_PREFIX_RESERVEDUNMARSHAL + alias))
+
+ if category in ["struct", "union"] and not alias:
+
+ structInfo = self.typeInfo.structs[name]
+
+ marshalParams = self.marshalingParams + \
+ [makeVulkanTypeSimple(True, name, 1, MARSHAL_INPUT_VAR_NAME),
+ self.ptrVarType]
+
+ freeParams = []
+ letParams = []
+
+ for (envname, bindingInfo) in list(sorted(structInfo.environment.items(), key = lambda kv: kv[0])):
+ if None == bindingInfo["binding"]:
+ freeParams.append(makeVulkanTypeSimple(True, bindingInfo["type"], 0, envname))
+ else:
+ if not bindingInfo["structmember"]:
+ letParams.append(makeVulkanTypeSimple(True, bindingInfo["type"], 0, envname))
+
+ marshalPrototype = \
+ VulkanAPI(API_PREFIX_RESERVEDMARSHAL + name,
+ STREAM_RET_TYPE,
+ marshalParams + freeParams)
+
+ marshalPrototypeNoFilter = \
+ VulkanAPI(API_PREFIX_RESERVEDMARSHAL + name,
+ STREAM_RET_TYPE,
+ marshalParams)
+
+ def structMarshalingCustom(cgen):
+ self.writeCodegen.cgen = cgen
+ self.writeCodegen.currentStructInfo = structInfo
+ marshalingCode = \
+ CUSTOM_MARSHAL_TYPES[name]["common"] + \
+ CUSTOM_MARSHAL_TYPES[name]["reservedmarshaling"].format(
+ streamVarName=self.writeCodegen.streamVarName,
+ rootTypeVarName=self.writeCodegen.rootTypeVarName,
+ inputVarName=self.writeCodegen.inputVarName,
+ newInputVarName=self.writeCodegen.inputVarName + "_new")
+ for line in marshalingCode.split('\n'):
+ cgen.line(line)
+
+ def structMarshalingDef(cgen):
+ self.writeCodegen.cgen = cgen
+ self.writeCodegen.currentStructInfo = structInfo
+ self.writeCodegen.cgen.stmt("(void)%s" % VULKAN_STREAM_VAR_NAME)
+ self.writeCodegen.cgen.stmt("(void)%s" % ROOT_TYPE_VAR_NAME)
+
+ if category == "struct":
+ # marshal 'let' parameters first
+ for letp in letParams:
+ self.writeCodegen.streamLetParameter(self.typeInfo, letp)
+
+ for member in structInfo.members:
+ iterateVulkanType(self.typeInfo, member, self.writeCodegen)
+ if category == "union":
+ iterateVulkanType(self.typeInfo, structInfo.members[0], self.writeCodegen)
+
+ def structMarshalingDefNoFilter(cgen):
+ self.writeCodegen.cgen = cgen
+ self.writeCodegen.currentStructInfo = structInfo
+ self.writeCodegen.doFiltering = False
+ self.writeCodegen.cgen.stmt("(void)%s" % VULKAN_STREAM_VAR_NAME)
+ self.writeCodegen.cgen.stmt("(void)%s" % ROOT_TYPE_VAR_NAME)
+
+ if category == "struct":
+ # marshal 'let' parameters first
+ for letp in letParams:
+ self.writeCodegen.streamLetParameter(self.typeInfo, letp)
+
+ for member in structInfo.members:
+ iterateVulkanType(self.typeInfo, member, self.writeCodegen)
+ if category == "union":
+ iterateVulkanType(self.typeInfo, structInfo.members[0], self.writeCodegen)
+ self.writeCodegen.doFiltering = True
+
+ if self.variant != "host":
+ self.module.appendHeader(
+ self.cgenHeader.makeFuncDecl(marshalPrototype))
+
+ if name in CUSTOM_MARSHAL_TYPES:
+ self.module.appendImpl(
+ self.cgenImpl.makeFuncImpl(
+ marshalPrototype, structMarshalingCustom))
+ else:
+ self.module.appendImpl(
+ self.cgenImpl.makeFuncImpl(
+ marshalPrototype, structMarshalingDef))
+
+ if freeParams != []:
+ self.module.appendHeader(
+ self.cgenHeader.makeFuncDecl(marshalPrototypeNoFilter))
+ self.module.appendImpl(
+ self.cgenImpl.makeFuncImpl(
+ marshalPrototypeNoFilter, structMarshalingDefNoFilter))
+
+ unmarshalPrototype = \
+ VulkanAPI(API_PREFIX_RESERVEDUNMARSHAL + name,
+ STREAM_RET_TYPE,
+ self.marshalingParams + [makeVulkanTypeSimple(False, name, 1, UNMARSHAL_INPUT_VAR_NAME), self.ptrVarTypeUnmarshal] + freeParams)
+
+ unmarshalPrototypeNoFilter = \
+ VulkanAPI(API_PREFIX_RESERVEDUNMARSHAL + name,
+ STREAM_RET_TYPE,
+ self.marshalingParams + [makeVulkanTypeSimple(False, name, 1, UNMARSHAL_INPUT_VAR_NAME), self.ptrVarTypeUnmarshal])
+
+ def structUnmarshalingCustom(cgen):
+ self.readCodegen.cgen = cgen
+ self.readCodegen.currentStructInfo = structInfo
+ unmarshalingCode = \
+ CUSTOM_MARSHAL_TYPES[name]["common"] + \
+ CUSTOM_MARSHAL_TYPES[name]["reservedunmarshaling"].format(
+ streamVarName=self.readCodegen.streamVarName,
+ rootTypeVarName=self.readCodegen.rootTypeVarName,
+ inputVarName=self.readCodegen.inputVarName,
+ newInputVarName=self.readCodegen.inputVarName + "_new")
+ for line in unmarshalingCode.split('\n'):
+ cgen.line(line)
+
+ def structUnmarshalingDef(cgen):
+ self.readCodegen.cgen = cgen
+ self.readCodegen.currentStructInfo = structInfo
+ if category == "struct":
+ # unmarshal 'let' parameters first
+ for letp in letParams:
+ self.readCodegen.streamLetParameter(self.typeInfo, letp)
+
+ for member in structInfo.members:
+ iterateVulkanType(self.typeInfo, member, self.readCodegen)
+ if category == "union":
+ iterateVulkanType(self.typeInfo, structInfo.members[0], self.readCodegen)
+
+ def structUnmarshalingDefNoFilter(cgen):
+ self.readCodegen.cgen = cgen
+ self.readCodegen.currentStructInfo = structInfo
+ self.readCodegen.doFiltering = False
+ if category == "struct":
+ # unmarshal 'let' parameters first
+ for letp in letParams:
+ iterateVulkanType(self.typeInfo, letp, self.readCodegen)
+ for member in structInfo.members:
+ iterateVulkanType(self.typeInfo, member, self.readCodegen)
+ if category == "union":
+ iterateVulkanType(self.typeInfo, structInfo.members[0], self.readCodegen)
+ self.readCodegen.doFiltering = True
+
+ if self.variant != "guest":
+ self.module.appendHeader(
+ self.cgenHeader.makeFuncDecl(unmarshalPrototype))
+
+ if name in CUSTOM_MARSHAL_TYPES:
+ self.module.appendImpl(
+ self.cgenImpl.makeFuncImpl(
+ unmarshalPrototype, structUnmarshalingCustom))
+ else:
+ self.module.appendImpl(
+ self.cgenImpl.makeFuncImpl(
+ unmarshalPrototype, structUnmarshalingDef))
+
+ if freeParams != []:
+ self.module.appendHeader(
+ self.cgenHeader.makeFuncDecl(unmarshalPrototypeNoFilter))
+ self.module.appendImpl(
+ self.cgenImpl.makeFuncImpl(
+ unmarshalPrototypeNoFilter, structUnmarshalingDefNoFilter))
+
+ def onGenCmd(self, cmdinfo, name, alias):
+ VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
+
+ def doExtensionStructMarshalingCodegen(self, cgen, retType, extParam, forEach, funcproto, direction):
+ accessVar = "structAccess"
+ sizeVar = "currExtSize"
+ cgen.stmt("VkInstanceCreateInfo* %s = (VkInstanceCreateInfo*)(%s)" % (accessVar, extParam.paramName))
+ 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))
+
+ cgen.beginIf("!%s && %s" % (sizeVar, extParam.paramName))
+
+ cgen.line("// unknown struct extension; skip and call on its pNext field");
+ cgen.funcCall(None, funcproto.name, ["vkStream", ROOT_TYPE_VAR_NAME, "(void*)%s->pNext" % accessVar, self.ptrVarName])
+ cgen.stmt("return")
+
+ cgen.endIf()
+ cgen.beginElse()
+
+ cgen.line("// known or null extension struct")
+
+ if direction == "write":
+ cgen.stmt("memcpy(*%s, &%s, sizeof(uint32_t));" % (self.ptrVarName, sizeVar))
+ cgen.stmt("android::base::Stream::toBe32((uint8_t*)*%s); *%s += sizeof(uint32_t)" % (self.ptrVarName, self.ptrVarName))
+ elif not self.dynAlloc:
+ cgen.stmt("memcpy(&%s, *%s, sizeof(uint32_t));" % (sizeVar, self.ptrVarName))
+ cgen.stmt("android::base::Stream::fromBe32((uint8_t*)&%s); *%s += sizeof(uint32_t)" % (sizeVar, self.ptrVarName))
+
+ cgen.beginIf("!%s" % (sizeVar))
+ cgen.line("// exit if this was a null extension struct (size == 0 in this branch)")
+ cgen.stmt("return")
+ cgen.endIf()
+
+ cgen.endIf()
+
+ # Now we can do stream stuff
+ if direction == "write":
+ cgen.stmt("memcpy(*%s, %s, sizeof(VkStructureType)); *%s += sizeof(VkStructureType)" % (self.ptrVarName, extParam.paramName, self.ptrVarName))
+ elif not self.dynAlloc:
+ cgen.stmt("uint64_t pNext_placeholder")
+ placeholderAccess = "(&pNext_placeholder)"
+ cgen.stmt("memcpy(%s, *%s, sizeof(VkStructureType)); *%s += sizeof(VkStructureType)" % (placeholderAccess, self.ptrVarName, self.ptrVarName))
+ cgen.stmt("(void)pNext_placeholder")
+
+ def fatalDefault(cgen):
+ cgen.line("// fatal; the switch is only taken if the extension struct is known");
+ cgen.stmt("abort()")
+ pass
+
+ self.emitForEachStructExtension(
+ cgen,
+ retType,
+ extParam,
+ forEach,
+ defaultEmit=fatalDefault,
+ rootTypeVar=ROOT_TYPE_PARAM)
+
+ def onEnd(self,):
+ VulkanWrapperGenerator.onEnd(self)
+
+ def forEachExtensionMarshal(ext, castedAccess, cgen):
+ cgen.funcCall(None, API_PREFIX_RESERVEDMARSHAL + ext.name,
+ [VULKAN_STREAM_VAR_NAME, ROOT_TYPE_VAR_NAME, castedAccess, self.ptrVarName])
+
+ def forEachExtensionUnmarshal(ext, castedAccess, cgen):
+ cgen.funcCall(None, API_PREFIX_RESERVEDUNMARSHAL + ext.name,
+ [VULKAN_STREAM_VAR_NAME, ROOT_TYPE_VAR_NAME, castedAccess, self.ptrVarName])
+
+ if self.variant != "host":
+ self.module.appendImpl(
+ self.cgenImpl.makeFuncImpl(
+ self.extensionMarshalPrototype,
+ lambda cgen: self.doExtensionStructMarshalingCodegen(
+ cgen,
+ STREAM_RET_TYPE,
+ STRUCT_EXTENSION_PARAM,
+ forEachExtensionMarshal,
+ self.extensionMarshalPrototype,
+ "write")))
+
+ if self.variant != "guest":
+ self.module.appendImpl(
+ self.cgenImpl.makeFuncImpl(
+ self.extensionUnmarshalPrototype,
+ lambda cgen: self.doExtensionStructMarshalingCodegen(
+ cgen,
+ STREAM_RET_TYPE,
+ STRUCT_EXTENSION_PARAM_FOR_WRITE,
+ forEachExtensionUnmarshal,
+ self.extensionUnmarshalPrototype,
+ "read")))