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