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