• 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) GFXSTREAM_ABORT(::emugl::FatalError(::emugl::ABORT_REASON_OTHER))")
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
558def decode_unsupported_api(typeInfo, api, cgen):
559    cgen.line(f"// Decoding {api.name} is not supported. This should not run.")
560    cgen.stmt(f"fprintf(stderr, \"stream %p: fatal: decoding unsupported API {api.name}\\n\", ioStream)");
561    cgen.stmt("__builtin_trap()")
562
563custom_decodes = {
564    "vkEnumerateInstanceVersion" : emit_global_state_wrapped_decoding,
565    "vkCreateInstance" : emit_global_state_wrapped_decoding,
566    "vkDestroyInstance" : emit_global_state_wrapped_decoding,
567    "vkEnumeratePhysicalDevices" : emit_global_state_wrapped_decoding,
568
569    "vkGetPhysicalDeviceFeatures" : emit_global_state_wrapped_decoding,
570    "vkGetPhysicalDeviceFeatures2" : emit_global_state_wrapped_decoding,
571    "vkGetPhysicalDeviceFeatures2KHR" : emit_global_state_wrapped_decoding,
572    "vkGetPhysicalDeviceFormatProperties" : emit_global_state_wrapped_decoding,
573    "vkGetPhysicalDeviceFormatProperties2" : emit_global_state_wrapped_decoding,
574    "vkGetPhysicalDeviceFormatProperties2KHR" : emit_global_state_wrapped_decoding,
575    "vkGetPhysicalDeviceImageFormatProperties" : emit_global_state_wrapped_decoding,
576    "vkGetPhysicalDeviceImageFormatProperties2" : emit_global_state_wrapped_decoding,
577    "vkGetPhysicalDeviceImageFormatProperties2KHR" : emit_global_state_wrapped_decoding,
578    "vkGetPhysicalDeviceProperties" : emit_global_state_wrapped_decoding,
579    "vkGetPhysicalDeviceProperties2" : emit_global_state_wrapped_decoding,
580    "vkGetPhysicalDeviceProperties2KHR" : emit_global_state_wrapped_decoding,
581
582    "vkGetPhysicalDeviceMemoryProperties" : emit_global_state_wrapped_decoding,
583    "vkGetPhysicalDeviceMemoryProperties2" : emit_global_state_wrapped_decoding,
584    "vkGetPhysicalDeviceMemoryProperties2KHR" : emit_global_state_wrapped_decoding,
585
586    "vkGetPhysicalDeviceExternalSemaphoreProperties" : emit_global_state_wrapped_decoding,
587    "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR" : emit_global_state_wrapped_decoding,
588
589    "vkEnumerateDeviceExtensionProperties" : emit_global_state_wrapped_decoding,
590
591    "vkCreateBuffer" : emit_global_state_wrapped_decoding,
592    "vkDestroyBuffer" : emit_global_state_wrapped_decoding,
593
594    "vkBindBufferMemory" : emit_global_state_wrapped_decoding,
595    "vkBindBufferMemory2" : emit_global_state_wrapped_decoding,
596    "vkBindBufferMemory2KHR" : emit_global_state_wrapped_decoding,
597
598    "vkCreateDevice" : emit_global_state_wrapped_decoding,
599    "vkGetDeviceQueue" : emit_global_state_wrapped_decoding,
600    "vkDestroyDevice" : emit_global_state_wrapped_decoding,
601
602    "vkBindImageMemory" : emit_global_state_wrapped_decoding,
603    "vkCreateImage" : emit_global_state_wrapped_decoding,
604    "vkCreateImageView" : emit_global_state_wrapped_decoding,
605    "vkCreateSampler" : emit_global_state_wrapped_decoding,
606    "vkDestroyImage" : emit_global_state_wrapped_decoding,
607    "vkDestroyImageView" : emit_global_state_wrapped_decoding,
608    "vkDestroySampler" : emit_global_state_wrapped_decoding,
609    "vkCmdCopyBufferToImage" : emit_global_state_wrapped_decoding,
610    "vkCmdCopyImage" : emit_global_state_wrapped_decoding,
611    "vkCmdCopyImageToBuffer" : emit_global_state_wrapped_decoding,
612    "vkGetImageMemoryRequirements" : emit_global_state_wrapped_decoding,
613    "vkGetImageMemoryRequirements2" : emit_global_state_wrapped_decoding,
614    "vkGetImageMemoryRequirements2KHR" : emit_global_state_wrapped_decoding,
615
616    "vkCreateDescriptorSetLayout" : emit_global_state_wrapped_decoding,
617    "vkDestroyDescriptorSetLayout" : emit_global_state_wrapped_decoding,
618    "vkCreateDescriptorPool" : emit_global_state_wrapped_decoding,
619    "vkDestroyDescriptorPool" : emit_global_state_wrapped_decoding,
620    "vkResetDescriptorPool" : emit_global_state_wrapped_decoding,
621    "vkAllocateDescriptorSets" : emit_global_state_wrapped_decoding,
622    "vkFreeDescriptorSets" : emit_global_state_wrapped_decoding,
623
624    "vkUpdateDescriptorSets" : emit_global_state_wrapped_decoding,
625
626    "vkAllocateMemory" : emit_global_state_wrapped_decoding,
627    "vkFreeMemory" : emit_global_state_wrapped_decoding,
628    "vkMapMemory" : emit_global_state_wrapped_decoding,
629    "vkUnmapMemory" : emit_global_state_wrapped_decoding,
630    "vkFlushMappedMemoryRanges" : decode_vkFlushMappedMemoryRanges,
631    "vkInvalidateMappedMemoryRanges" : decode_vkInvalidateMappedMemoryRanges,
632
633    "vkAllocateCommandBuffers" : emit_global_state_wrapped_decoding,
634    "vkCmdExecuteCommands" : emit_global_state_wrapped_decoding,
635    "vkQueueSubmit" : emit_global_state_wrapped_decoding,
636    "vkQueueWaitIdle" : emit_global_state_wrapped_decoding,
637    "vkBeginCommandBuffer" : emit_global_state_wrapped_decoding,
638    "vkEndCommandBuffer" : emit_global_state_wrapped_decoding,
639    "vkResetCommandBuffer" : emit_global_state_wrapped_decoding,
640    "vkFreeCommandBuffers" : emit_global_state_wrapped_decoding,
641    "vkCreateCommandPool" : emit_global_state_wrapped_decoding,
642    "vkDestroyCommandPool" : emit_global_state_wrapped_decoding,
643    "vkResetCommandPool" : emit_global_state_wrapped_decoding,
644    "vkCmdPipelineBarrier" : emit_global_state_wrapped_decoding,
645    "vkCmdBindPipeline" : emit_global_state_wrapped_decoding,
646    "vkCmdBindDescriptorSets" : emit_global_state_wrapped_decoding,
647
648    "vkCreateRenderPass" : emit_global_state_wrapped_decoding,
649
650    # VK_ANDROID_native_buffer
651    "vkGetSwapchainGrallocUsageANDROID" : emit_global_state_wrapped_decoding,
652    "vkGetSwapchainGrallocUsage2ANDROID" : emit_global_state_wrapped_decoding,
653    "vkAcquireImageANDROID" : emit_global_state_wrapped_decoding,
654    "vkQueueSignalReleaseImageANDROID" : emit_global_state_wrapped_decoding,
655
656    "vkCreateSemaphore" : emit_global_state_wrapped_decoding,
657    "vkGetSemaphoreFdKHR" : emit_global_state_wrapped_decoding,
658    "vkImportSemaphoreFdKHR" : emit_global_state_wrapped_decoding,
659    "vkDestroySemaphore" : emit_global_state_wrapped_decoding,
660
661    "vkCreateFence" : emit_global_state_wrapped_decoding,
662    "vkResetFences" : emit_global_state_wrapped_decoding,
663    "vkDestroyFence" : emit_global_state_wrapped_decoding,
664
665    # VK_GOOGLE_gfxstream
666    "vkFreeMemorySyncGOOGLE" : emit_global_state_wrapped_decoding,
667    "vkMapMemoryIntoAddressSpaceGOOGLE" : emit_global_state_wrapped_decoding,
668    "vkGetMemoryHostAddressInfoGOOGLE" : emit_global_state_wrapped_decoding,
669
670    # VK_GOOGLE_color_buffer
671    "vkRegisterImageColorBufferGOOGLE" : emit_global_state_wrapped_decoding,
672    "vkRegisterBufferColorBufferGOOGLE" : emit_global_state_wrapped_decoding,
673
674    # Descriptor update templates
675    "vkCreateDescriptorUpdateTemplate" : emit_global_state_wrapped_decoding,
676    "vkCreateDescriptorUpdateTemplateKHR" : emit_global_state_wrapped_decoding,
677    "vkDestroyDescriptorUpdateTemplate" : emit_global_state_wrapped_decoding,
678    "vkDestroyDescriptorUpdateTemplateKHR" : emit_global_state_wrapped_decoding,
679    "vkUpdateDescriptorSetWithTemplateSizedGOOGLE" : emit_global_state_wrapped_decoding,
680
681    # VK_GOOGLE_gfxstream
682    "vkBeginCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding,
683    "vkEndCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding,
684    "vkResetCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding,
685    "vkCommandBufferHostSyncGOOGLE" : emit_global_state_wrapped_decoding,
686    "vkCreateImageWithRequirementsGOOGLE" : emit_global_state_wrapped_decoding,
687    "vkCreateBufferWithRequirementsGOOGLE" : emit_global_state_wrapped_decoding,
688    "vkQueueHostSyncGOOGLE" : emit_global_state_wrapped_decoding,
689    "vkQueueSubmitAsyncGOOGLE" : emit_global_state_wrapped_decoding,
690    "vkQueueWaitIdleAsyncGOOGLE" : emit_global_state_wrapped_decoding,
691    "vkQueueBindSparseAsyncGOOGLE" : emit_global_state_wrapped_decoding,
692    "vkGetLinearImageLayoutGOOGLE" : emit_global_state_wrapped_decoding,
693    "vkGetLinearImageLayout2GOOGLE" : emit_global_state_wrapped_decoding,
694    "vkQueueFlushCommandsGOOGLE" : emit_global_state_wrapped_decoding,
695    "vkQueueCommitDescriptorSetUpdatesGOOGLE" : emit_global_state_wrapped_decoding,
696    "vkCollectDescriptorPoolIdsGOOGLE" : emit_global_state_wrapped_decoding,
697    "vkQueueSignalReleaseImageANDROIDAsyncGOOGLE" : emit_global_state_wrapped_decoding,
698
699    "vkQueueBindSparse" : emit_global_state_wrapped_decoding,
700
701    # VK_KHR_xcb_surface
702    "vkCreateXcbSurfaceKHR": decode_unsupported_api,
703    "vkGetPhysicalDeviceXcbPresentationSupportKHR": decode_unsupported_api,
704
705    # VK_EXT_metal_surface
706    "vkCreateMetalSurfaceEXT": decode_unsupported_api,
707}
708
709class VulkanDecoder(VulkanWrapperGenerator):
710    def __init__(self, module, typeInfo):
711        VulkanWrapperGenerator.__init__(self, module, typeInfo)
712        self.typeInfo = typeInfo
713        self.cgen = CodeGen()
714
715    def onBegin(self,):
716        self.module.appendHeader(decoder_decl_preamble)
717        self.module.appendImpl(decoder_impl_preamble)
718
719        self.module.appendImpl(
720            "size_t VkDecoder::Impl::decode(void* buf, size_t len, IOStream* ioStream, uint32_t* seqnoPtr)\n")
721
722        self.cgen.beginBlock() # function body
723
724        self.cgen.stmt("if (len < 8) return 0;")
725        self.cgen.stmt("bool queueSubmitWithCommandsEnabled = feature_is_enabled(kFeature_VulkanQueueSubmitWithCommands)")
726        self.cgen.stmt("unsigned char *ptr = (unsigned char *)buf")
727        self.cgen.stmt("const unsigned char* const end = (const unsigned char*)buf + len")
728
729        self.cgen.beginIf("m_forSnapshotLoad")
730        self.cgen.stmt("ptr += m_state->setCreatedHandlesForSnapshotLoad(ptr)");
731        self.cgen.endIf()
732
733        self.cgen.line("while (end - ptr >= 8)")
734        self.cgen.beginBlock() # while loop
735
736        self.cgen.stmt("uint32_t opcode = *(uint32_t *)ptr")
737        self.cgen.stmt("uint32_t packetLen = *(uint32_t *)(ptr + 4)")
738        self.cgen.stmt("if (end - ptr < packetLen) return ptr - (unsigned char*)buf")
739
740        self.cgen.stmt("stream()->setStream(ioStream)")
741        self.cgen.stmt("VulkanStream* %s = stream()" % WRITE_STREAM)
742        self.cgen.stmt("VulkanMemReadingStream* %s = readStream()" % READ_STREAM)
743        self.cgen.stmt("%s->setBuf((uint8_t*)(ptr + 8))" % READ_STREAM)
744        self.cgen.stmt("uint8_t* readStreamPtr = %s->getBuf(); uint8_t** readStreamPtrPtr = &readStreamPtr" % READ_STREAM)
745        self.cgen.stmt("uint8_t* snapshotTraceBegin = %s->beginTrace()" % READ_STREAM)
746        self.cgen.stmt("%s->setHandleMapping(&m_boxedHandleUnwrapMapping)" % READ_STREAM)
747        self.cgen.line("""
748                 if (queueSubmitWithCommandsEnabled && ((opcode >= OP_vkFirst && opcode < OP_vkLast) || (opcode >= OP_vkFirst_old && opcode < OP_vkLast_old))) {
749            uint32_t seqno; memcpy(&seqno, *readStreamPtrPtr, sizeof(uint32_t)); *readStreamPtrPtr += sizeof(uint32_t);
750            if (seqnoPtr && !m_forSnapshotLoad) {
751                while ((seqno - __atomic_load_n(seqnoPtr, __ATOMIC_SEQ_CST) != 1));
752            }
753        }
754        """)
755        self.cgen.stmt("auto vk = m_vk")
756
757        self.cgen.line("switch (opcode)")
758        self.cgen.beginBlock() # switch stmt
759
760        self.module.appendImpl(self.cgen.swapCode())
761
762    def onGenCmd(self, cmdinfo, name, alias):
763        typeInfo = self.typeInfo
764        cgen = self.cgen
765        api = typeInfo.apis[name]
766
767        cgen.line("case OP_%s:" % name)
768        cgen.beginBlock()
769        cgen.stmt("android::base::beginTrace(\"%s decode\")" % name)
770
771        if api.name in custom_decodes.keys():
772            custom_decodes[api.name](typeInfo, api, cgen)
773        else:
774            emit_default_decoding(typeInfo, api, cgen)
775
776        cgen.stmt("android::base::endTrace()")
777        cgen.stmt("break")
778        cgen.endBlock()
779        self.module.appendImpl(self.cgen.swapCode())
780
781    def onEnd(self,):
782        self.cgen.line("default:")
783        self.cgen.beginBlock()
784        self.cgen.stmt("m_pool.freeAll()")
785        self.cgen.stmt("return ptr - (unsigned char *)buf")
786        self.cgen.endBlock()
787
788        self.cgen.endBlock() # switch stmt
789
790        self.cgen.stmt("ptr += packetLen")
791        self.cgen.endBlock() # while loop
792
793        self.cgen.beginIf("m_forSnapshotLoad")
794        self.cgen.stmt("m_state->clearCreatedHandlesForSnapshotLoad()");
795        self.cgen.endIf()
796
797        self.cgen.stmt("m_pool.freeAll()")
798        self.cgen.stmt("return ptr - (unsigned char*)buf;")
799        self.cgen.endBlock() # function body
800        self.module.appendImpl(self.cgen.swapCode())
801