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