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