diff options
Diffstat (limited to 'codegen/vulkan/scripts/cereal/functable.py')
-rw-r--r-- | codegen/vulkan/scripts/cereal/functable.py | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/codegen/vulkan/scripts/cereal/functable.py b/codegen/vulkan/scripts/cereal/functable.py new file mode 100644 index 00000000..f16735a3 --- /dev/null +++ b/codegen/vulkan/scripts/cereal/functable.py @@ -0,0 +1,360 @@ +from .common.codegen import CodeGen, VulkanWrapperGenerator +from .common.vulkantypes import \ + VulkanAPI, makeVulkanTypeSimple, iterateVulkanType +from .common.vulkantypes import EXCLUDED_APIS + +RESOURCE_TRACKER_ENTRIES = [ + "vkEnumerateInstanceExtensionProperties", + "vkEnumerateDeviceExtensionProperties", + "vkEnumeratePhysicalDevices", + "vkAllocateMemory", + "vkFreeMemory", + "vkCreateImage", + "vkDestroyImage", + "vkGetImageMemoryRequirements", + "vkGetImageMemoryRequirements2", + "vkGetImageMemoryRequirements2KHR", + "vkBindImageMemory", + "vkBindImageMemory2", + "vkBindImageMemory2KHR", + "vkCreateBuffer", + "vkDestroyBuffer", + "vkGetBufferMemoryRequirements", + "vkGetBufferMemoryRequirements2", + "vkGetBufferMemoryRequirements2KHR", + "vkBindBufferMemory", + "vkBindBufferMemory2", + "vkBindBufferMemory2KHR", + "vkCreateSemaphore", + "vkDestroySemaphore", + "vkQueueSubmit", + "vkQueueWaitIdle", + "vkImportSemaphoreFdKHR", + "vkGetSemaphoreFdKHR", + # Warning: These need to be defined in vk.xml (currently no-op) { + "vkGetMemoryFuchsiaHandleKHR", + "vkGetMemoryFuchsiaHandlePropertiesKHR", + "vkGetSemaphoreFuchsiaHandleKHR", + "vkImportSemaphoreFuchsiaHandleKHR", + # } end Warning: These need to be defined in vk.xml (currently no-op) + "vkGetAndroidHardwareBufferPropertiesANDROID", + "vkGetMemoryAndroidHardwareBufferANDROID", + "vkCreateSamplerYcbcrConversion", + "vkDestroySamplerYcbcrConversion", + "vkCreateSamplerYcbcrConversionKHR", + "vkDestroySamplerYcbcrConversionKHR", + "vkUpdateDescriptorSetWithTemplate", + "vkGetPhysicalDeviceImageFormatProperties2", + "vkGetPhysicalDeviceImageFormatProperties2KHR", + "vkBeginCommandBuffer", + "vkEndCommandBuffer", + "vkResetCommandBuffer", + "vkCreateImageView", + "vkCreateSampler", + "vkGetPhysicalDeviceExternalFenceProperties", + "vkGetPhysicalDeviceExternalFencePropertiesKHR", + "vkCreateFence", + "vkResetFences", + "vkImportFenceFdKHR", + "vkGetFenceFdKHR", + "vkWaitForFences", + "vkCreateDescriptorPool", + "vkDestroyDescriptorPool", + "vkResetDescriptorPool", + "vkAllocateDescriptorSets", + "vkFreeDescriptorSets", + "vkCreateDescriptorSetLayout", + "vkUpdateDescriptorSets", + "vkCmdExecuteCommands", + "vkCmdBindDescriptorSets", + "vkDestroyDescriptorSetLayout", + "vkAllocateCommandBuffers", + "vkQueueSignalReleaseImageANDROID", + "vkCmdPipelineBarrier", + "vkCreateGraphicsPipelines", +] + +SUCCESS_VAL = { + "VkResult" : ["VK_SUCCESS"], +} + +POSTPROCESSES = { + "vkResetCommandPool" : """if (vkResetCommandPool_VkResult_return == VK_SUCCESS) { + ResourceTracker::get()->resetCommandPoolStagingInfo(commandPool); + }""", + "vkAllocateCommandBuffers" : """if (vkAllocateCommandBuffers_VkResult_return == VK_SUCCESS) { + ResourceTracker::get()->addToCommandPool(pAllocateInfo->commandPool, pAllocateInfo->commandBufferCount, pCommandBuffers); + }""", +} + +def is_cmdbuf_dispatch(api): + return "VkCommandBuffer" == api.parameters[0].typeName + +def is_queue_dispatch(api): + return "VkQueue" == api.parameters[0].typeName + +class VulkanFuncTable(VulkanWrapperGenerator): + def __init__(self, module, typeInfo): + VulkanWrapperGenerator.__init__(self, module, typeInfo) + self.typeInfo = typeInfo + self.cgen = CodeGen() + self.entries = [] + self.entryFeatures = [] + self.cmdToFeatureType = {} + self.feature = None + self.featureType = None + + def onBegin(self,): + cgen = self.cgen + cgen.line("static void sOnInvalidDynamicallyCheckedCall(const char* apiname, const char* neededFeature)") + cgen.beginBlock() + cgen.stmt("ALOGE(\"invalid call to %s: %s not supported\", apiname, neededFeature)") + cgen.stmt("abort()") + cgen.endBlock() + self.module.appendImpl(cgen.swapCode()) + pass + + def onBeginFeature(self, featureName, featureType): + self.feature = featureName + self.featureType = featureType + + def onEndFeature(self): + self.feature = None + self.featureType = None + + def onFeatureNewCmd(self, name): + self.cmdToFeatureType[name] = self.featureType + + def onGenCmd(self, cmdinfo, name, alias): + typeInfo = self.typeInfo + cgen = self.cgen + api = typeInfo.apis[name] + self.entries.append(api) + self.entryFeatures.append(self.feature) + + def genEncoderOrResourceTrackerCall(cgen, api, declareResources=True): + cgen.stmt("AEMU_SCOPED_TRACE(\"%s\")" % api.name) + + if is_cmdbuf_dispatch(api): + cgen.stmt("auto vkEnc = ResourceTracker::getCommandBufferEncoder(commandBuffer)") + elif is_queue_dispatch(api): + cgen.stmt("auto vkEnc = ResourceTracker::getQueueEncoder(queue)") + else: + cgen.stmt("auto vkEnc = ResourceTracker::getThreadLocalEncoder()") + callLhs = None + retTypeName = api.getRetTypeExpr() + if retTypeName != "void": + retVar = api.getRetVarExpr() + cgen.stmt("%s %s = (%s)0" % (retTypeName, retVar, retTypeName)) + callLhs = retVar + + if name in RESOURCE_TRACKER_ENTRIES: + if declareResources: + cgen.stmt("auto resources = ResourceTracker::get()") + cgen.funcCall( + callLhs, "resources->" + "on_" + api.name, + ["vkEnc"] + SUCCESS_VAL.get(retTypeName, []) + \ + [p.paramName for p in api.parameters]) + else: + cgen.funcCall( + callLhs, "vkEnc->" + api.name, [p.paramName for p in api.parameters] + ["true /* do lock */"]) + + if name in POSTPROCESSES: + cgen.line(POSTPROCESSES[name]) + + if retTypeName != "void": + cgen.stmt("return %s" % retVar) + + + api_entry = api.withModifiedName("entry_" + api.name) + + cgen.line("static " + self.cgen.makeFuncProto(api_entry)) + cgen.beginBlock() + genEncoderOrResourceTrackerCall(cgen, api) + cgen.endBlock() + + if self.isDeviceDispatch(api) and self.feature != "VK_VERSION_1_0": + api_entry_dyn_check = api.withModifiedName("dynCheck_entry_" + api.name) + cgen.line("static " + self.cgen.makeFuncProto(api_entry_dyn_check)) + cgen.beginBlock() + if self.feature == "VK_VERSION_1_1": + cgen.stmt("auto resources = ResourceTracker::get()") + if "VkCommandBuffer" == api.parameters[0].typeName: + cgen.stmt("VkDevice device = resources->getDevice(commandBuffer)") + cgen.beginIf("resources->getApiVersionFromDevice(device) < VK_API_VERSION_1_1") + cgen.stmt("sOnInvalidDynamicallyCheckedCall(\"%s\", \"%s\")" % (api.name, self.feature)) + cgen.endIf() + elif self.feature != "VK_VERSION_1_0": + cgen.stmt("auto resources = ResourceTracker::get()") + if "VkCommandBuffer" == api.parameters[0].typeName: + cgen.stmt("VkDevice device = resources->getDevice(commandBuffer);") + cgen.beginIf("!resources->hasDeviceExtension(device, \"%s\")" % self.feature) + cgen.stmt("sOnInvalidDynamicallyCheckedCall(\"%s\", \"%s\")" % (api.name, self.feature)) + cgen.endIf() + else: + print("About to generate a frivolous api!: dynCheck entry: %s" % api.name) + raise + genEncoderOrResourceTrackerCall(cgen, api, declareResources = False) + cgen.endBlock() + + self.module.appendImpl(cgen.swapCode()) + + def onEnd(self,): + getProcAddressDecl = "void* goldfish_vulkan_get_proc_address(const char* name)" + self.module.appendHeader(getProcAddressDecl + ";\n") + self.module.appendImpl(getProcAddressDecl) + self.cgen.beginBlock() + + prevFeature = None + for e, f in zip(self.entries, self.entryFeatures): + featureEndif = prevFeature is not None and (f != prevFeature) + featureif = not featureEndif and (f != prevFeature) + + if featureEndif: + self.cgen.leftline("#endif") + self.cgen.leftline("#ifdef %s" % f) + + if featureif: + self.cgen.leftline("#ifdef %s" % f) + + self.cgen.beginIf("!strcmp(name, \"%s\")" % e.name) + if e.name in EXCLUDED_APIS: + self.cgen.stmt("return nullptr") + elif f == "VK_VERSION_1_1": + self.cgen.stmt("return nullptr") + elif f != "VK_VERSION_1_0": + self.cgen.stmt("return nullptr") + else: + self.cgen.stmt("return (void*)%s" % ("entry_" + e.name)) + self.cgen.endIf() + prevFeature = f + + self.cgen.leftline("#endif") + + self.cgen.stmt("return nullptr") + self.cgen.endBlock() + self.module.appendImpl(self.cgen.swapCode()) + + getInstanceProcAddressDecl = "void* goldfish_vulkan_get_instance_proc_address(VkInstance instance, const char* name)" + self.module.appendHeader(getInstanceProcAddressDecl + ";\n") + self.module.appendImpl(getInstanceProcAddressDecl) + self.cgen.beginBlock() + + self.cgen.stmt( + "auto resources = ResourceTracker::get()") + self.cgen.stmt( + "bool has1_1OrHigher = resources->getApiVersionFromInstance(instance) >= VK_API_VERSION_1_1") + self.cgen.stmt( + "bool has1_2OrHigher = resources->getApiVersionFromInstance(instance) >= VK_API_VERSION_1_2") + + prevFeature = None + for e, f in zip(self.entries, self.entryFeatures): + featureEndif = prevFeature is not None and (f != prevFeature) + featureif = not featureEndif and (f != prevFeature) + + if featureEndif: + self.cgen.leftline("#endif") + self.cgen.leftline("#ifdef %s" % f) + + if featureif: + self.cgen.leftline("#ifdef %s" % f) + + self.cgen.beginIf("!strcmp(name, \"%s\")" % e.name) + + entryPointExpr = "(void*)%s" % ("entry_" + e.name) + + if e.name in EXCLUDED_APIS: + self.cgen.stmt("return nullptr") + elif f == "VK_VERSION_1_2": + if self.isDeviceDispatch(e): + self.cgen.stmt("return (void*)dynCheck_entry_%s" % e.name) + else: + self.cgen.stmt( \ + "return has1_2OrHigher ? %s : nullptr" % \ + entryPointExpr) + elif f == "VK_VERSION_1_1": + if self.isDeviceDispatch(e): + self.cgen.stmt("return (void*)dynCheck_entry_%s" % e.name) + else: + self.cgen.stmt( \ + "return has1_1OrHigher ? %s : nullptr" % \ + entryPointExpr) + elif f != "VK_VERSION_1_0": + entryNeedsInstanceExtensionCheck = self.cmdToFeatureType[e.name] == "instance" + + entryPrefix = "dynCheck_" if self.isDeviceDispatch(e) else "" + entryPointExpr = "(void*)%sentry_%s" % (entryPrefix, e.name) + + if entryNeedsInstanceExtensionCheck: + self.cgen.stmt("bool hasExt = resources->hasInstanceExtension(instance, \"%s\")" % f) + self.cgen.stmt("return hasExt ? %s : nullptr" % entryPointExpr) + else: + # TODO(b/236246382): We need to check the device extension support here. + self.cgen.stmt("// TODO(b/236246382): Check support for device extension"); + self.cgen.stmt("return %s" % entryPointExpr) + + else: + self.cgen.stmt("return %s" % entryPointExpr) + self.cgen.endIf() + prevFeature = f + + self.cgen.leftline("#endif") + + self.cgen.stmt("return nullptr") + self.cgen.endBlock() + self.module.appendImpl(self.cgen.swapCode()) + + getDeviceProcAddressDecl = "void* goldfish_vulkan_get_device_proc_address(VkDevice device, const char* name)" + self.module.appendHeader(getDeviceProcAddressDecl + ";\n") + self.module.appendImpl(getDeviceProcAddressDecl) + self.cgen.beginBlock() + + self.cgen.stmt( + "auto resources = ResourceTracker::get()") + self.cgen.stmt( + "bool has1_1OrHigher = resources->getApiVersionFromDevice(device) >= VK_API_VERSION_1_1") + + prevFeature = None + for e, f in zip(self.entries, self.entryFeatures): + featureEndif = prevFeature is not None and (f != prevFeature) + featureif = not featureEndif and (f != prevFeature) + + if featureEndif: + self.cgen.leftline("#endif") + self.cgen.leftline("#ifdef %s" % f) + + if featureif: + self.cgen.leftline("#ifdef %s" % f) + + self.cgen.beginIf("!strcmp(name, \"%s\")" % e.name) + + entryPointExpr = "(void*)%s" % ("entry_" + e.name) + + if e.name in EXCLUDED_APIS: + self.cgen.stmt("return nullptr") + elif f == "VK_VERSION_1_1": + self.cgen.stmt( \ + "return has1_1OrHigher ? %s : nullptr" % \ + entryPointExpr) + elif f != "VK_VERSION_1_0": + self.cgen.stmt( \ + "bool hasExt = resources->hasDeviceExtension(device, \"%s\")" % f) + self.cgen.stmt("return hasExt ? %s : nullptr" % entryPointExpr) + else: + self.cgen.stmt("return %s" % entryPointExpr) + self.cgen.endIf() + prevFeature = f + + self.cgen.leftline("#endif") + + self.cgen.stmt("return nullptr") + self.cgen.endBlock() + + self.module.appendImpl(self.cgen.swapCode()) + + def isDeviceDispatch(self, api): + # TODO(230793667): improve the heuristic and just use "cmdToFeatureType" + return (len(api.parameters) > 0 and + "VkDevice" == api.parameters[0].typeName) or ( + "VkCommandBuffer" == api.parameters[0].typeName and + self.cmdToFeatureType.get(api.name, "") == "device") |