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