| 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<Impl> 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<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_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() |