• 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 .marshaling import VulkanMarshalingCodegen
6from .reservedmarshaling import VulkanReservedMarshalingCodegen
7from .transform import TransformCodegen, genTransformsForVulkanType
8
9from .wrapperdefs import API_PREFIX_MARSHAL
10from .wrapperdefs import API_PREFIX_UNMARSHAL, API_PREFIX_RESERVEDUNMARSHAL
11from .wrapperdefs import VULKAN_STREAM_TYPE
12from .wrapperdefs import ROOT_TYPE_DEFAULT_VALUE
13from .wrapperdefs import RELAXED_APIS
14
15from copy import copy
16
17SKIPPED_DECODER_DELETES = [
18    "vkFreeDescriptorSets",
19]
20
21DELAYED_DECODER_DELETES = [
22    "vkDestroyPipelineLayout",
23]
24
25decoder_decl_preamble = """
26
27class IOStream;
28
29class VkDecoder {
30public:
31    VkDecoder();
32    ~VkDecoder();
33    void setForSnapshotLoad(bool forSnapshotLoad);
34    size_t decode(void* buf, size_t bufsize, IOStream* stream, uint32_t* seqnoPtr);
35private:
36    class Impl;
37    std::unique_ptr<Impl> mImpl;
38};
39"""
40
41decoder_impl_preamble ="""
42using emugl::vkDispatch;
43
44using namespace goldfish_vk;
45
46class VkDecoder::Impl {
47public:
48    Impl() : m_logCalls(android::base::getEnvironmentVariable("ANDROID_EMU_VK_LOG_CALLS") == "1"),
49             m_vk(vkDispatch()),
50             m_state(VkDecoderGlobalState::get()),
51             m_boxedHandleUnwrapMapping(m_state),
52             m_boxedHandleCreateMapping(m_state),
53             m_boxedHandleDestroyMapping(m_state),
54             m_boxedHandleUnwrapAndDeleteMapping(m_state),
55             m_boxedHandleUnwrapAndDeletePreserveBoxedMapping(m_state) { }
56    %s* stream() { return &m_vkStream; }
57    VulkanMemReadingStream* readStream() { return &m_vkMemReadingStream; }
58
59    void setForSnapshotLoad(bool forSnapshotLoad) {
60        m_forSnapshotLoad = forSnapshotLoad;
61    }
62
63    size_t decode(void* buf, size_t bufsize, IOStream* stream, uint32_t* seqnoPtr);
64
65private:
66    bool m_logCalls;
67    bool m_forSnapshotLoad = false;
68    VulkanDispatch* m_vk;
69    VkDecoderGlobalState* m_state;
70    %s m_vkStream { nullptr };
71    VulkanMemReadingStream m_vkMemReadingStream { nullptr };
72    BoxedHandleUnwrapMapping m_boxedHandleUnwrapMapping;
73    BoxedHandleCreateMapping m_boxedHandleCreateMapping;
74    BoxedHandleDestroyMapping m_boxedHandleDestroyMapping;
75    BoxedHandleUnwrapAndDeleteMapping m_boxedHandleUnwrapAndDeleteMapping;
76    android::base::BumpPool m_pool;
77    BoxedHandleUnwrapAndDeletePreserveBoxedMapping m_boxedHandleUnwrapAndDeletePreserveBoxedMapping;
78};
79
80VkDecoder::VkDecoder() :
81    mImpl(new VkDecoder::Impl()) { }
82
83VkDecoder::~VkDecoder() = default;
84
85void VkDecoder::setForSnapshotLoad(bool forSnapshotLoad) {
86    mImpl->setForSnapshotLoad(forSnapshotLoad);
87}
88
89size_t VkDecoder::decode(void* buf, size_t bufsize, IOStream* stream, uint32_t* seqnoPtr) {
90    return mImpl->decode(buf, bufsize, stream, seqnoPtr);
91}
92
93// VkDecoder::Impl::decode to follow
94""" % (VULKAN_STREAM_TYPE, VULKAN_STREAM_TYPE)
95
96READ_STREAM = "vkReadStream"
97WRITE_STREAM = "vkStream"
98
99# Driver workarounds for APIs that don't work well multithreaded
100driver_workarounds_global_lock_apis = [ \
101    "vkCreatePipelineLayout",
102    "vkDestroyPipelineLayout",
103]
104
105def emit_param_decl_for_reading(param, cgen):
106    if param.staticArrExpr:
107        cgen.stmt(
108            cgen.makeRichCTypeDecl(param.getForNonConstAccess()))
109    else:
110        cgen.stmt(
111            cgen.makeRichCTypeDecl(param))
112
113def emit_unmarshal(typeInfo, param, cgen, output = False, destroy = False, noUnbox = False):
114    if destroy:
115        iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen(
116            cgen,
117            READ_STREAM,
118            ROOT_TYPE_DEFAULT_VALUE,
119            param.paramName,
120            "readStreamPtrPtr",
121            API_PREFIX_RESERVEDUNMARSHAL,
122            "",
123            direction="read",
124            dynAlloc=True))
125        lenAccess = cgen.generalLengthAccess(param)
126        lenAccessGuard = cgen.generalLengthAccessGuard(param)
127        if None == lenAccess or "1" == lenAccess:
128            cgen.stmt("boxed_%s_preserve = %s" % (param.paramName, param.paramName))
129            cgen.stmt("%s = unbox_%s(%s)" % (param.paramName, param.typeName, param.paramName))
130        else:
131            if lenAccessGuard is not None:
132                cgen.beginIf(lenAccessGuard)
133            cgen.beginFor("uint32_t i = 0", "i < %s" % lenAccess, "++i")
134            cgen.stmt("boxed_%s_preserve[i] = %s[i]" % (param.paramName, param.paramName))
135            cgen.stmt("((%s*)(%s))[i] = unbox_%s(%s[i])" % (param.typeName, param.paramName, param.typeName, param.paramName))
136            cgen.endFor()
137            if lenAccessGuard is not None:
138                cgen.endIf()
139    else:
140        if noUnbox:
141            cgen.line("// No unbox for %s" % (param.paramName))
142        iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen(
143            cgen,
144            READ_STREAM,
145            ROOT_TYPE_DEFAULT_VALUE,
146            param.paramName,
147            "readStreamPtrPtr",
148            API_PREFIX_RESERVEDUNMARSHAL,
149            "" if (output or noUnbox) else "unbox_",
150            direction="read",
151            dynAlloc=True))
152
153def emit_dispatch_unmarshal(typeInfo, param, cgen, globalWrapped):
154    if globalWrapped:
155        cgen.stmt("// Begin global wrapped dispatchable handle unboxing for %s" % param.paramName)
156        iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen(
157            cgen,
158            READ_STREAM,
159            ROOT_TYPE_DEFAULT_VALUE,
160            param.paramName,
161            "readStreamPtrPtr",
162            API_PREFIX_RESERVEDUNMARSHAL,
163            "",
164            direction="read",
165            dynAlloc=True))
166    else:
167        cgen.stmt("// Begin non wrapped dispatchable handle unboxing for %s" % param.paramName)
168        # cgen.stmt("%s->unsetHandleMapping()" % READ_STREAM)
169        iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen(
170            cgen,
171            READ_STREAM,
172            ROOT_TYPE_DEFAULT_VALUE,
173            param.paramName,
174            "readStreamPtrPtr",
175            API_PREFIX_RESERVEDUNMARSHAL,
176            "",
177            direction="read",
178            dynAlloc=True))
179        cgen.stmt("auto unboxed_%s = unbox_%s(%s)" %
180                  (param.paramName, param.typeName, param.paramName))
181        cgen.stmt("auto vk = dispatch_%s(%s)" %
182                  (param.typeName, param.paramName))
183        cgen.stmt("// End manual dispatchable handle unboxing for %s" % param.paramName)
184
185def emit_transform(typeInfo, param, cgen, variant="tohost"):
186    res = \
187        iterateVulkanType(typeInfo, param, TransformCodegen( \
188            cgen, param.paramName, "m_state", "transform_%s_" % variant, variant))
189    if not res:
190        cgen.stmt("(void)%s" % param.paramName)
191
192def emit_marshal(typeInfo, param, cgen, handleMapOverwrites=False):
193    iterateVulkanType(typeInfo, param, VulkanMarshalingCodegen(
194        cgen,
195        WRITE_STREAM,
196        ROOT_TYPE_DEFAULT_VALUE,
197        param.paramName,
198        API_PREFIX_MARSHAL,
199        direction="write",
200        handleMapOverwrites=handleMapOverwrites))
201
202class DecodingParameters(object):
203    def __init__(self, api):
204        self.params = []
205        self.toRead = []
206        self.toWrite = []
207
208        i = 0
209
210        for param in api.parameters:
211            param.nonDispatchableHandleCreate = False
212            param.nonDispatchableHandleDestroy = False
213            param.dispatchHandle = False
214            param.dispatchableHandleCreate = False
215            param.dispatchableHandleDestroy = False
216
217            if i == 0 and param.isDispatchableHandleType():
218                param.dispatchHandle = True
219
220            if param.isNonDispatchableHandleType() and param.isCreatedBy(api):
221                param.nonDispatchableHandleCreate = True
222
223            if param.isNonDispatchableHandleType() and param.isDestroyedBy(api):
224                param.nonDispatchableHandleDestroy = True
225
226            if param.isDispatchableHandleType() and param.isCreatedBy(api):
227                param.dispatchableHandleCreate = True
228
229            if param.isDispatchableHandleType() and param.isDestroyedBy(api):
230                param.dispatchableHandleDestroy = True
231
232            self.toRead.append(param)
233
234            if param.possiblyOutput():
235                self.toWrite.append(param)
236
237            self.params.append(param)
238
239            i += 1
240
241def emit_call_log(api, cgen):
242    decodingParams = DecodingParameters(api)
243    paramsToRead = decodingParams.toRead
244
245    cgen.beginIf("m_logCalls")
246    paramLogFormat = ""
247    paramLogArgs = []
248    for p in paramsToRead:
249        paramLogFormat += "0x%llx "
250    for p in paramsToRead:
251        paramLogArgs.append("(unsigned long long)%s" % (p.paramName))
252    cgen.stmt("fprintf(stderr, \"stream %%p: call %s %s\\n\", ioStream, %s)" % (api.name, paramLogFormat, ", ".join(paramLogArgs)))
253    cgen.endIf()
254
255def emit_decode_parameters(typeInfo, api, cgen, globalWrapped=False):
256
257    decodingParams = DecodingParameters(api)
258
259    paramsToRead = decodingParams.toRead
260
261    for p in paramsToRead:
262        emit_param_decl_for_reading(p, cgen)
263
264    i = 0
265    for p in paramsToRead:
266        lenAccess =  cgen.generalLengthAccess(p)
267
268        if p.dispatchHandle:
269            emit_dispatch_unmarshal(typeInfo, p, cgen, globalWrapped)
270        else:
271            destroy = p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy
272            noUnbox = api.name == "vkQueueFlushCommandsGOOGLE" and p.paramName == "commandBuffer"
273
274            if p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy:
275                destroy = True
276                cgen.stmt("// Begin manual non dispatchable handle destroy unboxing for %s" % p.paramName)
277                if None == lenAccess or "1" == lenAccess:
278                    cgen.stmt("%s boxed_%s_preserve" % (p.typeName, p.paramName))
279                else:
280                    cgen.stmt("%s* boxed_%s_preserve; %s->alloc((void**)&boxed_%s_preserve, %s * sizeof(%s))" % (p.typeName, p.paramName, READ_STREAM, p.paramName, lenAccess, p.typeName))
281
282            if p.possiblyOutput():
283                cgen.stmt("// Begin manual dispatchable handle unboxing for %s" % p.paramName)
284                cgen.stmt("%s->unsetHandleMapping()" % READ_STREAM)
285
286            emit_unmarshal(typeInfo, p, cgen, output = p.possiblyOutput(), destroy = destroy, noUnbox = noUnbox)
287        i += 1
288
289    for p in paramsToRead:
290        emit_transform(typeInfo, p, cgen, variant="tohost");
291
292    emit_call_log(api, cgen)
293
294def emit_dispatch_call(api, cgen):
295
296    decodingParams = DecodingParameters(api)
297
298    customParams = []
299
300    delay = api.name in DELAYED_DECODER_DELETES
301
302    for (i, p) in enumerate(api.parameters):
303        customParam = p.paramName
304        if decodingParams.params[i].dispatchHandle:
305            customParam = "unboxed_%s" % p.paramName
306        customParams.append(customParam)
307
308    if delay:
309        cgen.line("std::function<void()> delayed_remove_callback = [vk, %s]() {" % ", ".join(customParams))
310
311    if api.name in driver_workarounds_global_lock_apis:
312        if delay:
313            cgen.stmt("auto state = VkDecoderGlobalState::get()")
314            cgen.stmt("// state already locked")
315        else:
316            cgen.stmt("m_state->lock()")
317
318    cgen.vkApiCall(api, customPrefix="vk->", customParameters=customParams)
319
320    if api.name in driver_workarounds_global_lock_apis:
321        if not delay:
322            cgen.stmt("m_state->unlock()")
323        # for delayed remove, state is already locked, so we do not need to
324        # unlock
325
326    if delay:
327        cgen.line("};")
328
329def emit_global_state_wrapped_call(api, cgen):
330    if api.name in DELAYED_DECODER_DELETES:
331        print("Error: Cannot generate a global state wrapped call that is also a delayed delete (yet)");
332        raise
333
334    customParams = ["&m_pool"] + list(map(lambda p: p.paramName, api.parameters))
335    cgen.vkApiCall(api, customPrefix="m_state->on_", \
336        customParameters=customParams)
337
338def emit_decode_parameters_writeback(typeInfo, api, cgen, autobox=True):
339    decodingParams = DecodingParameters(api)
340
341    paramsToWrite = decodingParams.toWrite
342
343    cgen.stmt("%s->unsetHandleMapping()" % WRITE_STREAM)
344
345    handleMapOverwrites = False
346
347    for p in paramsToWrite:
348        emit_transform(typeInfo, p, cgen, variant="fromhost")
349
350        handleMapOverwrites = False
351
352        if p.nonDispatchableHandleCreate or p.dispatchableHandleCreate:
353            handleMapOverwrites = True
354
355        if autobox and p.nonDispatchableHandleCreate:
356            cgen.stmt("// Begin auto non dispatchable handle create for %s" % p.paramName)
357            cgen.stmt("if (%s == VK_SUCCESS) %s->setHandleMapping(&m_boxedHandleCreateMapping)" % \
358                      (api.getRetVarExpr(), WRITE_STREAM))
359
360        if (not autobox) and p.nonDispatchableHandleCreate:
361            cgen.stmt("// Begin manual non dispatchable handle create for %s" % p.paramName)
362            cgen.stmt("%s->unsetHandleMapping()" % WRITE_STREAM)
363
364        emit_marshal(typeInfo, p, cgen, handleMapOverwrites=handleMapOverwrites)
365
366        if autobox and p.nonDispatchableHandleCreate:
367            cgen.stmt("// Begin auto non dispatchable handle create for %s" % p.paramName)
368            cgen.stmt("%s->setHandleMapping(&m_boxedHandleUnwrapMapping)" % WRITE_STREAM)
369
370        if (not autobox) and p.nonDispatchableHandleCreate:
371            cgen.stmt("// Begin manual non dispatchable handle create for %s" % p.paramName)
372            cgen.stmt("%s->setHandleMapping(&m_boxedHandleUnwrapMapping)" % WRITE_STREAM)
373
374def emit_decode_return_writeback(api, cgen):
375    retTypeName = api.getRetTypeExpr()
376    if retTypeName != "void":
377        retVar = api.getRetVarExpr()
378        cgen.stmt("%s->write(&%s, %s)" %
379            (WRITE_STREAM, retVar, cgen.sizeofExpr(api.retType)))
380
381def emit_decode_finish(api, cgen):
382    decodingParams = DecodingParameters(api)
383    retTypeName = api.getRetTypeExpr()
384    paramsToWrite = decodingParams.toWrite
385
386    if retTypeName != "void" or len(paramsToWrite) != 0:
387        cgen.stmt("%s->commitWrite()" % WRITE_STREAM)
388
389def emit_destroyed_handle_cleanup(api, cgen):
390    decodingParams = DecodingParameters(api)
391    paramsToRead = decodingParams.toRead
392
393    skipDelete = api.name in SKIPPED_DECODER_DELETES
394
395    if skipDelete:
396        cgen.line("// Skipping handle cleanup for %s" % api.name)
397        return
398
399    for p in paramsToRead:
400        if p.dispatchHandle:
401            pass
402        else:
403            lenAccess = cgen.generalLengthAccess(p)
404            lenAccessGuard = cgen.generalLengthAccess(p)
405            destroy = p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy
406            if destroy:
407                if None == lenAccess or "1" == lenAccess:
408                    if api.name in DELAYED_DECODER_DELETES:
409                        cgen.stmt("delayed_delete_%s(boxed_%s_preserve, unboxed_device, delayed_remove_callback)" % (p.typeName, p.paramName))
410                    else:
411                        cgen.stmt("delete_%s(boxed_%s_preserve)" % (p.typeName, p.paramName))
412                else:
413                    if lenAccessGuard is not None:
414                        cgen.beginIf(lenAccessGuard)
415                    cgen.beginFor("uint32_t i = 0", "i < %s" % lenAccess, "++i")
416                    if api.name in DELAYED_DECODER_DELETES:
417                        cgen.stmt("delayed_delete_%s(boxed_%s_preserve[i], unboxed_device, delayed_remove_callback)" % (p.typeName, p.paramName))
418                    else:
419                        cgen.stmt("delete_%s(boxed_%s_preserve[i])" % (p.typeName, p.paramName))
420                    cgen.endFor()
421                    if lenAccessGuard is not None:
422                        cgen.endIf()
423
424def emit_pool_free(cgen):
425    cgen.stmt("%s->clearPool()" % READ_STREAM)
426
427def emit_seqno_incr(api, cgen):
428    cgen.stmt("if (queueSubmitWithCommandsEnabled) __atomic_fetch_add(seqnoPtr, 1, __ATOMIC_SEQ_CST)")
429
430def emit_snapshot(typeInfo, api, cgen):
431
432    cgen.stmt("%s->setReadPos((uintptr_t)(*readStreamPtrPtr) - (uintptr_t)snapshotTraceBegin)" % READ_STREAM)
433    cgen.stmt("size_t snapshotTraceBytes = %s->endTrace()" % READ_STREAM)
434
435    additionalParams = [ \
436        makeVulkanTypeSimple(True, "uint8_t", 1, "snapshotTraceBegin"),
437        makeVulkanTypeSimple(False, "size_t", 0, "snapshotTraceBytes"),
438        makeVulkanTypeSimple(False, "android::base::BumpPool", 1, "&m_pool"),
439    ]
440
441    retTypeName = api.getRetTypeExpr()
442    if retTypeName != "void":
443        retVar = api.getRetVarExpr()
444        additionalParams.append(makeVulkanTypeSimple(False, retTypeName, 0, retVar))
445
446    paramsForSnapshot = []
447
448    decodingParams = DecodingParameters(api)
449
450    for p in decodingParams.toRead:
451        if p.nonDispatchableHandleDestroy or (not p.dispatchHandle and p.dispatchableHandleDestroy):
452            paramsForSnapshot.append(p.withModifiedName("boxed_%s_preserve" % p.paramName))
453        else:
454            paramsForSnapshot.append(p)
455
456    customParams = additionalParams + paramsForSnapshot
457
458    apiForSnapshot = \
459        api.withCustomReturnType(makeVulkanTypeSimple(False, "void", 0, "void")). \
460            withCustomParameters(customParams)
461
462    cgen.beginIf("m_state->snapshotsEnabled()")
463    cgen.vkApiCall(apiForSnapshot, customPrefix="m_state->snapshot()->")
464    cgen.endIf()
465
466def emit_default_decoding(typeInfo, api, cgen):
467    isAcquire = api.name in RELAXED_APIS
468    emit_decode_parameters(typeInfo, api, cgen)
469
470    if isAcquire:
471        emit_seqno_incr(api, cgen)
472
473    emit_dispatch_call(api, cgen)
474    emit_decode_parameters_writeback(typeInfo, api, cgen)
475    emit_decode_return_writeback(api, cgen)
476    emit_decode_finish(api, cgen)
477    emit_snapshot(typeInfo, api, cgen)
478    emit_destroyed_handle_cleanup(api, cgen)
479    emit_pool_free(cgen)
480
481    if not isAcquire:
482        emit_seqno_incr(api, cgen)
483
484def emit_global_state_wrapped_decoding(typeInfo, api, cgen):
485    isAcquire = api.name in RELAXED_APIS
486
487    emit_decode_parameters(typeInfo, api, cgen, globalWrapped=True)
488
489    if isAcquire:
490        emit_seqno_incr(api, cgen)
491
492    emit_global_state_wrapped_call(api, cgen)
493    emit_decode_parameters_writeback(typeInfo, api, cgen, autobox=False)
494    emit_decode_return_writeback(api, cgen)
495    emit_decode_finish(api, cgen)
496    emit_snapshot(typeInfo, api, cgen)
497    emit_destroyed_handle_cleanup(api, cgen)
498    emit_pool_free(cgen)
499    if not isAcquire:
500        emit_seqno_incr(api, cgen)
501
502## Custom decoding definitions##################################################
503def decode_vkFlushMappedMemoryRanges(typeInfo, api, cgen):
504    emit_decode_parameters(typeInfo, api, cgen)
505
506    cgen.beginIf("!m_state->usingDirectMapping()")
507    cgen.beginFor("uint32_t i = 0", "i < memoryRangeCount", "++i")
508    cgen.stmt("auto range = pMemoryRanges[i]")
509    cgen.stmt("auto memory = pMemoryRanges[i].memory")
510    cgen.stmt("auto size = pMemoryRanges[i].size")
511    cgen.stmt("auto offset = pMemoryRanges[i].offset")
512    cgen.stmt("uint64_t readStream = 0")
513    cgen.stmt("memcpy(&readStream, *readStreamPtrPtr, sizeof(uint64_t)); *readStreamPtrPtr += sizeof(uint64_t)")
514    cgen.stmt("auto hostPtr = m_state->getMappedHostPointer(memory)")
515    cgen.stmt("if (!hostPtr && readStream > 0) abort()")
516    cgen.stmt("if (!hostPtr) continue")
517    cgen.stmt("uint8_t* targetRange = hostPtr + offset")
518    cgen.stmt("memcpy(targetRange, *readStreamPtrPtr, readStream); *readStreamPtrPtr += readStream")
519    cgen.endFor()
520    cgen.endIf()
521
522    emit_dispatch_call(api, cgen)
523    emit_decode_parameters_writeback(typeInfo, api, cgen)
524    emit_decode_return_writeback(api, cgen)
525    emit_decode_finish(api, cgen)
526    emit_snapshot(typeInfo, api, cgen);
527    emit_pool_free(cgen)
528    emit_seqno_incr(api, cgen)
529
530def decode_vkInvalidateMappedMemoryRanges(typeInfo, api, cgen):
531    emit_decode_parameters(typeInfo, api, cgen)
532    emit_dispatch_call(api, cgen)
533    emit_decode_parameters_writeback(typeInfo, api, cgen)
534    emit_decode_return_writeback(api, cgen)
535
536    cgen.beginIf("!m_state->usingDirectMapping()")
537    cgen.beginFor("uint32_t i = 0", "i < memoryRangeCount", "++i")
538    cgen.stmt("auto range = pMemoryRanges[i]")
539    cgen.stmt("auto memory = range.memory")
540    cgen.stmt("auto size = range.size")
541    cgen.stmt("auto offset = range.offset")
542    cgen.stmt("auto hostPtr = m_state->getMappedHostPointer(memory)")
543    cgen.stmt("auto actualSize = size == VK_WHOLE_SIZE ? m_state->getDeviceMemorySize(memory) : size")
544    cgen.stmt("uint64_t writeStream = 0")
545    cgen.stmt("if (!hostPtr) { %s->write(&writeStream, sizeof(uint64_t)); continue; }" % WRITE_STREAM)
546    cgen.stmt("uint8_t* targetRange = hostPtr + offset")
547    cgen.stmt("writeStream = actualSize")
548    cgen.stmt("%s->write(&writeStream, sizeof(uint64_t))" % WRITE_STREAM)
549    cgen.stmt("%s->write(targetRange, actualSize)" % WRITE_STREAM)
550    cgen.endFor()
551    cgen.endIf()
552
553    emit_decode_finish(api, cgen)
554    emit_snapshot(typeInfo, api, cgen);
555    emit_pool_free(cgen)
556    emit_seqno_incr(api, cgen)
557
558custom_decodes = {
559    "vkEnumerateInstanceVersion" : emit_global_state_wrapped_decoding,
560    "vkCreateInstance" : emit_global_state_wrapped_decoding,
561    "vkDestroyInstance" : emit_global_state_wrapped_decoding,
562    "vkEnumeratePhysicalDevices" : emit_global_state_wrapped_decoding,
563
564    "vkGetPhysicalDeviceFeatures" : emit_global_state_wrapped_decoding,
565    "vkGetPhysicalDeviceFeatures2" : emit_global_state_wrapped_decoding,
566    "vkGetPhysicalDeviceFeatures2KHR" : emit_global_state_wrapped_decoding,
567    "vkGetPhysicalDeviceFormatProperties" : emit_global_state_wrapped_decoding,
568    "vkGetPhysicalDeviceFormatProperties2" : emit_global_state_wrapped_decoding,
569    "vkGetPhysicalDeviceFormatProperties2KHR" : emit_global_state_wrapped_decoding,
570    "vkGetPhysicalDeviceImageFormatProperties" : emit_global_state_wrapped_decoding,
571    "vkGetPhysicalDeviceImageFormatProperties2" : emit_global_state_wrapped_decoding,
572    "vkGetPhysicalDeviceImageFormatProperties2KHR" : emit_global_state_wrapped_decoding,
573    "vkGetPhysicalDeviceProperties" : emit_global_state_wrapped_decoding,
574    "vkGetPhysicalDeviceProperties2" : emit_global_state_wrapped_decoding,
575    "vkGetPhysicalDeviceProperties2KHR" : emit_global_state_wrapped_decoding,
576
577    "vkGetPhysicalDeviceMemoryProperties" : emit_global_state_wrapped_decoding,
578    "vkGetPhysicalDeviceMemoryProperties2" : emit_global_state_wrapped_decoding,
579    "vkGetPhysicalDeviceMemoryProperties2KHR" : emit_global_state_wrapped_decoding,
580
581    "vkGetPhysicalDeviceExternalSemaphoreProperties" : emit_global_state_wrapped_decoding,
582    "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR" : emit_global_state_wrapped_decoding,
583
584    "vkEnumerateDeviceExtensionProperties" : emit_global_state_wrapped_decoding,
585
586    "vkCreateBuffer" : emit_global_state_wrapped_decoding,
587    "vkDestroyBuffer" : emit_global_state_wrapped_decoding,
588
589    "vkBindBufferMemory" : emit_global_state_wrapped_decoding,
590    "vkBindBufferMemory2" : emit_global_state_wrapped_decoding,
591    "vkBindBufferMemory2KHR" : emit_global_state_wrapped_decoding,
592
593    "vkCreateDevice" : emit_global_state_wrapped_decoding,
594    "vkGetDeviceQueue" : emit_global_state_wrapped_decoding,
595    "vkDestroyDevice" : emit_global_state_wrapped_decoding,
596
597    "vkBindImageMemory" : emit_global_state_wrapped_decoding,
598    "vkCreateImage" : emit_global_state_wrapped_decoding,
599    "vkCreateImageView" : emit_global_state_wrapped_decoding,
600    "vkCreateSampler" : emit_global_state_wrapped_decoding,
601    "vkDestroyImage" : emit_global_state_wrapped_decoding,
602    "vkDestroyImageView" : emit_global_state_wrapped_decoding,
603    "vkDestroySampler" : emit_global_state_wrapped_decoding,
604    "vkCmdCopyBufferToImage" : emit_global_state_wrapped_decoding,
605    "vkCmdCopyImage" : emit_global_state_wrapped_decoding,
606    "vkCmdCopyImageToBuffer" : emit_global_state_wrapped_decoding,
607    "vkGetImageMemoryRequirements" : emit_global_state_wrapped_decoding,
608    "vkGetImageMemoryRequirements2" : emit_global_state_wrapped_decoding,
609    "vkGetImageMemoryRequirements2KHR" : emit_global_state_wrapped_decoding,
610
611    "vkCreateDescriptorSetLayout" : emit_global_state_wrapped_decoding,
612    "vkDestroyDescriptorSetLayout" : emit_global_state_wrapped_decoding,
613    "vkCreateDescriptorPool" : emit_global_state_wrapped_decoding,
614    "vkDestroyDescriptorPool" : emit_global_state_wrapped_decoding,
615    "vkResetDescriptorPool" : emit_global_state_wrapped_decoding,
616    "vkAllocateDescriptorSets" : emit_global_state_wrapped_decoding,
617    "vkFreeDescriptorSets" : emit_global_state_wrapped_decoding,
618
619    "vkUpdateDescriptorSets" : emit_global_state_wrapped_decoding,
620
621    "vkAllocateMemory" : emit_global_state_wrapped_decoding,
622    "vkFreeMemory" : emit_global_state_wrapped_decoding,
623    "vkMapMemory" : emit_global_state_wrapped_decoding,
624    "vkUnmapMemory" : emit_global_state_wrapped_decoding,
625    "vkFlushMappedMemoryRanges" : decode_vkFlushMappedMemoryRanges,
626    "vkInvalidateMappedMemoryRanges" : decode_vkInvalidateMappedMemoryRanges,
627
628    "vkAllocateCommandBuffers" : emit_global_state_wrapped_decoding,
629    "vkCmdExecuteCommands" : emit_global_state_wrapped_decoding,
630    "vkQueueSubmit" : emit_global_state_wrapped_decoding,
631    "vkQueueWaitIdle" : emit_global_state_wrapped_decoding,
632    "vkBeginCommandBuffer" : emit_global_state_wrapped_decoding,
633    "vkResetCommandBuffer" : emit_global_state_wrapped_decoding,
634    "vkFreeCommandBuffers" : emit_global_state_wrapped_decoding,
635    "vkCreateCommandPool" : emit_global_state_wrapped_decoding,
636    "vkDestroyCommandPool" : emit_global_state_wrapped_decoding,
637    "vkResetCommandPool" : emit_global_state_wrapped_decoding,
638    "vkCmdPipelineBarrier" : emit_global_state_wrapped_decoding,
639    "vkCmdBindPipeline" : emit_global_state_wrapped_decoding,
640    "vkCmdBindDescriptorSets" : emit_global_state_wrapped_decoding,
641
642    "vkCreateRenderPass" : emit_global_state_wrapped_decoding,
643
644    # VK_ANDROID_native_buffer
645    "vkGetSwapchainGrallocUsageANDROID" : emit_global_state_wrapped_decoding,
646    "vkGetSwapchainGrallocUsage2ANDROID" : emit_global_state_wrapped_decoding,
647    "vkAcquireImageANDROID" : emit_global_state_wrapped_decoding,
648    "vkQueueSignalReleaseImageANDROID" : emit_global_state_wrapped_decoding,
649
650    "vkCreateSemaphore" : emit_global_state_wrapped_decoding,
651    "vkGetSemaphoreFdKHR" : emit_global_state_wrapped_decoding,
652    "vkImportSemaphoreFdKHR" : emit_global_state_wrapped_decoding,
653    "vkDestroySemaphore" : emit_global_state_wrapped_decoding,
654
655    "vkCreateFence" : emit_global_state_wrapped_decoding,
656    "vkDestroyFence" : emit_global_state_wrapped_decoding,
657
658    # VK_GOOGLE_gfxstream
659    "vkFreeMemorySyncGOOGLE" : emit_global_state_wrapped_decoding,
660    "vkMapMemoryIntoAddressSpaceGOOGLE" : emit_global_state_wrapped_decoding,
661    "vkGetMemoryHostAddressInfoGOOGLE" : emit_global_state_wrapped_decoding,
662
663    # VK_GOOGLE_color_buffer
664    "vkRegisterImageColorBufferGOOGLE" : emit_global_state_wrapped_decoding,
665    "vkRegisterBufferColorBufferGOOGLE" : emit_global_state_wrapped_decoding,
666
667    # Descriptor update templates
668    "vkCreateDescriptorUpdateTemplate" : emit_global_state_wrapped_decoding,
669    "vkCreateDescriptorUpdateTemplateKHR" : emit_global_state_wrapped_decoding,
670    "vkDestroyDescriptorUpdateTemplate" : emit_global_state_wrapped_decoding,
671    "vkDestroyDescriptorUpdateTemplateKHR" : emit_global_state_wrapped_decoding,
672    "vkUpdateDescriptorSetWithTemplateSizedGOOGLE" : emit_global_state_wrapped_decoding,
673
674    # VK_GOOGLE_gfxstream
675    "vkBeginCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding,
676    "vkEndCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding,
677    "vkResetCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding,
678    "vkCommandBufferHostSyncGOOGLE" : emit_global_state_wrapped_decoding,
679    "vkCreateImageWithRequirementsGOOGLE" : emit_global_state_wrapped_decoding,
680    "vkCreateBufferWithRequirementsGOOGLE" : emit_global_state_wrapped_decoding,
681    "vkQueueHostSyncGOOGLE" : emit_global_state_wrapped_decoding,
682    "vkQueueSubmitAsyncGOOGLE" : emit_global_state_wrapped_decoding,
683    "vkQueueWaitIdleAsyncGOOGLE" : emit_global_state_wrapped_decoding,
684    "vkQueueBindSparseAsyncGOOGLE" : emit_global_state_wrapped_decoding,
685    "vkGetLinearImageLayoutGOOGLE" : emit_global_state_wrapped_decoding,
686    "vkQueueFlushCommandsGOOGLE" : emit_global_state_wrapped_decoding,
687    "vkQueueCommitDescriptorSetUpdatesGOOGLE" : emit_global_state_wrapped_decoding,
688    "vkCollectDescriptorPoolIdsGOOGLE" : emit_global_state_wrapped_decoding,
689}
690
691class VulkanDecoder(VulkanWrapperGenerator):
692    def __init__(self, module, typeInfo):
693        VulkanWrapperGenerator.__init__(self, module, typeInfo)
694        self.typeInfo = typeInfo
695        self.cgen = CodeGen()
696
697    def onBegin(self,):
698        self.module.appendHeader(decoder_decl_preamble)
699        self.module.appendImpl(decoder_impl_preamble)
700
701        self.module.appendImpl(
702            "size_t VkDecoder::Impl::decode(void* buf, size_t len, IOStream* ioStream, uint32_t* seqnoPtr)\n")
703
704        self.cgen.beginBlock() # function body
705
706        self.cgen.stmt("if (len < 8) return 0;")
707        self.cgen.stmt("bool queueSubmitWithCommandsEnabled = feature_is_enabled(kFeature_VulkanQueueSubmitWithCommands)")
708        self.cgen.stmt("unsigned char *ptr = (unsigned char *)buf")
709        self.cgen.stmt("const unsigned char* const end = (const unsigned char*)buf + len")
710
711        self.cgen.beginIf("m_forSnapshotLoad")
712        self.cgen.stmt("ptr += m_state->setCreatedHandlesForSnapshotLoad(ptr)");
713        self.cgen.endIf()
714
715        self.cgen.line("while (end - ptr >= 8)")
716        self.cgen.beginBlock() # while loop
717
718        self.cgen.stmt("uint32_t opcode = *(uint32_t *)ptr")
719        self.cgen.stmt("int32_t packetLen = *(int32_t *)(ptr + 4)")
720        self.cgen.stmt("if (end - ptr < packetLen) return ptr - (unsigned char*)buf")
721
722        self.cgen.stmt("stream()->setStream(ioStream)")
723        self.cgen.stmt("VulkanStream* %s = stream()" % WRITE_STREAM)
724        self.cgen.stmt("VulkanMemReadingStream* %s = readStream()" % READ_STREAM)
725        self.cgen.stmt("%s->setBuf((uint8_t*)(ptr + 8))" % READ_STREAM)
726        self.cgen.stmt("uint8_t* readStreamPtr = %s->getBuf(); uint8_t** readStreamPtrPtr = &readStreamPtr" % READ_STREAM)
727        self.cgen.stmt("uint8_t* snapshotTraceBegin = %s->beginTrace()" % READ_STREAM)
728        self.cgen.stmt("%s->setHandleMapping(&m_boxedHandleUnwrapMapping)" % READ_STREAM)
729        self.cgen.line("""
730                 if (queueSubmitWithCommandsEnabled && ((opcode >= OP_vkFirst && opcode < OP_vkLast) || (opcode >= OP_vkFirst_old && opcode < OP_vkLast_old))) {
731            uint32_t seqno; memcpy(&seqno, *readStreamPtrPtr, sizeof(uint32_t)); *readStreamPtrPtr += sizeof(uint32_t);
732            if (seqnoPtr && !m_forSnapshotLoad) {
733                while ((seqno - __atomic_load_n(seqnoPtr, __ATOMIC_SEQ_CST) != 1));
734            }
735        }
736        """)
737        self.cgen.stmt("auto vk = m_vk")
738
739        self.cgen.line("switch (opcode)")
740        self.cgen.beginBlock() # switch stmt
741
742        self.module.appendImpl(self.cgen.swapCode())
743
744    def onGenCmd(self, cmdinfo, name, alias):
745        typeInfo = self.typeInfo
746        cgen = self.cgen
747        api = typeInfo.apis[name]
748
749        cgen.line("case OP_%s:" % name)
750        cgen.beginBlock()
751        cgen.stmt("android::base::beginTrace(\"%s decode\")" % name)
752
753        if api.name in custom_decodes.keys():
754            custom_decodes[api.name](typeInfo, api, cgen)
755        else:
756            emit_default_decoding(typeInfo, api, cgen)
757
758        cgen.stmt("android::base::endTrace()")
759        cgen.stmt("break")
760        cgen.endBlock()
761        self.module.appendImpl(self.cgen.swapCode())
762
763    def onEnd(self,):
764        self.cgen.line("default:")
765        self.cgen.beginBlock()
766        self.cgen.stmt("m_pool.freeAll()")
767        self.cgen.stmt("return ptr - (unsigned char *)buf")
768        self.cgen.endBlock()
769
770        self.cgen.endBlock() # switch stmt
771
772        self.cgen.stmt("ptr += packetLen")
773        self.cgen.endBlock() # while loop
774
775        self.cgen.beginIf("m_forSnapshotLoad")
776        self.cgen.stmt("m_state->clearCreatedHandlesForSnapshotLoad()");
777        self.cgen.endIf()
778
779        self.cgen.stmt("m_pool.freeAll()")
780        self.cgen.stmt("return ptr - (unsigned char*)buf;")
781        self.cgen.endBlock() # function body
782        self.module.appendImpl(self.cgen.swapCode())
783