• 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    "vkQueueSignalReleaseImageANDROID",
73]
74
75SUCCESS_VAL = {
76    "VkResult" : ["VK_SUCCESS"],
77}
78
79POSTPROCESSES = {
80    "vkResetCommandPool" : """if (vkResetCommandPool_VkResult_return == VK_SUCCESS) {
81        ResourceTracker::get()->resetCommandPoolStagingInfo(commandPool);
82    }""",
83    "vkAllocateCommandBuffers" : """if (vkAllocateCommandBuffers_VkResult_return == VK_SUCCESS) {
84        ResourceTracker::get()->addToCommandPool(pAllocateInfo->commandPool, pAllocateInfo->commandBufferCount, pCommandBuffers);
85    }""",
86}
87
88def is_cmdbuf_dispatch(api):
89    return "VkCommandBuffer" == api.parameters[0].typeName
90
91def is_queue_dispatch(api):
92    return "VkQueue" == api.parameters[0].typeName
93
94class VulkanFuncTable(VulkanWrapperGenerator):
95    def __init__(self, module, typeInfo):
96        VulkanWrapperGenerator.__init__(self, module, typeInfo)
97        self.typeInfo = typeInfo
98        self.cgen = CodeGen()
99        self.entries = []
100        self.entryFeatures = []
101        self.feature = None
102
103    def onBegin(self,):
104        cgen = self.cgen
105        cgen.line("static void sOnInvalidDynamicallyCheckedCall(const char* apiname, const char* neededFeature)")
106        cgen.beginBlock()
107        cgen.stmt("ALOGE(\"invalid call to %s: %s not supported\", apiname, neededFeature)")
108        cgen.stmt("abort()")
109        cgen.endBlock()
110        self.module.appendImpl(cgen.swapCode())
111        pass
112
113    def onBeginFeature(self, featureName):
114        self.feature = featureName
115
116    def onGenCmd(self, cmdinfo, name, alias):
117        typeInfo = self.typeInfo
118        cgen = self.cgen
119        api = typeInfo.apis[name]
120        self.entries.append(api)
121        self.entryFeatures.append(self.feature)
122
123        def genEncoderOrResourceTrackerCall(cgen, api, declareResources=True):
124            cgen.stmt("AEMU_SCOPED_TRACE(\"%s\")" % api.name)
125
126            if is_cmdbuf_dispatch(api):
127                cgen.stmt("auto vkEnc = ResourceTracker::getCommandBufferEncoder(commandBuffer)")
128            elif is_queue_dispatch(api):
129                cgen.stmt("auto vkEnc = ResourceTracker::getQueueEncoder(queue)")
130            else:
131                cgen.stmt("auto vkEnc = ResourceTracker::getThreadLocalEncoder()")
132            callLhs = None
133            retTypeName = api.getRetTypeExpr()
134            if retTypeName != "void":
135                retVar = api.getRetVarExpr()
136                cgen.stmt("%s %s = (%s)0" % (retTypeName, retVar, retTypeName))
137                callLhs = retVar
138
139            if name in RESOURCE_TRACKER_ENTRIES:
140                if declareResources:
141                    cgen.stmt("auto resources = ResourceTracker::get()")
142                cgen.funcCall(
143                    callLhs, "resources->" + "on_" + api.name,
144                    ["vkEnc"] + SUCCESS_VAL.get(retTypeName, []) + \
145                    [p.paramName for p in api.parameters])
146            else:
147                cgen.funcCall(
148                    callLhs, "vkEnc->" + api.name, [p.paramName for p in api.parameters] + ["true /* do lock */"])
149
150            if name in POSTPROCESSES:
151                cgen.line(POSTPROCESSES[name])
152
153            if retTypeName != "void":
154                cgen.stmt("return %s" % retVar)
155
156
157        api_entry = api.withModifiedName("entry_" + api.name)
158
159        cgen.line("static " + self.cgen.makeFuncProto(api_entry))
160        cgen.beginBlock()
161        genEncoderOrResourceTrackerCall(cgen, api)
162        cgen.endBlock()
163
164        if self.isDeviceDispatch(api) and self.feature != "VK_VERSION_1_0":
165            api_entry_dyn_check = api.withModifiedName("dynCheck_entry_" + api.name)
166            cgen.line("static " + self.cgen.makeFuncProto(api_entry_dyn_check))
167            cgen.beginBlock()
168            if self.feature == "VK_VERSION_1_1":
169                cgen.stmt("auto resources = ResourceTracker::get()")
170                cgen.beginIf("resources->getApiVersionFromDevice(device) < VK_API_VERSION_1_1")
171                cgen.stmt("sOnInvalidDynamicallyCheckedCall(\"%s\", \"%s\")" % (api.name, self.feature))
172                cgen.endIf()
173            elif self.feature != "VK_VERSION_1_0":
174                cgen.stmt("auto resources = ResourceTracker::get()")
175                cgen.beginIf("!resources->hasDeviceExtension(device, \"%s\")" % self.feature)
176                cgen.stmt("sOnInvalidDynamicallyCheckedCall(\"%s\", \"%s\")" % (api.name, self.feature))
177                cgen.endIf()
178            else:
179                print("About to generate a frivolous api!: dynCheck entry: %s" % api.name)
180                raise
181            genEncoderOrResourceTrackerCall(cgen, api, declareResources = False)
182            cgen.endBlock()
183
184        self.module.appendImpl(cgen.swapCode())
185
186    def onEnd(self,):
187        getProcAddressDecl = "void* goldfish_vulkan_get_proc_address(const char* name)"
188        self.module.appendHeader(getProcAddressDecl + ";\n")
189        self.module.appendImpl(getProcAddressDecl)
190        self.cgen.beginBlock()
191
192        prevFeature = None
193        for e, f in zip(self.entries, self.entryFeatures):
194            featureEndif = prevFeature is not None and (f != prevFeature)
195            featureif = not featureEndif and (f != prevFeature)
196
197            if featureEndif:
198                self.cgen.leftline("#endif")
199                self.cgen.leftline("#ifdef %s" % f)
200
201            if featureif:
202                self.cgen.leftline("#ifdef %s" % f)
203
204            self.cgen.beginIf("!strcmp(name, \"%s\")" % e.name)
205            if e.name in EXCLUDED_APIS:
206                self.cgen.stmt("return nullptr")
207            elif f == "VK_VERSION_1_1":
208                self.cgen.stmt("return nullptr")
209            elif f != "VK_VERSION_1_0":
210                self.cgen.stmt("return nullptr")
211            else:
212                self.cgen.stmt("return (void*)%s" % ("entry_" + e.name))
213            self.cgen.endIf()
214            prevFeature = f
215
216        self.cgen.leftline("#endif")
217
218        self.cgen.stmt("return nullptr")
219        self.cgen.endBlock()
220        self.module.appendImpl(self.cgen.swapCode())
221
222        getInstanceProcAddressDecl = "void* goldfish_vulkan_get_instance_proc_address(VkInstance instance, const char* name)"
223        self.module.appendHeader(getInstanceProcAddressDecl + ";\n")
224        self.module.appendImpl(getInstanceProcAddressDecl)
225        self.cgen.beginBlock()
226
227        self.cgen.stmt(
228            "auto resources = ResourceTracker::get()")
229        self.cgen.stmt(
230            "bool has1_1OrHigher = resources->getApiVersionFromInstance(instance) >= VK_API_VERSION_1_1")
231
232        prevFeature = None
233        for e, f in zip(self.entries, self.entryFeatures):
234            featureEndif = prevFeature is not None and (f != prevFeature)
235            featureif = not featureEndif and (f != prevFeature)
236
237            if featureEndif:
238                self.cgen.leftline("#endif")
239                self.cgen.leftline("#ifdef %s" % f)
240
241            if featureif:
242                self.cgen.leftline("#ifdef %s" % f)
243
244            self.cgen.beginIf("!strcmp(name, \"%s\")" % e.name)
245
246            entryPointExpr = "(void*)%s" % ("entry_" + e.name)
247
248            if e.name in EXCLUDED_APIS:
249                self.cgen.stmt("return nullptr")
250            elif f == "VK_VERSION_1_1":
251                if self.isDeviceDispatch(e):
252                    self.cgen.stmt("return (void*)dynCheck_entry_%s" % e.name)
253                else:
254                    self.cgen.stmt( \
255                        "return has1_1OrHigher ? %s : nullptr" % \
256                        entryPointExpr)
257            elif f != "VK_VERSION_1_0":
258                if self.isDeviceDispatch(e):
259                    self.cgen.stmt("return (void*)dynCheck_entry_%s" % e.name)
260                else:
261                    self.cgen.stmt( \
262                        "bool hasExt = resources->hasInstanceExtension(instance, \"%s\")"  % f)
263                    self.cgen.stmt("return hasExt ? %s : nullptr" % entryPointExpr)
264            else:
265                self.cgen.stmt("return %s" % entryPointExpr)
266            self.cgen.endIf()
267            prevFeature = f
268
269        self.cgen.leftline("#endif")
270
271        self.cgen.stmt("return nullptr")
272        self.cgen.endBlock()
273        self.module.appendImpl(self.cgen.swapCode())
274
275        getDeviceProcAddressDecl = "void* goldfish_vulkan_get_device_proc_address(VkDevice device, const char* name)"
276        self.module.appendHeader(getDeviceProcAddressDecl + ";\n")
277        self.module.appendImpl(getDeviceProcAddressDecl)
278        self.cgen.beginBlock()
279
280        self.cgen.stmt(
281            "auto resources = ResourceTracker::get()")
282        self.cgen.stmt(
283            "bool has1_1OrHigher = resources->getApiVersionFromDevice(device) >= VK_API_VERSION_1_1")
284
285        prevFeature = None
286        for e, f in zip(self.entries, self.entryFeatures):
287            featureEndif = prevFeature is not None and (f != prevFeature)
288            featureif = not featureEndif and (f != prevFeature)
289
290            if featureEndif:
291                self.cgen.leftline("#endif")
292                self.cgen.leftline("#ifdef %s" % f)
293
294            if featureif:
295                self.cgen.leftline("#ifdef %s" % f)
296
297            self.cgen.beginIf("!strcmp(name, \"%s\")" % e.name)
298
299            entryPointExpr = "(void*)%s" % ("entry_" + e.name)
300
301            if e.name in EXCLUDED_APIS:
302                self.cgen.stmt("return nullptr")
303            elif f == "VK_VERSION_1_1":
304                self.cgen.stmt( \
305                    "return has1_1OrHigher ? %s : nullptr" % \
306                    entryPointExpr)
307            elif f != "VK_VERSION_1_0":
308                self.cgen.stmt( \
309                    "bool hasExt = resources->hasDeviceExtension(device, \"%s\")"  % f)
310                self.cgen.stmt("return hasExt ? %s : nullptr" % entryPointExpr)
311            else:
312                self.cgen.stmt("return %s" % entryPointExpr)
313            self.cgen.endIf()
314            prevFeature = f
315
316        self.cgen.leftline("#endif")
317
318        self.cgen.stmt("return nullptr")
319        self.cgen.endBlock()
320
321        self.module.appendImpl(self.cgen.swapCode())
322
323    def isDeviceDispatch(self, api):
324        return len(api.parameters) > 0 and "VkDevice" == api.parameters[0].typeName
325