1# Copyright 2018 Google LLC 2# SPDX-License-Identifier: MIT 3 4from .common.codegen import CodeGen 5from .common.vulkantypes import \ 6 VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator 7 8from .wrapperdefs import VulkanWrapperGenerator 9from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE, EXTENSION_SIZE_API_NAME 10 11class DeepcopyCodegen(VulkanTypeIterator): 12 def __init__(self, cgen, inputVars, poolVarName, rootVarName, prefix, skipValues=False): 13 self.cgen = cgen 14 self.inputVars = inputVars 15 self.prefix = prefix 16 self.poolVarName = poolVarName 17 self.rootVarName = rootVarName 18 self.skipValues = skipValues 19 20 def makeAccess(varName, asPtr = True): 21 return lambda t: self.cgen.generalAccess(t, parentVarName = varName, asPtr = asPtr) 22 23 def makeLengthAccess(varName): 24 return lambda t: self.cgen.generalLengthAccess(t, parentVarName = varName) 25 26 def makeLengthAccessGuard(varName): 27 return lambda t: self.cgen.generalLengthAccessGuard(t, parentVarName=varName) 28 29 self.exprAccessorLhs = makeAccess(self.inputVars[0]) 30 self.exprAccessorRhs = makeAccess(self.inputVars[1]) 31 32 self.exprAccessorValueLhs = makeAccess(self.inputVars[0], asPtr = False) 33 self.exprAccessorValueRhs = makeAccess(self.inputVars[1], asPtr = False) 34 35 self.lenAccessorLhs = makeLengthAccess(self.inputVars[0]) 36 self.lenAccessorRhs = makeLengthAccess(self.inputVars[1]) 37 38 self.lenAccessorGuardLhs = makeLengthAccessGuard(self.inputVars[0]) 39 self.lenAccessorGuardRhs = makeLengthAccessGuard(self.inputVars[1]) 40 41 self.checked = False 42 43 def needSkip(self, vulkanType): 44 return False 45 46 def makeCastExpr(self, vulkanType): 47 return "(%s)" % ( 48 self.cgen.makeCTypeDecl(vulkanType, useParamName=False)) 49 50 def makeNonConstCastForCopy(self, access, vulkanType): 51 if vulkanType.staticArrExpr: 52 casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access) 53 elif vulkanType.accessibleAsPointer(): 54 casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForNonConstAccess()), access) 55 else: 56 casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access) 57 return casted 58 59 def makeAllocBytesExpr(self, lenAccess, vulkanType): 60 sizeof = self.cgen.sizeofExpr( \ 61 vulkanType.getForValueAccess()) 62 if lenAccess: 63 bytesExpr = "%s * %s" % (lenAccess, sizeof) 64 else: 65 bytesExpr = sizeof 66 67 return bytesExpr 68 69 def onCheck(self, vulkanType): 70 pass 71 72 def endCheck(self, vulkanType): 73 pass 74 75 def onCompoundType(self, vulkanType): 76 77 if self.needSkip(vulkanType): 78 self.cgen.line("// TODO: Unsupported : %s" % 79 self.cgen.makeCTypeDecl(vulkanType)) 80 return 81 82 accessLhs = self.exprAccessorLhs(vulkanType) 83 accessRhs = self.exprAccessorRhs(vulkanType) 84 85 lenAccessLhs = self.lenAccessorLhs(vulkanType) 86 lenAccessRhs = self.lenAccessorRhs(vulkanType) 87 88 lenAccessorGuardLhs = self.lenAccessorGuardLhs(vulkanType) 89 lenAccessorGuardRhs = self.lenAccessorGuardRhs(vulkanType) 90 91 isPtr = vulkanType.pointerIndirectionLevels > 0 92 93 if lenAccessorGuardLhs is not None: 94 self.cgen.beginIf(lenAccessorGuardLhs) 95 96 if isPtr: 97 self.cgen.stmt("%s = nullptr" % accessRhs) 98 self.cgen.beginIf(accessLhs) 99 100 self.cgen.stmt( \ 101 "%s = %s%s->alloc(%s)" % \ 102 (accessRhs, self.makeCastExpr(vulkanType.getForNonConstAccess()), 103 self.poolVarName, self.makeAllocBytesExpr(lenAccessLhs, vulkanType))) 104 105 if lenAccessLhs is not None: 106 107 loopVar = "i" 108 accessLhs = "%s + %s" % (accessLhs, loopVar) 109 forInit = "uint32_t %s = 0" % loopVar 110 forCond = "%s < (uint32_t)%s" % (loopVar, lenAccessLhs) 111 forIncr = "++%s" % loopVar 112 113 if isPtr: 114 # Avoid generating a self-assign. 115 if lenAccessRhs != lenAccessLhs: 116 self.cgen.stmt("%s = %s" % (lenAccessRhs, lenAccessLhs)) 117 118 accessRhs = "%s + %s" % (accessRhs, loopVar) 119 self.cgen.beginFor(forInit, forCond, forIncr) 120 121 122 accessRhsCasted = self.makeNonConstCastForCopy(accessRhs, vulkanType) 123 124 self.cgen.funcCall(None, self.prefix + vulkanType.typeName, 125 [self.poolVarName, self.rootVarName, accessLhs, accessRhsCasted]) 126 127 if lenAccessLhs is not None: 128 self.cgen.endFor() 129 130 if isPtr: 131 self.cgen.endIf() 132 133 if lenAccessorGuardLhs is not None: 134 self.cgen.endIf() 135 136 def onString(self, vulkanType): 137 accessLhs = self.exprAccessorLhs(vulkanType) 138 accessRhs = self.exprAccessorRhs(vulkanType) 139 140 self.cgen.stmt("%s = nullptr" % accessRhs) 141 self.cgen.beginIf(accessLhs) 142 143 self.cgen.stmt( \ 144 "%s = %s->strDup(%s)" % \ 145 (accessRhs, 146 self.poolVarName, 147 accessLhs)) 148 149 self.cgen.endIf() 150 151 def onStringArray(self, vulkanType): 152 accessLhs = self.exprAccessorLhs(vulkanType) 153 accessRhs = self.exprAccessorRhs(vulkanType) 154 155 lenAccessLhs = self.lenAccessorLhs(vulkanType) 156 157 self.cgen.stmt("%s = nullptr" % accessRhs) 158 self.cgen.beginIf("%s && %s" % (accessLhs, lenAccessLhs)) 159 160 self.cgen.stmt( \ 161 "%s = %s->strDupArray(%s, %s)" % \ 162 (accessRhs, 163 self.poolVarName, 164 accessLhs, 165 lenAccessLhs)) 166 167 self.cgen.endIf() 168 169 def onStaticArr(self, vulkanType): 170 accessLhs = self.exprAccessorValueLhs(vulkanType) 171 accessRhs = self.exprAccessorValueRhs(vulkanType) 172 173 lenAccessLhs = self.lenAccessorLhs(vulkanType) 174 175 bytesExpr = self.makeAllocBytesExpr(lenAccessLhs, vulkanType) 176 self.cgen.stmt("memcpy(%s, %s, %s)" % (accessRhs, accessLhs, bytesExpr)) 177 178 def onStructExtension(self, vulkanType): 179 180 lhs = self.exprAccessorLhs(vulkanType) 181 rhs = self.exprAccessorRhs(vulkanType) 182 183 rhsExpr = "(%s)(%s)" % ("void*", rhs) 184 185 nextVar = "from_%s" % vulkanType.paramName 186 sizeVar = "%s_size" % vulkanType.paramName 187 188 self.cgen.beginIf("%s == VK_STRUCTURE_TYPE_MAX_ENUM" % 189 self.rootVarName) 190 self.cgen.stmt("%s = from->sType" % self.rootVarName) 191 self.cgen.endIf() 192 193 self.cgen.stmt("const void* %s = %s" % (nextVar, self.inputVars[0])) 194 self.cgen.stmt("size_t %s = 0u" % sizeVar) 195 self.cgen.beginWhile("!%s && %s" % (sizeVar, nextVar)) 196 self.cgen.stmt("%s = static_cast<const vk_struct_common*>(%s)->%s" % ( 197 nextVar, nextVar, vulkanType.paramName 198 )) 199 self.cgen.stmt("%s = %s(%s, %s)" % ( 200 sizeVar, EXTENSION_SIZE_API_NAME, self.rootVarName, nextVar)) 201 self.cgen.endWhile() 202 203 self.cgen.stmt("%s = nullptr" % rhs) 204 205 self.cgen.beginIf(sizeVar) 206 207 self.cgen.stmt( \ 208 "%s = %s%s->alloc(%s)" % \ 209 (rhs, self.makeCastExpr(vulkanType.getForNonConstAccess()), self.poolVarName, sizeVar)) 210 211 self.cgen.funcCall(None, self.prefix + "extension_struct", 212 [self.poolVarName, self.rootVarName, nextVar, rhsExpr]) 213 214 self.cgen.endIf() 215 216 def onPointer(self, vulkanType): 217 218 accessLhs = self.exprAccessorLhs(vulkanType) 219 accessRhs = self.exprAccessorRhs(vulkanType) 220 221 if self.needSkip(vulkanType): 222 self.cgen.stmt("%s = nullptr" % accessRhs) 223 return 224 225 lenAccessLhs = self.lenAccessorLhs(vulkanType) 226 227 self.cgen.stmt("%s = nullptr" % accessRhs) 228 self.cgen.beginIf(accessLhs) 229 230 bytesExpr = self.makeAllocBytesExpr(lenAccessLhs, vulkanType) 231 232 self.cgen.stmt( \ 233 "%s = %s%s->dupArray(%s, %s)" % \ 234 (accessRhs, 235 self.makeCastExpr(vulkanType.getForNonConstAccess()), 236 self.poolVarName, 237 accessLhs, 238 bytesExpr)) 239 240 self.cgen.endIf() 241 242 def onValue(self, vulkanType): 243 if self.skipValues: 244 return 245 246 accessLhs = self.exprAccessorValueLhs(vulkanType) 247 accessRhs = self.exprAccessorValueRhs(vulkanType) 248 249 self.cgen.stmt("%s = %s" % (accessRhs, accessLhs)) 250 251class VulkanDeepcopy(VulkanWrapperGenerator): 252 253 def __init__(self, module, typeInfo): 254 VulkanWrapperGenerator.__init__(self, module, typeInfo) 255 256 self.codegen = CodeGen() 257 258 self.deepcopyPrefix = "deepcopy_" 259 self.deepcopyVars = ["from", "to"] 260 self.deepcopyAllocatorVarName = "alloc" 261 self.deepcopyAllocatorParam = \ 262 makeVulkanTypeSimple(False, "Allocator", 1, 263 self.deepcopyAllocatorVarName) 264 self.deepcopyRootVarName = "rootType" 265 self.deepcopyRootParam = \ 266 makeVulkanTypeSimple(False, "VkStructureType", 267 0, self.deepcopyRootVarName) 268 self.voidType = makeVulkanTypeSimple(False, "void", 0) 269 270 self.deepcopyCodegen = \ 271 DeepcopyCodegen( 272 None, 273 self.deepcopyVars, 274 self.deepcopyAllocatorVarName, 275 self.deepcopyRootVarName, 276 self.deepcopyPrefix, 277 skipValues=True) 278 279 self.knownDefs = {} 280 281 self.extensionDeepcopyPrototype = \ 282 VulkanAPI(self.deepcopyPrefix + "extension_struct", 283 self.voidType, 284 [self.deepcopyAllocatorParam, 285 self.deepcopyRootParam, 286 STRUCT_EXTENSION_PARAM, 287 STRUCT_EXTENSION_PARAM_FOR_WRITE]) 288 289 def onBegin(self,): 290 VulkanWrapperGenerator.onBegin(self) 291 self.module.appendImpl(self.codegen.makeFuncDecl( 292 self.extensionDeepcopyPrototype)) 293 294 def onGenType(self, typeXml, name, alias): 295 VulkanWrapperGenerator.onGenType(self, typeXml, name, alias) 296 297 if name in self.knownDefs: 298 return 299 300 category = self.typeInfo.categoryOf(name) 301 302 if category in ["struct", "union"] and alias: 303 self.module.appendHeader( 304 self.codegen.makeFuncAlias(self.deepcopyPrefix + name, 305 self.deepcopyPrefix + alias)) 306 307 if category in ["struct", "union"] and not alias: 308 309 structInfo = self.typeInfo.structs[name] 310 311 typeFromName = \ 312 lambda varname: \ 313 makeVulkanTypeSimple(varname == "from", name, 1, varname) 314 315 deepcopyParams = \ 316 [self.deepcopyAllocatorParam, self.deepcopyRootParam] + \ 317 list(map(typeFromName, self.deepcopyVars)) 318 319 deepcopyPrototype = \ 320 VulkanAPI(self.deepcopyPrefix + name, 321 self.voidType, 322 deepcopyParams) 323 324 def structDeepcopyDef(cgen): 325 self.deepcopyCodegen.cgen = cgen 326 canSimplyAssign = True 327 for member in structInfo.members: 328 if not member.isSimpleValueType(self.typeInfo): 329 canSimplyAssign = False 330 331 cgen.stmt("(void)%s" % self.deepcopyAllocatorVarName) 332 cgen.stmt("(void)%s" % self.deepcopyRootVarName) 333 cgen.stmt("*to = *from") 334 if canSimplyAssign: 335 pass 336 else: 337 for member in structInfo.members: 338 iterateVulkanType(self.typeInfo, member, 339 self.deepcopyCodegen) 340 341 self.module.appendHeader( 342 self.codegen.makeFuncDecl(deepcopyPrototype)) 343 self.module.appendImpl( 344 self.codegen.makeFuncImpl(deepcopyPrototype, structDeepcopyDef)) 345 346 def onGenCmd(self, cmdinfo, name, alias): 347 VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias) 348 349 def onEnd(self,): 350 VulkanWrapperGenerator.onEnd(self) 351 352 def deepcopyDstExpr(cgen, typeName): 353 return cgen.makeReinterpretCast( \ 354 STRUCT_EXTENSION_PARAM_FOR_WRITE.paramName, 355 typeName, const=False) 356 357 def forEachExtensionDeepcopy(ext, castedAccess, cgen): 358 cgen.funcCall(None, self.deepcopyPrefix + ext.name, 359 [self.deepcopyAllocatorVarName, 360 self.deepcopyRootVarName, 361 castedAccess, deepcopyDstExpr(cgen, ext.name)]) 362 363 self.module.appendImpl( 364 self.codegen.makeFuncImpl( 365 self.extensionDeepcopyPrototype, 366 lambda cgen: self.emitForEachStructExtension( 367 cgen, 368 self.voidType, 369 STRUCT_EXTENSION_PARAM, 370 forEachExtensionDeepcopy, 371 rootTypeVar=self.deepcopyRootParam))) 372