xref: /aosp_15_r20/external/mesa3d/src/gfxstream/codegen/scripts/cereal/decodersnapshot.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1# Copyright 2018 Google LLC
2# SPDX-License-Identifier: MIT
3
4from .common.codegen import CodeGen, VulkanWrapperGenerator, VulkanAPIWrapper
5from .common.vulkantypes import \
6        VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, DISPATCHABLE_HANDLE_TYPES, NON_DISPATCHABLE_HANDLE_TYPES
7
8from .transform import TransformCodegen, genTransformsForVulkanType
9
10from .wrapperdefs import API_PREFIX_MARSHAL
11from .wrapperdefs import API_PREFIX_UNMARSHAL
12from .wrapperdefs import VULKAN_STREAM_TYPE
13
14from copy import copy
15from dataclasses import dataclass
16
17decoder_snapshot_decl_preamble = """
18
19namespace android {
20namespace base {
21class BumpPool;
22class Stream;
23} // namespace base {
24} // namespace android {
25
26class VkDecoderSnapshot {
27public:
28    VkDecoderSnapshot();
29    ~VkDecoderSnapshot();
30
31    void save(android::base::Stream* stream);
32    void load(android::base::Stream* stream, emugl::GfxApiLogger& gfx_logger,
33              emugl::HealthMonitor<>* healthMonitor);
34    void createExtraHandlesForNextApi(const uint64_t* created, uint32_t count);
35"""
36
37decoder_snapshot_decl_postamble = """
38private:
39    class Impl;
40    std::unique_ptr<Impl> mImpl;
41
42};
43"""
44
45decoder_snapshot_impl_preamble ="""
46
47using namespace gfxstream::vk;
48using emugl::GfxApiLogger;
49using emugl::HealthMonitor;
50
51class VkDecoderSnapshot::Impl {
52public:
53    Impl() { }
54
55    void save(android::base::Stream* stream) {
56        mReconstruction.save(stream);
57    }
58
59    void load(android::base::Stream* stream, GfxApiLogger& gfx_logger,
60              HealthMonitor<>* healthMonitor) {
61        mReconstruction.load(stream, gfx_logger, healthMonitor);
62    }
63
64    void createExtraHandlesForNextApi(const uint64_t* created, uint32_t count) {
65        mLock.lock();
66        mReconstruction.createExtraHandlesForNextApi(created, count);
67    }
68"""
69
70decoder_snapshot_impl_postamble = """
71private:
72    android::base::Lock mLock;
73    VkReconstruction mReconstruction;
74};
75
76VkDecoderSnapshot::VkDecoderSnapshot() :
77    mImpl(new VkDecoderSnapshot::Impl()) { }
78
79void VkDecoderSnapshot::save(android::base::Stream* stream) {
80    mImpl->save(stream);
81}
82
83void VkDecoderSnapshot::load(android::base::Stream* stream, GfxApiLogger& gfx_logger,
84                             HealthMonitor<>* healthMonitor) {
85    mImpl->load(stream, gfx_logger, healthMonitor);
86}
87
88void VkDecoderSnapshot::createExtraHandlesForNextApi(const uint64_t* created, uint32_t count) {
89    mImpl->createExtraHandlesForNextApi(created, count);
90}
91
92VkDecoderSnapshot::~VkDecoderSnapshot() = default;
93"""
94
95AUXILIARY_SNAPSHOT_API_BASE_PARAM_COUNT = 3
96
97AUXILIARY_SNAPSHOT_API_PARAM_NAMES = [
98    "input_result",
99]
100
101# Vulkan handle dependencies.
102# (a, b): a depends on b
103SNAPSHOT_HANDLE_DEPENDENCIES = [
104    # Dispatchable handle types
105    ("VkCommandBuffer", "VkCommandPool"),
106    ("VkCommandPool", "VkDevice"),
107    ("VkQueue", "VkDevice"),
108    ("VkDevice", "VkPhysicalDevice"),
109    ("VkPhysicalDevice", "VkInstance")] + \
110    list(map(lambda handleType : (handleType, "VkDevice"), NON_DISPATCHABLE_HANDLE_TYPES))
111
112handleDependenciesDict = dict(SNAPSHOT_HANDLE_DEPENDENCIES)
113
114def extract_deps_vkAllocateMemory(param, access, lenExpr, api, cgen):
115    cgen.stmt("const VkMemoryDedicatedAllocateInfo* dedicatedAllocateInfo = vk_find_struct<VkMemoryDedicatedAllocateInfo>(pAllocateInfo)");
116    cgen.beginIf("dedicatedAllocateInfo");
117    cgen.beginIf("dedicatedAllocateInfo->image")
118    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \
119              (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkImage(dedicatedAllocateInfo->image)"))
120    cgen.endIf()
121    cgen.beginIf("dedicatedAllocateInfo->buffer")
122    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \
123              (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkBuffer(dedicatedAllocateInfo->buffer)"))
124    cgen.endIf()
125    cgen.endIf()
126
127def extract_deps_vkAllocateCommandBuffers(param, access, lenExpr, api, cgen):
128    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \
129              (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkCommandPool(pAllocateInfo->commandPool)"))
130
131def extract_deps_vkAllocateDescriptorSets(param, access, lenExpr, api, cgen):
132    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \
133              (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkDescriptorPool(pAllocateInfo->descriptorPool)"))
134
135def extract_deps_vkUpdateDescriptorSets(param, access, lenExpr, api, cgen):
136    cgen.beginFor("uint32_t i = 0", "i < descriptorWriteCount", "++i")
137    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkDescriptorSet( pDescriptorWrites[i].dstSet))")
138    cgen.beginFor("uint32_t j = 0", "j < pDescriptorWrites[i].descriptorCount", "++j")
139    cgen.beginIf("(pDescriptorWrites[i].pImageInfo)")
140    cgen.beginIf("pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER")
141    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkSampler( pDescriptorWrites[i].pImageInfo[j].sampler))")
142    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkImageView( pDescriptorWrites[i].pImageInfo[j].imageView))")
143    cgen.endIf()
144    cgen.beginIf("pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER")
145    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkSampler( pDescriptorWrites[i].pImageInfo[j].sampler))")
146    cgen.endIf()
147    cgen.endIf()
148    cgen.beginIf("pDescriptorWrites[i].pBufferInfo");
149    cgen.beginIf("pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER");
150    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkBuffer( pDescriptorWrites[i].pBufferInfo[j].buffer))")
151    cgen.endIf()
152    cgen.endIf()
153    cgen.endFor()
154    cgen.endFor()
155
156def extract_deps_vkCreateImageView(param, access, lenExpr, api, cgen):
157    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s, VkReconstruction::CREATED, VkReconstruction::BOUND_MEMORY)" % \
158              (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkImage(pCreateInfo->image)"))
159
160def extract_deps_vkCreateGraphicsPipelines(param, access, lenExpr, api, cgen):
161    cgen.beginFor("uint32_t i = 0", "i < createInfoCount", "++i")
162    cgen.beginFor("uint32_t j = 0", "j < pCreateInfos[i].stageCount", "++j")
163    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(%s + i), %s, (uint64_t)(uintptr_t)%s)" % \
164              (access, 1, "unboxed_to_boxed_non_dispatchable_VkShaderModule(pCreateInfos[i].pStages[j].module)"))
165    cgen.endFor()
166    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(%s + i), %s, (uint64_t)(uintptr_t)%s)" % \
167              (access, 1, "unboxed_to_boxed_non_dispatchable_VkRenderPass(pCreateInfos[i].renderPass)"))
168    cgen.endFor()
169
170def extract_deps_vkCreateFramebuffer(param, access, lenExpr, api, cgen):
171    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \
172              (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkRenderPass(pCreateInfo->renderPass)"))
173    cgen.beginFor("uint32_t i = 0", "i < pCreateInfo->attachmentCount" , "++i")
174    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \
175              (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkImageView(pCreateInfo->pAttachments[i])"))
176    cgen.endFor()
177
178def extract_deps_vkBindImageMemory(param, access, lenExpr, api, cgen):
179    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s, VkReconstruction::BOUND_MEMORY)" % \
180              (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkDeviceMemory(memory)"))
181    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)((%s)[0]), VkReconstruction::BOUND_MEMORY)" % \
182              (access, lenExpr, access))
183
184def extract_deps_vkBindBufferMemory(param, access, lenExpr, api, cgen):
185    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s, VkReconstruction::BOUND_MEMORY)" % \
186              (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkDeviceMemory(memory)"))
187    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)((%s)[0]), VkReconstruction::BOUND_MEMORY)" % \
188              (access, lenExpr, access))
189
190specialCaseDependencyExtractors = {
191    "vkAllocateCommandBuffers" : extract_deps_vkAllocateCommandBuffers,
192    "vkAllocateDescriptorSets" : extract_deps_vkAllocateDescriptorSets,
193    "vkAllocateMemory" : extract_deps_vkAllocateMemory,
194    "vkCreateImageView" : extract_deps_vkCreateImageView,
195    "vkCreateGraphicsPipelines" : extract_deps_vkCreateGraphicsPipelines,
196    "vkCreateFramebuffer" : extract_deps_vkCreateFramebuffer,
197    "vkBindImageMemory": extract_deps_vkBindImageMemory,
198    "vkBindBufferMemory": extract_deps_vkBindBufferMemory,
199    "vkUpdateDescriptorSets" : extract_deps_vkUpdateDescriptorSets,
200}
201
202apiSequences = {
203    "vkAllocateMemory" : ["vkAllocateMemory", "vkMapMemoryIntoAddressSpaceGOOGLE"]
204}
205
206apiCrreateExtraHandles = [
207    "vkCreateDevice",
208    "vkCreateDescriptorPool",
209]
210
211@dataclass(frozen=True)
212class VkObjectState:
213    vk_object : str
214    state : str = "VkReconstruction::CREATED"
215
216# TODO: add vkBindImageMemory2 and vkBindBufferMemory2 into this list
217apiChangeState = {
218    "vkBindImageMemory": VkObjectState("image", "VkReconstruction::BOUND_MEMORY"),
219    "vkBindBufferMemory": VkObjectState("buffer", "VkReconstruction::BOUND_MEMORY"),
220}
221
222def api_special_implementation_vkBindImageMemory2(api, cgen):
223    childType = "VkImage"
224    parentType = "VkDeviceMemory"
225    childObj = "boxed_%s" % childType
226    parentObj = "boxed_%s" % parentType
227    cgen.stmt("android::base::AutoLock lock(mLock)")
228    cgen.beginFor("uint32_t i = 0", "i < bindInfoCount", "++i")
229    cgen.stmt("%s boxed_%s = unboxed_to_boxed_non_dispatchable_%s(pBindInfos[i].image)"
230              % (childType, childType, childType))
231    cgen.stmt("%s boxed_%s = unboxed_to_boxed_non_dispatchable_%s(pBindInfos[i].memory)"
232              % (parentType, parentType, parentType))
233    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)&%s, %s, (uint64_t)(uintptr_t)%s, VkReconstruction::BOUND_MEMORY)" % \
234              (childObj, "1", parentObj))
235    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)&%s, %s, (uint64_t)(uintptr_t)%s, VkReconstruction::BOUND_MEMORY)" % \
236              (childObj, "1", childObj))
237    cgen.endFor()
238
239    cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()")
240    cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)")
241    cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name)
242    cgen.line("// Note: the implementation does not work with bindInfoCount > 1");
243    cgen.beginFor("uint32_t i = 0", "i < bindInfoCount", "++i")
244    cgen.stmt("%s boxed_%s = unboxed_to_boxed_non_dispatchable_%s(pBindInfos[i].image)"
245              % (childType, childType, childType))
246    cgen.stmt(f"mReconstruction.forEachHandleAddApi((const uint64_t*)&{childObj}, {1}, apiHandle, VkReconstruction::BOUND_MEMORY)")
247    cgen.endFor()
248
249apiSpecialImplementation = {
250    "vkBindImageMemory2": api_special_implementation_vkBindImageMemory2,
251    "vkBindImageMemory2KHR": api_special_implementation_vkBindImageMemory2,
252}
253
254apiModifies = {
255    "vkMapMemoryIntoAddressSpaceGOOGLE" : ["memory"],
256    "vkGetBlobGOOGLE" : ["memory"],
257    "vkBeginCommandBuffer" : ["commandBuffer"],
258    "vkEndCommandBuffer" : ["commandBuffer"],
259}
260
261apiActions = {
262    "vkUpdateDescriptorSets" : ["pDescriptorWrites"],
263}
264
265apiClearModifiers = {
266    "vkResetCommandBuffer" : ["commandBuffer"],
267}
268
269delayedDestroys = [
270    "vkDestroyShaderModule",
271]
272
273# The following types are created and cached by other commands.
274# Thus we should not snapshot their "create" commands.
275skipCreatorSnapshotTypes = [
276    "VkQueue", # created by vkCreateDevice
277]
278
279def is_state_change_operation(api, param):
280    if param.isCreatedBy(api) and param.typeName not in skipCreatorSnapshotTypes:
281        return True
282    if api.name in apiChangeState:
283        if param.paramName == apiChangeState[api.name].vk_object:
284            return True
285    return False
286
287def get_target_state(api, param):
288    if param.isCreatedBy(api):
289        return "VkReconstruction::CREATED"
290    if api.name in apiActions:
291        return "VkReconstruction::CREATED"
292    if api.name in apiChangeState:
293        if param.paramName == apiChangeState[api.name].vk_object:
294            return apiChangeState[api.name].state
295    return None
296
297def is_action_operation(api, param):
298    if api.name in apiActions:
299        if param.paramName in apiActions[api.name]:
300            return True
301    return False
302
303def is_modify_operation(api, param):
304    if api.name in apiModifies:
305        if param.paramName in apiModifies[api.name]:
306            return True
307    if api.name.startswith('vkCmd') and param.paramName == 'commandBuffer':
308        return True
309    return False
310
311def is_clear_modifier_operation(api, param):
312    if api.name in apiClearModifiers:
313        if param.paramName in apiClearModifiers[api.name]:
314            return True
315
316
317def emit_impl(typeInfo, api, cgen):
318    if api.name in apiSpecialImplementation:
319        apiSpecialImplementation[api.name](api, cgen)
320    for p in api.parameters:
321        if not (p.isHandleType):
322            continue
323
324        lenExpr = cgen.generalLengthAccess(p)
325        lenAccessGuard = cgen.generalLengthAccessGuard(p)
326
327        if lenExpr is None:
328            lenExpr = "1"
329
330        # Note that in vkCreate*, the last parameter (the output) is boxed. But all input parameters are unboxed.
331
332        if p.pointerIndirectionLevels > 0:
333            access = p.paramName
334        else:
335            access = "(&%s)" % p.paramName
336
337        if is_state_change_operation(api, p):
338            if p.isCreatedBy(api):
339                boxed_access = access
340            else:
341                cgen.stmt("%s boxed_%s = unboxed_to_boxed_non_dispatchable_%s(%s[0])" % (p.typeName, p.typeName, p.typeName, access))
342                boxed_access = "&boxed_%s" % p.typeName
343            if p.pointerIndirectionLevels > 0:
344                cgen.stmt("if (!%s) return" % access)
345            isCreateExtraHandleApi = api.name in apiCrreateExtraHandles
346            if isCreateExtraHandleApi:
347                cgen.stmt("mLock.tryLock()");
348            else:
349                cgen.stmt("android::base::AutoLock lock(mLock)")
350            cgen.line("// %s create" % p.paramName)
351            if p.isCreatedBy(api):
352                cgen.stmt("mReconstruction.addHandles((const uint64_t*)%s, %s)" % (boxed_access, lenExpr));
353
354            if p.isCreatedBy(api) and p.typeName in handleDependenciesDict:
355                dependsOnType = handleDependenciesDict[p.typeName];
356                for p2 in api.parameters:
357                    if p2.typeName == dependsOnType:
358                        cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % (boxed_access, lenExpr, p2.paramName))
359            if api.name in specialCaseDependencyExtractors:
360                specialCaseDependencyExtractors[api.name](p, boxed_access, lenExpr, api, cgen)
361
362            cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()")
363            cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)")
364            cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name)
365            if lenAccessGuard is not None:
366                cgen.beginIf(lenAccessGuard)
367            cgen.stmt(f"mReconstruction.forEachHandleAddApi((const uint64_t*){boxed_access}, {lenExpr}, apiHandle, {get_target_state(api, p)})")
368            if p.isCreatedBy(api):
369                cgen.stmt("mReconstruction.setCreatedHandlesForApi(apiHandle, (const uint64_t*)%s, %s)" % (boxed_access, lenExpr))
370            if lenAccessGuard is not None:
371                cgen.endIf()
372            if isCreateExtraHandleApi:
373                cgen.stmt("mLock.unlock()")
374
375        if p.isDestroyedBy(api):
376            cgen.stmt("android::base::AutoLock lock(mLock)")
377            cgen.line("// %s destroy" % p.paramName)
378            if lenAccessGuard is not None:
379                cgen.beginIf(lenAccessGuard)
380            shouldRecursiveDestroy = "false" if api.name in delayedDestroys else "true"
381            cgen.stmt("mReconstruction.removeHandles((const uint64_t*)%s, %s, %s)" % (access, lenExpr, shouldRecursiveDestroy));
382            if lenAccessGuard is not None:
383                cgen.endIf()
384
385        if is_action_operation(api, p):
386            cgen.stmt("android::base::AutoLock lock(mLock)")
387            cgen.line("// %s action" % p.paramName)
388            cgen.stmt("VkDecoderGlobalState* m_state = VkDecoderGlobalState::get()")
389            cgen.beginIf("m_state->batchedDescriptorSetUpdateEnabled()")
390            cgen.stmt("return")
391            cgen.endIf();
392            cgen.stmt("uint64_t handle = m_state->newGlobalVkGenericHandle()")
393            cgen.stmt("mReconstruction.addHandles((const uint64_t*)(&handle), 1)");
394            cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()")
395            cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)")
396            cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name)
397            if api.name in specialCaseDependencyExtractors:
398                specialCaseDependencyExtractors[api.name](p, None, None, api, cgen)
399            cgen.stmt(f"mReconstruction.forEachHandleAddApi((const uint64_t*)(&handle), 1, apiHandle, {get_target_state(api, p)})")
400            cgen.stmt("mReconstruction.setCreatedHandlesForApi(apiHandle, (const uint64_t*)(&handle), 1)")
401
402        elif is_modify_operation(api, p) or is_clear_modifier_operation(api, p):
403            cgen.stmt("android::base::AutoLock lock(mLock)")
404            cgen.line("// %s modify" % p.paramName)
405            cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()")
406            cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)")
407            cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name)
408            if lenAccessGuard is not None:
409                cgen.beginIf(lenAccessGuard)
410            cgen.beginFor("uint32_t i = 0", "i < %s" % lenExpr, "++i")
411            if p.isNonDispatchableHandleType():
412                cgen.stmt("%s boxed = unboxed_to_boxed_non_dispatchable_%s(%s[i])" % (p.typeName, p.typeName, access))
413            else:
414                cgen.line("// %s is already boxed, no need to box again" % p.paramName)
415                cgen.stmt("%s boxed = %s(%s[i])" % (p.typeName, p.typeName, access))
416            if is_modify_operation(api, p):
417                cgen.stmt("mReconstruction.forEachHandleAddModifyApi((const uint64_t*)(&boxed), 1, apiHandle)")
418            else: # is clear modifier operation
419                cgen.stmt("mReconstruction.forEachHandleClearModifyApi((const uint64_t*)(&boxed), 1)")
420            cgen.endFor()
421            if lenAccessGuard is not None:
422                cgen.endIf()
423
424def emit_passthrough_to_impl(typeInfo, api, cgen):
425    cgen.vkApiCall(api, customPrefix = "mImpl->")
426
427class VulkanDecoderSnapshot(VulkanWrapperGenerator):
428    def __init__(self, module, typeInfo):
429        VulkanWrapperGenerator.__init__(self, module, typeInfo)
430
431        self.typeInfo = typeInfo
432
433        self.cgenHeader = CodeGen()
434        self.cgenHeader.incrIndent()
435
436        self.cgenImpl = CodeGen()
437
438        self.currentFeature = None
439
440        self.feature_apis = []
441
442    def onBegin(self,):
443        self.module.appendHeader(decoder_snapshot_decl_preamble)
444        self.module.appendImpl(decoder_snapshot_impl_preamble)
445
446    def onBeginFeature(self, featureName, featureType):
447        VulkanWrapperGenerator.onBeginFeature(self, featureName, featureType)
448        self.currentFeature = featureName
449
450    def onGenCmd(self, cmdinfo, name, alias):
451        VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
452
453        api = self.typeInfo.apis[name]
454
455        additionalParams = [ \
456            makeVulkanTypeSimple(True, "uint8_t", 1, "snapshotTraceBegin"),
457            makeVulkanTypeSimple(False, "size_t", 0, "snapshotTraceBytes"),
458            makeVulkanTypeSimple(False, "android::base::BumpPool", 1, "pool"),]
459
460        if api.retType.typeName != "void":
461            additionalParams.append( \
462                makeVulkanTypeSimple(False, api.retType.typeName, 0, "input_result"))
463
464        apiForSnapshot = \
465            api.withCustomParameters( \
466                additionalParams + \
467                api.parameters).withCustomReturnType( \
468                    makeVulkanTypeSimple(False, "void", 0, "void"))
469
470        self.feature_apis.append((self.currentFeature, apiForSnapshot))
471
472        self.cgenHeader.stmt(self.cgenHeader.makeFuncProto(apiForSnapshot))
473        self.module.appendHeader(self.cgenHeader.swapCode())
474
475        self.cgenImpl.emitFuncImpl( \
476            apiForSnapshot, lambda cgen: emit_impl(self.typeInfo, apiForSnapshot, cgen))
477        self.module.appendImpl(self.cgenImpl.swapCode())
478
479    def onEnd(self,):
480        self.module.appendHeader(decoder_snapshot_decl_postamble)
481        self.module.appendImpl(decoder_snapshot_impl_postamble)
482        self.cgenHeader.decrIndent()
483
484        for feature, api in self.feature_apis:
485            if feature is not None:
486                self.cgenImpl.line("#ifdef %s" % feature)
487
488            apiImplShell = \
489                api.withModifiedName("VkDecoderSnapshot::" + api.name)
490
491            self.cgenImpl.emitFuncImpl( \
492                apiImplShell, lambda cgen: emit_passthrough_to_impl(self.typeInfo, api, cgen))
493
494            if feature is not None:
495                self.cgenImpl.line("#endif")
496
497        self.module.appendImpl(self.cgenImpl.swapCode())
498
499