1# Copyright 2023 Google LLC 2# SPDX-License-Identifier: MIT 3 4from .common.codegen import CodeGen, VulkanWrapperGenerator 5from .common.vulkantypes import VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeInfo,\ 6 VulkanType 7 8from .marshaling import VulkanMarshalingCodegen 9from .reservedmarshaling import VulkanReservedMarshalingCodegen 10from .transform import TransformCodegen 11 12from .wrapperdefs import API_PREFIX_MARSHAL 13from .wrapperdefs import API_PREFIX_RESERVEDUNMARSHAL 14from .wrapperdefs import MAX_PACKET_LENGTH 15from .wrapperdefs import VULKAN_STREAM_TYPE 16from .wrapperdefs import ROOT_TYPE_DEFAULT_VALUE 17from .wrapperdefs import RELAXED_APIS 18 19 20SKIPPED_DECODER_DELETES = [ 21 "vkFreeDescriptorSets", 22] 23 24DELAYED_DECODER_DELETES = [ 25 "vkDestroyPipelineLayout", 26] 27 28DELAYED_DECODER_DELETE_DICT_ENTRIES = [ 29 "vkDestroyShaderModule", 30] 31 32global_state_prefix = "m_state->on_" 33 34decoder_decl_preamble = """ 35 36namespace gfxstream { 37class IOStream; 38} // namespace gfxstream 39 40namespace gfxstream { 41namespace vk { 42 43class VkDecoder { 44public: 45 VkDecoder(); 46 ~VkDecoder(); 47 void setForSnapshotLoad(bool forSnapshotLoad); 48 size_t decode(void* buf, size_t bufsize, IOStream* stream, 49 const ProcessResources* processResources, const VkDecoderContext&); 50private: 51 class Impl; 52 std::unique_ptr<Impl> mImpl; 53}; 54 55} // namespace vk 56} // namespace gfxstream 57 58""" 59 60decoder_impl_preamble =""" 61namespace gfxstream { 62namespace vk { 63 64using android::base::MetricEventBadPacketLength; 65using android::base::MetricEventDuplicateSequenceNum; 66 67class VkDecoder::Impl { 68public: 69 Impl() : m_logCalls(android::base::getEnvironmentVariable("ANDROID_EMU_VK_LOG_CALLS") == "1"), 70 m_vk(vkDispatch()), 71 m_state(VkDecoderGlobalState::get()), 72 m_vkStream(nullptr, m_state->getFeatures()), 73 m_vkMemReadingStream(nullptr, m_state->getFeatures()), 74 m_boxedHandleUnwrapMapping(m_state), 75 m_boxedHandleCreateMapping(m_state), 76 m_boxedHandleDestroyMapping(m_state), 77 m_boxedHandleUnwrapAndDeleteMapping(m_state), 78 m_boxedHandleUnwrapAndDeletePreserveBoxedMapping(m_state), 79 m_prevSeqno(std::nullopt), 80 m_queueSubmitWithCommandsEnabled(m_state->getFeatures().VulkanQueueSubmitWithCommands.enabled) {} 81 %s* stream() { return &m_vkStream; } 82 VulkanMemReadingStream* readStream() { return &m_vkMemReadingStream; } 83 84 void setForSnapshotLoad(bool forSnapshotLoad) { 85 m_forSnapshotLoad = forSnapshotLoad; 86 } 87 88 size_t decode(void* buf, size_t bufsize, IOStream* stream, 89 const ProcessResources* processResources, const VkDecoderContext&); 90 91private: 92 bool m_logCalls; 93 bool m_forSnapshotLoad = false; 94 VulkanDispatch* m_vk; 95 VkDecoderGlobalState* m_state; 96 %s m_vkStream; 97 VulkanMemReadingStream m_vkMemReadingStream; 98 BoxedHandleUnwrapMapping m_boxedHandleUnwrapMapping; 99 BoxedHandleCreateMapping m_boxedHandleCreateMapping; 100 BoxedHandleDestroyMapping m_boxedHandleDestroyMapping; 101 BoxedHandleUnwrapAndDeleteMapping m_boxedHandleUnwrapAndDeleteMapping; 102 android::base::BumpPool m_pool; 103 BoxedHandleUnwrapAndDeletePreserveBoxedMapping m_boxedHandleUnwrapAndDeletePreserveBoxedMapping; 104 std::optional<uint32_t> m_prevSeqno; 105 bool m_queueSubmitWithCommandsEnabled = false; 106}; 107 108VkDecoder::VkDecoder() : 109 mImpl(new VkDecoder::Impl()) { } 110 111VkDecoder::~VkDecoder() = default; 112 113void VkDecoder::setForSnapshotLoad(bool forSnapshotLoad) { 114 mImpl->setForSnapshotLoad(forSnapshotLoad); 115} 116 117size_t VkDecoder::decode(void* buf, size_t bufsize, IOStream* stream, 118 const ProcessResources* processResources, 119 const VkDecoderContext& context) { 120 return mImpl->decode(buf, bufsize, stream, processResources, context); 121} 122 123// VkDecoder::Impl::decode to follow 124""" % (VULKAN_STREAM_TYPE, VULKAN_STREAM_TYPE) 125 126decoder_impl_postamble = """ 127 128} // namespace vk 129} // namespace gfxstream 130 131""" 132 133READ_STREAM = "vkReadStream" 134WRITE_STREAM = "vkStream" 135 136# Driver workarounds for APIs that don't work well multithreaded 137driver_workarounds_global_lock_apis = [ \ 138 "vkCreatePipelineLayout", 139 "vkDestroyPipelineLayout", 140] 141 142def emit_param_decl_for_reading(param, cgen): 143 if param.staticArrExpr: 144 cgen.stmt( 145 cgen.makeRichCTypeDecl(param.getForNonConstAccess())) 146 else: 147 cgen.stmt( 148 cgen.makeRichCTypeDecl(param)) 149 150def emit_unmarshal(typeInfo, param, cgen, output = False, destroy = False, noUnbox = False): 151 if destroy: 152 iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen( 153 cgen, 154 "host", 155 READ_STREAM, 156 ROOT_TYPE_DEFAULT_VALUE, 157 param.paramName, 158 "readStreamPtrPtr", 159 API_PREFIX_RESERVEDUNMARSHAL, 160 "", 161 direction="read", 162 dynAlloc=True)) 163 lenAccess = cgen.generalLengthAccess(param) 164 lenAccessGuard = cgen.generalLengthAccessGuard(param) 165 if None == lenAccess or "1" == lenAccess: 166 cgen.stmt("boxed_%s_preserve = %s" % (param.paramName, param.paramName)) 167 cgen.stmt("%s = try_unbox_%s(%s)" % (param.paramName, param.typeName, param.paramName)) 168 else: 169 if lenAccessGuard is not None: 170 cgen.beginIf(lenAccessGuard) 171 cgen.beginFor("uint32_t i = 0", "i < %s" % lenAccess, "++i") 172 cgen.stmt("boxed_%s_preserve[i] = %s[i]" % (param.paramName, param.paramName)) 173 cgen.stmt("((%s*)(%s))[i] = try_unbox_%s(%s[i])" % (param.typeName, param.paramName, param.typeName, param.paramName)) 174 cgen.endFor() 175 if lenAccessGuard is not None: 176 cgen.endIf() 177 else: 178 if noUnbox: 179 cgen.line("// No unbox for %s" % (param.paramName)) 180 iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen( 181 cgen, 182 "host", 183 READ_STREAM, 184 ROOT_TYPE_DEFAULT_VALUE, 185 param.paramName, 186 "readStreamPtrPtr", 187 API_PREFIX_RESERVEDUNMARSHAL, 188 "" if (output or noUnbox) else "unbox_", 189 direction="read", 190 dynAlloc=True)) 191 192 193def emit_dispatch_unmarshal(typeInfo: VulkanTypeInfo, param: VulkanType, cgen, globalWrapped): 194 cgen.stmt("// Begin {} wrapped dispatchable handle unboxing for {}".format( 195 "global" if globalWrapped else "non", 196 param.paramName)) 197 198 iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen( 199 cgen, 200 "host", 201 READ_STREAM, 202 ROOT_TYPE_DEFAULT_VALUE, 203 param.paramName, 204 "readStreamPtrPtr", 205 API_PREFIX_RESERVEDUNMARSHAL, 206 "", 207 direction="read", 208 dynAlloc=True)) 209 210 if not globalWrapped: 211 cgen.stmt("auto unboxed_%s = unbox_%s(%s)" % 212 (param.paramName, param.typeName, param.paramName)) 213 cgen.stmt("auto vk = dispatch_%s(%s)" % 214 (param.typeName, param.paramName)) 215 cgen.stmt("// End manual dispatchable handle unboxing for %s" % param.paramName) 216 217 218def emit_transform(typeInfo, param, cgen, variant="tohost"): 219 res = iterateVulkanType(typeInfo, param, TransformCodegen( 220 cgen, param.paramName, "m_state", "transform_%s_" % variant, variant)) 221 if not res: 222 cgen.stmt("(void)%s" % param.paramName) 223 224 225def emit_marshal(typeInfo, param, cgen, handleMapOverwrites=False): 226 iterateVulkanType(typeInfo, param, VulkanMarshalingCodegen( 227 cgen, 228 WRITE_STREAM, 229 ROOT_TYPE_DEFAULT_VALUE, 230 param.paramName, 231 API_PREFIX_MARSHAL, 232 direction="write", 233 handleMapOverwrites=handleMapOverwrites)) 234 235 236class DecodingParameters(object): 237 def __init__(self, api: VulkanAPI): 238 self.params: list[VulkanType] = [] 239 self.toRead: list[VulkanType] = [] 240 self.toWrite: list[VulkanType] = [] 241 242 for i, param in enumerate(api.parameters): 243 if i == 0 and param.isDispatchableHandleType(): 244 param.dispatchHandle = True 245 246 if param.isNonDispatchableHandleType() and param.isCreatedBy(api): 247 param.nonDispatchableHandleCreate = True 248 249 if param.isNonDispatchableHandleType() and param.isDestroyedBy(api): 250 param.nonDispatchableHandleDestroy = True 251 252 if param.isDispatchableHandleType() and param.isCreatedBy(api): 253 param.dispatchableHandleCreate = True 254 255 if param.isDispatchableHandleType() and param.isDestroyedBy(api): 256 param.dispatchableHandleDestroy = True 257 258 self.toRead.append(param) 259 260 if param.possiblyOutput(): 261 self.toWrite.append(param) 262 263 self.params.append(param) 264 265 266def emit_call_log(api, cgen): 267 decodingParams = DecodingParameters(api) 268 paramsToRead = decodingParams.toRead 269 270 cgen.beginIf("m_logCalls") 271 paramLogFormat = "" 272 paramLogArgs = [] 273 for p in paramsToRead: 274 paramLogFormat += "0x%llx " 275 for p in paramsToRead: 276 paramLogArgs.append("(unsigned long long)%s" % (p.paramName)) 277 cgen.stmt("fprintf(stderr, \"stream %%p: call %s %s\\n\", ioStream, %s)" % (api.name, paramLogFormat, ", ".join(paramLogArgs))) 278 cgen.endIf() 279 280def emit_decode_parameters(typeInfo: VulkanTypeInfo, api: VulkanAPI, cgen, globalWrapped=False): 281 decodingParams = DecodingParameters(api) 282 283 paramsToRead = decodingParams.toRead 284 285 for p in paramsToRead: 286 emit_param_decl_for_reading(p, cgen) 287 288 for i, p in enumerate(paramsToRead): 289 lenAccess = cgen.generalLengthAccess(p) 290 291 if p.dispatchHandle: 292 if api.name in DELAYED_DECODER_DELETE_DICT_ENTRIES: 293 emit_dispatch_unmarshal(typeInfo, p, cgen, False) 294 else: 295 emit_dispatch_unmarshal(typeInfo, p, cgen, globalWrapped) 296 else: 297 destroy = p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy 298 noUnbox = api.name in ["vkQueueFlushCommandsGOOGLE", "vkQueueFlushCommandsFromAuxMemoryGOOGLE"] and p.paramName == "commandBuffer" 299 300 if p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy: 301 destroy = True 302 cgen.stmt("// Begin manual non dispatchable handle destroy unboxing for %s" % p.paramName) 303 if None == lenAccess or "1" == lenAccess: 304 cgen.stmt("%s boxed_%s_preserve" % (p.typeName, p.paramName)) 305 else: 306 cgen.stmt("%s* boxed_%s_preserve; %s->alloc((void**)&boxed_%s_preserve, %s * sizeof(%s))" % (p.typeName, p.paramName, READ_STREAM, p.paramName, lenAccess, p.typeName)) 307 308 if p.possiblyOutput(): 309 cgen.stmt("// Begin manual dispatchable handle unboxing for %s" % p.paramName) 310 cgen.stmt("%s->unsetHandleMapping()" % READ_STREAM) 311 312 emit_unmarshal(typeInfo, p, cgen, output = p.possiblyOutput(), destroy = destroy, noUnbox = noUnbox) 313 314 for p in paramsToRead: 315 emit_transform(typeInfo, p, cgen, variant="tohost") 316 317 emit_call_log(api, cgen) 318 319def emit_dispatch_call(api, cgen): 320 321 decodingParams = DecodingParameters(api) 322 323 customParams = [] 324 325 delay = api.name in DELAYED_DECODER_DELETES 326 327 for i, p in enumerate(api.parameters): 328 customParam = p.paramName 329 if decodingParams.params[i].dispatchHandle: 330 customParam = "unboxed_%s" % p.paramName 331 customParams.append(customParam) 332 333 if delay: 334 cgen.line("std::function<void()> delayed_remove_callback = [vk, %s]() {" % ", ".join(customParams)) 335 336 if api.name in driver_workarounds_global_lock_apis: 337 if delay: 338 cgen.stmt("auto state = VkDecoderGlobalState::get()") 339 cgen.stmt("// state already locked") 340 else: 341 cgen.stmt("m_state->lock()") 342 343 cgen.vkApiCall(api, customPrefix="vk->", customParameters=customParams, \ 344 globalStatePrefix=global_state_prefix, checkForDeviceLost=True, 345 checkForOutOfMemory=True) 346 347 if api.name in driver_workarounds_global_lock_apis: 348 if not delay: 349 cgen.stmt("m_state->unlock()") 350 # for delayed remove, state is already locked, so we do not need to 351 # unlock 352 353 if delay: 354 cgen.line("};") 355 356def emit_global_state_wrapped_call(api, cgen, context): 357 if api.name in DELAYED_DECODER_DELETES: 358 print("Error: Cannot generate a global state wrapped call that is also a delayed delete (yet)"); 359 raise 360 361 customParams = ["&m_pool"] + list(map(lambda p: p.paramName, api.parameters)) 362 if context: 363 customParams += ["context"] 364 cgen.vkApiCall(api, customPrefix=global_state_prefix, \ 365 customParameters=customParams, globalStatePrefix=global_state_prefix, \ 366 checkForDeviceLost=True, checkForOutOfMemory=True) 367 368def emit_decode_parameters_writeback(typeInfo, api, cgen, autobox=True): 369 decodingParams = DecodingParameters(api) 370 371 paramsToWrite = decodingParams.toWrite 372 373 cgen.stmt("%s->unsetHandleMapping()" % WRITE_STREAM) 374 375 handleMapOverwrites = False 376 377 for p in paramsToWrite: 378 emit_transform(typeInfo, p, cgen, variant="fromhost") 379 380 handleMapOverwrites = False 381 382 if p.nonDispatchableHandleCreate or p.dispatchableHandleCreate: 383 handleMapOverwrites = True 384 385 if autobox and p.nonDispatchableHandleCreate: 386 cgen.stmt("// Begin auto non dispatchable handle create for %s" % p.paramName) 387 cgen.stmt("if (%s == VK_SUCCESS) %s->setHandleMapping(&m_boxedHandleCreateMapping)" % \ 388 (api.getRetVarExpr(), WRITE_STREAM)) 389 390 if (not autobox) and p.nonDispatchableHandleCreate: 391 cgen.stmt("// Begin manual non dispatchable handle create for %s" % p.paramName) 392 cgen.stmt("%s->unsetHandleMapping()" % WRITE_STREAM) 393 394 emit_marshal(typeInfo, p, cgen, handleMapOverwrites=handleMapOverwrites) 395 396 if autobox and p.nonDispatchableHandleCreate: 397 cgen.stmt("// Begin auto non dispatchable handle create for %s" % p.paramName) 398 cgen.stmt("%s->setHandleMapping(&m_boxedHandleUnwrapMapping)" % WRITE_STREAM) 399 400 if (not autobox) and p.nonDispatchableHandleCreate: 401 cgen.stmt("// Begin manual non dispatchable handle create for %s" % p.paramName) 402 cgen.stmt("%s->setHandleMapping(&m_boxedHandleUnwrapMapping)" % WRITE_STREAM) 403 404def emit_decode_return_writeback(api, cgen): 405 retTypeName = api.getRetTypeExpr() 406 if retTypeName != "void": 407 retVar = api.getRetVarExpr() 408 cgen.stmt("%s->write(&%s, %s)" % 409 (WRITE_STREAM, retVar, cgen.sizeofExpr(api.retType))) 410 411def emit_decode_finish(api, cgen): 412 decodingParams = DecodingParameters(api) 413 retTypeName = api.getRetTypeExpr() 414 paramsToWrite = decodingParams.toWrite 415 416 if retTypeName != "void" or len(paramsToWrite) != 0: 417 cgen.stmt("%s->commitWrite()" % WRITE_STREAM) 418 419def emit_destroyed_handle_cleanup(api, cgen): 420 decodingParams = DecodingParameters(api) 421 paramsToRead = decodingParams.toRead 422 423 skipDelete = api.name in SKIPPED_DECODER_DELETES 424 425 if skipDelete: 426 cgen.line("// Skipping handle cleanup for %s" % api.name) 427 return 428 429 for p in paramsToRead: 430 if p.dispatchHandle: 431 pass 432 else: 433 lenAccess = cgen.generalLengthAccess(p) 434 lenAccessGuard = cgen.generalLengthAccess(p) 435 destroy = p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy 436 if destroy: 437 if None == lenAccess or "1" == lenAccess: 438 if api.name in DELAYED_DECODER_DELETES: 439 cgen.stmt("delayed_delete_%s(boxed_%s_preserve, unboxed_device, delayed_remove_callback)" % (p.typeName, p.paramName)) 440 elif api.name in DELAYED_DECODER_DELETE_DICT_ENTRIES: 441 cgen.stmt("delayed_delete_%s(boxed_%s_preserve, unboxed_device, nullptr)" % (p.typeName, p.paramName)) 442 else: 443 cgen.stmt("delete_%s(boxed_%s_preserve)" % (p.typeName, p.paramName)) 444 else: 445 if lenAccessGuard is not None: 446 cgen.beginIf(lenAccessGuard) 447 cgen.beginFor("uint32_t i = 0", "i < %s" % lenAccess, "++i") 448 if api.name in DELAYED_DECODER_DELETES: 449 cgen.stmt("delayed_delete_%s(boxed_%s_preserve[i], unboxed_device, delayed_remove_callback)" % (p.typeName, p.paramName)) 450 else: 451 cgen.stmt("delete_%s(boxed_%s_preserve[i])" % (p.typeName, p.paramName)) 452 cgen.endFor() 453 if lenAccessGuard is not None: 454 cgen.endIf() 455 456def emit_pool_free(cgen): 457 cgen.stmt("%s->clearPool()" % READ_STREAM) 458 459def emit_seqno_incr(api, cgen): 460 cgen.stmt("if (m_queueSubmitWithCommandsEnabled) seqnoPtr->fetch_add(1, std::memory_order_seq_cst)") 461 462def emit_snapshot(typeInfo, api, cgen): 463 464 cgen.stmt("%s->setReadPos((uintptr_t)(*readStreamPtrPtr) - (uintptr_t)snapshotTraceBegin)" % READ_STREAM) 465 cgen.stmt("size_t snapshotTraceBytes = %s->endTrace()" % READ_STREAM) 466 467 additionalParams = [ \ 468 makeVulkanTypeSimple(True, "uint8_t", 1, "snapshotTraceBegin"), 469 makeVulkanTypeSimple(False, "size_t", 0, "snapshotTraceBytes"), 470 makeVulkanTypeSimple(False, "android::base::BumpPool", 1, "&m_pool"), 471 ] 472 473 retTypeName = api.getRetTypeExpr() 474 if retTypeName != "void": 475 retVar = api.getRetVarExpr() 476 additionalParams.append(makeVulkanTypeSimple(False, retTypeName, 0, retVar)) 477 478 paramsForSnapshot = [] 479 480 decodingParams = DecodingParameters(api) 481 482 for p in decodingParams.toRead: 483 if p.nonDispatchableHandleDestroy or (not p.dispatchHandle and p.dispatchableHandleDestroy): 484 paramsForSnapshot.append(p.withModifiedName("boxed_%s_preserve" % p.paramName)) 485 else: 486 paramsForSnapshot.append(p) 487 488 customParams = additionalParams + paramsForSnapshot 489 490 apiForSnapshot = \ 491 api.withCustomReturnType(makeVulkanTypeSimple(False, "void", 0, "void")). \ 492 withCustomParameters(customParams) 493 494 cgen.beginIf("m_state->snapshotsEnabled()") 495 cgen.vkApiCall(apiForSnapshot, customPrefix="m_state->snapshot()->") 496 cgen.endIf() 497 498def emit_decoding(typeInfo, api, cgen, globalWrapped=False, context=False): 499 isAcquire = api.name in RELAXED_APIS 500 emit_decode_parameters(typeInfo, api, cgen, globalWrapped) 501 502 if isAcquire: 503 emit_seqno_incr(api, cgen) 504 505 if globalWrapped: 506 emit_global_state_wrapped_call(api, cgen, context) 507 else: 508 emit_dispatch_call(api, cgen) 509 510 emit_decode_parameters_writeback(typeInfo, api, cgen, autobox=not globalWrapped) 511 emit_decode_return_writeback(api, cgen) 512 emit_decode_finish(api, cgen) 513 emit_snapshot(typeInfo, api, cgen) 514 emit_destroyed_handle_cleanup(api, cgen) 515 emit_pool_free(cgen) 516 517 if not isAcquire: 518 emit_seqno_incr(api, cgen) 519 520def emit_default_decoding(typeInfo, api, cgen): 521 emit_decoding(typeInfo, api, cgen) 522 523def emit_global_state_wrapped_decoding(typeInfo, api, cgen): 524 emit_decoding(typeInfo, api, cgen, globalWrapped=True) 525 526def emit_global_state_wrapped_decoding_with_context(typeInfo, api, cgen): 527 emit_decoding(typeInfo, api, cgen, globalWrapped=True, context=True) 528 529## Custom decoding definitions################################################## 530def decode_vkFlushMappedMemoryRanges(typeInfo: VulkanTypeInfo, api, cgen): 531 emit_decode_parameters(typeInfo, api, cgen) 532 533 cgen.beginIf("!m_state->usingDirectMapping()") 534 cgen.stmt("// This is to deal with a deficiency in the encoder,"); 535 cgen.stmt("// where usingDirectMapping fails to set the proper packet size,"); 536 cgen.stmt("// meaning we can read off the end of the packet."); 537 cgen.stmt("uint64_t sizeLeft = end - *readStreamPtrPtr") 538 cgen.beginFor("uint32_t i = 0", "i < memoryRangeCount", "++i") 539 cgen.beginIf("sizeLeft < sizeof(uint64_t)") 540 cgen.beginIf("m_prevSeqno") 541 cgen.stmt("m_prevSeqno = m_prevSeqno.value() - 1") 542 cgen.endIf() 543 cgen.stmt("return ptr - (unsigned char*)buf;") 544 cgen.endIf() 545 cgen.stmt("auto range = pMemoryRanges[i]") 546 cgen.stmt("auto memory = pMemoryRanges[i].memory") 547 cgen.stmt("auto size = pMemoryRanges[i].size") 548 cgen.stmt("auto offset = pMemoryRanges[i].offset") 549 cgen.stmt("uint64_t readStream = 0") 550 cgen.stmt("memcpy(&readStream, *readStreamPtrPtr, sizeof(uint64_t)); *readStreamPtrPtr += sizeof(uint64_t)") 551 cgen.stmt("sizeLeft -= sizeof(uint64_t)") 552 cgen.stmt("auto hostPtr = m_state->getMappedHostPointer(memory)") 553 cgen.stmt("if (!hostPtr && readStream > 0) GFXSTREAM_ABORT(::emugl::FatalError(::emugl::ABORT_REASON_OTHER))") 554 cgen.stmt("if (!hostPtr) continue") 555 cgen.beginIf("sizeLeft < readStream") 556 cgen.beginIf("m_prevSeqno") 557 cgen.stmt("m_prevSeqno = m_prevSeqno.value() - 1") 558 cgen.endIf() 559 cgen.stmt("return ptr - (unsigned char*)buf;") 560 cgen.endIf() 561 cgen.stmt("sizeLeft -= readStream") 562 cgen.stmt("uint8_t* targetRange = hostPtr + offset") 563 cgen.stmt("memcpy(targetRange, *readStreamPtrPtr, readStream); *readStreamPtrPtr += readStream") 564 cgen.stmt("packetLen += 8 + readStream") 565 cgen.endFor() 566 cgen.endIf() 567 568 emit_dispatch_call(api, cgen) 569 emit_decode_parameters_writeback(typeInfo, api, cgen) 570 emit_decode_return_writeback(api, cgen) 571 emit_decode_finish(api, cgen) 572 emit_snapshot(typeInfo, api, cgen); 573 emit_pool_free(cgen) 574 emit_seqno_incr(api, cgen) 575 576def decode_vkInvalidateMappedMemoryRanges(typeInfo, api, cgen): 577 emit_decode_parameters(typeInfo, api, cgen) 578 emit_dispatch_call(api, cgen) 579 emit_decode_parameters_writeback(typeInfo, api, cgen) 580 emit_decode_return_writeback(api, cgen) 581 582 cgen.beginIf("!m_state->usingDirectMapping()") 583 cgen.beginFor("uint32_t i = 0", "i < memoryRangeCount", "++i") 584 cgen.stmt("auto range = pMemoryRanges[i]") 585 cgen.stmt("auto memory = range.memory") 586 cgen.stmt("auto size = range.size") 587 cgen.stmt("auto offset = range.offset") 588 cgen.stmt("auto hostPtr = m_state->getMappedHostPointer(memory)") 589 cgen.stmt("auto actualSize = size == VK_WHOLE_SIZE ? m_state->getDeviceMemorySize(memory) : size") 590 cgen.stmt("uint64_t writeStream = 0") 591 cgen.stmt("if (!hostPtr) { %s->write(&writeStream, sizeof(uint64_t)); continue; }" % WRITE_STREAM) 592 cgen.stmt("uint8_t* targetRange = hostPtr + offset") 593 cgen.stmt("writeStream = actualSize") 594 cgen.stmt("%s->write(&writeStream, sizeof(uint64_t))" % WRITE_STREAM) 595 cgen.stmt("%s->write(targetRange, actualSize)" % WRITE_STREAM) 596 cgen.endFor() 597 cgen.endIf() 598 599 emit_decode_finish(api, cgen) 600 emit_snapshot(typeInfo, api, cgen); 601 emit_pool_free(cgen) 602 emit_seqno_incr(api, cgen) 603 604def decode_unsupported_api(typeInfo, api, cgen): 605 cgen.line(f"// Decoding {api.name} is not supported. This should not run.") 606 cgen.stmt(f"fprintf(stderr, \"stream %p: fatal: decoding unsupported API {api.name}\\n\", ioStream)"); 607 cgen.stmt("__builtin_trap()") 608 609custom_decodes = { 610 "vkEnumerateInstanceVersion" : emit_global_state_wrapped_decoding, 611 "vkCreateInstance" : emit_global_state_wrapped_decoding, 612 "vkDestroyInstance" : emit_global_state_wrapped_decoding, 613 "vkEnumeratePhysicalDevices" : emit_global_state_wrapped_decoding, 614 615 "vkGetPhysicalDeviceFeatures" : emit_global_state_wrapped_decoding, 616 "vkGetPhysicalDeviceFeatures2" : emit_global_state_wrapped_decoding, 617 "vkGetPhysicalDeviceFeatures2KHR" : emit_global_state_wrapped_decoding, 618 "vkGetPhysicalDeviceFormatProperties" : emit_global_state_wrapped_decoding, 619 "vkGetPhysicalDeviceFormatProperties2" : emit_global_state_wrapped_decoding, 620 "vkGetPhysicalDeviceFormatProperties2KHR" : emit_global_state_wrapped_decoding, 621 "vkGetPhysicalDeviceImageFormatProperties" : emit_global_state_wrapped_decoding, 622 "vkGetPhysicalDeviceImageFormatProperties2" : emit_global_state_wrapped_decoding, 623 "vkGetPhysicalDeviceImageFormatProperties2KHR" : emit_global_state_wrapped_decoding, 624 "vkGetPhysicalDeviceProperties" : emit_global_state_wrapped_decoding, 625 "vkGetPhysicalDeviceProperties2" : emit_global_state_wrapped_decoding, 626 "vkGetPhysicalDeviceProperties2KHR" : emit_global_state_wrapped_decoding, 627 628 "vkGetPhysicalDeviceMemoryProperties" : emit_global_state_wrapped_decoding, 629 "vkGetPhysicalDeviceMemoryProperties2" : emit_global_state_wrapped_decoding, 630 "vkGetPhysicalDeviceMemoryProperties2KHR" : emit_global_state_wrapped_decoding, 631 632 "vkGetPhysicalDeviceExternalSemaphoreProperties" : emit_global_state_wrapped_decoding, 633 "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR" : emit_global_state_wrapped_decoding, 634 635 "vkEnumerateDeviceExtensionProperties" : emit_global_state_wrapped_decoding, 636 637 "vkCreateBuffer" : emit_global_state_wrapped_decoding, 638 "vkDestroyBuffer" : emit_global_state_wrapped_decoding, 639 640 "vkBindBufferMemory" : emit_global_state_wrapped_decoding, 641 "vkBindBufferMemory2" : emit_global_state_wrapped_decoding, 642 "vkBindBufferMemory2KHR" : emit_global_state_wrapped_decoding, 643 644 "vkCreateDevice" : emit_global_state_wrapped_decoding, 645 "vkDestroyDevice" : emit_global_state_wrapped_decoding, 646 647 "vkGetDeviceQueue" : emit_global_state_wrapped_decoding, 648 "vkGetDeviceQueue2" : emit_global_state_wrapped_decoding, 649 650 "vkGetPhysicalDeviceQueueFamilyProperties" : emit_global_state_wrapped_decoding, 651 "vkGetPhysicalDeviceQueueFamilyProperties2" : emit_global_state_wrapped_decoding, 652 653 "vkQueueBindSparse" : emit_global_state_wrapped_decoding, 654 "vkQueuePresentKHR" : emit_global_state_wrapped_decoding, 655 656 "vkBindImageMemory" : emit_global_state_wrapped_decoding, 657 "vkBindImageMemory2" : emit_global_state_wrapped_decoding, 658 "vkBindImageMemory2KHR" : emit_global_state_wrapped_decoding, 659 660 "vkCreateImage" : emit_global_state_wrapped_decoding, 661 "vkCreateImageView" : emit_global_state_wrapped_decoding, 662 "vkCreateSampler" : emit_global_state_wrapped_decoding, 663 "vkDestroyImage" : emit_global_state_wrapped_decoding, 664 "vkDestroyImageView" : emit_global_state_wrapped_decoding, 665 "vkDestroySampler" : emit_global_state_wrapped_decoding, 666 "vkCmdCopyBufferToImage" : emit_global_state_wrapped_decoding_with_context, 667 "vkCmdCopyImage" : emit_global_state_wrapped_decoding, 668 "vkCmdCopyImageToBuffer" : emit_global_state_wrapped_decoding, 669 "vkCmdCopyBufferToImage2" : emit_global_state_wrapped_decoding_with_context, 670 "vkCmdCopyImage2" : emit_global_state_wrapped_decoding, 671 "vkCmdCopyImageToBuffer2" : emit_global_state_wrapped_decoding, 672 "vkGetImageMemoryRequirements" : emit_global_state_wrapped_decoding, 673 "vkGetImageMemoryRequirements2" : emit_global_state_wrapped_decoding, 674 "vkGetImageMemoryRequirements2KHR" : emit_global_state_wrapped_decoding, 675 "vkGetBufferMemoryRequirements" : emit_global_state_wrapped_decoding, 676 "vkGetBufferMemoryRequirements2": emit_global_state_wrapped_decoding, 677 "vkGetBufferMemoryRequirements2KHR": emit_global_state_wrapped_decoding, 678 679 "vkCreateDescriptorSetLayout" : emit_global_state_wrapped_decoding, 680 "vkDestroyDescriptorSetLayout" : emit_global_state_wrapped_decoding, 681 "vkCreateDescriptorPool" : emit_global_state_wrapped_decoding, 682 "vkDestroyDescriptorPool" : emit_global_state_wrapped_decoding, 683 "vkResetDescriptorPool" : emit_global_state_wrapped_decoding, 684 "vkAllocateDescriptorSets" : emit_global_state_wrapped_decoding, 685 "vkFreeDescriptorSets" : emit_global_state_wrapped_decoding, 686 687 "vkUpdateDescriptorSets" : emit_global_state_wrapped_decoding, 688 689 "vkCreateShaderModule": emit_global_state_wrapped_decoding, 690 "vkDestroyShaderModule": emit_global_state_wrapped_decoding, 691 "vkCreatePipelineCache": emit_global_state_wrapped_decoding, 692 "vkDestroyPipelineCache": emit_global_state_wrapped_decoding, 693 "vkCreateComputePipelines": emit_global_state_wrapped_decoding, 694 "vkCreateGraphicsPipelines": emit_global_state_wrapped_decoding, 695 "vkDestroyPipeline": emit_global_state_wrapped_decoding, 696 697 "vkAllocateMemory" : emit_global_state_wrapped_decoding, 698 "vkFreeMemory" : emit_global_state_wrapped_decoding, 699 "vkMapMemory" : emit_global_state_wrapped_decoding, 700 "vkUnmapMemory" : emit_global_state_wrapped_decoding, 701 "vkFlushMappedMemoryRanges" : decode_vkFlushMappedMemoryRanges, 702 "vkInvalidateMappedMemoryRanges" : decode_vkInvalidateMappedMemoryRanges, 703 704 "vkAllocateCommandBuffers" : emit_global_state_wrapped_decoding, 705 "vkCmdExecuteCommands" : emit_global_state_wrapped_decoding, 706 "vkQueueSubmit" : emit_global_state_wrapped_decoding, 707 "vkQueueSubmit2" : emit_global_state_wrapped_decoding, 708 "vkQueueWaitIdle" : emit_global_state_wrapped_decoding, 709 "vkBeginCommandBuffer" : emit_global_state_wrapped_decoding_with_context, 710 "vkEndCommandBuffer" : emit_global_state_wrapped_decoding_with_context, 711 "vkResetCommandBuffer" : emit_global_state_wrapped_decoding, 712 "vkFreeCommandBuffers" : emit_global_state_wrapped_decoding, 713 "vkCreateCommandPool" : emit_global_state_wrapped_decoding, 714 "vkDestroyCommandPool" : emit_global_state_wrapped_decoding, 715 "vkResetCommandPool" : emit_global_state_wrapped_decoding, 716 "vkCmdPipelineBarrier" : emit_global_state_wrapped_decoding, 717 "vkCmdPipelineBarrier2" : emit_global_state_wrapped_decoding, 718 "vkCmdBindPipeline" : emit_global_state_wrapped_decoding, 719 "vkCmdBindDescriptorSets" : emit_global_state_wrapped_decoding, 720 721 "vkCreateRenderPass" : emit_global_state_wrapped_decoding, 722 "vkCreateRenderPass2" : emit_global_state_wrapped_decoding, 723 "vkCreateRenderPass2KHR" : emit_global_state_wrapped_decoding, 724 "vkDestroyRenderPass" : emit_global_state_wrapped_decoding, 725 "vkCreateFramebuffer" : emit_global_state_wrapped_decoding, 726 "vkDestroyFramebuffer" : emit_global_state_wrapped_decoding, 727 "vkDestroyFramebuffer" : emit_global_state_wrapped_decoding, 728 "vkCmdBeginRenderPass" : emit_global_state_wrapped_decoding, 729 "vkCmdBeginRenderPass2" : emit_global_state_wrapped_decoding, 730 "vkCmdBeginRenderPass2KHR" : emit_global_state_wrapped_decoding, 731 732 "vkCreateSamplerYcbcrConversion": emit_global_state_wrapped_decoding, 733 "vkDestroySamplerYcbcrConversion": emit_global_state_wrapped_decoding, 734 735 # VK_ANDROID_native_buffer 736 "vkGetSwapchainGrallocUsageANDROID" : emit_global_state_wrapped_decoding, 737 "vkGetSwapchainGrallocUsage2ANDROID" : emit_global_state_wrapped_decoding, 738 "vkAcquireImageANDROID" : emit_global_state_wrapped_decoding, 739 "vkQueueSignalReleaseImageANDROID" : emit_global_state_wrapped_decoding, 740 741 "vkCreateSemaphore" : emit_global_state_wrapped_decoding, 742 "vkGetSemaphoreFdKHR" : emit_global_state_wrapped_decoding, 743 "vkImportSemaphoreFdKHR" : emit_global_state_wrapped_decoding, 744 "vkDestroySemaphore" : emit_global_state_wrapped_decoding, 745 746 "vkCreateFence" : emit_global_state_wrapped_decoding, 747 "vkResetFences" : emit_global_state_wrapped_decoding, 748 "vkDestroyFence" : emit_global_state_wrapped_decoding, 749 750 # VK_GOOGLE_gfxstream 751 "vkFreeMemorySyncGOOGLE" : emit_global_state_wrapped_decoding, 752 "vkMapMemoryIntoAddressSpaceGOOGLE" : emit_global_state_wrapped_decoding, 753 "vkGetMemoryHostAddressInfoGOOGLE" : emit_global_state_wrapped_decoding, 754 "vkGetBlobGOOGLE" : emit_global_state_wrapped_decoding, 755 "vkGetSemaphoreGOOGLE" : emit_global_state_wrapped_decoding, 756 757 # Descriptor update templates 758 "vkCreateDescriptorUpdateTemplate" : emit_global_state_wrapped_decoding, 759 "vkCreateDescriptorUpdateTemplateKHR" : emit_global_state_wrapped_decoding, 760 "vkDestroyDescriptorUpdateTemplate" : emit_global_state_wrapped_decoding, 761 "vkDestroyDescriptorUpdateTemplateKHR" : emit_global_state_wrapped_decoding, 762 "vkUpdateDescriptorSetWithTemplateSizedGOOGLE" : emit_global_state_wrapped_decoding, 763 "vkUpdateDescriptorSetWithTemplateSized2GOOGLE" : emit_global_state_wrapped_decoding, 764 765 # VK_GOOGLE_gfxstream 766 "vkBeginCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding_with_context, 767 "vkEndCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding_with_context, 768 "vkResetCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding, 769 "vkCommandBufferHostSyncGOOGLE" : emit_global_state_wrapped_decoding, 770 "vkCreateImageWithRequirementsGOOGLE" : emit_global_state_wrapped_decoding, 771 "vkCreateBufferWithRequirementsGOOGLE" : emit_global_state_wrapped_decoding, 772 "vkQueueHostSyncGOOGLE" : emit_global_state_wrapped_decoding, 773 "vkQueueSubmitAsyncGOOGLE" : emit_global_state_wrapped_decoding, 774 "vkQueueSubmitAsync2GOOGLE" : emit_global_state_wrapped_decoding, 775 "vkQueueWaitIdleAsyncGOOGLE" : emit_global_state_wrapped_decoding, 776 "vkQueueBindSparseAsyncGOOGLE" : emit_global_state_wrapped_decoding, 777 "vkGetLinearImageLayoutGOOGLE" : emit_global_state_wrapped_decoding, 778 "vkGetLinearImageLayout2GOOGLE" : emit_global_state_wrapped_decoding, 779 "vkQueueFlushCommandsGOOGLE" : emit_global_state_wrapped_decoding_with_context, 780 "vkQueueFlushCommandsFromAuxMemoryGOOGLE" : emit_global_state_wrapped_decoding_with_context, 781 "vkQueueCommitDescriptorSetUpdatesGOOGLE" : emit_global_state_wrapped_decoding, 782 "vkCollectDescriptorPoolIdsGOOGLE" : emit_global_state_wrapped_decoding, 783 "vkQueueSignalReleaseImageANDROIDAsyncGOOGLE" : emit_global_state_wrapped_decoding, 784 785 "vkQueueBindSparse" : emit_global_state_wrapped_decoding, 786 787 # VK_KHR_xcb_surface 788 "vkCreateXcbSurfaceKHR": decode_unsupported_api, 789 "vkGetPhysicalDeviceXcbPresentationSupportKHR": decode_unsupported_api, 790 791 # VK_EXT_metal_surface 792 "vkCreateMetalSurfaceEXT": decode_unsupported_api, 793 794 # VK_KHR_sampler_ycbcr_conversion 795 "vkCreateSamplerYcbcrConversionKHR": emit_global_state_wrapped_decoding, 796 "vkDestroySamplerYcbcrConversionKHR": emit_global_state_wrapped_decoding, 797 798 #VK_KHR_copy_commands2 799 "vkCmdCopyBufferToImage2KHR" : emit_global_state_wrapped_decoding_with_context, 800 "vkCmdCopyImage2KHR" : emit_global_state_wrapped_decoding, 801 "vkCmdCopyImageToBuffer2KHR" : emit_global_state_wrapped_decoding, 802 803 # VK_KHR_device_group_creation / VK_VERSION_1_1 804 "vkEnumeratePhysicalDeviceGroups" : emit_global_state_wrapped_decoding, 805 "vkEnumeratePhysicalDeviceGroupsKHR" : emit_global_state_wrapped_decoding, 806} 807 808class VulkanDecoder(VulkanWrapperGenerator): 809 def __init__(self, module, typeInfo): 810 VulkanWrapperGenerator.__init__(self, module, typeInfo) 811 self.typeInfo: VulkanTypeInfo = typeInfo 812 self.cgen = CodeGen() 813 814 def onBegin(self,): 815 self.module.appendImpl( 816 "#define MAX_PACKET_LENGTH %s\n" % MAX_PACKET_LENGTH) 817 self.module.appendHeader(decoder_decl_preamble) 818 self.module.appendImpl(decoder_impl_preamble) 819 820 self.module.appendImpl( 821 """ 822size_t VkDecoder::Impl::decode(void* buf, size_t len, IOStream* ioStream, 823 const ProcessResources* processResources, 824 const VkDecoderContext& context) 825""") 826 827 self.cgen.beginBlock() # function body 828 829 self.cgen.stmt("const char* processName = context.processName") 830 self.cgen.stmt("auto& gfx_logger = *context.gfxApiLogger") 831 self.cgen.stmt("auto* healthMonitor = context.healthMonitor") 832 self.cgen.stmt("auto& metricsLogger = *context.metricsLogger") 833 self.cgen.stmt("if (len < 8) return 0") 834 self.cgen.stmt("unsigned char *ptr = (unsigned char *)buf") 835 self.cgen.stmt("const unsigned char* const end = (const unsigned char*)buf + len") 836 837 self.cgen.beginIf("m_forSnapshotLoad") 838 self.cgen.stmt("ptr += m_state->setCreatedHandlesForSnapshotLoad(ptr)"); 839 self.cgen.endIf() 840 self.cgen.line("while (end - ptr >= 8)") 841 self.cgen.beginBlock() # while loop 842 843 self.cgen.stmt("uint32_t opcode = *(uint32_t *)ptr") 844 self.cgen.stmt("uint32_t packetLen = *(uint32_t *)(ptr + 4)") 845 self.cgen.line(""" 846 // packetLen should be at least 8 (op code and packet length) and should not be excessively large 847 if (packetLen < 8 || packetLen > MAX_PACKET_LENGTH) { 848 WARN("Bad packet length %d detected, decode may fail", packetLen); 849 metricsLogger.logMetricEvent(MetricEventBadPacketLength{ .len = packetLen }); 850 } 851 """) 852 self.cgen.stmt("if (end - ptr < packetLen) return ptr - (unsigned char*)buf") 853 self.cgen.stmt("gfx_logger.record(ptr, std::min(size_t(packetLen + 8), size_t(end - ptr)))") 854 855 self.cgen.stmt("stream()->setStream(ioStream)") 856 self.cgen.stmt("VulkanStream* %s = stream()" % WRITE_STREAM) 857 self.cgen.stmt("VulkanMemReadingStream* %s = readStream()" % READ_STREAM) 858 self.cgen.stmt("%s->setBuf((uint8_t*)(ptr + 8))" % READ_STREAM) 859 self.cgen.stmt("uint8_t* readStreamPtr = %s->getBuf(); uint8_t** readStreamPtrPtr = &readStreamPtr" % READ_STREAM) 860 self.cgen.stmt("uint8_t* snapshotTraceBegin = %s->beginTrace()" % READ_STREAM) 861 self.cgen.stmt("%s->setHandleMapping(&m_boxedHandleUnwrapMapping)" % READ_STREAM) 862 self.cgen.line(""" 863 std::unique_ptr<EventHangMetadata::HangAnnotations> executionData = 864 std::make_unique<EventHangMetadata::HangAnnotations>(); 865 if (healthMonitor) { 866 executionData->insert( 867 {{"packet_length", std::to_string(packetLen)}, 868 {"opcode", std::to_string(opcode)}}); 869 if (processName) { 870 executionData->insert( 871 {{"renderthread_guest_process", std::string(processName)}}); 872 } 873 if (m_prevSeqno) { 874 executionData->insert({{"previous_seqno", std::to_string(m_prevSeqno.value())}}); 875 } 876 } 877 878 std::atomic<uint32_t>* seqnoPtr = processResources ? 879 processResources->getSequenceNumberPtr() : nullptr; 880 881 if (m_queueSubmitWithCommandsEnabled && ((opcode >= OP_vkFirst && opcode < OP_vkLast) || (opcode >= OP_vkFirst_old && opcode < OP_vkLast_old))) { 882 uint32_t seqno; 883 memcpy(&seqno, *readStreamPtrPtr, sizeof(uint32_t)); *readStreamPtrPtr += sizeof(uint32_t); 884 if (healthMonitor) executionData->insert({{"seqno", std::to_string(seqno)}}); 885 if (m_prevSeqno && seqno == m_prevSeqno.value()) { 886 WARN( 887 "Seqno %d is the same as previously processed on thread %d. It might be a " 888 "duplicate command.", 889 seqno, getCurrentThreadId()); 890 metricsLogger.logMetricEvent(MetricEventDuplicateSequenceNum{ .opcode = opcode }); 891 } 892 if (seqnoPtr && !m_forSnapshotLoad) { 893 { 894 auto seqnoWatchdog = 895 WATCHDOG_BUILDER(healthMonitor, 896 "RenderThread seqno loop") 897 .setHangType(EventHangMetadata::HangType::kRenderThread) 898 .setAnnotations(std::make_unique<EventHangMetadata::HangAnnotations>(*executionData)) 899 /* Data gathered if this hangs*/ 900 .setOnHangCallback([=]() { 901 auto annotations = std::make_unique<EventHangMetadata::HangAnnotations>(); 902 annotations->insert({{"seqnoPtr", std::to_string(seqnoPtr->load(std::memory_order_seq_cst))}}); 903 return annotations; 904 }) 905 .build(); 906 while ((seqno - seqnoPtr->load(std::memory_order_seq_cst) != 1)) { 907 #if (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))) 908 _mm_pause(); 909 #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) 910 __asm__ __volatile__("pause;"); 911 #endif 912 } 913 m_prevSeqno = seqno; 914 } 915 } 916 } 917 """) 918 919 self.cgen.line(""" 920 gfx_logger.recordCommandExecution(); 921 """) 922 923 self.cgen.line(""" 924 auto executionWatchdog = 925 WATCHDOG_BUILDER(healthMonitor, "RenderThread VkDecoder command execution") 926 .setHangType(EventHangMetadata::HangType::kRenderThread) 927 .setAnnotations(std::move(executionData)) 928 .build(); 929 """) 930 931 self.cgen.stmt("auto vk = m_vk") 932 933 self.cgen.line("switch (opcode)") 934 self.cgen.beginBlock() # switch stmt 935 936 self.module.appendImpl(self.cgen.swapCode()) 937 938 def onGenCmd(self, cmdinfo, name, alias): 939 typeInfo = self.typeInfo 940 cgen = self.cgen 941 api: VulkanAPI = typeInfo.apis[name] 942 943 cgen.line("case OP_%s:" % name) 944 cgen.beginBlock() 945 cgen.stmt("GFXSTREAM_TRACE_EVENT(GFXSTREAM_TRACE_DECODER_CATEGORY, \"VkDecoder %s\")" % name) 946 947 if api.name in custom_decodes.keys(): 948 custom_decodes[api.name](typeInfo, api, cgen) 949 else: 950 emit_default_decoding(typeInfo, api, cgen) 951 952 cgen.stmt("break") 953 cgen.endBlock() 954 self.module.appendImpl(self.cgen.swapCode()) 955 956 def onEnd(self,): 957 self.cgen.line("default:") 958 self.cgen.beginBlock() 959 self.cgen.stmt("m_pool.freeAll()") 960 self.cgen.stmt("return ptr - (unsigned char *)buf") 961 self.cgen.endBlock() 962 963 self.cgen.endBlock() # switch stmt 964 965 self.cgen.stmt("ptr += packetLen") 966 self.cgen.stmt("vkStream->clearPool()") 967 self.cgen.endBlock() # while loop 968 969 self.cgen.beginIf("m_forSnapshotLoad") 970 self.cgen.stmt("m_state->clearCreatedHandlesForSnapshotLoad()"); 971 self.cgen.endIf() 972 973 self.cgen.stmt("m_pool.freeAll()") 974 self.cgen.stmt("return ptr - (unsigned char*)buf;") 975 self.cgen.endBlock() # function body 976 self.module.appendImpl(self.cgen.swapCode()) 977 self.module.appendImpl(decoder_impl_postamble) 978