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. 15from copy import copy 16 17from .common.codegen import CodeGen, VulkanAPIWrapper 18from .common.vulkantypes import \ 19 VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator, Atom, FuncExpr, FuncExprVal, FuncLambda 20 21from .wrapperdefs import VulkanWrapperGenerator 22from .wrapperdefs import VULKAN_STREAM_VAR_NAME 23from .wrapperdefs import ROOT_TYPE_VAR_NAME, ROOT_TYPE_PARAM 24from .wrapperdefs import STREAM_RET_TYPE 25from .wrapperdefs import MARSHAL_INPUT_VAR_NAME 26from .wrapperdefs import UNMARSHAL_INPUT_VAR_NAME 27from .wrapperdefs import PARAMETERS_MARSHALING 28from .wrapperdefs import PARAMETERS_MARSHALING_GUEST 29from .wrapperdefs import STYPE_OVERRIDE 30from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE, EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME 31from .wrapperdefs import API_PREFIX_RESERVEDMARSHAL 32from .wrapperdefs import API_PREFIX_RESERVEDUNMARSHAL 33 34from .marshalingdefs import CUSTOM_MARSHAL_TYPES 35class VulkanReservedMarshalingCodegen(VulkanTypeIterator): 36 def __init__(self, 37 cgen, 38 streamVarName, 39 rootTypeVarName, 40 inputVarName, 41 ptrVarName, 42 marshalPrefix, 43 handlemapPrefix, 44 direction = "write", 45 forApiOutput = False, 46 dynAlloc = False, 47 mapHandles = True, 48 handleMapOverwrites = False, 49 doFiltering = True, 50 stackVar=None, 51 stackArrSize=None): 52 self.cgen = cgen 53 self.direction = direction 54 self.processSimple = "write" if self.direction == "write" else "read" 55 self.forApiOutput = forApiOutput 56 57 self.checked = False 58 59 self.streamVarName = streamVarName 60 self.rootTypeVarName = rootTypeVarName 61 self.inputVarName = inputVarName 62 self.ptrVar = ptrVarName 63 self.marshalPrefix = marshalPrefix 64 self.handlemapPrefix = handlemapPrefix 65 66 self.exprAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.inputVarName, asPtr = True) 67 self.exprValueAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.inputVarName, asPtr = False) 68 self.exprPrimitiveValueAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.inputVarName, asPtr = False) 69 self.lenAccessor = lambda t: self.cgen.generalLengthAccess(t, parentVarName = self.inputVarName) 70 self.lenAccessorGuard = lambda t: self.cgen.generalLengthAccessGuard( 71 t, parentVarName=self.inputVarName) 72 self.filterVarAccessor = lambda t: self.cgen.filterVarAccess(t, parentVarName = self.inputVarName) 73 74 self.dynAlloc = dynAlloc 75 self.mapHandles = mapHandles 76 self.handleMapOverwrites = handleMapOverwrites 77 self.doFiltering = doFiltering 78 79 self.stackVar = stackVar 80 self.stackArrSize = stackArrSize 81 82 def getTypeForStreaming(self, vulkanType): 83 res = copy(vulkanType) 84 85 if not vulkanType.accessibleAsPointer(): 86 res = res.getForAddressAccess() 87 88 if vulkanType.staticArrExpr: 89 res = res.getForAddressAccess() 90 91 if self.direction == "write": 92 return res 93 else: 94 return res.getForNonConstAccess() 95 96 def makeCastExpr(self, vulkanType): 97 return "(%s)" % ( 98 self.cgen.makeCTypeDecl(vulkanType, useParamName=False)) 99 100 def genPtrIncr(self, sizeExpr): 101 self.cgen.stmt("*%s += %s" % (self.ptrVar, sizeExpr)) 102 103 def genMemcpyAndIncr(self, varname, cast, toStreamExpr, sizeExpr, toBe = False, actualSize = 4): 104 if self.direction == "write": 105 self.cgen.stmt("memcpy(*%s, %s%s, %s)" % (varname, cast, toStreamExpr, sizeExpr)) 106 else: 107 self.cgen.stmt("memcpy(%s%s, *%s, %s)" % (cast, toStreamExpr, varname, sizeExpr)) 108 109 if toBe: 110 streamPrefix = "to" 111 if "read" == self.direction: 112 streamPrefix = "from" 113 114 streamMethod = streamPrefix 115 116 if 1 == actualSize: 117 streamMethod += "Byte" 118 elif 2 == actualSize: 119 streamMethod += "Be16" 120 elif 4 == actualSize: 121 streamMethod += "Be32" 122 elif 8 == actualSize: 123 streamMethod += "Be64" 124 else: 125 pass 126 127 if self.direction == "write": 128 self.cgen.stmt("android::base::Stream::%s((uint8_t*)*%s)" % (streamMethod, varname)) 129 else: 130 self.cgen.stmt("android::base::Stream::%s((uint8_t*)%s)" % (streamMethod, toStreamExpr)) 131 132 self.genPtrIncr(sizeExpr) 133 134 def genStreamCall(self, vulkanType, toStreamExpr, sizeExpr): 135 varname = self.ptrVar 136 cast = self.makeCastExpr(self.getTypeForStreaming(vulkanType)) 137 self.genMemcpyAndIncr(varname, cast, toStreamExpr, sizeExpr) 138 139 def genPrimitiveStreamCall(self, vulkanType, access): 140 varname = self.ptrVar 141 self.cgen.memcpyPrimitive( 142 self.typeInfo, 143 "(*" + varname + ")", 144 access, 145 vulkanType, 146 direction=self.direction) 147 self.genPtrIncr(str(self.cgen.countPrimitive( 148 self.typeInfo, 149 vulkanType))) 150 151 def genHandleMappingCall(self, vulkanType, access, lenAccess, lenAccessGuard): 152 153 if lenAccess is None: 154 lenAccess = "1" 155 handle64Bytes = "8" 156 else: 157 handle64Bytes = "%s * 8" % lenAccess 158 159 handle64Var = self.cgen.var() 160 if lenAccess != "1": 161 self.cgen.beginIf(lenAccess) 162 self.cgen.stmt("uint8_t* %s_ptr = (uint8_t*)(*%s)" % (handle64Var, self.ptrVar)) 163 handle64VarAccess = handle64Var 164 handle64VarType = \ 165 makeVulkanTypeSimple(False, "uint64_t", 1, paramName=handle64Var) 166 else: 167 self.cgen.stmt("uint64_t %s" % handle64Var) 168 handle64VarAccess = "&%s" % handle64Var 169 handle64VarType = \ 170 makeVulkanTypeSimple(False, "uint64_t", 0, paramName=handle64Var) 171 172 if "" == self.handlemapPrefix: 173 mapFunc = ("(%s)" % vulkanType.typeName) 174 mapFunc64 = ("(%s)" % "uint64_t") 175 else: 176 mapFunc = self.handlemapPrefix + vulkanType.typeName 177 mapFunc64 = mapFunc 178 179 if self.direction == "write": 180 if self.handleMapOverwrites: 181 self.cgen.stmt( 182 "static_assert(8 == sizeof(%s), \"handle map overwrite requres %s to be 8 bytes long\")" % \ 183 (vulkanType.typeName, vulkanType.typeName)) 184 if "1" == lenAccess: 185 self.cgen.stmt("*%s = (%s)%s(*%s)" % (access, vulkanType.typeName, mapFunc, access)) 186 self.genStreamCall(vulkanType, access, "8 * %s" % lenAccess) 187 else: 188 if lenAccessGuard is not None: 189 self.cgen.beginIf(lenAccessGuard) 190 self.cgen.beginFor("uint32_t k = 0", "k < %s" % lenAccess, "++k") 191 self.cgen.stmt("%s[k] = (%s)%s(%s[k])" % (access, vulkanType.typeName, mapFunc, access)) 192 self.cgen.endFor() 193 if lenAccessGuard is not None: 194 self.cgen.endIf() 195 self.genPtrIncr("8 * %s" % lenAccess) 196 else: 197 if "1" == lenAccess: 198 self.cgen.stmt("*%s = %s((*%s))" % (handle64VarAccess, mapFunc64, access)) 199 self.genStreamCall(handle64VarType, handle64VarAccess, handle64Bytes) 200 else: 201 if lenAccessGuard is not None: 202 self.cgen.beginIf(lenAccessGuard) 203 self.cgen.beginFor("uint32_t k = 0", "k < %s" % lenAccess, "++k") 204 self.cgen.stmt("uint64_t tmpval = %s(%s[k])" % (mapFunc64, access)) 205 self.cgen.stmt("memcpy(%s_ptr + k * 8, &tmpval, sizeof(uint64_t))" % (handle64Var)) 206 self.cgen.endFor() 207 if lenAccessGuard is not None: 208 self.cgen.endIf() 209 self.genPtrIncr("8 * %s" % lenAccess) 210 else: 211 if "1" == lenAccess: 212 self.genStreamCall(handle64VarType, handle64VarAccess, handle64Bytes) 213 self.cgen.stmt("*%s%s = (%s)%s((%s)(*%s))" % ( 214 self.makeCastExpr(vulkanType.getForNonConstAccess()), access, 215 vulkanType.typeName, mapFunc, vulkanType.typeName, handle64VarAccess)) 216 else: 217 self.genPtrIncr("8 * %s" % lenAccess) 218 if lenAccessGuard is not None: 219 self.cgen.beginIf(lenAccessGuard) 220 self.cgen.beginFor("uint32_t k = 0", "k < %s" % lenAccess, "++k") 221 self.cgen.stmt("uint64_t tmpval; memcpy(&tmpval, %s_ptr + k * 8, sizeof(uint64_t))" % handle64Var) 222 self.cgen.stmt("*((%s%s) + k) = (%s)%s((%s)tmpval)" % ( 223 self.makeCastExpr(vulkanType.getForNonConstAccess()), access, 224 vulkanType.typeName, mapFunc, vulkanType.typeName)) 225 if lenAccessGuard is not None: 226 self.cgen.endIf() 227 self.cgen.endFor() 228 229 if lenAccess != "1": 230 self.cgen.endIf() 231 232 def doAllocSpace(self, vulkanType): 233 if self.dynAlloc and self.direction == "read": 234 access = self.exprAccessor(vulkanType) 235 lenAccess = self.lenAccessor(vulkanType) 236 sizeof = self.cgen.sizeofExpr(vulkanType.getForValueAccess()) 237 if lenAccess: 238 bytesExpr = "%s * %s" % (lenAccess, sizeof) 239 else: 240 bytesExpr = sizeof 241 lenAccess = "1" 242 243 if self.stackVar: 244 if self.stackArrSize != lenAccess: 245 self.cgen.beginIf("%s <= %s" % (lenAccess, self.stackArrSize)) 246 247 self.cgen.stmt( 248 "%s = %s%s" % (access, self.makeCastExpr(vulkanType.getForNonConstAccess()), self.stackVar)) 249 250 if self.stackArrSize != lenAccess: 251 self.cgen.endIf() 252 self.cgen.beginElse() 253 254 if self.stackArrSize != lenAccess: 255 self.cgen.stmt( 256 "%s->alloc((void**)&%s, %s)" % 257 (self.streamVarName, 258 access, bytesExpr)) 259 260 if self.stackArrSize != lenAccess: 261 self.cgen.endIf() 262 else: 263 self.cgen.stmt( 264 "%s->alloc((void**)&%s, %s)" % 265 (self.streamVarName, 266 access, bytesExpr)) 267 268 def getOptionalStringFeatureExpr(self, vulkanType): 269 if vulkanType.optionalStr is not None: 270 if vulkanType.optionalStr.startswith("streamFeature:"): 271 splitted = vulkanType.optionalStr.split(":") 272 featureExpr = "%s->getFeatureBits() & %s" % (self.streamVarName, splitted[1]) 273 return featureExpr 274 return None 275 276 def onCheck(self, vulkanType): 277 if self.forApiOutput: 278 return 279 280 featureExpr = self.getOptionalStringFeatureExpr(vulkanType) 281 self.checked = True 282 access = self.exprAccessor(vulkanType) 283 needConsistencyCheck = False 284 285 self.cgen.line("// WARNING PTR CHECK") 286 if (self.dynAlloc and self.direction == "read") or self.direction == "write": 287 checkAccess = self.exprAccessor(vulkanType) 288 addrExpr = "&" + checkAccess 289 sizeExpr = self.cgen.sizeofExpr(vulkanType) 290 else: 291 checkName = "check_%s" % vulkanType.paramName 292 self.cgen.stmt("%s %s" % ( 293 self.cgen.makeCTypeDecl(vulkanType, useParamName = False), checkName)) 294 checkAccess = checkName 295 addrExpr = "&" + checkAccess 296 sizeExpr = self.cgen.sizeofExpr(vulkanType) 297 needConsistencyCheck = True 298 299 if featureExpr is not None: 300 self.cgen.beginIf(featureExpr) 301 302 self.genPrimitiveStreamCall( 303 vulkanType, 304 checkAccess) 305 306 if featureExpr is not None: 307 self.cgen.endIf() 308 309 if featureExpr is not None: 310 self.cgen.beginIf("(!(%s) || %s)" % (featureExpr, access)) 311 else: 312 self.cgen.beginIf(access) 313 314 if needConsistencyCheck and featureExpr is None: 315 self.cgen.beginIf("!(%s)" % checkName) 316 self.cgen.stmt( 317 "fprintf(stderr, \"fatal: %s inconsistent between guest and host\\n\")" % (access)) 318 self.cgen.endIf() 319 320 def onCheckWithNullOptionalStringFeature(self, vulkanType): 321 self.cgen.beginIf("%s->getFeatureBits() & VULKAN_STREAM_FEATURE_NULL_OPTIONAL_STRINGS_BIT" % self.streamVarName) 322 self.onCheck(vulkanType) 323 324 def endCheckWithNullOptionalStringFeature(self, vulkanType): 325 self.endCheck(vulkanType) 326 self.cgen.endIf() 327 self.cgen.beginElse() 328 329 def finalCheckWithNullOptionalStringFeature(self, vulkanType): 330 self.cgen.endElse() 331 332 def endCheck(self, vulkanType): 333 334 if self.checked: 335 self.cgen.endIf() 336 self.checked = False 337 338 def genFilterFunc(self, filterfunc, env): 339 340 def loop(expr, lambdaEnv={}): 341 def do_func(expr): 342 fnamestr = expr.name.name 343 if "not" == fnamestr: 344 return "!(%s)" % (loop(expr.args[0], lambdaEnv)) 345 if "eq" == fnamestr: 346 return "(%s == %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv)) 347 if "and" == fnamestr: 348 return "(%s && %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv)) 349 if "or" == fnamestr: 350 return "(%s || %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv)) 351 if "bitwise_and" == fnamestr: 352 return "(%s & %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv)) 353 if "getfield" == fnamestr: 354 ptrlevels = get_ptrlevels(expr.args[0].val.name) 355 if ptrlevels == 0: 356 return "%s.%s" % (loop(expr.args[0], lambdaEnv), expr.args[1].val) 357 else: 358 return "(%s(%s)).%s" % ("*" * ptrlevels, loop(expr.args[0], lambdaEnv), expr.args[1].val) 359 360 if "if" == fnamestr: 361 return "((%s) ? (%s) : (%s))" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv), loop(expr.args[2], lambdaEnv)) 362 363 return "%s(%s)" % (fnamestr, ", ".join(map(lambda e: loop(e, lambdaEnv), expr.args))) 364 365 def do_expratom(atomname, lambdaEnv= {}): 366 if lambdaEnv.get(atomname, None) is not None: 367 return atomname 368 369 enventry = env.get(atomname, None) 370 if None != enventry: 371 return self.getEnvAccessExpr(atomname) 372 return atomname 373 374 def get_ptrlevels(atomname, lambdaEnv= {}): 375 if lambdaEnv.get(atomname, None) is not None: 376 return 0 377 378 enventry = env.get(atomname, None) 379 if None != enventry: 380 return self.getPointerIndirectionLevels(atomname) 381 382 return 0 383 384 def do_exprval(expr, lambdaEnv= {}): 385 expratom = expr.val 386 387 if Atom == type(expratom): 388 return do_expratom(expratom.name, lambdaEnv) 389 390 return "%s" % expratom 391 392 def do_lambda(expr, lambdaEnv= {}): 393 params = expr.vs 394 body = expr.body 395 newEnv = {} 396 397 for (k, v) in lambdaEnv.items(): 398 newEnv[k] = v 399 400 for p in params: 401 newEnv[p.name] = p.typ 402 403 return "[](%s) { return %s; }" % (", ".join(list(map(lambda p: "%s %s" % (p.typ, p.name), params))), loop(body, lambdaEnv=newEnv)) 404 405 if FuncExpr == type(expr): 406 return do_func(expr) 407 if FuncLambda == type(expr): 408 return do_lambda(expr) 409 elif FuncExprVal == type(expr): 410 return do_exprval(expr) 411 412 return loop(filterfunc) 413 414 def beginFilterGuard(self, vulkanType): 415 if vulkanType.filterVar == None: 416 return 417 418 if self.doFiltering == False: 419 return 420 421 filterVarAccess = self.getEnvAccessExpr(vulkanType.filterVar) 422 423 filterValsExpr = None 424 filterFuncExpr = None 425 filterExpr = None 426 427 filterFeature = "%s->getFeatureBits() & VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT" % self.streamVarName 428 429 if None != vulkanType.filterVals: 430 filterValsExpr = " || ".join(map(lambda filterval: "(%s == %s)" % (filterval, filterVarAccess), vulkanType.filterVals)) 431 432 if None != vulkanType.filterFunc: 433 filterFuncExpr = self.genFilterFunc(vulkanType.filterFunc, self.currentStructInfo.environment) 434 435 if None != filterValsExpr and None != filterFuncExpr: 436 filterExpr = "%s || %s" % (filterValsExpr, filterFuncExpr) 437 elif None == filterValsExpr and None == filterFuncExpr: 438 # Assume is bool 439 self.cgen.beginIf(filterVarAccess) 440 elif None != filterValsExpr: 441 self.cgen.beginIf("(!(%s) || (%s))" % (filterFeature, filterValsExpr)) 442 elif None != filterFuncExpr: 443 self.cgen.beginIf("(!(%s) || (%s))" % (filterFeature, filterFuncExpr)) 444 445 def endFilterGuard(self, vulkanType, cleanupExpr=None): 446 if vulkanType.filterVar == None: 447 return 448 449 if self.doFiltering == False: 450 return 451 452 if cleanupExpr == None: 453 self.cgen.endIf() 454 else: 455 self.cgen.endIf() 456 self.cgen.beginElse() 457 self.cgen.stmt(cleanupExpr) 458 self.cgen.endElse() 459 460 def getEnvAccessExpr(self, varName): 461 parentEnvEntry = self.currentStructInfo.environment.get(varName, None) 462 463 if parentEnvEntry != None: 464 isParentMember = parentEnvEntry["structmember"] 465 466 if isParentMember: 467 envAccess = self.exprValueAccessor(list(filter(lambda member: member.paramName == varName, self.currentStructInfo.members))[0]) 468 else: 469 envAccess = varName 470 return envAccess 471 472 return None 473 474 def getPointerIndirectionLevels(self, varName): 475 parentEnvEntry = self.currentStructInfo.environment.get(varName, None) 476 477 if parentEnvEntry != None: 478 isParentMember = parentEnvEntry["structmember"] 479 480 if isParentMember: 481 return list(filter(lambda member: member.paramName == varName, self.currentStructInfo.members))[0].pointerIndirectionLevels 482 else: 483 return 0 484 return 0 485 486 return 0 487 488 489 def onCompoundType(self, vulkanType): 490 491 access = self.exprAccessor(vulkanType) 492 lenAccess = self.lenAccessor(vulkanType) 493 494 self.beginFilterGuard(vulkanType) 495 496 if vulkanType.pointerIndirectionLevels > 0: 497 self.doAllocSpace(vulkanType) 498 499 if lenAccess is not None: 500 loopVar = "i" 501 access = "%s + %s" % (access, loopVar) 502 forInit = "uint32_t %s = 0" % loopVar 503 forCond = "%s < (uint32_t)%s" % (loopVar, lenAccess) 504 forIncr = "++%s" % loopVar 505 self.cgen.beginFor(forInit, forCond, forIncr) 506 507 accessWithCast = "%s(%s)" % (self.makeCastExpr( 508 self.getTypeForStreaming(vulkanType)), access) 509 510 callParams = [self.streamVarName, self.rootTypeVarName, accessWithCast, self.ptrVar] 511 512 for (bindName, localName) in vulkanType.binds.items(): 513 callParams.append(self.getEnvAccessExpr(localName)) 514 515 self.cgen.funcCall(None, self.marshalPrefix + vulkanType.typeName, 516 callParams) 517 518 if lenAccess is not None: 519 self.cgen.endFor() 520 521 if self.direction == "read": 522 self.endFilterGuard(vulkanType, "%s = 0" % self.exprAccessor(vulkanType)) 523 else: 524 self.endFilterGuard(vulkanType) 525 526 def onString(self, vulkanType): 527 access = self.exprAccessor(vulkanType) 528 529 if self.direction == "write": 530 self.cgen.beginBlock() 531 self.cgen.stmt("uint32_t l = %s ? strlen(%s): 0" % (access, access)) 532 self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)" ,"&l", "sizeof(uint32_t)", toBe = True, actualSize = 4) 533 self.genMemcpyAndIncr(self.ptrVar, "(char*)", access, "l") 534 self.cgen.endBlock() 535 else: 536 castExpr = \ 537 self.makeCastExpr( \ 538 self.getTypeForStreaming( \ 539 vulkanType.getForAddressAccess())) 540 self.cgen.stmt( \ 541 "%s->loadStringInPlaceWithStreamPtr(%s&%s, %s)" % (self.streamVarName, castExpr, access, self.ptrVar)) 542 543 def onStringArray(self, vulkanType): 544 access = self.exprAccessor(vulkanType) 545 lenAccess = self.lenAccessor(vulkanType) 546 lenAccessGuard = self.lenAccessorGuard(vulkanType) 547 548 if self.direction == "write": 549 self.cgen.beginBlock() 550 551 self.cgen.stmt("uint32_t c = 0") 552 if lenAccessGuard is not None: 553 self.cgen.beginIf(lenAccessGuard) 554 self.cgen.stmt("c = %s" % (lenAccess)) 555 if lenAccessGuard is not None: 556 self.cgen.endIf() 557 self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)" ,"&c", "sizeof(uint32_t)", toBe = True, actualSize = 4) 558 559 self.cgen.beginFor("uint32_t i = 0", "i < c", "++i") 560 self.cgen.stmt("uint32_t l = %s ? strlen(%s[i]): 0" % (access, access)) 561 self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)" ,"&l", "sizeof(uint32_t)", toBe = True, actualSize = 4) 562 self.cgen.beginIf("l") 563 self.genMemcpyAndIncr(self.ptrVar, "(char*)", "(%s[i])" % access, "l") 564 self.cgen.endIf() 565 self.cgen.endFor() 566 567 self.cgen.endBlock() 568 else: 569 castExpr = \ 570 self.makeCastExpr( \ 571 self.getTypeForStreaming( \ 572 vulkanType.getForAddressAccess())) 573 574 self.cgen.stmt("%s->loadStringArrayInPlaceWithStreamPtr(%s&%s, %s)" % (self.streamVarName, castExpr, access, self.ptrVar)) 575 576 def onStaticArr(self, vulkanType): 577 access = self.exprValueAccessor(vulkanType) 578 lenAccess = self.lenAccessor(vulkanType) 579 finalLenExpr = "%s * %s" % (lenAccess, self.cgen.sizeofExpr(vulkanType)) 580 self.genStreamCall(vulkanType, access, finalLenExpr) 581 582 # Old version VkEncoder may have some sType values conflict with VkDecoder 583 # of new versions. For host decoder, it should not carry the incorrect old 584 # sType values to the |forUnmarshaling| struct. Instead it should overwrite 585 # the sType value. 586 def overwriteSType(self, vulkanType): 587 if self.direction == "read": 588 sTypeParam = copy(vulkanType) 589 sTypeParam.paramName = "sType" 590 sTypeAccess = self.exprAccessor(sTypeParam) 591 592 typeName = vulkanType.parent.typeName 593 if typeName in STYPE_OVERRIDE: 594 self.cgen.stmt("%s = %s" % 595 (sTypeAccess, STYPE_OVERRIDE[typeName])) 596 597 def onStructExtension(self, vulkanType): 598 self.overwriteSType(vulkanType) 599 600 sTypeParam = copy(vulkanType) 601 sTypeParam.paramName = "sType" 602 603 access = self.exprAccessor(vulkanType) 604 sizeVar = "%s_size" % vulkanType.paramName 605 606 if self.direction == "read": 607 castedAccessExpr = "(%s)(%s)" % ("void*", access) 608 else: 609 castedAccessExpr = access 610 611 sTypeAccess = self.exprAccessor(sTypeParam) 612 self.cgen.beginIf("%s == VK_STRUCTURE_TYPE_MAX_ENUM" % self.rootTypeVarName) 613 self.cgen.stmt("%s = %s" % (self.rootTypeVarName, sTypeAccess)) 614 self.cgen.endIf() 615 616 if self.direction == "read" and self.dynAlloc: 617 self.cgen.stmt("uint32_t %s" % sizeVar) 618 619 self.genMemcpyAndIncr(self.ptrVar, "(uint32_t*)", "&" + sizeVar, "sizeof(uint32_t)", toBe = True, actualSize = 4) 620 621 self.cgen.stmt("%s = nullptr" % access) 622 self.cgen.beginIf(sizeVar) 623 self.cgen.stmt( \ 624 "%s->alloc((void**)&%s, sizeof(VkStructureType))" % 625 (self.streamVarName, access)) 626 627 self.genStreamCall(vulkanType, access, "sizeof(VkStructureType)") 628 self.cgen.stmt("VkStructureType extType = *(VkStructureType*)(%s)" % access) 629 self.cgen.stmt( \ 630 "%s->alloc((void**)&%s, %s(%s->getFeatureBits(), %s, %s))" % 631 (self.streamVarName, access, EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME, self.streamVarName, self.rootTypeVarName, access)) 632 self.cgen.stmt("*(VkStructureType*)%s = extType" % access) 633 634 self.cgen.funcCall(None, self.marshalPrefix + "extension_struct", 635 [self.streamVarName, self.rootTypeVarName, castedAccessExpr, self.ptrVar]) 636 self.cgen.endIf() 637 else: 638 639 self.cgen.funcCall(None, self.marshalPrefix + "extension_struct", 640 [self.streamVarName, self.rootTypeVarName, castedAccessExpr, self.ptrVar]) 641 642 def onPointer(self, vulkanType): 643 access = self.exprAccessor(vulkanType) 644 645 lenAccess = self.lenAccessor(vulkanType) 646 lenAccessGuard = self.lenAccessorGuard(vulkanType) 647 648 self.beginFilterGuard(vulkanType) 649 self.doAllocSpace(vulkanType) 650 651 if vulkanType.filterVar != None: 652 print("onPointer Needs filter: %s filterVar %s" % (access, vulkanType.filterVar)) 653 654 if vulkanType.isHandleType() and self.mapHandles: 655 self.genHandleMappingCall( 656 vulkanType, access, lenAccess, lenAccessGuard) 657 else: 658 if self.typeInfo.isNonAbiPortableType(vulkanType.typeName): 659 if lenAccess is not None: 660 if lenAccessGuard is not None: 661 self.cgen.beginIf(lenAccessGuard) 662 self.cgen.beginFor("uint32_t i = 0", "i < (uint32_t)%s" % lenAccess, "++i") 663 self.genPrimitiveStreamCall(vulkanType.getForValueAccess(), "%s[i]" % access) 664 self.cgen.endFor() 665 if lenAccessGuard is not None: 666 self.cgen.endIf() 667 else: 668 self.genPrimitiveStreamCall(vulkanType.getForValueAccess(), "(*%s)" % access) 669 else: 670 if lenAccess is not None: 671 finalLenExpr = "%s * %s" % ( 672 lenAccess, self.cgen.sizeofExpr(vulkanType.getForValueAccess())) 673 else: 674 finalLenExpr = "%s" % ( 675 self.cgen.sizeofExpr(vulkanType.getForValueAccess())) 676 self.genStreamCall(vulkanType, access, finalLenExpr) 677 678 if self.direction == "read": 679 self.endFilterGuard(vulkanType, "%s = 0" % access) 680 else: 681 self.endFilterGuard(vulkanType) 682 683 def onValue(self, vulkanType): 684 self.beginFilterGuard(vulkanType) 685 686 if vulkanType.isHandleType() and self.mapHandles: 687 access = self.exprAccessor(vulkanType) 688 if vulkanType.filterVar != None: 689 print("onValue Needs filter: %s filterVar %s" % (access, vulkanType.filterVar)) 690 self.genHandleMappingCall( 691 vulkanType.getForAddressAccess(), access, "1", None) 692 elif self.typeInfo.isNonAbiPortableType(vulkanType.typeName): 693 access = self.exprPrimitiveValueAccessor(vulkanType) 694 self.genPrimitiveStreamCall(vulkanType, access) 695 else: 696 access = self.exprAccessor(vulkanType) 697 self.genStreamCall(vulkanType, access, self.cgen.sizeofExpr(vulkanType)) 698 699 self.endFilterGuard(vulkanType) 700 701 def streamLetParameter(self, structInfo, letParamInfo): 702 filterFeature = "%s->getFeatureBits() & VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT" % self.streamVarName 703 self.cgen.stmt("%s %s = 1" % (letParamInfo.typeName, letParamInfo.paramName)) 704 705 self.cgen.beginIf(filterFeature) 706 707 if self.direction == "write": 708 bodyExpr = self.currentStructInfo.environment[letParamInfo.paramName]["body"] 709 self.cgen.stmt("%s = %s" % (letParamInfo.paramName, self.genFilterFunc(bodyExpr, self.currentStructInfo.environment))) 710 711 self.genPrimitiveStreamCall(letParamInfo, letParamInfo.paramName) 712 713 self.cgen.endIf() 714 715class VulkanReservedMarshaling(VulkanWrapperGenerator): 716 717 def __init__(self, module, typeInfo, variant="host"): 718 VulkanWrapperGenerator.__init__(self, module, typeInfo) 719 720 self.cgenHeader = CodeGen() 721 self.cgenImpl = CodeGen() 722 723 self.variant = variant 724 725 self.currentFeature = None 726 self.apiOpcodes = {} 727 self.dynAlloc = self.variant != "guest" 728 self.ptrVarName = "ptr" 729 self.ptrVarType = makeVulkanTypeSimple(False, "uint8_t", 2, self.ptrVarName) 730 self.ptrVarTypeUnmarshal = makeVulkanTypeSimple(False, "uint8_t", 2, self.ptrVarName) 731 732 if self.variant == "guest": 733 self.marshalingParams = PARAMETERS_MARSHALING_GUEST 734 else: 735 self.marshalingParams = PARAMETERS_MARSHALING 736 737 self.writeCodegen = \ 738 VulkanReservedMarshalingCodegen( 739 None, 740 VULKAN_STREAM_VAR_NAME, 741 ROOT_TYPE_VAR_NAME, 742 MARSHAL_INPUT_VAR_NAME, 743 self.ptrVarName, 744 API_PREFIX_RESERVEDMARSHAL, 745 "get_host_u64_" if "guest" == self.variant else "", 746 direction = "write") 747 748 self.readCodegen = \ 749 VulkanReservedMarshalingCodegen( 750 None, 751 VULKAN_STREAM_VAR_NAME, 752 ROOT_TYPE_VAR_NAME, 753 UNMARSHAL_INPUT_VAR_NAME, 754 self.ptrVarName, 755 API_PREFIX_RESERVEDUNMARSHAL, 756 "unbox_" if "host" == self.variant else "", 757 direction = "read", 758 dynAlloc=self.dynAlloc) 759 760 self.knownDefs = {} 761 762 self.extensionMarshalPrototype = \ 763 VulkanAPI(API_PREFIX_RESERVEDMARSHAL + "extension_struct", 764 STREAM_RET_TYPE, 765 self.marshalingParams + 766 [STRUCT_EXTENSION_PARAM, self.ptrVarType]) 767 768 self.extensionUnmarshalPrototype = \ 769 VulkanAPI(API_PREFIX_RESERVEDUNMARSHAL + "extension_struct", 770 STREAM_RET_TYPE, 771 self.marshalingParams + 772 [STRUCT_EXTENSION_PARAM_FOR_WRITE, self.ptrVarTypeUnmarshal]) 773 774 def onBegin(self,): 775 VulkanWrapperGenerator.onBegin(self) 776 self.module.appendImpl(self.cgenImpl.makeFuncDecl(self.extensionMarshalPrototype)) 777 self.module.appendImpl(self.cgenImpl.makeFuncDecl(self.extensionUnmarshalPrototype)) 778 779 def onBeginFeature(self, featureName, featureType): 780 VulkanWrapperGenerator.onBeginFeature(self, featureName, featureType) 781 self.currentFeature = featureName 782 783 def onGenType(self, typeXml, name, alias): 784 VulkanWrapperGenerator.onGenType(self, typeXml, name, alias) 785 786 if name in self.knownDefs: 787 return 788 789 category = self.typeInfo.categoryOf(name) 790 791 if category in ["struct", "union"] and alias: 792 if self.variant != "host": 793 self.module.appendHeader( 794 self.cgenHeader.makeFuncAlias(API_PREFIX_RESERVEDMARSHAL + name, 795 API_PREFIX_RESERVEDMARSHAL + alias)) 796 if self.variant != "guest": 797 self.module.appendHeader( 798 self.cgenHeader.makeFuncAlias(API_PREFIX_RESERVEDUNMARSHAL + name, 799 API_PREFIX_RESERVEDUNMARSHAL + alias)) 800 801 if category in ["struct", "union"] and not alias: 802 803 structInfo = self.typeInfo.structs[name] 804 805 marshalParams = self.marshalingParams + \ 806 [makeVulkanTypeSimple(True, name, 1, MARSHAL_INPUT_VAR_NAME), 807 self.ptrVarType] 808 809 freeParams = [] 810 letParams = [] 811 812 for (envname, bindingInfo) in list(sorted(structInfo.environment.items(), key = lambda kv: kv[0])): 813 if None == bindingInfo["binding"]: 814 freeParams.append(makeVulkanTypeSimple(True, bindingInfo["type"], 0, envname)) 815 else: 816 if not bindingInfo["structmember"]: 817 letParams.append(makeVulkanTypeSimple(True, bindingInfo["type"], 0, envname)) 818 819 marshalPrototype = \ 820 VulkanAPI(API_PREFIX_RESERVEDMARSHAL + name, 821 STREAM_RET_TYPE, 822 marshalParams + freeParams) 823 824 marshalPrototypeNoFilter = \ 825 VulkanAPI(API_PREFIX_RESERVEDMARSHAL + name, 826 STREAM_RET_TYPE, 827 marshalParams) 828 829 def structMarshalingCustom(cgen): 830 self.writeCodegen.cgen = cgen 831 self.writeCodegen.currentStructInfo = structInfo 832 marshalingCode = \ 833 CUSTOM_MARSHAL_TYPES[name]["common"] + \ 834 CUSTOM_MARSHAL_TYPES[name]["reservedmarshaling"].format( 835 streamVarName=self.writeCodegen.streamVarName, 836 rootTypeVarName=self.writeCodegen.rootTypeVarName, 837 inputVarName=self.writeCodegen.inputVarName, 838 newInputVarName=self.writeCodegen.inputVarName + "_new") 839 for line in marshalingCode.split('\n'): 840 cgen.line(line) 841 842 def structMarshalingDef(cgen): 843 self.writeCodegen.cgen = cgen 844 self.writeCodegen.currentStructInfo = structInfo 845 self.writeCodegen.cgen.stmt("(void)%s" % VULKAN_STREAM_VAR_NAME) 846 self.writeCodegen.cgen.stmt("(void)%s" % ROOT_TYPE_VAR_NAME) 847 848 if category == "struct": 849 # marshal 'let' parameters first 850 for letp in letParams: 851 self.writeCodegen.streamLetParameter(self.typeInfo, letp) 852 853 for member in structInfo.members: 854 iterateVulkanType(self.typeInfo, member, self.writeCodegen) 855 if category == "union": 856 iterateVulkanType(self.typeInfo, structInfo.members[0], self.writeCodegen) 857 858 def structMarshalingDefNoFilter(cgen): 859 self.writeCodegen.cgen = cgen 860 self.writeCodegen.currentStructInfo = structInfo 861 self.writeCodegen.doFiltering = False 862 self.writeCodegen.cgen.stmt("(void)%s" % VULKAN_STREAM_VAR_NAME) 863 self.writeCodegen.cgen.stmt("(void)%s" % ROOT_TYPE_VAR_NAME) 864 865 if category == "struct": 866 # marshal 'let' parameters first 867 for letp in letParams: 868 self.writeCodegen.streamLetParameter(self.typeInfo, letp) 869 870 for member in structInfo.members: 871 iterateVulkanType(self.typeInfo, member, self.writeCodegen) 872 if category == "union": 873 iterateVulkanType(self.typeInfo, structInfo.members[0], self.writeCodegen) 874 self.writeCodegen.doFiltering = True 875 876 if self.variant != "host": 877 self.module.appendHeader( 878 self.cgenHeader.makeFuncDecl(marshalPrototype)) 879 880 if name in CUSTOM_MARSHAL_TYPES: 881 self.module.appendImpl( 882 self.cgenImpl.makeFuncImpl( 883 marshalPrototype, structMarshalingCustom)) 884 else: 885 self.module.appendImpl( 886 self.cgenImpl.makeFuncImpl( 887 marshalPrototype, structMarshalingDef)) 888 889 if freeParams != []: 890 self.module.appendHeader( 891 self.cgenHeader.makeFuncDecl(marshalPrototypeNoFilter)) 892 self.module.appendImpl( 893 self.cgenImpl.makeFuncImpl( 894 marshalPrototypeNoFilter, structMarshalingDefNoFilter)) 895 896 unmarshalPrototype = \ 897 VulkanAPI(API_PREFIX_RESERVEDUNMARSHAL + name, 898 STREAM_RET_TYPE, 899 self.marshalingParams + [makeVulkanTypeSimple(False, name, 1, UNMARSHAL_INPUT_VAR_NAME), self.ptrVarTypeUnmarshal] + freeParams) 900 901 unmarshalPrototypeNoFilter = \ 902 VulkanAPI(API_PREFIX_RESERVEDUNMARSHAL + name, 903 STREAM_RET_TYPE, 904 self.marshalingParams + [makeVulkanTypeSimple(False, name, 1, UNMARSHAL_INPUT_VAR_NAME), self.ptrVarTypeUnmarshal]) 905 906 def structUnmarshalingCustom(cgen): 907 self.readCodegen.cgen = cgen 908 self.readCodegen.currentStructInfo = structInfo 909 unmarshalingCode = \ 910 CUSTOM_MARSHAL_TYPES[name]["common"] + \ 911 CUSTOM_MARSHAL_TYPES[name]["reservedunmarshaling"].format( 912 streamVarName=self.readCodegen.streamVarName, 913 rootTypeVarName=self.readCodegen.rootTypeVarName, 914 inputVarName=self.readCodegen.inputVarName, 915 newInputVarName=self.readCodegen.inputVarName + "_new") 916 for line in unmarshalingCode.split('\n'): 917 cgen.line(line) 918 919 def structUnmarshalingDef(cgen): 920 self.readCodegen.cgen = cgen 921 self.readCodegen.currentStructInfo = structInfo 922 if category == "struct": 923 # unmarshal 'let' parameters first 924 for letp in letParams: 925 self.readCodegen.streamLetParameter(self.typeInfo, letp) 926 927 for member in structInfo.members: 928 iterateVulkanType(self.typeInfo, member, self.readCodegen) 929 if category == "union": 930 iterateVulkanType(self.typeInfo, structInfo.members[0], self.readCodegen) 931 932 def structUnmarshalingDefNoFilter(cgen): 933 self.readCodegen.cgen = cgen 934 self.readCodegen.currentStructInfo = structInfo 935 self.readCodegen.doFiltering = False 936 if category == "struct": 937 # unmarshal 'let' parameters first 938 for letp in letParams: 939 iterateVulkanType(self.typeInfo, letp, self.readCodegen) 940 for member in structInfo.members: 941 iterateVulkanType(self.typeInfo, member, self.readCodegen) 942 if category == "union": 943 iterateVulkanType(self.typeInfo, structInfo.members[0], self.readCodegen) 944 self.readCodegen.doFiltering = True 945 946 if self.variant != "guest": 947 self.module.appendHeader( 948 self.cgenHeader.makeFuncDecl(unmarshalPrototype)) 949 950 if name in CUSTOM_MARSHAL_TYPES: 951 self.module.appendImpl( 952 self.cgenImpl.makeFuncImpl( 953 unmarshalPrototype, structUnmarshalingCustom)) 954 else: 955 self.module.appendImpl( 956 self.cgenImpl.makeFuncImpl( 957 unmarshalPrototype, structUnmarshalingDef)) 958 959 if freeParams != []: 960 self.module.appendHeader( 961 self.cgenHeader.makeFuncDecl(unmarshalPrototypeNoFilter)) 962 self.module.appendImpl( 963 self.cgenImpl.makeFuncImpl( 964 unmarshalPrototypeNoFilter, structUnmarshalingDefNoFilter)) 965 966 def onGenCmd(self, cmdinfo, name, alias): 967 VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias) 968 969 def doExtensionStructMarshalingCodegen(self, cgen, retType, extParam, forEach, funcproto, direction): 970 accessVar = "structAccess" 971 sizeVar = "currExtSize" 972 cgen.stmt("VkInstanceCreateInfo* %s = (VkInstanceCreateInfo*)(%s)" % (accessVar, extParam.paramName)) 973 cgen.stmt("uint32_t %s = %s(%s->getFeatureBits(), %s, %s)" % (sizeVar, EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME, VULKAN_STREAM_VAR_NAME, ROOT_TYPE_VAR_NAME, extParam.paramName)) 974 975 cgen.beginIf("!%s && %s" % (sizeVar, extParam.paramName)) 976 977 cgen.line("// unknown struct extension; skip and call on its pNext field"); 978 cgen.funcCall(None, funcproto.name, ["vkStream", ROOT_TYPE_VAR_NAME, "(void*)%s->pNext" % accessVar, self.ptrVarName]) 979 cgen.stmt("return") 980 981 cgen.endIf() 982 cgen.beginElse() 983 984 cgen.line("// known or null extension struct") 985 986 if direction == "write": 987 cgen.stmt("memcpy(*%s, &%s, sizeof(uint32_t));" % (self.ptrVarName, sizeVar)) 988 cgen.stmt("android::base::Stream::toBe32((uint8_t*)*%s); *%s += sizeof(uint32_t)" % (self.ptrVarName, self.ptrVarName)) 989 elif not self.dynAlloc: 990 cgen.stmt("memcpy(&%s, *%s, sizeof(uint32_t));" % (sizeVar, self.ptrVarName)) 991 cgen.stmt("android::base::Stream::fromBe32((uint8_t*)&%s); *%s += sizeof(uint32_t)" % (sizeVar, self.ptrVarName)) 992 993 cgen.beginIf("!%s" % (sizeVar)) 994 cgen.line("// exit if this was a null extension struct (size == 0 in this branch)") 995 cgen.stmt("return") 996 cgen.endIf() 997 998 cgen.endIf() 999 1000 # Now we can do stream stuff 1001 if direction == "write": 1002 cgen.stmt("memcpy(*%s, %s, sizeof(VkStructureType)); *%s += sizeof(VkStructureType)" % (self.ptrVarName, extParam.paramName, self.ptrVarName)) 1003 elif not self.dynAlloc: 1004 cgen.stmt("uint64_t pNext_placeholder") 1005 placeholderAccess = "(&pNext_placeholder)" 1006 cgen.stmt("memcpy(%s, *%s, sizeof(VkStructureType)); *%s += sizeof(VkStructureType)" % (placeholderAccess, self.ptrVarName, self.ptrVarName)) 1007 cgen.stmt("(void)pNext_placeholder") 1008 1009 def fatalDefault(cgen): 1010 cgen.line("// fatal; the switch is only taken if the extension struct is known"); 1011 cgen.stmt("abort()") 1012 pass 1013 1014 self.emitForEachStructExtension( 1015 cgen, 1016 retType, 1017 extParam, 1018 forEach, 1019 defaultEmit=fatalDefault, 1020 rootTypeVar=ROOT_TYPE_PARAM) 1021 1022 def onEnd(self,): 1023 VulkanWrapperGenerator.onEnd(self) 1024 1025 def forEachExtensionMarshal(ext, castedAccess, cgen): 1026 cgen.funcCall(None, API_PREFIX_RESERVEDMARSHAL + ext.name, 1027 [VULKAN_STREAM_VAR_NAME, ROOT_TYPE_VAR_NAME, castedAccess, self.ptrVarName]) 1028 1029 def forEachExtensionUnmarshal(ext, castedAccess, cgen): 1030 cgen.funcCall(None, API_PREFIX_RESERVEDUNMARSHAL + ext.name, 1031 [VULKAN_STREAM_VAR_NAME, ROOT_TYPE_VAR_NAME, castedAccess, self.ptrVarName]) 1032 1033 if self.variant != "host": 1034 self.module.appendImpl( 1035 self.cgenImpl.makeFuncImpl( 1036 self.extensionMarshalPrototype, 1037 lambda cgen: self.doExtensionStructMarshalingCodegen( 1038 cgen, 1039 STREAM_RET_TYPE, 1040 STRUCT_EXTENSION_PARAM, 1041 forEachExtensionMarshal, 1042 self.extensionMarshalPrototype, 1043 "write"))) 1044 1045 if self.variant != "guest": 1046 self.module.appendImpl( 1047 self.cgenImpl.makeFuncImpl( 1048 self.extensionUnmarshalPrototype, 1049 lambda cgen: self.doExtensionStructMarshalingCodegen( 1050 cgen, 1051 STREAM_RET_TYPE, 1052 STRUCT_EXTENSION_PARAM_FOR_WRITE, 1053 forEachExtensionUnmarshal, 1054 self.extensionUnmarshalPrototype, 1055 "read"))) 1056