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