summaryrefslogtreecommitdiff
path: root/codegen/vulkan/scripts/cereal/deepcopy.py
diff options
context:
space:
mode:
Diffstat (limited to 'codegen/vulkan/scripts/cereal/deepcopy.py')
-rw-r--r--codegen/vulkan/scripts/cereal/deepcopy.py383
1 files changed, 383 insertions, 0 deletions
diff --git a/codegen/vulkan/scripts/cereal/deepcopy.py b/codegen/vulkan/scripts/cereal/deepcopy.py
new file mode 100644
index 00000000..52842e99
--- /dev/null
+++ b/codegen/vulkan/scripts/cereal/deepcopy.py
@@ -0,0 +1,383 @@
+# 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 .common.codegen import CodeGen
+from .common.vulkantypes import \
+ VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator
+
+from .wrapperdefs import VulkanWrapperGenerator
+from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE, EXTENSION_SIZE_API_NAME
+
+class DeepcopyCodegen(VulkanTypeIterator):
+ def __init__(self, cgen, inputVars, poolVarName, rootVarName, prefix, skipValues=False):
+ self.cgen = cgen
+ self.inputVars = inputVars
+ self.prefix = prefix
+ self.poolVarName = poolVarName
+ self.rootVarName = rootVarName
+ self.skipValues = skipValues
+
+ def makeAccess(varName, asPtr = True):
+ return lambda t: self.cgen.generalAccess(t, parentVarName = varName, asPtr = asPtr)
+
+ def makeLengthAccess(varName):
+ return lambda t: self.cgen.generalLengthAccess(t, parentVarName = varName)
+
+ def makeLengthAccessGuard(varName):
+ return lambda t: self.cgen.generalLengthAccessGuard(t, parentVarName=varName)
+
+ self.exprAccessorLhs = makeAccess(self.inputVars[0])
+ self.exprAccessorRhs = makeAccess(self.inputVars[1])
+
+ self.exprAccessorValueLhs = makeAccess(self.inputVars[0], asPtr = False)
+ self.exprAccessorValueRhs = makeAccess(self.inputVars[1], asPtr = False)
+
+ self.lenAccessorLhs = makeLengthAccess(self.inputVars[0])
+ self.lenAccessorRhs = makeLengthAccess(self.inputVars[1])
+
+ self.lenAccessorGuardLhs = makeLengthAccessGuard(self.inputVars[0])
+ self.lenAccessorGuardRhs = makeLengthAccessGuard(self.inputVars[1])
+
+ self.checked = False
+
+ def needSkip(self, vulkanType):
+ return False
+
+ def makeCastExpr(self, vulkanType):
+ return "(%s)" % (
+ self.cgen.makeCTypeDecl(vulkanType, useParamName=False))
+
+ def makeNonConstCastForCopy(self, access, vulkanType):
+ if vulkanType.staticArrExpr:
+ casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
+ elif vulkanType.accessibleAsPointer():
+ casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForNonConstAccess()), access)
+ else:
+ casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
+ return casted
+
+ def makeAllocBytesExpr(self, lenAccess, vulkanType):
+ sizeof = self.cgen.sizeofExpr( \
+ vulkanType.getForValueAccess())
+ if lenAccess:
+ bytesExpr = "%s * %s" % (lenAccess, sizeof)
+ else:
+ bytesExpr = sizeof
+
+ return bytesExpr
+
+ def onCheck(self, vulkanType):
+ pass
+
+ def endCheck(self, vulkanType):
+ pass
+
+ def onCompoundType(self, vulkanType):
+
+ if self.needSkip(vulkanType):
+ self.cgen.line("// TODO: Unsupported : %s" %
+ self.cgen.makeCTypeDecl(vulkanType))
+ return
+
+ accessLhs = self.exprAccessorLhs(vulkanType)
+ accessRhs = self.exprAccessorRhs(vulkanType)
+
+ lenAccessLhs = self.lenAccessorLhs(vulkanType)
+ lenAccessRhs = self.lenAccessorRhs(vulkanType)
+
+ lenAccessorGuardLhs = self.lenAccessorGuardLhs(vulkanType)
+ lenAccessorGuardRhs = self.lenAccessorGuardRhs(vulkanType)
+
+ isPtr = vulkanType.pointerIndirectionLevels > 0
+
+ if lenAccessorGuardLhs is not None:
+ self.cgen.beginIf(lenAccessorGuardLhs)
+
+ if isPtr:
+ self.cgen.stmt("%s = nullptr" % accessRhs)
+ self.cgen.beginIf(accessLhs)
+
+ self.cgen.stmt( \
+ "%s = %s%s->alloc(%s)" % \
+ (accessRhs, self.makeCastExpr(vulkanType.getForNonConstAccess()),
+ self.poolVarName, self.makeAllocBytesExpr(lenAccessLhs, vulkanType)))
+
+ if lenAccessLhs is not None:
+
+ loopVar = "i"
+ accessLhs = "%s + %s" % (accessLhs, loopVar)
+ forInit = "uint32_t %s = 0" % loopVar
+ forCond = "%s < (uint32_t)%s" % (loopVar, lenAccessLhs)
+ forIncr = "++%s" % loopVar
+
+ if isPtr:
+ # Avoid generating a self-assign.
+ if lenAccessRhs != lenAccessLhs:
+ self.cgen.stmt("%s = %s" % (lenAccessRhs, lenAccessLhs))
+
+ accessRhs = "%s + %s" % (accessRhs, loopVar)
+ self.cgen.beginFor(forInit, forCond, forIncr)
+
+
+ accessRhsCasted = self.makeNonConstCastForCopy(accessRhs, vulkanType)
+
+ self.cgen.funcCall(None, self.prefix + vulkanType.typeName,
+ [self.poolVarName, self.rootVarName, accessLhs, accessRhsCasted])
+
+ if lenAccessLhs is not None:
+ self.cgen.endFor()
+
+ if isPtr:
+ self.cgen.endIf()
+
+ if lenAccessorGuardLhs is not None:
+ self.cgen.endIf()
+
+ def onString(self, vulkanType):
+ accessLhs = self.exprAccessorLhs(vulkanType)
+ accessRhs = self.exprAccessorRhs(vulkanType)
+
+ self.cgen.stmt("%s = nullptr" % accessRhs)
+ self.cgen.beginIf(accessLhs)
+
+ self.cgen.stmt( \
+ "%s = %s->strDup(%s)" % \
+ (accessRhs,
+ self.poolVarName,
+ accessLhs))
+
+ self.cgen.endIf()
+
+ def onStringArray(self, vulkanType):
+ accessLhs = self.exprAccessorLhs(vulkanType)
+ accessRhs = self.exprAccessorRhs(vulkanType)
+
+ lenAccessLhs = self.lenAccessorLhs(vulkanType)
+
+ self.cgen.stmt("%s = nullptr" % accessRhs)
+ self.cgen.beginIf("%s && %s" % (accessLhs, lenAccessLhs))
+
+ self.cgen.stmt( \
+ "%s = %s->strDupArray(%s, %s)" % \
+ (accessRhs,
+ self.poolVarName,
+ accessLhs,
+ lenAccessLhs))
+
+ self.cgen.endIf()
+
+ def onStaticArr(self, vulkanType):
+ accessLhs = self.exprAccessorValueLhs(vulkanType)
+ accessRhs = self.exprAccessorValueRhs(vulkanType)
+
+ lenAccessLhs = self.lenAccessorLhs(vulkanType)
+
+ bytesExpr = self.makeAllocBytesExpr(lenAccessLhs, vulkanType)
+ self.cgen.stmt("memcpy(%s, %s, %s)" % (accessRhs, accessLhs, bytesExpr))
+
+ def onStructExtension(self, vulkanType):
+
+ lhs = self.exprAccessorLhs(vulkanType)
+ rhs = self.exprAccessorRhs(vulkanType)
+
+ rhsExpr = "(%s)(%s)" % ("void*", rhs)
+
+ nextVar = "from_%s" % vulkanType.paramName
+ sizeVar = "%s_size" % vulkanType.paramName
+
+ self.cgen.beginIf("%s == VK_STRUCTURE_TYPE_MAX_ENUM" %
+ self.rootVarName)
+ self.cgen.stmt("%s = from->sType" % self.rootVarName)
+ self.cgen.endIf()
+
+ self.cgen.stmt("const void* %s = %s" % (nextVar, self.inputVars[0]))
+ self.cgen.stmt("size_t %s = 0u" % sizeVar)
+ self.cgen.beginWhile("!%s && %s" % (sizeVar, nextVar))
+ self.cgen.stmt("%s = static_cast<const vk_struct_common*>(%s)->%s" % (
+ nextVar, nextVar, vulkanType.paramName
+ ))
+ self.cgen.stmt("%s = %s(%s, %s)" % (
+ sizeVar, EXTENSION_SIZE_API_NAME, self.rootVarName, nextVar))
+ self.cgen.endWhile()
+
+ self.cgen.stmt("%s = nullptr" % rhs)
+
+ self.cgen.beginIf(sizeVar)
+
+ self.cgen.stmt( \
+ "%s = %s%s->alloc(%s)" % \
+ (rhs, self.makeCastExpr(vulkanType.getForNonConstAccess()), self.poolVarName, sizeVar))
+
+ self.cgen.funcCall(None, self.prefix + "extension_struct",
+ [self.poolVarName, self.rootVarName, nextVar, rhsExpr])
+
+ self.cgen.endIf()
+
+ def onPointer(self, vulkanType):
+
+ accessLhs = self.exprAccessorLhs(vulkanType)
+ accessRhs = self.exprAccessorRhs(vulkanType)
+
+ if self.needSkip(vulkanType):
+ self.cgen.stmt("%s = nullptr" % accessRhs)
+ return
+
+ lenAccessLhs = self.lenAccessorLhs(vulkanType)
+
+ self.cgen.stmt("%s = nullptr" % accessRhs)
+ self.cgen.beginIf(accessLhs)
+
+ bytesExpr = self.makeAllocBytesExpr(lenAccessLhs, vulkanType)
+
+ self.cgen.stmt( \
+ "%s = %s%s->dupArray(%s, %s)" % \
+ (accessRhs,
+ self.makeCastExpr(vulkanType.getForNonConstAccess()),
+ self.poolVarName,
+ accessLhs,
+ bytesExpr))
+
+ self.cgen.endIf()
+
+ def onValue(self, vulkanType):
+ if self.skipValues:
+ return
+
+ accessLhs = self.exprAccessorValueLhs(vulkanType)
+ accessRhs = self.exprAccessorValueRhs(vulkanType)
+
+ self.cgen.stmt("%s = %s" % (accessRhs, accessLhs))
+
+class VulkanDeepcopy(VulkanWrapperGenerator):
+
+ def __init__(self, module, typeInfo):
+ VulkanWrapperGenerator.__init__(self, module, typeInfo)
+
+ self.codegen = CodeGen()
+
+ self.deepcopyPrefix = "deepcopy_"
+ self.deepcopyVars = ["from", "to"]
+ self.deepcopyAllocatorVarName = "alloc"
+ self.deepcopyAllocatorParam = \
+ makeVulkanTypeSimple(False, "Allocator", 1,
+ self.deepcopyAllocatorVarName)
+ self.deepcopyRootVarName = "rootType"
+ self.deepcopyRootParam = \
+ makeVulkanTypeSimple(False, "VkStructureType",
+ 0, self.deepcopyRootVarName)
+ self.voidType = makeVulkanTypeSimple(False, "void", 0)
+
+ self.deepcopyCodegen = \
+ DeepcopyCodegen(
+ None,
+ self.deepcopyVars,
+ self.deepcopyAllocatorVarName,
+ self.deepcopyRootVarName,
+ self.deepcopyPrefix,
+ skipValues=True)
+
+ self.knownDefs = {}
+
+ self.extensionDeepcopyPrototype = \
+ VulkanAPI(self.deepcopyPrefix + "extension_struct",
+ self.voidType,
+ [self.deepcopyAllocatorParam,
+ self.deepcopyRootParam,
+ STRUCT_EXTENSION_PARAM,
+ STRUCT_EXTENSION_PARAM_FOR_WRITE])
+
+ def onBegin(self,):
+ VulkanWrapperGenerator.onBegin(self)
+ self.module.appendImpl(self.codegen.makeFuncDecl(
+ self.extensionDeepcopyPrototype))
+
+ 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:
+ self.module.appendHeader(
+ self.codegen.makeFuncAlias(self.deepcopyPrefix + name,
+ self.deepcopyPrefix + alias))
+
+ if category in ["struct", "union"] and not alias:
+
+ structInfo = self.typeInfo.structs[name]
+
+ typeFromName = \
+ lambda varname: \
+ makeVulkanTypeSimple(varname == "from", name, 1, varname)
+
+ deepcopyParams = \
+ [self.deepcopyAllocatorParam, self.deepcopyRootParam] + \
+ list(map(typeFromName, self.deepcopyVars))
+
+ deepcopyPrototype = \
+ VulkanAPI(self.deepcopyPrefix + name,
+ self.voidType,
+ deepcopyParams)
+
+ def structDeepcopyDef(cgen):
+ self.deepcopyCodegen.cgen = cgen
+ canSimplyAssign = True
+ for member in structInfo.members:
+ if not member.isSimpleValueType(self.typeInfo):
+ canSimplyAssign = False
+
+ cgen.stmt("(void)%s" % self.deepcopyAllocatorVarName)
+ cgen.stmt("(void)%s" % self.deepcopyRootVarName)
+ cgen.stmt("*to = *from")
+ if canSimplyAssign:
+ pass
+ else:
+ for member in structInfo.members:
+ iterateVulkanType(self.typeInfo, member,
+ self.deepcopyCodegen)
+
+ self.module.appendHeader(
+ self.codegen.makeFuncDecl(deepcopyPrototype))
+ self.module.appendImpl(
+ self.codegen.makeFuncImpl(deepcopyPrototype, structDeepcopyDef))
+
+ def onGenCmd(self, cmdinfo, name, alias):
+ VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
+
+ def onEnd(self,):
+ VulkanWrapperGenerator.onEnd(self)
+
+ def deepcopyDstExpr(cgen, typeName):
+ return cgen.makeReinterpretCast( \
+ STRUCT_EXTENSION_PARAM_FOR_WRITE.paramName,
+ typeName, const=False)
+
+ def forEachExtensionDeepcopy(ext, castedAccess, cgen):
+ cgen.funcCall(None, self.deepcopyPrefix + ext.name,
+ [self.deepcopyAllocatorVarName,
+ self.deepcopyRootVarName,
+ castedAccess, deepcopyDstExpr(cgen, ext.name)])
+
+ self.module.appendImpl(
+ self.codegen.makeFuncImpl(
+ self.extensionDeepcopyPrototype,
+ lambda cgen: self.emitForEachStructExtension(
+ cgen,
+ self.voidType,
+ STRUCT_EXTENSION_PARAM,
+ forEachExtensionDeepcopy,
+ rootTypeVar=self.deepcopyRootParam)))