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