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