import copy from .common.codegen import CodeGen, VulkanWrapperGenerator from .common.vulkantypes import \ VulkanAPI, makeVulkanTypeSimple, iterateVulkanType from .marshaling import VulkanMarshalingCodegen from .reservedmarshaling import VulkanReservedMarshalingCodegen from .counting import VulkanCountingCodegen from .handlemap import HandleMapCodegen from .deepcopy import DeepcopyCodegen from .transform import TransformCodegen, genTransformsForVulkanType from .wrapperdefs import API_PREFIX_RESERVEDMARSHAL from .wrapperdefs import API_PREFIX_MARSHAL from .wrapperdefs import API_PREFIX_UNMARSHAL from .wrapperdefs import ROOT_TYPE_DEFAULT_VALUE from .wrapperdefs import VULKAN_STREAM_TYPE_GUEST encoder_decl_preamble = """ class VkEncoder { public: VkEncoder(gfxstream::guest::IOStream* stream, gfxstream::guest::HealthMonitor<>* healthMonitor = nullptr); ~VkEncoder(); #include "VkEncoder.h.inl" """ encoder_decl_postamble = """ private: class Impl; std::unique_ptr mImpl; gfxstream::guest::HealthMonitor<>* mHealthMonitor; }; """ encoder_impl_preamble =""" using namespace gfxstream::vk; using gfxstream::guest::AutoLock; using gfxstream::guest::Lock; using gfxstream::guest::BumpPool; #include "VkEncoder.cpp.inl" #define VALIDATE_RET(retType, success, validate) \\ retType goldfish_vk_validateResult = validate; \\ if (goldfish_vk_validateResult != success) return goldfish_vk_validateResult; \\ #define VALIDATE_VOID(validate) \\ VkResult goldfish_vk_validateResult = validate; \\ if (goldfish_vk_validateResult != VK_SUCCESS) return; \\ """ STREAM = "stream" RESOURCES = "sResourceTracker" POOL = "pool" ENCODER_PREVALIDATED_APIS = [ "vkFlushMappedMemoryRanges", "vkInvalidateMappedMemoryRanges", ] ENCODER_CUSTOM_RESOURCE_PREPROCESS = [ "vkMapMemoryIntoAddressSpaceGOOGLE", "vkDestroyDevice", ] ENCODER_CUSTOM_RESOURCE_POSTPROCESS = [ "vkCreateInstance", "vkCreateDevice", "vkMapMemoryIntoAddressSpaceGOOGLE", "vkGetPhysicalDeviceFeatures2", "vkGetPhysicalDeviceFeatures2KHR", "vkGetPhysicalDeviceProperties", "vkGetPhysicalDeviceProperties2", "vkGetPhysicalDeviceProperties2KHR", "vkCreateDescriptorUpdateTemplate", "vkCreateDescriptorUpdateTemplateKHR", "vkGetPhysicalDeviceExternalSemaphoreProperties", "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR", "vkGetDeviceQueue", "vkGetDeviceQueue2", ] ENCODER_EXPLICIT_FLUSHED_APIS = [ "vkEndCommandBufferAsyncGOOGLE", "vkQueueSubmitAsyncGOOGLE", "vkQueueBindSparseAsyncGOOGLE", "vkQueueWaitIdleAsyncGOOGLE", "vkQueueSignalReleaseImageANDROID", "vkDestroyDevice", ] SUCCESS_RET_TYPES = { "VkResult" : "VK_SUCCESS", "void" : None, # TODO: Put up success results for other return types here. } ENCODER_THIS_PARAM = makeVulkanTypeSimple(False, "VkEncoder", 1, "this") # Common components of encoding a Vulkan API call def make_event_handler_call( handler_access, api, context_param, input_result_param, cgen, suffix=""): extraParams = [context_param.paramName] if input_result_param: extraParams.append(input_result_param) return cgen.makeCallExpr( \ "%s->on_%s%s" % (handler_access, api.name, suffix), extraParams + \ [p.paramName for p in api.parameters[:-1]]) def emit_custom_pre_validate(typeInfo, api, cgen): if api.name in ENCODER_PREVALIDATED_APIS: callExpr = \ make_event_handler_call( \ "mImpl->validation()", api, ENCODER_THIS_PARAM, SUCCESS_RET_TYPES[api.getRetTypeExpr()], cgen) if api.getRetTypeExpr() == "void": cgen.stmt("VALIDATE_VOID(%s)" % callExpr) else: cgen.stmt("VALIDATE_RET(%s, %s, %s)" % \ (api.getRetTypeExpr(), SUCCESS_RET_TYPES[api.getRetTypeExpr()], callExpr)) def emit_custom_resource_preprocess(typeInfo, api, cgen): if api.name in ENCODER_CUSTOM_RESOURCE_PREPROCESS: cgen.stmt( \ make_event_handler_call( \ "sResourceTracker", api, ENCODER_THIS_PARAM, SUCCESS_RET_TYPES[api.getRetTypeExpr()], cgen, suffix="_pre")) def emit_custom_resource_postprocess(typeInfo, api, cgen): if api.name in ENCODER_CUSTOM_RESOURCE_POSTPROCESS: cgen.stmt(make_event_handler_call( \ "sResourceTracker", api, ENCODER_THIS_PARAM, api.getRetVarExpr(), cgen)) def emit_count_marshal(typeInfo, param, cgen): res = \ iterateVulkanType( typeInfo, param, VulkanCountingCodegen( \ cgen, "sFeatureBits", param.paramName, "countPtr", ROOT_TYPE_DEFAULT_VALUE, "count_")) if not res: cgen.stmt("(void)%s" % param.paramName) def emit_marshal(typeInfo, param, cgen): forOutput = param.isHandleType() and ("out" in param.inout) if forOutput: cgen.stmt("/* is handle, possibly out */") res = \ iterateVulkanType( typeInfo, param, VulkanReservedMarshalingCodegen( \ cgen, "guest", STREAM, ROOT_TYPE_DEFAULT_VALUE, param.paramName, "streamPtrPtr", API_PREFIX_RESERVEDMARSHAL, "" if forOutput else "get_host_u64_", direction="write")) if not res: cgen.stmt("(void)%s" % param.paramName) if forOutput: cgen.stmt("/* is handle, possibly out */") def emit_unmarshal(typeInfo, param, cgen): iterateVulkanType( typeInfo, param, VulkanMarshalingCodegen( \ cgen, STREAM, ROOT_TYPE_DEFAULT_VALUE, param.paramName, API_PREFIX_UNMARSHAL, direction="read")) def emit_deepcopy(typeInfo, param, cgen): res = \ iterateVulkanType(typeInfo, param, DeepcopyCodegen( cgen, [param.paramName, "local_" + param.paramName], "pool", ROOT_TYPE_DEFAULT_VALUE, "deepcopy_")) if not res: cgen.stmt("(void)%s" % param.paramName) def emit_transform(typeInfo, param, cgen, variant="tohost"): res = \ iterateVulkanType(typeInfo, param, TransformCodegen( \ cgen, param.paramName, "sResourceTracker", "transform_%s_" % variant, variant)) if not res: cgen.stmt("(void)%s" % param.paramName) def emit_handlemap_create(typeInfo, param, cgen): iterateVulkanType(typeInfo, param, HandleMapCodegen( cgen, None, "sResourceTracker", "handlemap_", lambda vtype: typeInfo.isHandleType(vtype.typeName) )) def custom_encoder_args(api): params = ["this"] if api.getRetVarExpr() is not None: params.append(api.getRetVarExpr()) return params def emit_handlemap_destroy(typeInfo, param, cgen): iterateVulkanType(typeInfo, param, HandleMapCodegen( cgen, None, "sResourceTracker->destroyMapping()", "handlemap_", lambda vtype: typeInfo.isHandleType(vtype.typeName) )) class EncodingParameters(object): def __init__(self, api): self.localCopied = [] self.toWrite = [] self.toRead = [] self.toCreate = [] self.toDestroy = [] for param in api.parameters: param.action = None param.inout = "in" if param.paramName == "doLock": continue if param.possiblyOutput(): param.inout += "out" self.toWrite.append(param) self.toRead.append(param) if param.isCreatedBy(api): self.toCreate.append(param) param.action = "create" else: if param.paramName == "doLock": continue if param.isDestroyedBy(api): self.toDestroy.append(param) param.action = "destroy" localCopyParam = \ param.getForNonConstAccess().withModifiedName( \ "local_" + param.paramName) self.localCopied.append((param, localCopyParam)) self.toWrite.append(localCopyParam) def emit_parameter_encode_preamble_write(typeInfo, api, cgen): emit_custom_pre_validate(typeInfo, api, cgen); emit_custom_resource_preprocess(typeInfo, api, cgen); cgen.stmt("auto %s = mImpl->stream()" % STREAM) cgen.stmt("auto %s = mImpl->pool()" % POOL) # cgen.stmt("%s->setHandleMapping(%s->unwrapMapping())" % (STREAM, RESOURCES)) encodingParams = EncodingParameters(api) for (_, localCopyParam) in encodingParams.localCopied: cgen.stmt(cgen.makeRichCTypeDecl(localCopyParam)) def emit_parameter_encode_copy_unwrap_count(typeInfo, api, cgen, customUnwrap=None): encodingParams = EncodingParameters(api) for (origParam, localCopyParam) in encodingParams.localCopied: shouldCustomCopy = \ customUnwrap and \ origParam.paramName in customUnwrap and \ "copyOp" in customUnwrap[origParam.paramName] shouldCustomMap = \ customUnwrap and \ origParam.paramName in customUnwrap and \ "mapOp" in customUnwrap[origParam.paramName] if shouldCustomCopy: customUnwrap[origParam.paramName]["copyOp"](cgen, origParam, localCopyParam) else: # if this is a pointer type and we don't do custom copy nor unwrap, # and the transform doesn't end up doing anything, # don't deepcopy, just cast it. avoidDeepcopy = False if origParam.pointerIndirectionLevels > 0: testCgen = CodeGen() genTransformsForVulkanType("sResourceTracker", origParam, lambda p: testCgen.generalAccess(p, parentVarName = None, asPtr = True), lambda p: testCgen.generalLengthAccess(p, parentVarName = None), testCgen) emit_transform(typeInfo, origParam, testCgen, variant="tohost") if "" == testCgen.swapCode(): avoidDeepcopy = True if avoidDeepcopy: cgen.line("// Avoiding deepcopy for %s" % origParam.paramName) cgen.stmt("%s = (%s%s)%s" % (localCopyParam.paramName, localCopyParam.typeName, "*" * origParam.pointerIndirectionLevels, origParam.paramName)) else: emit_deepcopy(typeInfo, origParam, cgen) for (origParam, localCopyParam) in encodingParams.localCopied: shouldCustomMap = \ customUnwrap and \ origParam.paramName in customUnwrap and \ "mapOp" in customUnwrap[origParam.paramName] if shouldCustomMap: customUnwrap[origParam.paramName]["mapOp"](cgen, origParam, localCopyParam) else: if localCopyParam.typeName == "VkAllocationCallbacks": cgen.stmt("%s = nullptr" % localCopyParam.paramName) apiForTransform = \ api.withCustomParameters( \ map(lambda p: p[1], \ encodingParams.localCopied)) # Apply transforms if applicable. # Apply transform to API itself: genTransformsForVulkanType( "sResourceTracker", apiForTransform, lambda p: cgen.generalAccess(p, parentVarName = None, asPtr = True), lambda p: cgen.generalLengthAccess(p, parentVarName = None), cgen) # For all local copied parameters, run the transforms for localParam in apiForTransform.parameters: if "doLock" in localParam.paramName: continue emit_transform(typeInfo, localParam, cgen, variant="tohost") cgen.stmt("size_t count = 0") cgen.stmt("size_t* countPtr = &count") cgen.beginBlock() # Use counting stream to calculate the packet size. for p in encodingParams.toWrite: emit_count_marshal(typeInfo, p, cgen) cgen.endBlock() def is_cmdbuf_dispatch(api): return "VkCommandBuffer" == api.parameters[0].typeName def emit_parameter_encode_write_packet_info(typeInfo, api, cgen): # Seqno and skipping dispatch serialize are for use with VULKAN_STREAM_FEATURE_QUEUE_SUBMIT_WITH_COMMANDS_BIT doSeqno = True doDispatchSerialize = True if is_cmdbuf_dispatch(api): doSeqno = False doDispatchSerialize = False if doSeqno: cgen.stmt("uint32_t packetSize_%s = 4 + 4 + (queueSubmitWithCommandsEnabled ? 4 : 0) + count" % (api.name)) else: cgen.stmt("uint32_t packetSize_%s = 4 + 4 + count" % (api.name)) cgen.stmt("healthMonitorAnnotation_packetSize = std::make_optional(packetSize_%s)" % (api.name)) if not doDispatchSerialize: cgen.stmt("if (queueSubmitWithCommandsEnabled) packetSize_%s -= 8" % api.name) cgen.stmt("uint8_t* streamPtr = %s->reserve(packetSize_%s)" % (STREAM, api.name)) cgen.stmt("uint8_t* packetBeginPtr = streamPtr") cgen.stmt("uint8_t** streamPtrPtr = &streamPtr") cgen.stmt("uint32_t opcode_%s = OP_%s" % (api.name, api.name)) if doSeqno: cgen.stmt("uint32_t seqno; if (queueSubmitWithCommandsEnabled) seqno = ResourceTracker::nextSeqno()") cgen.stmt("healthMonitorAnnotation_seqno = std::make_optional(seqno)") cgen.stmt("memcpy(streamPtr, &opcode_%s, sizeof(uint32_t)); streamPtr += sizeof(uint32_t)" % api.name) cgen.stmt("memcpy(streamPtr, &packetSize_%s, sizeof(uint32_t)); streamPtr += sizeof(uint32_t)" % api.name) if doSeqno: cgen.line("if (queueSubmitWithCommandsEnabled) { memcpy(streamPtr, &seqno, sizeof(uint32_t)); streamPtr += sizeof(uint32_t); }") def emit_parameter_encode_do_parameter_write(typeInfo, api, cgen): encodingParams = EncodingParameters(api) dispatchDone = False for p in encodingParams.toWrite: if is_cmdbuf_dispatch(api) and not dispatchDone: cgen.beginIf("!queueSubmitWithCommandsEnabled") emit_marshal(typeInfo, p, cgen) cgen.endIf() else: emit_marshal(typeInfo, p, cgen) dispatchDone = True cgen.beginIf("watchdog") cgen.stmt("size_t watchdogBufSize = std::min(static_cast(packetSize_%s), kWatchdogBufferMax)" % (api.name)) cgen.stmt("healthMonitorAnnotation_packetContents.resize(watchdogBufSize)") cgen.stmt("memcpy(&healthMonitorAnnotation_packetContents[0], packetBeginPtr, watchdogBufSize)") cgen.endIf() def emit_parameter_encode_read(typeInfo, api, cgen): encodingParams = EncodingParameters(api) for p in encodingParams.toRead: if p.action == "create": cgen.stmt( "%s->setHandleMapping(%s->createMapping())" % \ (STREAM, RESOURCES)) emit_unmarshal(typeInfo, p, cgen) if p.action == "create": cgen.stmt( "%s->unsetHandleMapping()" % STREAM) emit_transform(typeInfo, p, cgen, variant="fromhost") def emit_post(typeInfo, api, cgen): encodingParams = EncodingParameters(api) emit_custom_resource_postprocess(typeInfo, api, cgen) for p in encodingParams.toDestroy: emit_handlemap_destroy(typeInfo, p, cgen) doSeqno = True if is_cmdbuf_dispatch(api): doSeqno = False retType = api.getRetTypeExpr() if api.name in ENCODER_EXPLICIT_FLUSHED_APIS: cgen.stmt("stream->flush()"); return if doSeqno: if retType == "void": encodingParams = EncodingParameters(api) if 0 == len(encodingParams.toRead): cgen.stmt("stream->flush()"); def emit_pool_free(cgen): cgen.stmt("++encodeCount") cgen.beginIf("0 == encodeCount % POOL_CLEAR_INTERVAL") cgen.stmt("pool->freeAll()") cgen.stmt("%s->clearPool()" % STREAM) cgen.endIf() def emit_return_unmarshal(typeInfo, api, cgen): retType = api.getRetTypeExpr() if retType == "void": return retVar = api.getRetVarExpr() cgen.stmt("%s %s = (%s)0" % (retType, retVar, retType)) cgen.stmt("%s->read(&%s, %s)" % \ (STREAM, retVar, cgen.sizeofExpr(api.retType))) def emit_return(typeInfo, api, cgen): if api.getRetTypeExpr() == "void": return retVar = api.getRetVarExpr() cgen.stmt("return %s" % retVar) def emit_lock(cgen): cgen.stmt("(void)doLock"); cgen.stmt("bool queueSubmitWithCommandsEnabled = sFeatureBits & VULKAN_STREAM_FEATURE_QUEUE_SUBMIT_WITH_COMMANDS_BIT") cgen.stmt("if (!queueSubmitWithCommandsEnabled && doLock) this->lock()") def emit_unlock(cgen): cgen.stmt("if (!queueSubmitWithCommandsEnabled && doLock) this->unlock()") def emit_debug_log(typeInfo, api, cgen): logFormat = [] logVargs = [] for param in api.parameters: if param.paramName == "doLock": continue paramFormatSpecifier = param.getPrintFormatSpecifier() if not paramFormatSpecifier: continue logFormat.append(param.paramName + ":" + paramFormatSpecifier) logVargs.append(param.paramName) logFormatStr = ", ".join(logFormat) logVargsStr = ", ".join(logVargs) cgen.stmt("ENCODER_DEBUG_LOG(\"%s(%s)\", %s)" % (api.name, logFormatStr, logVargsStr)) def emit_health_watchdog(api, cgen): cgen.stmt("std::optional healthMonitorAnnotation_seqno = std::nullopt") cgen.stmt("std::optional healthMonitorAnnotation_packetSize = std::nullopt") cgen.stmt("std::vector healthMonitorAnnotation_packetContents") cgen.line(""" auto watchdog = WATCHDOG_BUILDER(mHealthMonitor, \"%s in VkEncoder\") .setOnHangCallback([&]() { auto annotations = std::make_unique(); if (healthMonitorAnnotation_seqno) { annotations->insert({{"seqno", std::to_string(healthMonitorAnnotation_seqno.value())}}); } if (healthMonitorAnnotation_packetSize) { annotations->insert({{"packetSize", std::to_string(healthMonitorAnnotation_packetSize.value())}}); } if (!healthMonitorAnnotation_packetContents.empty()) { annotations->insert( {{"packetContents", getPacketContents( &healthMonitorAnnotation_packetContents[0], healthMonitorAnnotation_packetContents.size())}}); } return std::move(annotations); }) .build(); """% (api.name) ) def emit_default_encoding(typeInfo, api, cgen): emit_debug_log(typeInfo, api, cgen) emit_lock(cgen) emit_parameter_encode_preamble_write(typeInfo, api, cgen) emit_parameter_encode_copy_unwrap_count(typeInfo, api, cgen) emit_parameter_encode_write_packet_info(typeInfo, api, cgen) emit_parameter_encode_do_parameter_write(typeInfo, api, cgen) emit_parameter_encode_read(typeInfo, api, cgen) emit_return_unmarshal(typeInfo, api, cgen) emit_post(typeInfo, api, cgen) emit_pool_free(cgen) emit_unlock(cgen) emit_return(typeInfo, api, cgen) ## Custom encoding definitions################################################## def emit_only_goldfish_custom(typeInfo, api, cgen): emit_lock(cgen) cgen.vkApiCall( \ api, customPrefix="sResourceTracker->on_", customParameters=custom_encoder_args(api) + \ [p.paramName for p in api.parameters[:-1]]) emit_unlock(cgen) emit_return(typeInfo, api, cgen) def emit_only_resource_event(typeInfo, api, cgen): cgen.stmt("(void)doLock"); input_result = None retExpr = api.getRetVarExpr() if retExpr: retType = api.getRetTypeExpr() input_result = SUCCESS_RET_TYPES[retType] cgen.stmt("%s %s = (%s)0" % (retType, retExpr, retType)) cgen.stmt( (("%s = " % retExpr) if retExpr else "") + make_event_handler_call( "sResourceTracker", api, ENCODER_THIS_PARAM, input_result, cgen)) if retExpr: emit_return(typeInfo, api, cgen) def emit_with_custom_unwrap(custom): def call(typeInfo, api, cgen): emit_lock(cgen) emit_parameter_encode_preamble_write(typeInfo, api, cgen) emit_parameter_encode_copy_unwrap_count( typeInfo, api, cgen, customUnwrap=custom) emit_parameter_encode_write_packet_info(typeInfo, api, cgen) emit_parameter_encode_do_parameter_write(typeInfo, api, cgen) emit_parameter_encode_read(typeInfo, api, cgen) emit_return_unmarshal(typeInfo, api, cgen) emit_pool_free(cgen) emit_unlock(cgen) emit_return(typeInfo, api, cgen) return call def encode_vkFlushMappedMemoryRanges(typeInfo, api, cgen): emit_lock(cgen) emit_parameter_encode_preamble_write(typeInfo, api, cgen) emit_parameter_encode_copy_unwrap_count(typeInfo, api, cgen) def emit_flush_ranges(streamVar): cgen.beginIf("!sResourceTracker->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 streamSize = 0") cgen.stmt("if (!memory) { %s->write(&streamSize, sizeof(uint64_t)); continue; }" % streamVar) cgen.stmt("auto hostPtr = sResourceTracker->getMappedPointer(memory)") cgen.stmt("auto actualSize = size == VK_WHOLE_SIZE ? sResourceTracker->getMappedSize(memory) : size") cgen.stmt("if (!hostPtr) { %s->write(&streamSize, sizeof(uint64_t)); continue; }" % streamVar) cgen.stmt("streamSize = actualSize") cgen.stmt("%s->write(&streamSize, sizeof(uint64_t))" % streamVar) cgen.stmt("uint8_t* targetRange = hostPtr + offset") cgen.stmt("%s->write(targetRange, actualSize)" % streamVar) cgen.endFor() cgen.endIf() emit_parameter_encode_write_packet_info(typeInfo, api, cgen) emit_parameter_encode_do_parameter_write(typeInfo, api, cgen) emit_flush_ranges(STREAM) emit_parameter_encode_read(typeInfo, api, cgen) emit_return_unmarshal(typeInfo, api, cgen) emit_pool_free(cgen) emit_unlock(cgen) emit_return(typeInfo, api, cgen) def encode_vkInvalidateMappedMemoryRanges(typeInfo, api, cgen): emit_lock(cgen) emit_parameter_encode_preamble_write(typeInfo, api, cgen) emit_parameter_encode_copy_unwrap_count(typeInfo, api, cgen) emit_parameter_encode_write_packet_info(typeInfo, api, cgen) emit_parameter_encode_do_parameter_write(typeInfo, api, cgen) emit_parameter_encode_read(typeInfo, api, cgen) emit_return_unmarshal(typeInfo, api, cgen) def emit_invalidate_ranges(streamVar): cgen.beginIf("!sResourceTracker->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 streamSize = 0") cgen.stmt("if (!memory) { %s->read(&streamSize, sizeof(uint64_t)); continue; }" % streamVar) cgen.stmt("auto hostPtr = sResourceTracker->getMappedPointer(memory)") cgen.stmt("auto actualSize = size == VK_WHOLE_SIZE ? sResourceTracker->getMappedSize(memory) : size") cgen.stmt("if (!hostPtr) { %s->read(&streamSize, sizeof(uint64_t)); continue; }" % streamVar) cgen.stmt("streamSize = actualSize") cgen.stmt("%s->read(&streamSize, sizeof(uint64_t))" % streamVar) cgen.stmt("uint8_t* targetRange = hostPtr + offset") cgen.stmt("%s->read(targetRange, actualSize)" % streamVar) cgen.endFor() cgen.endIf() emit_invalidate_ranges(STREAM) emit_pool_free(cgen) emit_unlock(cgen) emit_return(typeInfo, api, cgen) def emit_manual_inline(typeInfo, api, cgen): cgen.line("#include \"%s_encode_impl.cpp.inl\"" % api.name) def unwrap_vkCreateImage_pCreateInfo(): def mapOp(cgen, orig, local): cgen.stmt("sResourceTracker->unwrap_vkCreateImage_pCreateInfo(%s, %s)" % (orig.paramName, local.paramName)) return { "pCreateInfo" : { "mapOp" : mapOp } } def unwrap_vkBindImageMemory2_pBindInfos(): def mapOp(cgen, orig, local): cgen.stmt("sResourceTracker->unwrap_VkBindImageMemory2_pBindInfos(bindInfoCount, %s, %s)" % (orig.paramName, local.paramName)) return { "pBindInfos" : { "mapOp" : mapOp } } def unwrap_vkAcquireImageANDROID_nativeFenceFd(): def mapOp(cgen, orig, local): cgen.stmt("sResourceTracker->unwrap_vkAcquireImageANDROID_nativeFenceFd(%s, &%s)" % (orig.paramName, local.paramName)) return { "nativeFenceFd" : { "mapOp" : mapOp } } custom_encodes = { "vkMapMemory" : emit_only_resource_event, "vkUnmapMemory" : emit_only_resource_event, "vkFlushMappedMemoryRanges" : encode_vkFlushMappedMemoryRanges, "vkInvalidateMappedMemoryRanges" : encode_vkInvalidateMappedMemoryRanges, "vkCreateImage" : emit_with_custom_unwrap(unwrap_vkCreateImage_pCreateInfo()), "vkCreateImageWithRequirementsGOOGLE" : emit_with_custom_unwrap(unwrap_vkCreateImage_pCreateInfo()), "vkBindImageMemory2": emit_with_custom_unwrap(unwrap_vkBindImageMemory2_pBindInfos()), "vkAcquireImageANDROID" : emit_with_custom_unwrap(unwrap_vkAcquireImageANDROID_nativeFenceFd()), "vkQueueFlushCommandsGOOGLE" : emit_manual_inline, } class VulkanEncoder(VulkanWrapperGenerator): def __init__(self, module, typeInfo): VulkanWrapperGenerator.__init__(self, module, typeInfo) self.typeInfo = typeInfo self.cgenHeader = CodeGen() self.cgenHeader.incrIndent() self.cgenImpl = CodeGen() def onBegin(self,): self.module.appendHeader(encoder_decl_preamble) self.module.appendImpl(encoder_impl_preamble) def onGenCmd(self, cmdinfo, name, alias): VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias) api = copy.deepcopy(self.typeInfo.apis[name]) api.parameters.append(makeVulkanTypeSimple(False, "uint32_t", 0, "doLock")) self.cgenHeader.stmt(self.cgenHeader.makeFuncProto(api)) apiImpl = api.withModifiedName("VkEncoder::" + api.name) self.module.appendHeader(self.cgenHeader.swapCode()) def emit_function_impl(cgen): emit_health_watchdog(api, cgen) if api.name in custom_encodes.keys(): custom_encodes[api.name](self.typeInfo, api, cgen) else: emit_default_encoding(self.typeInfo, api, cgen) self.module.appendImpl(self.cgenImpl.makeFuncImpl(apiImpl, emit_function_impl)) def onEnd(self,): self.module.appendHeader(encoder_decl_postamble) self.cgenHeader.decrIndent()