• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from .common.codegen import CodeGen, VulkanWrapperGenerator
2from .common.vulkantypes import \
3        VulkanAPI, makeVulkanTypeSimple, iterateVulkanType
4from .common.vulkantypes import EXCLUDED_APIS
5
6RESOURCE_TRACKER_ENTRIES = [
7    "vkEnumerateInstanceExtensionProperties",
8    "vkEnumerateDeviceExtensionProperties",
9    "vkEnumeratePhysicalDevices",
10    "vkAllocateMemory",
11    "vkFreeMemory",
12    "vkCreateImage",
13    "vkDestroyImage",
14    "vkGetImageMemoryRequirements",
15    "vkGetImageMemoryRequirements2",
16    "vkGetImageMemoryRequirements2KHR",
17    "vkBindImageMemory",
18    "vkBindImageMemory2",
19    "vkBindImageMemory2KHR",
20    "vkCreateBuffer",
21    "vkDestroyBuffer",
22    "vkGetBufferMemoryRequirements",
23    "vkGetBufferMemoryRequirements2",
24    "vkGetBufferMemoryRequirements2KHR",
25    "vkBindBufferMemory",
26    "vkBindBufferMemory2",
27    "vkBindBufferMemory2KHR",
28    "vkCreateSemaphore",
29    "vkDestroySemaphore",
30    "vkQueueSubmit",
31    "vkQueueWaitIdle",
32    "vkImportSemaphoreFdKHR",
33    "vkGetSemaphoreFdKHR",
34    # Warning: These need to be defined in vk.xml (currently no-op) {
35    "vkGetMemoryFuchsiaHandleKHR",
36    "vkGetMemoryFuchsiaHandlePropertiesKHR",
37    "vkGetSemaphoreFuchsiaHandleKHR",
38    "vkImportSemaphoreFuchsiaHandleKHR",
39    # } end Warning: These need to be defined in vk.xml (currently no-op)
40    "vkGetAndroidHardwareBufferPropertiesANDROID",
41    "vkGetMemoryAndroidHardwareBufferANDROID",
42    "vkCreateSamplerYcbcrConversion",
43    "vkDestroySamplerYcbcrConversion",
44    "vkCreateSamplerYcbcrConversionKHR",
45    "vkDestroySamplerYcbcrConversionKHR",
46    "vkUpdateDescriptorSetWithTemplate",
47    "vkGetPhysicalDeviceImageFormatProperties2",
48    "vkGetPhysicalDeviceImageFormatProperties2KHR",
49    "vkBeginCommandBuffer",
50    "vkEndCommandBuffer",
51    "vkResetCommandBuffer",
52    "vkCreateImageView",
53    "vkCreateSampler",
54    "vkGetPhysicalDeviceExternalFenceProperties",
55    "vkGetPhysicalDeviceExternalFencePropertiesKHR",
56    "vkCreateFence",
57    "vkResetFences",
58    "vkImportFenceFdKHR",
59    "vkGetFenceFdKHR",
60    "vkWaitForFences",
61    "vkCreateDescriptorPool",
62    "vkDestroyDescriptorPool",
63    "vkResetDescriptorPool",
64    "vkAllocateDescriptorSets",
65    "vkFreeDescriptorSets",
66    "vkCreateDescriptorSetLayout",
67    "vkUpdateDescriptorSets",
68    "vkCmdExecuteCommands",
69    "vkCmdBindDescriptorSets",
70    "vkDestroyDescriptorSetLayout",
71    "vkAllocateCommandBuffers",
72]
73
74SUCCESS_VAL = {
75    "VkResult" : ["VK_SUCCESS"],
76}
77
78POSTPROCESSES = {
79    "vkResetCommandPool" : """if (vkResetCommandPool_VkResult_return == VK_SUCCESS) {
80        ResourceTracker::get()->resetCommandPoolStagingInfo(commandPool);
81    }""",
82    "vkAllocateCommandBuffers" : """if (vkAllocateCommandBuffers_VkResult_return == VK_SUCCESS) {
83        ResourceTracker::get()->addToCommandPool(pAllocateInfo->commandPool, pAllocateInfo->commandBufferCount, pCommandBuffers);
84    }""",
85}
86
87def is_cmdbuf_dispatch(api):
88    return "VkCommandBuffer" == api.parameters[0].typeName
89
90def is_queue_dispatch(api):
91    return "VkQueue" == api.parameters[0].typeName
92
93class VulkanFuncTable(VulkanWrapperGenerator):
94    def __init__(self, module, typeInfo):
95        VulkanWrapperGenerator.__init__(self, module, typeInfo)
96        self.typeInfo = typeInfo
97        self.cgen = CodeGen()
98        self.entries = []
99        self.entryFeatures = []
100        self.feature = None
101
102    def onBegin(self,):
103        cgen = self.cgen
104        cgen.line("static void sOnInvalidDynamicallyCheckedCall(const char* apiname, const char* neededFeature)")
105        cgen.beginBlock()
106        cgen.stmt("ALOGE(\"invalid call to %s: %s not supported\", apiname, neededFeature)")
107        cgen.stmt("abort()")
108        cgen.endBlock()
109        self.module.appendImpl(cgen.swapCode())
110        pass
111
112    def onBeginFeature(self, featureName):
113        self.feature = featureName
114
115    def onGenCmd(self, cmdinfo, name, alias):
116        typeInfo = self.typeInfo
117        cgen = self.cgen
118        api = typeInfo.apis[name]
119        self.entries.append(api)
120        self.entryFeatures.append(self.feature)
121
122        def genEncoderOrResourceTrackerCall(cgen, api, declareResources=True):
123            cgen.stmt("AEMU_SCOPED_TRACE(\"%s\")" % api.name)
124
125            if is_cmdbuf_dispatch(api):
126                cgen.stmt("auto vkEnc = ResourceTracker::getCommandBufferEncoder(commandBuffer)")
127            elif is_queue_dispatch(api):
128                cgen.stmt("auto vkEnc = ResourceTracker::getQueueEncoder(queue)")
129            else:
130                cgen.stmt("auto vkEnc = ResourceTracker::getThreadLocalEncoder()")
131            callLhs = None
132            retTypeName = api.getRetTypeExpr()
133            if retTypeName != "void":
134                retVar = api.getRetVarExpr()
135                cgen.stmt("%s %s = (%s)0" % (retTypeName, retVar, retTypeName))
136                callLhs = retVar
137
138            if name in RESOURCE_TRACKER_ENTRIES:
139                if declareResources:
140                    cgen.stmt("auto resources = ResourceTracker::get()")
141                cgen.funcCall(
142                    callLhs, "resources->" + "on_" + api.name,
143                    ["vkEnc"] + SUCCESS_VAL.get(retTypeName, []) + \
144                    [p.paramName for p in api.parameters])
145            else:
146                cgen.funcCall(
147                    callLhs, "vkEnc->" + api.name, [p.paramName for p in api.parameters] + ["true /* do lock */"])
148
149            if name in POSTPROCESSES:
150                cgen.line(POSTPROCESSES[name])
151
152            if retTypeName != "void":
153                cgen.stmt("return %s" % retVar)
154
155
156        api_entry = api.withModifiedName("entry_" + api.name)
157
158        cgen.line("static " + self.cgen.makeFuncProto(api_entry))
159        cgen.beginBlock()
160        genEncoderOrResourceTrackerCall(cgen, api)
161        cgen.endBlock()
162
163        if self.isDeviceDispatch(api) and self.feature != "VK_VERSION_1_0":
164            api_entry_dyn_check = api.withModifiedName("dynCheck_entry_" + api.name)
165            cgen.line("static " + self.cgen.makeFuncProto(api_entry_dyn_check))
166            cgen.beginBlock()
167            if self.feature == "VK_VERSION_1_1":
168                cgen.stmt("auto resources = ResourceTracker::get()")
169                cgen.beginIf("resources->getApiVersionFromDevice(device) < VK_API_VERSION_1_1")
170                cgen.stmt("sOnInvalidDynamicallyCheckedCall(\"%s\", \"%s\")" % (api.name, self.feature))
171                cgen.endIf()
172            elif self.feature != "VK_VERSION_1_0":
173                cgen.stmt("auto resources = ResourceTracker::get()")
174                cgen.beginIf("!resources->hasDeviceExtension(device, \"%s\")" % self.feature)
175                cgen.stmt("sOnInvalidDynamicallyCheckedCall(\"%s\", \"%s\")" % (api.name, self.feature))
176                cgen.endIf()
177            else:
178                print("About to generate a frivolous api!: dynCheck entry: %s" % api.name)
179                raise
180            genEncoderOrResourceTrackerCall(cgen, api, declareResources = False)
181            cgen.endBlock()
182
183        self.module.appendImpl(cgen.swapCode())
184
185    def onEnd(self,):
186        getProcAddressDecl = "void* goldfish_vulkan_get_proc_address(const char* name)"
187        self.module.appendHeader(getProcAddressDecl + ";\n")
188        self.module.appendImpl(getProcAddressDecl)
189        self.cgen.beginBlock()
190
191        prevFeature = None
192        for e, f in zip(self.entries, self.entryFeatures):
193            featureEndif = prevFeature is not None and (f != prevFeature)
194            featureif = not featureEndif and (f != prevFeature)
195
196            if featureEndif:
197                self.cgen.leftline("#endif")
198                self.cgen.leftline("#ifdef %s" % f)
199
200            if featureif:
201                self.cgen.leftline("#ifdef %s" % f)
202
203            self.cgen.beginIf("!strcmp(name, \"%s\")" % e.name)
204            if e.name in EXCLUDED_APIS:
205                self.cgen.stmt("return nullptr")
206            elif f == "VK_VERSION_1_1":
207                self.cgen.stmt("return nullptr")
208            elif f != "VK_VERSION_1_0":
209                self.cgen.stmt("return nullptr")
210            else:
211                self.cgen.stmt("return (void*)%s" % ("entry_" + e.name))
212            self.cgen.endIf()
213            prevFeature = f
214
215        self.cgen.leftline("#endif")
216
217        self.cgen.stmt("return nullptr")
218        self.cgen.endBlock()
219        self.module.appendImpl(self.cgen.swapCode())
220
221        getInstanceProcAddressDecl = "void* goldfish_vulkan_get_instance_proc_address(VkInstance instance, const char* name)"
222        self.module.appendHeader(getInstanceProcAddressDecl + ";\n")
223        self.module.appendImpl(getInstanceProcAddressDecl)
224        self.cgen.beginBlock()
225
226        self.cgen.stmt(
227            "auto resources = ResourceTracker::get()")
228        self.cgen.stmt(
229            "bool has1_1OrHigher = resources->getApiVersionFromInstance(instance) >= VK_API_VERSION_1_1")
230
231        prevFeature = None
232        for e, f in zip(self.entries, self.entryFeatures):
233            featureEndif = prevFeature is not None and (f != prevFeature)
234            featureif = not featureEndif and (f != prevFeature)
235
236            if featureEndif:
237                self.cgen.leftline("#endif")
238                self.cgen.leftline("#ifdef %s" % f)
239
240            if featureif:
241                self.cgen.leftline("#ifdef %s" % f)
242
243            self.cgen.beginIf("!strcmp(name, \"%s\")" % e.name)
244
245            entryPointExpr = "(void*)%s" % ("entry_" + e.name)
246
247            if e.name in EXCLUDED_APIS:
248                self.cgen.stmt("return nullptr")
249            elif f == "VK_VERSION_1_1":
250                if self.isDeviceDispatch(e):
251                    self.cgen.stmt("return (void*)dynCheck_entry_%s" % e.name)
252                else:
253                    self.cgen.stmt( \
254                        "return has1_1OrHigher ? %s : nullptr" % \
255                        entryPointExpr)
256            elif f != "VK_VERSION_1_0":
257                if self.isDeviceDispatch(e):
258                    self.cgen.stmt("return (void*)dynCheck_entry_%s" % e.name)
259                else:
260                    self.cgen.stmt( \
261                        "bool hasExt = resources->hasInstanceExtension(instance, \"%s\")"  % f)
262                    self.cgen.stmt("return hasExt ? %s : nullptr" % entryPointExpr)
263            else:
264                self.cgen.stmt("return %s" % entryPointExpr)
265            self.cgen.endIf()
266            prevFeature = f
267
268        self.cgen.leftline("#endif")
269
270        self.cgen.stmt("return nullptr")
271        self.cgen.endBlock()
272        self.module.appendImpl(self.cgen.swapCode())
273
274        getDeviceProcAddressDecl = "void* goldfish_vulkan_get_device_proc_address(VkDevice device, const char* name)"
275        self.module.appendHeader(getDeviceProcAddressDecl + ";\n")
276        self.module.appendImpl(getDeviceProcAddressDecl)
277        self.cgen.beginBlock()
278
279        self.cgen.stmt(
280            "auto resources = ResourceTracker::get()")
281        self.cgen.stmt(
282            "bool has1_1OrHigher = resources->getApiVersionFromDevice(device) >= VK_API_VERSION_1_1")
283
284        prevFeature = None
285        for e, f in zip(self.entries, self.entryFeatures):
286            featureEndif = prevFeature is not None and (f != prevFeature)
287            featureif = not featureEndif and (f != prevFeature)
288
289            if featureEndif:
290                self.cgen.leftline("#endif")
291                self.cgen.leftline("#ifdef %s" % f)
292
293            if featureif:
294                self.cgen.leftline("#ifdef %s" % f)
295
296            self.cgen.beginIf("!strcmp(name, \"%s\")" % e.name)
297
298            entryPointExpr = "(void*)%s" % ("entry_" + e.name)
299
300            if e.name in EXCLUDED_APIS:
301                self.cgen.stmt("return nullptr")
302            elif f == "VK_VERSION_1_1":
303                self.cgen.stmt( \
304                    "return has1_1OrHigher ? %s : nullptr" % \
305                    entryPointExpr)
306            elif f != "VK_VERSION_1_0":
307                self.cgen.stmt( \
308                    "bool hasExt = resources->hasDeviceExtension(device, \"%s\")"  % f)
309                self.cgen.stmt("return hasExt ? %s : nullptr" % entryPointExpr)
310            else:
311                self.cgen.stmt("return %s" % entryPointExpr)
312            self.cgen.endIf()
313            prevFeature = f
314
315        self.cgen.leftline("#endif")
316
317        self.cgen.stmt("return nullptr")
318        self.cgen.endBlock()
319
320        self.module.appendImpl(self.cgen.swapCode())
321
322    def isDeviceDispatch(self, api):
323        return len(api.parameters) > 0 and "VkDevice" == api.parameters[0].typeName
324