• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from .common.codegen import CodeGen, VulkanWrapperGenerator, VulkanAPIWrapper
2from .common.vulkantypes import \
3        VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, DISPATCHABLE_HANDLE_TYPES, NON_DISPATCHABLE_HANDLE_TYPES
4
5from .transform import TransformCodegen, genTransformsForVulkanType
6
7from .wrapperdefs import API_PREFIX_MARSHAL
8from .wrapperdefs import API_PREFIX_UNMARSHAL
9from .wrapperdefs import VULKAN_STREAM_TYPE
10
11from copy import copy
12
13decoder_snapshot_decl_preamble = """
14
15namespace android {
16namespace base {
17class BumpPool;
18class Stream;
19} // namespace base {
20} // namespace android {
21
22class VkDecoderSnapshot {
23public:
24    VkDecoderSnapshot();
25    ~VkDecoderSnapshot();
26
27    void save(android::base::Stream* stream);
28    void load(android::base::Stream* stream);
29"""
30
31decoder_snapshot_decl_postamble = """
32private:
33    class Impl;
34    std::unique_ptr<Impl> mImpl;
35
36};
37"""
38
39decoder_snapshot_impl_preamble ="""
40
41using namespace goldfish_vk;
42
43class VkDecoderSnapshot::Impl {
44public:
45    Impl() { }
46
47    void save(android::base::Stream* stream) {
48        mReconstruction.save(stream);
49    }
50
51    void load(android::base::Stream* stream) {
52        mReconstruction.load(stream);
53    }
54
55"""
56
57decoder_snapshot_impl_postamble = """
58private:
59    android::base::Lock mLock;
60    VkReconstruction mReconstruction;
61};
62
63VkDecoderSnapshot::VkDecoderSnapshot() :
64    mImpl(new VkDecoderSnapshot::Impl()) { }
65
66void VkDecoderSnapshot::save(android::base::Stream* stream) {
67    mImpl->save(stream);
68}
69
70void VkDecoderSnapshot::load(android::base::Stream* stream) {
71    mImpl->load(stream);
72}
73
74VkDecoderSnapshot::~VkDecoderSnapshot() = default;
75"""
76
77AUXILIARY_SNAPSHOT_API_BASE_PARAM_COUNT = 3
78
79AUXILIARY_SNAPSHOT_API_PARAM_NAMES = [
80    "input_result",
81]
82
83# Vulkan handle dependencies.
84# (a, b): a depends on b
85SNAPSHOT_HANDLE_DEPENDENCIES = [
86    # Dispatchable handle types
87    ("VkCommandBuffer", "VkCommandPool"),
88    ("VkCommandPool", "VkDevice"),
89    ("VkQueue", "VkDevice"),
90    ("VkDevice", "VkPhysicalDevice"),
91    ("VkPhysicalDevice", "VkInstance")] + \
92    list(map(lambda handleType : (handleType, "VkDevice"), NON_DISPATCHABLE_HANDLE_TYPES))
93
94handleDependenciesDict = dict(SNAPSHOT_HANDLE_DEPENDENCIES)
95
96def extract_deps_vkAllocateCommandBuffers(param, access, lenExpr, api, cgen):
97    cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \
98              (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkCommandPool(pAllocateInfo->commandPool)"))
99
100specialCaseDependencyExtractors = {
101    "vkAllocateCommandBuffers" : extract_deps_vkAllocateCommandBuffers,
102}
103
104apiSequences = {
105    "vkAllocateMemory" : ["vkAllocateMemory", "vkMapMemoryIntoAddressSpaceGOOGLE"]
106}
107
108apiModifies = {
109    "vkMapMemoryIntoAddressSpaceGOOGLE" : ["memory"],
110}
111
112def is_modify_operation(api, param):
113    if api.name in apiModifies:
114        if param.paramName in apiModifies[api.name]:
115            return True
116    return False
117
118def emit_impl(typeInfo, api, cgen):
119
120    cgen.line("// TODO: Implement")
121
122    for p in api.parameters:
123        if not (p.isHandleType):
124            continue
125
126        lenExpr = cgen.generalLengthAccess(p)
127        lenAccessGuard = cgen.generalLengthAccessGuard(p)
128
129        if lenExpr is None:
130            lenExpr = "1"
131
132        if p.pointerIndirectionLevels > 0:
133            access = p.paramName
134        else:
135            access = "(&%s)" % p.paramName
136
137        if p.isCreatedBy(api):
138            cgen.stmt("android::base::AutoLock lock(mLock)")
139            cgen.line("// %s create" % p.paramName)
140            cgen.stmt("mReconstruction.addHandles((const uint64_t*)%s, %s)" % (access, lenExpr));
141
142            if p.typeName in handleDependenciesDict:
143                dependsOnType = handleDependenciesDict[p.typeName];
144                for p2 in api.parameters:
145                    if p2.typeName == dependsOnType:
146                        cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % (access, lenExpr, p2.paramName))
147                if api.name in specialCaseDependencyExtractors:
148                    specialCaseDependencyExtractors[api.name](p, access, lenExpr, api, cgen)
149
150            cgen.stmt("if (!%s) return" % access)
151            cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()")
152            cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)")
153            cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name)
154            if lenAccessGuard is not None:
155                cgen.beginIf(lenAccessGuard)
156            cgen.stmt("mReconstruction.forEachHandleAddApi((const uint64_t*)%s, %s, apiHandle)" % (access, lenExpr))
157            cgen.stmt("mReconstruction.setCreatedHandlesForApi(apiHandle, (const uint64_t*)%s, %s)" % (access, lenExpr))
158            if lenAccessGuard is not None:
159                cgen.endIf()
160
161        if p.isDestroyedBy(api):
162            cgen.stmt("android::base::AutoLock lock(mLock)")
163            cgen.line("// %s destroy" % p.paramName)
164            if lenAccessGuard is not None:
165                cgen.beginIf(lenAccessGuard)
166            cgen.stmt("mReconstruction.removeHandles((const uint64_t*)%s, %s)" % (access, lenExpr));
167            if lenAccessGuard is not None:
168                cgen.endIf()
169
170        if is_modify_operation(api, p):
171            cgen.stmt("android::base::AutoLock lock(mLock)")
172            cgen.line("// %s modify" % p.paramName)
173            cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()")
174            cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)")
175            cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name)
176            if lenAccessGuard is not None:
177                cgen.beginIf(lenAccessGuard)
178            cgen.beginFor("uint32_t i = 0", "i < %s" % lenExpr, "++i")
179            if p.isNonDispatchableHandleType():
180                cgen.stmt("%s boxed = unboxed_to_boxed_non_dispatchable_%s(%s[i])" % (p.typeName, p.typeName, access))
181            else:
182                cgen.stmt("%s boxed = unboxed_to_boxed_%s(%s[i])" % (p.typeName, p.typeName, access))
183            cgen.stmt("mReconstruction.forEachHandleAddModifyApi((const uint64_t*)(&boxed), 1, apiHandle)")
184            cgen.endFor()
185            if lenAccessGuard is not None:
186                cgen.endIf()
187
188def emit_passthrough_to_impl(typeInfo, api, cgen):
189    cgen.vkApiCall(api, customPrefix = "mImpl->")
190
191class VulkanDecoderSnapshot(VulkanWrapperGenerator):
192    def __init__(self, module, typeInfo):
193        VulkanWrapperGenerator.__init__(self, module, typeInfo)
194
195        self.typeInfo = typeInfo
196
197        self.cgenHeader = CodeGen()
198        self.cgenHeader.incrIndent()
199
200        self.cgenImpl = CodeGen()
201
202        self.currentFeature = None
203
204        self.feature_apis = []
205
206    def onBegin(self,):
207        self.module.appendHeader(decoder_snapshot_decl_preamble)
208        self.module.appendImpl(decoder_snapshot_impl_preamble)
209
210    def onBeginFeature(self, featureName):
211        VulkanWrapperGenerator.onBeginFeature(self, featureName)
212        self.currentFeature = featureName
213
214    def onGenCmd(self, cmdinfo, name, alias):
215        VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
216
217        api = self.typeInfo.apis[name]
218
219        additionalParams = [ \
220            makeVulkanTypeSimple(True, "uint8_t", 1, "snapshotTraceBegin"),
221            makeVulkanTypeSimple(False, "size_t", 0, "snapshotTraceBytes"),
222            makeVulkanTypeSimple(False, "android::base::BumpPool", 1, "pool"),]
223
224        if api.retType.typeName != "void":
225            additionalParams.append( \
226                makeVulkanTypeSimple(False, api.retType.typeName, 0, "input_result"))
227
228        apiForSnapshot = \
229            api.withCustomParameters( \
230                additionalParams + \
231                api.parameters).withCustomReturnType( \
232                    makeVulkanTypeSimple(False, "void", 0, "void"))
233
234        self.feature_apis.append((self.currentFeature, apiForSnapshot))
235
236        self.cgenHeader.stmt(self.cgenHeader.makeFuncProto(apiForSnapshot))
237        self.module.appendHeader(self.cgenHeader.swapCode())
238
239        self.cgenImpl.emitFuncImpl( \
240            apiForSnapshot, lambda cgen: emit_impl(self.typeInfo, apiForSnapshot, cgen))
241        self.module.appendImpl(self.cgenImpl.swapCode())
242
243    def onEnd(self,):
244        self.module.appendHeader(decoder_snapshot_decl_postamble)
245        self.module.appendImpl(decoder_snapshot_impl_postamble)
246        self.cgenHeader.decrIndent()
247
248        for feature, api in self.feature_apis:
249            if feature is not None:
250                self.cgenImpl.line("#ifdef %s" % feature)
251
252            apiImplShell = \
253                api.withModifiedName("VkDecoderSnapshot::" + api.name)
254
255            self.cgenImpl.emitFuncImpl( \
256                apiImplShell, lambda cgen: emit_passthrough_to_impl(self.typeInfo, api, cgen))
257
258            if feature is not None:
259                self.cgenImpl.line("#endif")
260
261        self.module.appendImpl(self.cgenImpl.swapCode())
262
263