384 lines
14 KiB
Python
384 lines
14 KiB
Python
# 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)))
|