diff options
Diffstat (limited to 'codegen/vulkan/scripts/cereal/encoder.py')
-rw-r--r-- | codegen/vulkan/scripts/cereal/encoder.py | 717 |
1 files changed, 717 insertions, 0 deletions
diff --git a/codegen/vulkan/scripts/cereal/encoder.py b/codegen/vulkan/scripts/cereal/encoder.py new file mode 100644 index 00000000..d3e39745 --- /dev/null +++ b/codegen/vulkan/scripts/cereal/encoder.py @@ -0,0 +1,717 @@ +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 = """ +using android::base::guest::HealthMonitor; + +class VkEncoder { +public: + VkEncoder(IOStream* stream, HealthMonitor<>* healthMonitor = nullptr); + ~VkEncoder(); + +#include "VkEncoder.h.inl" +""" + +encoder_decl_postamble = """ +private: + class Impl; + std::unique_ptr<Impl> mImpl; + HealthMonitor<>* mHealthMonitor; +}; +""" + +encoder_impl_preamble =""" + +using namespace gfxstream::vk; + +using android::base::guest::AutoLock; +using android::base::guest::Lock; +using android::base::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, 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<size_t>(static_cast<size_t>(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<uint32_t> healthMonitorAnnotation_seqno = std::nullopt") + cgen.stmt("std::optional<uint32_t> healthMonitorAnnotation_packetSize = std::nullopt") + cgen.stmt("std::vector<uint8_t> healthMonitorAnnotation_packetContents") + cgen.line(""" + auto watchdog = WATCHDOG_BUILDER(mHealthMonitor, \"%s in VkEncoder\") + .setOnHangCallback([&]() { + auto annotations = std::make_unique<EventHangMetadata::HangAnnotations>(); + 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_VkNativeBufferANDROID(): + def mapOp(cgen, orig, local): + cgen.stmt("sResourceTracker->unwrap_VkNativeBufferANDROID(%s, %s)" % + (orig.paramName, local.paramName)) + return { "pCreateInfo" : { "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_VkNativeBufferANDROID()), + "vkCreateImageWithRequirementsGOOGLE" : emit_with_custom_unwrap(unwrap_VkNativeBufferANDROID()), + "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() |