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