diff options
Diffstat (limited to 'codegen/vulkan/scripts/cereal/deepcopy.py')
-rw-r--r-- | codegen/vulkan/scripts/cereal/deepcopy.py | 383 |
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))) |