1import copy 2 3from .common.codegen import CodeGen, VulkanWrapperGenerator 4from .common.vulkantypes import \ 5 VulkanAPI, makeVulkanTypeSimple, iterateVulkanType 6 7from .marshaling import VulkanMarshalingCodegen 8from .reservedmarshaling import VulkanReservedMarshalingCodegen 9from .counting import VulkanCountingCodegen 10from .handlemap import HandleMapCodegen 11from .deepcopy import DeepcopyCodegen 12from .transform import TransformCodegen, genTransformsForVulkanType 13 14from .wrapperdefs import API_PREFIX_RESERVEDMARSHAL 15from .wrapperdefs import API_PREFIX_MARSHAL 16from .wrapperdefs import API_PREFIX_UNMARSHAL 17from .wrapperdefs import ROOT_TYPE_DEFAULT_VALUE 18from .wrapperdefs import VULKAN_STREAM_TYPE_GUEST 19 20encoder_decl_preamble = """ 21 22class VkEncoder { 23public: 24 VkEncoder(gfxstream::guest::IOStream* stream, gfxstream::guest::HealthMonitor<>* healthMonitor = nullptr); 25 ~VkEncoder(); 26 27#include "VkEncoder.h.inl" 28""" 29 30encoder_decl_postamble = """ 31private: 32 class Impl; 33 std::unique_ptr<Impl> mImpl; 34 gfxstream::guest::HealthMonitor<>* mHealthMonitor; 35}; 36""" 37 38encoder_impl_preamble =""" 39 40using namespace gfxstream::vk; 41 42using gfxstream::guest::AutoLock; 43using gfxstream::guest::Lock; 44using gfxstream::guest::BumpPool; 45 46#include "VkEncoder.cpp.inl" 47 48#define VALIDATE_RET(retType, success, validate) \\ 49 retType goldfish_vk_validateResult = validate; \\ 50 if (goldfish_vk_validateResult != success) return goldfish_vk_validateResult; \\ 51 52#define VALIDATE_VOID(validate) \\ 53 VkResult goldfish_vk_validateResult = validate; \\ 54 if (goldfish_vk_validateResult != VK_SUCCESS) return; \\ 55 56""" 57 58STREAM = "stream" 59RESOURCES = "sResourceTracker" 60POOL = "pool" 61 62ENCODER_PREVALIDATED_APIS = [ 63 "vkFlushMappedMemoryRanges", 64 "vkInvalidateMappedMemoryRanges", 65] 66 67ENCODER_CUSTOM_RESOURCE_PREPROCESS = [ 68 "vkMapMemoryIntoAddressSpaceGOOGLE", 69 "vkDestroyDevice", 70] 71 72ENCODER_CUSTOM_RESOURCE_POSTPROCESS = [ 73 "vkCreateInstance", 74 "vkCreateDevice", 75 "vkMapMemoryIntoAddressSpaceGOOGLE", 76 "vkGetPhysicalDeviceFeatures2", 77 "vkGetPhysicalDeviceFeatures2KHR", 78 "vkGetPhysicalDeviceProperties", 79 "vkGetPhysicalDeviceProperties2", 80 "vkGetPhysicalDeviceProperties2KHR", 81 "vkCreateDescriptorUpdateTemplate", 82 "vkCreateDescriptorUpdateTemplateKHR", 83 "vkGetPhysicalDeviceExternalSemaphoreProperties", 84 "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR", 85 "vkGetDeviceQueue", 86 "vkGetDeviceQueue2", 87] 88 89ENCODER_EXPLICIT_FLUSHED_APIS = [ 90 "vkEndCommandBufferAsyncGOOGLE", 91 "vkQueueSubmitAsyncGOOGLE", 92 "vkQueueBindSparseAsyncGOOGLE", 93 "vkQueueWaitIdleAsyncGOOGLE", 94 "vkQueueSignalReleaseImageANDROID", 95 "vkDestroyDevice", 96] 97 98SUCCESS_RET_TYPES = { 99 "VkResult" : "VK_SUCCESS", 100 "void" : None, 101 # TODO: Put up success results for other return types here. 102} 103 104ENCODER_THIS_PARAM = makeVulkanTypeSimple(False, "VkEncoder", 1, "this") 105 106# Common components of encoding a Vulkan API call 107def make_event_handler_call( 108 handler_access, 109 api, 110 context_param, 111 input_result_param, 112 cgen, 113 suffix=""): 114 extraParams = [context_param.paramName] 115 if input_result_param: 116 extraParams.append(input_result_param) 117 return cgen.makeCallExpr( \ 118 "%s->on_%s%s" % (handler_access, api.name, suffix), 119 extraParams + \ 120 [p.paramName for p in api.parameters[:-1]]) 121 122def emit_custom_pre_validate(typeInfo, api, cgen): 123 if api.name in ENCODER_PREVALIDATED_APIS: 124 callExpr = \ 125 make_event_handler_call( \ 126 "mImpl->validation()", api, 127 ENCODER_THIS_PARAM, 128 SUCCESS_RET_TYPES[api.getRetTypeExpr()], 129 cgen) 130 131 if api.getRetTypeExpr() == "void": 132 cgen.stmt("VALIDATE_VOID(%s)" % callExpr) 133 else: 134 cgen.stmt("VALIDATE_RET(%s, %s, %s)" % \ 135 (api.getRetTypeExpr(), 136 SUCCESS_RET_TYPES[api.getRetTypeExpr()], 137 callExpr)) 138 139def emit_custom_resource_preprocess(typeInfo, api, cgen): 140 if api.name in ENCODER_CUSTOM_RESOURCE_PREPROCESS: 141 cgen.stmt( \ 142 make_event_handler_call( \ 143 "sResourceTracker", api, 144 ENCODER_THIS_PARAM, 145 SUCCESS_RET_TYPES[api.getRetTypeExpr()], 146 cgen, suffix="_pre")) 147 148def emit_custom_resource_postprocess(typeInfo, api, cgen): 149 if api.name in ENCODER_CUSTOM_RESOURCE_POSTPROCESS: 150 cgen.stmt(make_event_handler_call( \ 151 "sResourceTracker", 152 api, 153 ENCODER_THIS_PARAM, 154 api.getRetVarExpr(), 155 cgen)) 156 157def emit_count_marshal(typeInfo, param, cgen): 158 res = \ 159 iterateVulkanType( 160 typeInfo, param, 161 VulkanCountingCodegen( \ 162 cgen, "sFeatureBits", param.paramName, "countPtr", ROOT_TYPE_DEFAULT_VALUE, 163 "count_")) 164 if not res: 165 cgen.stmt("(void)%s" % param.paramName) 166 167def emit_marshal(typeInfo, param, cgen): 168 forOutput = param.isHandleType() and ("out" in param.inout) 169 if forOutput: 170 cgen.stmt("/* is handle, possibly out */") 171 172 res = \ 173 iterateVulkanType( 174 typeInfo, param, 175 VulkanReservedMarshalingCodegen( \ 176 cgen, "guest", STREAM, ROOT_TYPE_DEFAULT_VALUE, param.paramName, "streamPtrPtr", 177 API_PREFIX_RESERVEDMARSHAL, 178 "" if forOutput else "get_host_u64_", 179 direction="write")) 180 if not res: 181 cgen.stmt("(void)%s" % param.paramName) 182 183 if forOutput: 184 cgen.stmt("/* is handle, possibly out */") 185 186def emit_unmarshal(typeInfo, param, cgen): 187 iterateVulkanType( 188 typeInfo, param, 189 VulkanMarshalingCodegen( \ 190 cgen, STREAM, ROOT_TYPE_DEFAULT_VALUE, param.paramName, 191 API_PREFIX_UNMARSHAL, direction="read")) 192 193def emit_deepcopy(typeInfo, param, cgen): 194 res = \ 195 iterateVulkanType(typeInfo, param, DeepcopyCodegen( 196 cgen, [param.paramName, "local_" + param.paramName], "pool", ROOT_TYPE_DEFAULT_VALUE, "deepcopy_")) 197 if not res: 198 cgen.stmt("(void)%s" % param.paramName) 199 200def emit_transform(typeInfo, param, cgen, variant="tohost"): 201 res = \ 202 iterateVulkanType(typeInfo, param, TransformCodegen( \ 203 cgen, param.paramName, "sResourceTracker", "transform_%s_" % variant, variant)) 204 if not res: 205 cgen.stmt("(void)%s" % param.paramName) 206 207def emit_handlemap_create(typeInfo, param, cgen): 208 iterateVulkanType(typeInfo, param, HandleMapCodegen( 209 cgen, None, "sResourceTracker", "handlemap_", 210 lambda vtype: typeInfo.isHandleType(vtype.typeName) 211 )) 212 213def custom_encoder_args(api): 214 params = ["this"] 215 if api.getRetVarExpr() is not None: 216 params.append(api.getRetVarExpr()) 217 return params 218 219def emit_handlemap_destroy(typeInfo, param, cgen): 220 iterateVulkanType(typeInfo, param, HandleMapCodegen( 221 cgen, None, "sResourceTracker->destroyMapping()", "handlemap_", 222 lambda vtype: typeInfo.isHandleType(vtype.typeName) 223 )) 224 225class EncodingParameters(object): 226 def __init__(self, api): 227 self.localCopied = [] 228 self.toWrite = [] 229 self.toRead = [] 230 self.toCreate = [] 231 self.toDestroy = [] 232 233 for param in api.parameters: 234 param.action = None 235 param.inout = "in" 236 237 if param.paramName == "doLock": 238 continue 239 240 if param.possiblyOutput(): 241 param.inout += "out" 242 self.toWrite.append(param) 243 self.toRead.append(param) 244 if param.isCreatedBy(api): 245 self.toCreate.append(param) 246 param.action = "create" 247 else: 248 249 if param.paramName == "doLock": 250 continue 251 252 if param.isDestroyedBy(api): 253 self.toDestroy.append(param) 254 param.action = "destroy" 255 localCopyParam = \ 256 param.getForNonConstAccess().withModifiedName( \ 257 "local_" + param.paramName) 258 self.localCopied.append((param, localCopyParam)) 259 self.toWrite.append(localCopyParam) 260 261def emit_parameter_encode_preamble_write(typeInfo, api, cgen): 262 emit_custom_pre_validate(typeInfo, api, cgen); 263 emit_custom_resource_preprocess(typeInfo, api, cgen); 264 265 cgen.stmt("auto %s = mImpl->stream()" % STREAM) 266 cgen.stmt("auto %s = mImpl->pool()" % POOL) 267 # cgen.stmt("%s->setHandleMapping(%s->unwrapMapping())" % (STREAM, RESOURCES)) 268 269 encodingParams = EncodingParameters(api) 270 for (_, localCopyParam) in encodingParams.localCopied: 271 cgen.stmt(cgen.makeRichCTypeDecl(localCopyParam)) 272 273def emit_parameter_encode_copy_unwrap_count(typeInfo, api, cgen, customUnwrap=None): 274 encodingParams = EncodingParameters(api) 275 276 for (origParam, localCopyParam) in encodingParams.localCopied: 277 shouldCustomCopy = \ 278 customUnwrap and \ 279 origParam.paramName in customUnwrap and \ 280 "copyOp" in customUnwrap[origParam.paramName] 281 282 shouldCustomMap = \ 283 customUnwrap and \ 284 origParam.paramName in customUnwrap and \ 285 "mapOp" in customUnwrap[origParam.paramName] 286 287 if shouldCustomCopy: 288 customUnwrap[origParam.paramName]["copyOp"](cgen, origParam, localCopyParam) 289 else: 290 # if this is a pointer type and we don't do custom copy nor unwrap, 291 # and the transform doesn't end up doing anything, 292 # don't deepcopy, just cast it. 293 294 avoidDeepcopy = False 295 296 if origParam.pointerIndirectionLevels > 0: 297 testCgen = CodeGen() 298 genTransformsForVulkanType("sResourceTracker", origParam, lambda p: testCgen.generalAccess(p, parentVarName = None, asPtr = True), lambda p: testCgen.generalLengthAccess(p, parentVarName = None), testCgen) 299 emit_transform(typeInfo, origParam, testCgen, variant="tohost") 300 if "" == testCgen.swapCode(): 301 avoidDeepcopy = True 302 if avoidDeepcopy: 303 cgen.line("// Avoiding deepcopy for %s" % origParam.paramName) 304 cgen.stmt("%s = (%s%s)%s" % (localCopyParam.paramName, localCopyParam.typeName, "*" * origParam.pointerIndirectionLevels, origParam.paramName)) 305 else: 306 emit_deepcopy(typeInfo, origParam, cgen) 307 308 for (origParam, localCopyParam) in encodingParams.localCopied: 309 shouldCustomMap = \ 310 customUnwrap and \ 311 origParam.paramName in customUnwrap and \ 312 "mapOp" in customUnwrap[origParam.paramName] 313 314 if shouldCustomMap: 315 customUnwrap[origParam.paramName]["mapOp"](cgen, origParam, localCopyParam) 316 else: 317 if localCopyParam.typeName == "VkAllocationCallbacks": 318 cgen.stmt("%s = nullptr" % localCopyParam.paramName) 319 320 apiForTransform = \ 321 api.withCustomParameters( \ 322 map(lambda p: p[1], \ 323 encodingParams.localCopied)) 324 325 # Apply transforms if applicable. 326 # Apply transform to API itself: 327 genTransformsForVulkanType( 328 "sResourceTracker", 329 apiForTransform, 330 lambda p: cgen.generalAccess(p, parentVarName = None, asPtr = True), 331 lambda p: cgen.generalLengthAccess(p, parentVarName = None), 332 cgen) 333 334 # For all local copied parameters, run the transforms 335 for localParam in apiForTransform.parameters: 336 if "doLock" in localParam.paramName: 337 continue 338 emit_transform(typeInfo, localParam, cgen, variant="tohost") 339 340 cgen.stmt("size_t count = 0") 341 cgen.stmt("size_t* countPtr = &count") 342 cgen.beginBlock() 343 344 # Use counting stream to calculate the packet size. 345 for p in encodingParams.toWrite: 346 emit_count_marshal(typeInfo, p, cgen) 347 348 cgen.endBlock() 349 350def is_cmdbuf_dispatch(api): 351 return "VkCommandBuffer" == api.parameters[0].typeName 352 353def emit_parameter_encode_write_packet_info(typeInfo, api, cgen): 354 # Seqno and skipping dispatch serialize are for use with VULKAN_STREAM_FEATURE_QUEUE_SUBMIT_WITH_COMMANDS_BIT 355 doSeqno = True 356 doDispatchSerialize = True 357 358 if is_cmdbuf_dispatch(api): 359 doSeqno = False 360 doDispatchSerialize = False 361 362 if doSeqno: 363 cgen.stmt("uint32_t packetSize_%s = 4 + 4 + (queueSubmitWithCommandsEnabled ? 4 : 0) + count" % (api.name)) 364 else: 365 cgen.stmt("uint32_t packetSize_%s = 4 + 4 + count" % (api.name)) 366 cgen.stmt("healthMonitorAnnotation_packetSize = std::make_optional(packetSize_%s)" % (api.name)) 367 368 if not doDispatchSerialize: 369 cgen.stmt("if (queueSubmitWithCommandsEnabled) packetSize_%s -= 8" % api.name) 370 371 cgen.stmt("uint8_t* streamPtr = %s->reserve(packetSize_%s)" % (STREAM, api.name)) 372 cgen.stmt("uint8_t* packetBeginPtr = streamPtr") 373 cgen.stmt("uint8_t** streamPtrPtr = &streamPtr") 374 cgen.stmt("uint32_t opcode_%s = OP_%s" % (api.name, api.name)) 375 376 if doSeqno: 377 cgen.stmt("uint32_t seqno; if (queueSubmitWithCommandsEnabled) seqno = ResourceTracker::nextSeqno()") 378 cgen.stmt("healthMonitorAnnotation_seqno = std::make_optional(seqno)") 379 380 cgen.stmt("memcpy(streamPtr, &opcode_%s, sizeof(uint32_t)); streamPtr += sizeof(uint32_t)" % api.name) 381 cgen.stmt("memcpy(streamPtr, &packetSize_%s, sizeof(uint32_t)); streamPtr += sizeof(uint32_t)" % api.name) 382 383 if doSeqno: 384 cgen.line("if (queueSubmitWithCommandsEnabled) { memcpy(streamPtr, &seqno, sizeof(uint32_t)); streamPtr += sizeof(uint32_t); }") 385 386def emit_parameter_encode_do_parameter_write(typeInfo, api, cgen): 387 encodingParams = EncodingParameters(api) 388 389 dispatchDone = False 390 391 for p in encodingParams.toWrite: 392 if is_cmdbuf_dispatch(api) and not dispatchDone: 393 cgen.beginIf("!queueSubmitWithCommandsEnabled") 394 emit_marshal(typeInfo, p, cgen) 395 cgen.endIf() 396 else: 397 emit_marshal(typeInfo, p, cgen) 398 399 dispatchDone = True 400 401 cgen.beginIf("watchdog") 402 cgen.stmt("size_t watchdogBufSize = std::min<size_t>(static_cast<size_t>(packetSize_%s), kWatchdogBufferMax)" % (api.name)) 403 cgen.stmt("healthMonitorAnnotation_packetContents.resize(watchdogBufSize)") 404 cgen.stmt("memcpy(&healthMonitorAnnotation_packetContents[0], packetBeginPtr, watchdogBufSize)") 405 cgen.endIf() 406 407def emit_parameter_encode_read(typeInfo, api, cgen): 408 encodingParams = EncodingParameters(api) 409 410 for p in encodingParams.toRead: 411 if p.action == "create": 412 cgen.stmt( 413 "%s->setHandleMapping(%s->createMapping())" % \ 414 (STREAM, RESOURCES)) 415 emit_unmarshal(typeInfo, p, cgen) 416 if p.action == "create": 417 cgen.stmt( 418 "%s->unsetHandleMapping()" % STREAM) 419 emit_transform(typeInfo, p, cgen, variant="fromhost") 420 421def emit_post(typeInfo, api, cgen): 422 encodingParams = EncodingParameters(api) 423 424 emit_custom_resource_postprocess(typeInfo, api, cgen) 425 426 for p in encodingParams.toDestroy: 427 emit_handlemap_destroy(typeInfo, p, cgen) 428 429 doSeqno = True 430 if is_cmdbuf_dispatch(api): 431 doSeqno = False 432 433 retType = api.getRetTypeExpr() 434 435 if api.name in ENCODER_EXPLICIT_FLUSHED_APIS: 436 cgen.stmt("stream->flush()"); 437 return 438 439 if doSeqno: 440 if retType == "void": 441 encodingParams = EncodingParameters(api) 442 if 0 == len(encodingParams.toRead): 443 cgen.stmt("stream->flush()"); 444 445def emit_pool_free(cgen): 446 cgen.stmt("++encodeCount") 447 cgen.beginIf("0 == encodeCount % POOL_CLEAR_INTERVAL") 448 cgen.stmt("pool->freeAll()") 449 cgen.stmt("%s->clearPool()" % STREAM) 450 cgen.endIf() 451 452def emit_return_unmarshal(typeInfo, api, cgen): 453 454 retType = api.getRetTypeExpr() 455 456 if retType == "void": 457 return 458 459 retVar = api.getRetVarExpr() 460 cgen.stmt("%s %s = (%s)0" % (retType, retVar, retType)) 461 cgen.stmt("%s->read(&%s, %s)" % \ 462 (STREAM, retVar, cgen.sizeofExpr(api.retType))) 463 464def emit_return(typeInfo, api, cgen): 465 if api.getRetTypeExpr() == "void": 466 return 467 468 retVar = api.getRetVarExpr() 469 cgen.stmt("return %s" % retVar) 470 471def emit_lock(cgen): 472 cgen.stmt("(void)doLock"); 473 cgen.stmt("bool queueSubmitWithCommandsEnabled = sFeatureBits & VULKAN_STREAM_FEATURE_QUEUE_SUBMIT_WITH_COMMANDS_BIT") 474 cgen.stmt("if (!queueSubmitWithCommandsEnabled && doLock) this->lock()") 475 476def emit_unlock(cgen): 477 cgen.stmt("if (!queueSubmitWithCommandsEnabled && doLock) this->unlock()") 478 479def emit_debug_log(typeInfo, api, cgen): 480 logFormat = [] 481 logVargs = [] 482 for param in api.parameters: 483 if param.paramName == "doLock": 484 continue 485 486 paramFormatSpecifier = param.getPrintFormatSpecifier() 487 if not paramFormatSpecifier: 488 continue 489 490 logFormat.append(param.paramName + ":" + paramFormatSpecifier) 491 logVargs.append(param.paramName) 492 493 logFormatStr = ", ".join(logFormat) 494 logVargsStr = ", ".join(logVargs) 495 496 cgen.stmt("ENCODER_DEBUG_LOG(\"%s(%s)\", %s)" % (api.name, logFormatStr, logVargsStr)) 497 498def emit_health_watchdog(api, cgen): 499 cgen.stmt("std::optional<uint32_t> healthMonitorAnnotation_seqno = std::nullopt") 500 cgen.stmt("std::optional<uint32_t> healthMonitorAnnotation_packetSize = std::nullopt") 501 cgen.stmt("std::vector<uint8_t> healthMonitorAnnotation_packetContents") 502 cgen.line(""" 503 auto watchdog = WATCHDOG_BUILDER(mHealthMonitor, \"%s in VkEncoder\") 504 .setOnHangCallback([&]() { 505 auto annotations = std::make_unique<EventHangMetadata::HangAnnotations>(); 506 if (healthMonitorAnnotation_seqno) { 507 annotations->insert({{"seqno", std::to_string(healthMonitorAnnotation_seqno.value())}}); 508 } 509 if (healthMonitorAnnotation_packetSize) { 510 annotations->insert({{"packetSize", std::to_string(healthMonitorAnnotation_packetSize.value())}}); 511 } 512 if (!healthMonitorAnnotation_packetContents.empty()) { 513 annotations->insert( 514 {{"packetContents", getPacketContents( 515 &healthMonitorAnnotation_packetContents[0], healthMonitorAnnotation_packetContents.size())}}); 516 } 517 return std::move(annotations); 518 }) 519 .build(); 520 """% (api.name) 521 ) 522 523def emit_default_encoding(typeInfo, api, cgen): 524 emit_debug_log(typeInfo, api, cgen) 525 emit_lock(cgen) 526 emit_parameter_encode_preamble_write(typeInfo, api, cgen) 527 emit_parameter_encode_copy_unwrap_count(typeInfo, api, cgen) 528 emit_parameter_encode_write_packet_info(typeInfo, api, cgen) 529 emit_parameter_encode_do_parameter_write(typeInfo, api, cgen) 530 emit_parameter_encode_read(typeInfo, api, cgen) 531 emit_return_unmarshal(typeInfo, api, cgen) 532 emit_post(typeInfo, api, cgen) 533 emit_pool_free(cgen) 534 emit_unlock(cgen) 535 emit_return(typeInfo, api, cgen) 536 537## Custom encoding definitions################################################## 538 539def emit_only_goldfish_custom(typeInfo, api, cgen): 540 emit_lock(cgen) 541 cgen.vkApiCall( \ 542 api, 543 customPrefix="sResourceTracker->on_", 544 customParameters=custom_encoder_args(api) + \ 545 [p.paramName for p in api.parameters[:-1]]) 546 emit_unlock(cgen) 547 emit_return(typeInfo, api, cgen) 548 549def emit_only_resource_event(typeInfo, api, cgen): 550 cgen.stmt("(void)doLock"); 551 input_result = None 552 retExpr = api.getRetVarExpr() 553 554 if retExpr: 555 retType = api.getRetTypeExpr() 556 input_result = SUCCESS_RET_TYPES[retType] 557 cgen.stmt("%s %s = (%s)0" % (retType, retExpr, retType)) 558 559 cgen.stmt( 560 (("%s = " % retExpr) if retExpr else "") + 561 make_event_handler_call( 562 "sResourceTracker", 563 api, 564 ENCODER_THIS_PARAM, 565 input_result, cgen)) 566 567 if retExpr: 568 emit_return(typeInfo, api, cgen) 569 570def emit_with_custom_unwrap(custom): 571 def call(typeInfo, api, cgen): 572 emit_lock(cgen) 573 emit_parameter_encode_preamble_write(typeInfo, api, cgen) 574 emit_parameter_encode_copy_unwrap_count( 575 typeInfo, api, cgen, customUnwrap=custom) 576 emit_parameter_encode_write_packet_info(typeInfo, api, cgen) 577 emit_parameter_encode_do_parameter_write(typeInfo, api, cgen) 578 emit_parameter_encode_read(typeInfo, api, cgen) 579 emit_return_unmarshal(typeInfo, api, cgen) 580 emit_pool_free(cgen) 581 emit_unlock(cgen) 582 emit_return(typeInfo, api, cgen) 583 return call 584 585def encode_vkFlushMappedMemoryRanges(typeInfo, api, cgen): 586 emit_lock(cgen) 587 emit_parameter_encode_preamble_write(typeInfo, api, cgen) 588 emit_parameter_encode_copy_unwrap_count(typeInfo, api, cgen) 589 590 def emit_flush_ranges(streamVar): 591 cgen.beginIf("!sResourceTracker->usingDirectMapping()") 592 cgen.beginFor("uint32_t i = 0", "i < memoryRangeCount", "++i") 593 cgen.stmt("auto range = pMemoryRanges[i]") 594 cgen.stmt("auto memory = pMemoryRanges[i].memory") 595 cgen.stmt("auto size = pMemoryRanges[i].size") 596 cgen.stmt("auto offset = pMemoryRanges[i].offset") 597 cgen.stmt("uint64_t streamSize = 0") 598 cgen.stmt("if (!memory) { %s->write(&streamSize, sizeof(uint64_t)); continue; }" % streamVar) 599 cgen.stmt("auto hostPtr = sResourceTracker->getMappedPointer(memory)") 600 cgen.stmt("auto actualSize = size == VK_WHOLE_SIZE ? sResourceTracker->getMappedSize(memory) : size") 601 cgen.stmt("if (!hostPtr) { %s->write(&streamSize, sizeof(uint64_t)); continue; }" % streamVar) 602 cgen.stmt("streamSize = actualSize") 603 cgen.stmt("%s->write(&streamSize, sizeof(uint64_t))" % streamVar) 604 cgen.stmt("uint8_t* targetRange = hostPtr + offset") 605 cgen.stmt("%s->write(targetRange, actualSize)" % streamVar) 606 cgen.endFor() 607 cgen.endIf() 608 609 emit_parameter_encode_write_packet_info(typeInfo, api, cgen) 610 emit_parameter_encode_do_parameter_write(typeInfo, api, cgen) 611 612 emit_flush_ranges(STREAM) 613 614 emit_parameter_encode_read(typeInfo, api, cgen) 615 emit_return_unmarshal(typeInfo, api, cgen) 616 emit_pool_free(cgen) 617 emit_unlock(cgen) 618 emit_return(typeInfo, api, cgen) 619 620def encode_vkInvalidateMappedMemoryRanges(typeInfo, api, cgen): 621 emit_lock(cgen) 622 emit_parameter_encode_preamble_write(typeInfo, api, cgen) 623 emit_parameter_encode_copy_unwrap_count(typeInfo, api, cgen) 624 emit_parameter_encode_write_packet_info(typeInfo, api, cgen) 625 emit_parameter_encode_do_parameter_write(typeInfo, api, cgen) 626 emit_parameter_encode_read(typeInfo, api, cgen) 627 emit_return_unmarshal(typeInfo, api, cgen) 628 629 def emit_invalidate_ranges(streamVar): 630 cgen.beginIf("!sResourceTracker->usingDirectMapping()") 631 cgen.beginFor("uint32_t i = 0", "i < memoryRangeCount", "++i") 632 cgen.stmt("auto range = pMemoryRanges[i]") 633 cgen.stmt("auto memory = pMemoryRanges[i].memory") 634 cgen.stmt("auto size = pMemoryRanges[i].size") 635 cgen.stmt("auto offset = pMemoryRanges[i].offset") 636 cgen.stmt("uint64_t streamSize = 0") 637 cgen.stmt("if (!memory) { %s->read(&streamSize, sizeof(uint64_t)); continue; }" % streamVar) 638 cgen.stmt("auto hostPtr = sResourceTracker->getMappedPointer(memory)") 639 cgen.stmt("auto actualSize = size == VK_WHOLE_SIZE ? sResourceTracker->getMappedSize(memory) : size") 640 cgen.stmt("if (!hostPtr) { %s->read(&streamSize, sizeof(uint64_t)); continue; }" % streamVar) 641 cgen.stmt("streamSize = actualSize") 642 cgen.stmt("%s->read(&streamSize, sizeof(uint64_t))" % streamVar) 643 cgen.stmt("uint8_t* targetRange = hostPtr + offset") 644 cgen.stmt("%s->read(targetRange, actualSize)" % streamVar) 645 cgen.endFor() 646 cgen.endIf() 647 648 emit_invalidate_ranges(STREAM) 649 emit_pool_free(cgen) 650 emit_unlock(cgen) 651 emit_return(typeInfo, api, cgen) 652 653def emit_manual_inline(typeInfo, api, cgen): 654 cgen.line("#include \"%s_encode_impl.cpp.inl\"" % api.name) 655 656def unwrap_vkCreateImage_pCreateInfo(): 657 def mapOp(cgen, orig, local): 658 cgen.stmt("sResourceTracker->unwrap_vkCreateImage_pCreateInfo(%s, %s)" % 659 (orig.paramName, local.paramName)) 660 return { "pCreateInfo" : { "mapOp" : mapOp } } 661 662def unwrap_vkBindImageMemory2_pBindInfos(): 663 def mapOp(cgen, orig, local): 664 cgen.stmt("sResourceTracker->unwrap_VkBindImageMemory2_pBindInfos(bindInfoCount, %s, %s)" % 665 (orig.paramName, local.paramName)) 666 return { "pBindInfos" : { "mapOp" : mapOp } } 667 668def unwrap_vkAcquireImageANDROID_nativeFenceFd(): 669 def mapOp(cgen, orig, local): 670 cgen.stmt("sResourceTracker->unwrap_vkAcquireImageANDROID_nativeFenceFd(%s, &%s)" % 671 (orig.paramName, local.paramName)) 672 return { "nativeFenceFd" : { "mapOp" : mapOp } } 673 674custom_encodes = { 675 "vkMapMemory" : emit_only_resource_event, 676 "vkUnmapMemory" : emit_only_resource_event, 677 "vkFlushMappedMemoryRanges" : encode_vkFlushMappedMemoryRanges, 678 "vkInvalidateMappedMemoryRanges" : encode_vkInvalidateMappedMemoryRanges, 679 "vkCreateImage" : emit_with_custom_unwrap(unwrap_vkCreateImage_pCreateInfo()), 680 "vkCreateImageWithRequirementsGOOGLE" : emit_with_custom_unwrap(unwrap_vkCreateImage_pCreateInfo()), 681 "vkBindImageMemory2": emit_with_custom_unwrap(unwrap_vkBindImageMemory2_pBindInfos()), 682 "vkAcquireImageANDROID" : emit_with_custom_unwrap(unwrap_vkAcquireImageANDROID_nativeFenceFd()), 683 "vkQueueFlushCommandsGOOGLE" : emit_manual_inline, 684} 685 686class VulkanEncoder(VulkanWrapperGenerator): 687 def __init__(self, module, typeInfo): 688 VulkanWrapperGenerator.__init__(self, module, typeInfo) 689 690 self.typeInfo = typeInfo 691 692 self.cgenHeader = CodeGen() 693 self.cgenHeader.incrIndent() 694 695 self.cgenImpl = CodeGen() 696 697 def onBegin(self,): 698 self.module.appendHeader(encoder_decl_preamble) 699 self.module.appendImpl(encoder_impl_preamble) 700 701 def onGenCmd(self, cmdinfo, name, alias): 702 VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias) 703 704 api = copy.deepcopy(self.typeInfo.apis[name]) 705 api.parameters.append(makeVulkanTypeSimple(False, "uint32_t", 0, "doLock")) 706 707 self.cgenHeader.stmt(self.cgenHeader.makeFuncProto(api)) 708 apiImpl = api.withModifiedName("VkEncoder::" + api.name) 709 710 self.module.appendHeader(self.cgenHeader.swapCode()) 711 712 def emit_function_impl(cgen): 713 emit_health_watchdog(api, cgen) 714 if api.name in custom_encodes.keys(): 715 custom_encodes[api.name](self.typeInfo, api, cgen) 716 else: 717 emit_default_encoding(self.typeInfo, api, cgen) 718 719 self.module.appendImpl(self.cgenImpl.makeFuncImpl(apiImpl, emit_function_impl)) 720 721 def onEnd(self,): 722 self.module.appendHeader(encoder_decl_postamble) 723 self.cgenHeader.decrIndent() 724