diff options
Diffstat (limited to 'codegen/vulkan/scripts/cereal/decoder.py')
-rw-r--r-- | codegen/vulkan/scripts/cereal/decoder.py | 912 |
1 files changed, 0 insertions, 912 deletions
diff --git a/codegen/vulkan/scripts/cereal/decoder.py b/codegen/vulkan/scripts/cereal/decoder.py deleted file mode 100644 index e082db0c..00000000 --- a/codegen/vulkan/scripts/cereal/decoder.py +++ /dev/null @@ -1,912 +0,0 @@ -from .common.codegen import CodeGen, VulkanWrapperGenerator -from .common.vulkantypes import VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeInfo,\ - VulkanType - -from .marshaling import VulkanMarshalingCodegen -from .reservedmarshaling import VulkanReservedMarshalingCodegen -from .transform import TransformCodegen - -from .wrapperdefs import API_PREFIX_MARSHAL -from .wrapperdefs import API_PREFIX_RESERVEDUNMARSHAL -from .wrapperdefs import MAX_PACKET_LENGTH -from .wrapperdefs import VULKAN_STREAM_TYPE -from .wrapperdefs import ROOT_TYPE_DEFAULT_VALUE -from .wrapperdefs import RELAXED_APIS - - -SKIPPED_DECODER_DELETES = [ - "vkFreeDescriptorSets", -] - -DELAYED_DECODER_DELETES = [ - "vkDestroyPipelineLayout", -] - -global_state_prefix = "m_state->on_" - -decoder_decl_preamble = """ - -namespace gfxstream { -class IOStream; -class ProcessResources; -} // namespace gfxstream - -namespace gfxstream { -namespace vk { - -class VkDecoder { -public: - VkDecoder(); - ~VkDecoder(); - void setForSnapshotLoad(bool forSnapshotLoad); - size_t decode(void* buf, size_t bufsize, IOStream* stream, - const ProcessResources* processResources, const VkDecoderContext&); -private: - class Impl; - std::unique_ptr<Impl> mImpl; -}; - -} // namespace vk -} // namespace gfxstream - -""" - -decoder_impl_preamble =""" -namespace gfxstream { -namespace vk { - -using android::base::MetricEventBadPacketLength; -using android::base::MetricEventDuplicateSequenceNum; - -class VkDecoder::Impl { -public: - Impl() : m_logCalls(android::base::getEnvironmentVariable("ANDROID_EMU_VK_LOG_CALLS") == "1"), - m_vk(vkDispatch()), - m_state(VkDecoderGlobalState::get()), - m_boxedHandleUnwrapMapping(m_state), - m_boxedHandleCreateMapping(m_state), - m_boxedHandleDestroyMapping(m_state), - m_boxedHandleUnwrapAndDeleteMapping(m_state), - m_boxedHandleUnwrapAndDeletePreserveBoxedMapping(m_state), - m_prevSeqno(std::nullopt) {} - %s* stream() { return &m_vkStream; } - VulkanMemReadingStream* readStream() { return &m_vkMemReadingStream; } - - void setForSnapshotLoad(bool forSnapshotLoad) { - m_forSnapshotLoad = forSnapshotLoad; - } - - size_t decode(void* buf, size_t bufsize, IOStream* stream, - const ProcessResources* processResources, const VkDecoderContext&); - -private: - bool m_logCalls; - bool m_forSnapshotLoad = false; - VulkanDispatch* m_vk; - VkDecoderGlobalState* m_state; - %s m_vkStream { nullptr }; - VulkanMemReadingStream m_vkMemReadingStream { nullptr }; - BoxedHandleUnwrapMapping m_boxedHandleUnwrapMapping; - BoxedHandleCreateMapping m_boxedHandleCreateMapping; - BoxedHandleDestroyMapping m_boxedHandleDestroyMapping; - BoxedHandleUnwrapAndDeleteMapping m_boxedHandleUnwrapAndDeleteMapping; - android::base::BumpPool m_pool; - BoxedHandleUnwrapAndDeletePreserveBoxedMapping m_boxedHandleUnwrapAndDeletePreserveBoxedMapping; - std::optional<uint32_t> m_prevSeqno; -}; - -VkDecoder::VkDecoder() : - mImpl(new VkDecoder::Impl()) { } - -VkDecoder::~VkDecoder() = default; - -void VkDecoder::setForSnapshotLoad(bool forSnapshotLoad) { - mImpl->setForSnapshotLoad(forSnapshotLoad); -} - -size_t VkDecoder::decode(void* buf, size_t bufsize, IOStream* stream, - const ProcessResources* processResources, - const VkDecoderContext& context) { - return mImpl->decode(buf, bufsize, stream, processResources, context); -} - -// VkDecoder::Impl::decode to follow -""" % (VULKAN_STREAM_TYPE, VULKAN_STREAM_TYPE) - -decoder_impl_postamble = """ - -} // namespace vk -} // namespace gfxstream - -""" - -READ_STREAM = "vkReadStream" -WRITE_STREAM = "vkStream" - -# Driver workarounds for APIs that don't work well multithreaded -driver_workarounds_global_lock_apis = [ \ - "vkCreatePipelineLayout", - "vkDestroyPipelineLayout", -] - -def emit_param_decl_for_reading(param, cgen): - if param.staticArrExpr: - cgen.stmt( - cgen.makeRichCTypeDecl(param.getForNonConstAccess())) - else: - cgen.stmt( - cgen.makeRichCTypeDecl(param)) - -def emit_unmarshal(typeInfo, param, cgen, output = False, destroy = False, noUnbox = False): - if destroy: - iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen( - cgen, - READ_STREAM, - ROOT_TYPE_DEFAULT_VALUE, - param.paramName, - "readStreamPtrPtr", - API_PREFIX_RESERVEDUNMARSHAL, - "", - direction="read", - dynAlloc=True)) - lenAccess = cgen.generalLengthAccess(param) - lenAccessGuard = cgen.generalLengthAccessGuard(param) - if None == lenAccess or "1" == lenAccess: - cgen.stmt("boxed_%s_preserve = %s" % (param.paramName, param.paramName)) - cgen.stmt("%s = unbox_%s(%s)" % (param.paramName, param.typeName, param.paramName)) - else: - if lenAccessGuard is not None: - cgen.beginIf(lenAccessGuard) - cgen.beginFor("uint32_t i = 0", "i < %s" % lenAccess, "++i") - cgen.stmt("boxed_%s_preserve[i] = %s[i]" % (param.paramName, param.paramName)) - cgen.stmt("((%s*)(%s))[i] = unbox_%s(%s[i])" % (param.typeName, param.paramName, param.typeName, param.paramName)) - cgen.endFor() - if lenAccessGuard is not None: - cgen.endIf() - else: - if noUnbox: - cgen.line("// No unbox for %s" % (param.paramName)) - iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen( - cgen, - READ_STREAM, - ROOT_TYPE_DEFAULT_VALUE, - param.paramName, - "readStreamPtrPtr", - API_PREFIX_RESERVEDUNMARSHAL, - "" if (output or noUnbox) else "unbox_", - direction="read", - dynAlloc=True)) - - -def emit_dispatch_unmarshal(typeInfo: VulkanTypeInfo, param: VulkanType, cgen, globalWrapped): - cgen.stmt("// Begin {} wrapped dispatchable handle unboxing for {}".format( - "global" if globalWrapped else "non", - param.paramName)) - - iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen( - cgen, - READ_STREAM, - ROOT_TYPE_DEFAULT_VALUE, - param.paramName, - "readStreamPtrPtr", - API_PREFIX_RESERVEDUNMARSHAL, - "", - direction="read", - dynAlloc=True)) - - if not globalWrapped: - cgen.stmt("auto unboxed_%s = unbox_%s(%s)" % - (param.paramName, param.typeName, param.paramName)) - cgen.stmt("auto vk = dispatch_%s(%s)" % - (param.typeName, param.paramName)) - cgen.stmt("// End manual dispatchable handle unboxing for %s" % param.paramName) - - -def emit_transform(typeInfo, param, cgen, variant="tohost"): - res = iterateVulkanType(typeInfo, param, TransformCodegen( - cgen, param.paramName, "m_state", "transform_%s_" % variant, variant)) - if not res: - cgen.stmt("(void)%s" % param.paramName) - - -def emit_marshal(typeInfo, param, cgen, handleMapOverwrites=False): - iterateVulkanType(typeInfo, param, VulkanMarshalingCodegen( - cgen, - WRITE_STREAM, - ROOT_TYPE_DEFAULT_VALUE, - param.paramName, - API_PREFIX_MARSHAL, - direction="write", - handleMapOverwrites=handleMapOverwrites)) - - -class DecodingParameters(object): - def __init__(self, api: VulkanAPI): - self.params: list[VulkanType] = [] - self.toRead: list[VulkanType] = [] - self.toWrite: list[VulkanType] = [] - - for i, param in enumerate(api.parameters): - if i == 0 and param.isDispatchableHandleType(): - param.dispatchHandle = True - - if param.isNonDispatchableHandleType() and param.isCreatedBy(api): - param.nonDispatchableHandleCreate = True - - if param.isNonDispatchableHandleType() and param.isDestroyedBy(api): - param.nonDispatchableHandleDestroy = True - - if param.isDispatchableHandleType() and param.isCreatedBy(api): - param.dispatchableHandleCreate = True - - if param.isDispatchableHandleType() and param.isDestroyedBy(api): - param.dispatchableHandleDestroy = True - - self.toRead.append(param) - - if param.possiblyOutput(): - self.toWrite.append(param) - - self.params.append(param) - - -def emit_call_log(api, cgen): - decodingParams = DecodingParameters(api) - paramsToRead = decodingParams.toRead - - cgen.beginIf("m_logCalls") - paramLogFormat = "" - paramLogArgs = [] - for p in paramsToRead: - paramLogFormat += "0x%llx " - for p in paramsToRead: - paramLogArgs.append("(unsigned long long)%s" % (p.paramName)) - cgen.stmt("fprintf(stderr, \"stream %%p: call %s %s\\n\", ioStream, %s)" % (api.name, paramLogFormat, ", ".join(paramLogArgs))) - cgen.endIf() - -def emit_decode_parameters(typeInfo: VulkanTypeInfo, api: VulkanAPI, cgen, globalWrapped=False): - decodingParams = DecodingParameters(api) - - paramsToRead = decodingParams.toRead - - for p in paramsToRead: - emit_param_decl_for_reading(p, cgen) - - for i, p in enumerate(paramsToRead): - lenAccess = cgen.generalLengthAccess(p) - - if p.dispatchHandle: - emit_dispatch_unmarshal(typeInfo, p, cgen, globalWrapped) - else: - destroy = p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy - noUnbox = api.name in ["vkQueueFlushCommandsGOOGLE", "vkQueueFlushCommandsFromAuxMemoryGOOGLE"] and p.paramName == "commandBuffer" - - if p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy: - destroy = True - cgen.stmt("// Begin manual non dispatchable handle destroy unboxing for %s" % p.paramName) - if None == lenAccess or "1" == lenAccess: - cgen.stmt("%s boxed_%s_preserve" % (p.typeName, p.paramName)) - else: - 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)) - - if p.possiblyOutput(): - cgen.stmt("// Begin manual dispatchable handle unboxing for %s" % p.paramName) - cgen.stmt("%s->unsetHandleMapping()" % READ_STREAM) - - emit_unmarshal(typeInfo, p, cgen, output = p.possiblyOutput(), destroy = destroy, noUnbox = noUnbox) - - for p in paramsToRead: - emit_transform(typeInfo, p, cgen, variant="tohost") - - emit_call_log(api, cgen) - -def emit_dispatch_call(api, cgen): - - decodingParams = DecodingParameters(api) - - customParams = [] - - delay = api.name in DELAYED_DECODER_DELETES - - for i, p in enumerate(api.parameters): - customParam = p.paramName - if decodingParams.params[i].dispatchHandle: - customParam = "unboxed_%s" % p.paramName - customParams.append(customParam) - - if delay: - cgen.line("std::function<void()> delayed_remove_callback = [vk, %s]() {" % ", ".join(customParams)) - - if api.name in driver_workarounds_global_lock_apis: - if delay: - cgen.stmt("auto state = VkDecoderGlobalState::get()") - cgen.stmt("// state already locked") - else: - cgen.stmt("m_state->lock()") - - cgen.vkApiCall(api, customPrefix="vk->", customParameters=customParams, \ - globalStatePrefix=global_state_prefix, checkForDeviceLost=True, - checkForOutOfMemory=True) - - if api.name in driver_workarounds_global_lock_apis: - if not delay: - cgen.stmt("m_state->unlock()") - # for delayed remove, state is already locked, so we do not need to - # unlock - - if delay: - cgen.line("};") - -def emit_global_state_wrapped_call(api, cgen, context): - if api.name in DELAYED_DECODER_DELETES: - print("Error: Cannot generate a global state wrapped call that is also a delayed delete (yet)"); - raise - - customParams = ["&m_pool"] + list(map(lambda p: p.paramName, api.parameters)) - if context: - customParams += ["context"] - cgen.vkApiCall(api, customPrefix=global_state_prefix, \ - customParameters=customParams, globalStatePrefix=global_state_prefix, \ - checkForDeviceLost=True, checkForOutOfMemory=True) - -def emit_decode_parameters_writeback(typeInfo, api, cgen, autobox=True): - decodingParams = DecodingParameters(api) - - paramsToWrite = decodingParams.toWrite - - cgen.stmt("%s->unsetHandleMapping()" % WRITE_STREAM) - - handleMapOverwrites = False - - for p in paramsToWrite: - emit_transform(typeInfo, p, cgen, variant="fromhost") - - handleMapOverwrites = False - - if p.nonDispatchableHandleCreate or p.dispatchableHandleCreate: - handleMapOverwrites = True - - if autobox and p.nonDispatchableHandleCreate: - cgen.stmt("// Begin auto non dispatchable handle create for %s" % p.paramName) - cgen.stmt("if (%s == VK_SUCCESS) %s->setHandleMapping(&m_boxedHandleCreateMapping)" % \ - (api.getRetVarExpr(), WRITE_STREAM)) - - if (not autobox) and p.nonDispatchableHandleCreate: - cgen.stmt("// Begin manual non dispatchable handle create for %s" % p.paramName) - cgen.stmt("%s->unsetHandleMapping()" % WRITE_STREAM) - - emit_marshal(typeInfo, p, cgen, handleMapOverwrites=handleMapOverwrites) - - if autobox and p.nonDispatchableHandleCreate: - cgen.stmt("// Begin auto non dispatchable handle create for %s" % p.paramName) - cgen.stmt("%s->setHandleMapping(&m_boxedHandleUnwrapMapping)" % WRITE_STREAM) - - if (not autobox) and p.nonDispatchableHandleCreate: - cgen.stmt("// Begin manual non dispatchable handle create for %s" % p.paramName) - cgen.stmt("%s->setHandleMapping(&m_boxedHandleUnwrapMapping)" % WRITE_STREAM) - -def emit_decode_return_writeback(api, cgen): - retTypeName = api.getRetTypeExpr() - if retTypeName != "void": - retVar = api.getRetVarExpr() - cgen.stmt("%s->write(&%s, %s)" % - (WRITE_STREAM, retVar, cgen.sizeofExpr(api.retType))) - -def emit_decode_finish(api, cgen): - decodingParams = DecodingParameters(api) - retTypeName = api.getRetTypeExpr() - paramsToWrite = decodingParams.toWrite - - if retTypeName != "void" or len(paramsToWrite) != 0: - cgen.stmt("%s->commitWrite()" % WRITE_STREAM) - -def emit_destroyed_handle_cleanup(api, cgen): - decodingParams = DecodingParameters(api) - paramsToRead = decodingParams.toRead - - skipDelete = api.name in SKIPPED_DECODER_DELETES - - if skipDelete: - cgen.line("// Skipping handle cleanup for %s" % api.name) - return - - for p in paramsToRead: - if p.dispatchHandle: - pass - else: - lenAccess = cgen.generalLengthAccess(p) - lenAccessGuard = cgen.generalLengthAccess(p) - destroy = p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy - if destroy: - if None == lenAccess or "1" == lenAccess: - if api.name in DELAYED_DECODER_DELETES: - cgen.stmt("delayed_delete_%s(boxed_%s_preserve, unboxed_device, delayed_remove_callback)" % (p.typeName, p.paramName)) - else: - cgen.stmt("delete_%s(boxed_%s_preserve)" % (p.typeName, p.paramName)) - else: - if lenAccessGuard is not None: - cgen.beginIf(lenAccessGuard) - cgen.beginFor("uint32_t i = 0", "i < %s" % lenAccess, "++i") - if api.name in DELAYED_DECODER_DELETES: - cgen.stmt("delayed_delete_%s(boxed_%s_preserve[i], unboxed_device, delayed_remove_callback)" % (p.typeName, p.paramName)) - else: - cgen.stmt("delete_%s(boxed_%s_preserve[i])" % (p.typeName, p.paramName)) - cgen.endFor() - if lenAccessGuard is not None: - cgen.endIf() - -def emit_pool_free(cgen): - cgen.stmt("%s->clearPool()" % READ_STREAM) - -def emit_seqno_incr(api, cgen): - cgen.stmt("if (queueSubmitWithCommandsEnabled) seqnoPtr->fetch_add(1, std::memory_order_seq_cst)") - -def emit_snapshot(typeInfo, api, cgen): - - cgen.stmt("%s->setReadPos((uintptr_t)(*readStreamPtrPtr) - (uintptr_t)snapshotTraceBegin)" % READ_STREAM) - cgen.stmt("size_t snapshotTraceBytes = %s->endTrace()" % READ_STREAM) - - additionalParams = [ \ - makeVulkanTypeSimple(True, "uint8_t", 1, "snapshotTraceBegin"), - makeVulkanTypeSimple(False, "size_t", 0, "snapshotTraceBytes"), - makeVulkanTypeSimple(False, "android::base::BumpPool", 1, "&m_pool"), - ] - - retTypeName = api.getRetTypeExpr() - if retTypeName != "void": - retVar = api.getRetVarExpr() - additionalParams.append(makeVulkanTypeSimple(False, retTypeName, 0, retVar)) - - paramsForSnapshot = [] - - decodingParams = DecodingParameters(api) - - for p in decodingParams.toRead: - if p.nonDispatchableHandleDestroy or (not p.dispatchHandle and p.dispatchableHandleDestroy): - paramsForSnapshot.append(p.withModifiedName("boxed_%s_preserve" % p.paramName)) - else: - paramsForSnapshot.append(p) - - customParams = additionalParams + paramsForSnapshot - - apiForSnapshot = \ - api.withCustomReturnType(makeVulkanTypeSimple(False, "void", 0, "void")). \ - withCustomParameters(customParams) - - cgen.beginIf("m_state->snapshotsEnabled()") - cgen.vkApiCall(apiForSnapshot, customPrefix="m_state->snapshot()->") - cgen.endIf() - -def emit_decoding(typeInfo, api, cgen, globalWrapped=False, context=False): - isAcquire = api.name in RELAXED_APIS - emit_decode_parameters(typeInfo, api, cgen, globalWrapped) - - if isAcquire: - emit_seqno_incr(api, cgen) - - if globalWrapped: - emit_global_state_wrapped_call(api, cgen, context) - else: - emit_dispatch_call(api, cgen) - - emit_decode_parameters_writeback(typeInfo, api, cgen, autobox=not globalWrapped) - emit_decode_return_writeback(api, cgen) - emit_decode_finish(api, cgen) - emit_snapshot(typeInfo, api, cgen) - emit_destroyed_handle_cleanup(api, cgen) - emit_pool_free(cgen) - - if not isAcquire: - emit_seqno_incr(api, cgen) - -def emit_default_decoding(typeInfo, api, cgen): - emit_decoding(typeInfo, api, cgen) - -def emit_global_state_wrapped_decoding(typeInfo, api, cgen): - emit_decoding(typeInfo, api, cgen, globalWrapped=True) - -def emit_global_state_wrapped_decoding_with_context(typeInfo, api, cgen): - emit_decoding(typeInfo, api, cgen, globalWrapped=True, context=True) - -## Custom decoding definitions################################################## -def decode_vkFlushMappedMemoryRanges(typeInfo: VulkanTypeInfo, api, cgen): - emit_decode_parameters(typeInfo, api, cgen) - - cgen.beginIf("!m_state->usingDirectMapping()") - cgen.beginFor("uint32_t i = 0", "i < memoryRangeCount", "++i") - cgen.stmt("auto range = pMemoryRanges[i]") - cgen.stmt("auto memory = pMemoryRanges[i].memory") - cgen.stmt("auto size = pMemoryRanges[i].size") - cgen.stmt("auto offset = pMemoryRanges[i].offset") - cgen.stmt("uint64_t readStream = 0") - cgen.stmt("memcpy(&readStream, *readStreamPtrPtr, sizeof(uint64_t)); *readStreamPtrPtr += sizeof(uint64_t)") - cgen.stmt("auto hostPtr = m_state->getMappedHostPointer(memory)") - cgen.stmt("if (!hostPtr && readStream > 0) GFXSTREAM_ABORT(::emugl::FatalError(::emugl::ABORT_REASON_OTHER))") - cgen.stmt("if (!hostPtr) continue") - cgen.stmt("uint8_t* targetRange = hostPtr + offset") - cgen.stmt("memcpy(targetRange, *readStreamPtrPtr, readStream); *readStreamPtrPtr += readStream") - cgen.endFor() - cgen.endIf() - - emit_dispatch_call(api, cgen) - emit_decode_parameters_writeback(typeInfo, api, cgen) - emit_decode_return_writeback(api, cgen) - emit_decode_finish(api, cgen) - emit_snapshot(typeInfo, api, cgen); - emit_pool_free(cgen) - emit_seqno_incr(api, cgen) - -def decode_vkInvalidateMappedMemoryRanges(typeInfo, api, cgen): - emit_decode_parameters(typeInfo, api, cgen) - emit_dispatch_call(api, cgen) - emit_decode_parameters_writeback(typeInfo, api, cgen) - emit_decode_return_writeback(api, cgen) - - cgen.beginIf("!m_state->usingDirectMapping()") - cgen.beginFor("uint32_t i = 0", "i < memoryRangeCount", "++i") - cgen.stmt("auto range = pMemoryRanges[i]") - cgen.stmt("auto memory = range.memory") - cgen.stmt("auto size = range.size") - cgen.stmt("auto offset = range.offset") - cgen.stmt("auto hostPtr = m_state->getMappedHostPointer(memory)") - cgen.stmt("auto actualSize = size == VK_WHOLE_SIZE ? m_state->getDeviceMemorySize(memory) : size") - cgen.stmt("uint64_t writeStream = 0") - cgen.stmt("if (!hostPtr) { %s->write(&writeStream, sizeof(uint64_t)); continue; }" % WRITE_STREAM) - cgen.stmt("uint8_t* targetRange = hostPtr + offset") - cgen.stmt("writeStream = actualSize") - cgen.stmt("%s->write(&writeStream, sizeof(uint64_t))" % WRITE_STREAM) - cgen.stmt("%s->write(targetRange, actualSize)" % WRITE_STREAM) - cgen.endFor() - cgen.endIf() - - emit_decode_finish(api, cgen) - emit_snapshot(typeInfo, api, cgen); - emit_pool_free(cgen) - emit_seqno_incr(api, cgen) - -def decode_unsupported_api(typeInfo, api, cgen): - cgen.line(f"// Decoding {api.name} is not supported. This should not run.") - cgen.stmt(f"fprintf(stderr, \"stream %p: fatal: decoding unsupported API {api.name}\\n\", ioStream)"); - cgen.stmt("__builtin_trap()") - -custom_decodes = { - "vkEnumerateInstanceVersion" : emit_global_state_wrapped_decoding, - "vkCreateInstance" : emit_global_state_wrapped_decoding, - "vkDestroyInstance" : emit_global_state_wrapped_decoding, - "vkEnumeratePhysicalDevices" : emit_global_state_wrapped_decoding, - - "vkGetPhysicalDeviceFeatures" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceFeatures2" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceFeatures2KHR" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceFormatProperties" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceFormatProperties2" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceFormatProperties2KHR" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceImageFormatProperties" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceImageFormatProperties2" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceImageFormatProperties2KHR" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceProperties" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceProperties2" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceProperties2KHR" : emit_global_state_wrapped_decoding, - - "vkGetPhysicalDeviceMemoryProperties" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceMemoryProperties2" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceMemoryProperties2KHR" : emit_global_state_wrapped_decoding, - - "vkGetPhysicalDeviceExternalSemaphoreProperties" : emit_global_state_wrapped_decoding, - "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR" : emit_global_state_wrapped_decoding, - - "vkEnumerateDeviceExtensionProperties" : emit_global_state_wrapped_decoding, - - "vkCreateBuffer" : emit_global_state_wrapped_decoding, - "vkDestroyBuffer" : emit_global_state_wrapped_decoding, - - "vkBindBufferMemory" : emit_global_state_wrapped_decoding, - "vkBindBufferMemory2" : emit_global_state_wrapped_decoding, - "vkBindBufferMemory2KHR" : emit_global_state_wrapped_decoding, - - "vkCreateDevice" : emit_global_state_wrapped_decoding, - "vkGetDeviceQueue" : emit_global_state_wrapped_decoding, - "vkDestroyDevice" : emit_global_state_wrapped_decoding, - - "vkGetDeviceQueue2" : emit_global_state_wrapped_decoding, - - "vkBindImageMemory" : emit_global_state_wrapped_decoding, - "vkBindImageMemory2" : emit_global_state_wrapped_decoding, - "vkBindImageMemory2KHR" : emit_global_state_wrapped_decoding, - - "vkCreateImage" : emit_global_state_wrapped_decoding, - "vkCreateImageView" : emit_global_state_wrapped_decoding, - "vkCreateSampler" : emit_global_state_wrapped_decoding, - "vkDestroyImage" : emit_global_state_wrapped_decoding, - "vkDestroyImageView" : emit_global_state_wrapped_decoding, - "vkDestroySampler" : emit_global_state_wrapped_decoding, - "vkCmdCopyBufferToImage" : emit_global_state_wrapped_decoding_with_context, - "vkCmdCopyImage" : emit_global_state_wrapped_decoding, - "vkCmdCopyImageToBuffer" : emit_global_state_wrapped_decoding, - "vkGetImageMemoryRequirements" : emit_global_state_wrapped_decoding, - "vkGetImageMemoryRequirements2" : emit_global_state_wrapped_decoding, - "vkGetImageMemoryRequirements2KHR" : emit_global_state_wrapped_decoding, - "vkGetBufferMemoryRequirements" : emit_global_state_wrapped_decoding, - "vkGetBufferMemoryRequirements2": emit_global_state_wrapped_decoding, - "vkGetBufferMemoryRequirements2KHR": emit_global_state_wrapped_decoding, - - "vkCreateDescriptorSetLayout" : emit_global_state_wrapped_decoding, - "vkDestroyDescriptorSetLayout" : emit_global_state_wrapped_decoding, - "vkCreateDescriptorPool" : emit_global_state_wrapped_decoding, - "vkDestroyDescriptorPool" : emit_global_state_wrapped_decoding, - "vkResetDescriptorPool" : emit_global_state_wrapped_decoding, - "vkAllocateDescriptorSets" : emit_global_state_wrapped_decoding, - "vkFreeDescriptorSets" : emit_global_state_wrapped_decoding, - - "vkUpdateDescriptorSets" : emit_global_state_wrapped_decoding, - - "vkCreateShaderModule": emit_global_state_wrapped_decoding, - "vkDestroyShaderModule": emit_global_state_wrapped_decoding, - "vkCreatePipelineCache": emit_global_state_wrapped_decoding, - "vkDestroyPipelineCache": emit_global_state_wrapped_decoding, - "vkCreateGraphicsPipelines": emit_global_state_wrapped_decoding, - "vkDestroyPipeline": emit_global_state_wrapped_decoding, - - "vkAllocateMemory" : emit_global_state_wrapped_decoding, - "vkFreeMemory" : emit_global_state_wrapped_decoding, - "vkMapMemory" : emit_global_state_wrapped_decoding, - "vkUnmapMemory" : emit_global_state_wrapped_decoding, - "vkFlushMappedMemoryRanges" : decode_vkFlushMappedMemoryRanges, - "vkInvalidateMappedMemoryRanges" : decode_vkInvalidateMappedMemoryRanges, - - "vkAllocateCommandBuffers" : emit_global_state_wrapped_decoding, - "vkCmdExecuteCommands" : emit_global_state_wrapped_decoding, - "vkQueueSubmit" : emit_global_state_wrapped_decoding, - "vkQueueWaitIdle" : emit_global_state_wrapped_decoding, - "vkBeginCommandBuffer" : emit_global_state_wrapped_decoding_with_context, - "vkEndCommandBuffer" : emit_global_state_wrapped_decoding_with_context, - "vkResetCommandBuffer" : emit_global_state_wrapped_decoding, - "vkFreeCommandBuffers" : emit_global_state_wrapped_decoding, - "vkCreateCommandPool" : emit_global_state_wrapped_decoding, - "vkDestroyCommandPool" : emit_global_state_wrapped_decoding, - "vkResetCommandPool" : emit_global_state_wrapped_decoding, - "vkCmdPipelineBarrier" : emit_global_state_wrapped_decoding, - "vkCmdBindPipeline" : emit_global_state_wrapped_decoding, - "vkCmdBindDescriptorSets" : emit_global_state_wrapped_decoding, - - "vkCreateRenderPass" : emit_global_state_wrapped_decoding, - "vkCreateRenderPass2" : emit_global_state_wrapped_decoding, - "vkCreateRenderPass2KHR" : emit_global_state_wrapped_decoding, - "vkDestroyRenderPass" : emit_global_state_wrapped_decoding, - "vkCreateFramebuffer" : emit_global_state_wrapped_decoding, - "vkDestroyFramebuffer" : emit_global_state_wrapped_decoding, - - "vkCreateSamplerYcbcrConversion": emit_global_state_wrapped_decoding, - "vkDestroySamplerYcbcrConversion": emit_global_state_wrapped_decoding, - - # VK_ANDROID_native_buffer - "vkGetSwapchainGrallocUsageANDROID" : emit_global_state_wrapped_decoding, - "vkGetSwapchainGrallocUsage2ANDROID" : emit_global_state_wrapped_decoding, - "vkAcquireImageANDROID" : emit_global_state_wrapped_decoding, - "vkQueueSignalReleaseImageANDROID" : emit_global_state_wrapped_decoding, - - "vkCreateSemaphore" : emit_global_state_wrapped_decoding, - "vkGetSemaphoreFdKHR" : emit_global_state_wrapped_decoding, - "vkImportSemaphoreFdKHR" : emit_global_state_wrapped_decoding, - "vkDestroySemaphore" : emit_global_state_wrapped_decoding, - - "vkCreateFence" : emit_global_state_wrapped_decoding, - "vkResetFences" : emit_global_state_wrapped_decoding, - "vkDestroyFence" : emit_global_state_wrapped_decoding, - - # VK_GOOGLE_gfxstream - "vkFreeMemorySyncGOOGLE" : emit_global_state_wrapped_decoding, - "vkMapMemoryIntoAddressSpaceGOOGLE" : emit_global_state_wrapped_decoding, - "vkGetMemoryHostAddressInfoGOOGLE" : emit_global_state_wrapped_decoding, - "vkGetBlobGOOGLE" : emit_global_state_wrapped_decoding, - - # Descriptor update templates - "vkCreateDescriptorUpdateTemplate" : emit_global_state_wrapped_decoding, - "vkCreateDescriptorUpdateTemplateKHR" : emit_global_state_wrapped_decoding, - "vkDestroyDescriptorUpdateTemplate" : emit_global_state_wrapped_decoding, - "vkDestroyDescriptorUpdateTemplateKHR" : emit_global_state_wrapped_decoding, - "vkUpdateDescriptorSetWithTemplateSizedGOOGLE" : emit_global_state_wrapped_decoding, - - # VK_GOOGLE_gfxstream - "vkBeginCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding_with_context, - "vkEndCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding_with_context, - "vkResetCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding, - "vkCommandBufferHostSyncGOOGLE" : emit_global_state_wrapped_decoding, - "vkCreateImageWithRequirementsGOOGLE" : emit_global_state_wrapped_decoding, - "vkCreateBufferWithRequirementsGOOGLE" : emit_global_state_wrapped_decoding, - "vkQueueHostSyncGOOGLE" : emit_global_state_wrapped_decoding, - "vkQueueSubmitAsyncGOOGLE" : emit_global_state_wrapped_decoding, - "vkQueueWaitIdleAsyncGOOGLE" : emit_global_state_wrapped_decoding, - "vkQueueBindSparseAsyncGOOGLE" : emit_global_state_wrapped_decoding, - "vkGetLinearImageLayoutGOOGLE" : emit_global_state_wrapped_decoding, - "vkGetLinearImageLayout2GOOGLE" : emit_global_state_wrapped_decoding, - "vkQueueFlushCommandsGOOGLE" : emit_global_state_wrapped_decoding_with_context, - "vkQueueFlushCommandsFromAuxMemoryGOOGLE" : emit_global_state_wrapped_decoding_with_context, - "vkQueueCommitDescriptorSetUpdatesGOOGLE" : emit_global_state_wrapped_decoding, - "vkCollectDescriptorPoolIdsGOOGLE" : emit_global_state_wrapped_decoding, - "vkQueueSignalReleaseImageANDROIDAsyncGOOGLE" : emit_global_state_wrapped_decoding, - - "vkQueueBindSparse" : emit_global_state_wrapped_decoding, - - # VK_KHR_xcb_surface - "vkCreateXcbSurfaceKHR": decode_unsupported_api, - "vkGetPhysicalDeviceXcbPresentationSupportKHR": decode_unsupported_api, - - # VK_EXT_metal_surface - "vkCreateMetalSurfaceEXT": decode_unsupported_api, - - # VK_KHR_sampler_ycbcr_conversion - "vkCreateSamplerYcbcrConversionKHR": emit_global_state_wrapped_decoding, - "vkDestroySamplerYcbcrConversionKHR": emit_global_state_wrapped_decoding, -} - -class VulkanDecoder(VulkanWrapperGenerator): - def __init__(self, module, typeInfo): - VulkanWrapperGenerator.__init__(self, module, typeInfo) - self.typeInfo: VulkanTypeInfo = typeInfo - self.cgen = CodeGen() - - def onBegin(self,): - self.module.appendImpl( - "#define MAX_PACKET_LENGTH %s\n" % MAX_PACKET_LENGTH) - self.module.appendHeader(decoder_decl_preamble) - self.module.appendImpl(decoder_impl_preamble) - - self.module.appendImpl( - """ -size_t VkDecoder::Impl::decode(void* buf, size_t len, IOStream* ioStream, - const ProcessResources* processResources, - const VkDecoderContext& context) -""") - - self.cgen.beginBlock() # function body - - self.cgen.stmt("const char* processName = context.processName") - self.cgen.stmt("auto& gfx_logger = *context.gfxApiLogger") - self.cgen.stmt("auto* healthMonitor = context.healthMonitor") - self.cgen.stmt("auto& metricsLogger = *context.metricsLogger") - self.cgen.stmt("if (len < 8) return 0") - self.cgen.stmt("bool queueSubmitWithCommandsEnabled = feature_is_enabled(kFeature_VulkanQueueSubmitWithCommands)") - self.cgen.stmt("unsigned char *ptr = (unsigned char *)buf") - self.cgen.stmt("const unsigned char* const end = (const unsigned char*)buf + len") - - self.cgen.beginIf("m_forSnapshotLoad") - self.cgen.stmt("ptr += m_state->setCreatedHandlesForSnapshotLoad(ptr)"); - self.cgen.endIf() - self.cgen.line("while (end - ptr >= 8)") - self.cgen.beginBlock() # while loop - - self.cgen.stmt("uint32_t opcode = *(uint32_t *)ptr") - self.cgen.stmt("uint32_t packetLen = *(uint32_t *)(ptr + 4)") - self.cgen.line(""" - // packetLen should be at least 8 (op code and packet length) and should not be excessively large - if (packetLen < 8 || packetLen > MAX_PACKET_LENGTH) { - WARN("Bad packet length %d detected, decode may fail", packetLen); - metricsLogger.logMetricEvent(MetricEventBadPacketLength{ .len = packetLen }); - } - """) - self.cgen.stmt("if (end - ptr < packetLen) return ptr - (unsigned char*)buf") - self.cgen.stmt("gfx_logger.record(ptr, std::min(size_t(packetLen + 8), size_t(end - ptr)))") - - self.cgen.stmt("stream()->setStream(ioStream)") - self.cgen.stmt("VulkanStream* %s = stream()" % WRITE_STREAM) - self.cgen.stmt("VulkanMemReadingStream* %s = readStream()" % READ_STREAM) - self.cgen.stmt("%s->setBuf((uint8_t*)(ptr + 8))" % READ_STREAM) - self.cgen.stmt("uint8_t* readStreamPtr = %s->getBuf(); uint8_t** readStreamPtrPtr = &readStreamPtr" % READ_STREAM) - self.cgen.stmt("uint8_t* snapshotTraceBegin = %s->beginTrace()" % READ_STREAM) - self.cgen.stmt("%s->setHandleMapping(&m_boxedHandleUnwrapMapping)" % READ_STREAM) - self.cgen.line(""" - std::unique_ptr<EventHangMetadata::HangAnnotations> executionData = - std::make_unique<EventHangMetadata::HangAnnotations>(); - if (healthMonitor) { - executionData->insert( - {{"packet_length", std::to_string(packetLen)}, - {"opcode", std::to_string(opcode)}}); - if (processName) { - executionData->insert( - {{"renderthread_guest_process", std::string(processName)}}); - } - if (m_prevSeqno) { - executionData->insert({{"previous_seqno", std::to_string(m_prevSeqno.value())}}); - } - } - - std::atomic<uint32_t>* seqnoPtr = processResources->getSequenceNumberPtr(); - - if (queueSubmitWithCommandsEnabled && ((opcode >= OP_vkFirst && opcode < OP_vkLast) || (opcode >= OP_vkFirst_old && opcode < OP_vkLast_old))) { - uint32_t seqno; - memcpy(&seqno, *readStreamPtrPtr, sizeof(uint32_t)); *readStreamPtrPtr += sizeof(uint32_t); - if (healthMonitor) executionData->insert({{"seqno", std::to_string(seqno)}}); - if (m_prevSeqno && seqno == m_prevSeqno.value()) { - WARN( - "Seqno %d is the same as previously processed on thread %d. It might be a " - "duplicate command.", - seqno, getCurrentThreadId()); - metricsLogger.logMetricEvent(MetricEventDuplicateSequenceNum{ .opcode = opcode }); - } - if (seqnoPtr && !m_forSnapshotLoad) { - { - auto seqnoWatchdog = - WATCHDOG_BUILDER(healthMonitor, - "RenderThread seqno loop") - .setHangType(EventHangMetadata::HangType::kRenderThread) - .setAnnotations(std::make_unique<EventHangMetadata::HangAnnotations>(*executionData)) - /* Data gathered if this hangs*/ - .setOnHangCallback([=]() { - auto annotations = std::make_unique<EventHangMetadata::HangAnnotations>(); - annotations->insert({{"seqnoPtr", std::to_string(seqnoPtr->load(std::memory_order_seq_cst))}}); - return annotations; - }) - .build(); - while ((seqno - seqnoPtr->load(std::memory_order_seq_cst) != 1)) { - #if (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))) - _mm_pause(); - #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) - __asm__ __volatile__("pause;"); - #endif - } - m_prevSeqno = seqno; - } - } - } - """) - - self.cgen.line(""" - gfx_logger.recordCommandExecution(); - """) - - self.cgen.line(""" - auto executionWatchdog = - WATCHDOG_BUILDER(healthMonitor, "RenderThread VkDecoder command execution") - .setHangType(EventHangMetadata::HangType::kRenderThread) - .setAnnotations(std::move(executionData)) - .build(); - """) - - self.cgen.stmt("auto vk = m_vk") - - self.cgen.line("switch (opcode)") - self.cgen.beginBlock() # switch stmt - - self.module.appendImpl(self.cgen.swapCode()) - - def onGenCmd(self, cmdinfo, name, alias): - typeInfo = self.typeInfo - cgen = self.cgen - api: VulkanAPI = typeInfo.apis[name] - - cgen.line("case OP_%s:" % name) - cgen.beginBlock() - cgen.stmt("android::base::beginTrace(\"%s decode\")" % name) - - if api.name in custom_decodes.keys(): - custom_decodes[api.name](typeInfo, api, cgen) - else: - emit_default_decoding(typeInfo, api, cgen) - - cgen.stmt("android::base::endTrace()") - cgen.stmt("break") - cgen.endBlock() - self.module.appendImpl(self.cgen.swapCode()) - - def onEnd(self,): - self.cgen.line("default:") - self.cgen.beginBlock() - self.cgen.stmt("m_pool.freeAll()") - self.cgen.stmt("return ptr - (unsigned char *)buf") - self.cgen.endBlock() - - self.cgen.endBlock() # switch stmt - - self.cgen.stmt("ptr += packetLen") - self.cgen.endBlock() # while loop - - self.cgen.beginIf("m_forSnapshotLoad") - self.cgen.stmt("m_state->clearCreatedHandlesForSnapshotLoad()"); - self.cgen.endIf() - - self.cgen.stmt("m_pool.freeAll()") - self.cgen.stmt("return ptr - (unsigned char*)buf;") - self.cgen.endBlock() # function body - self.module.appendImpl(self.cgen.swapCode()) - self.module.appendImpl(decoder_impl_postamble) |