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