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