• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python3 -i
2#
3# Copyright (c) 2013-2018 The Khronos Group Inc.
4# Copyright (c) 2013-2018 Google Inc.
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17
18import os, re, sys
19from generator import *
20from pathlib import Path, PurePosixPath
21
22import cereal
23from cereal.wrapperdefs import VULKAN_STREAM_TYPE
24from cereal.wrapperdefs import VULKAN_STREAM_TYPE_GUEST
25
26# CerealGenerator - generates set of driver sources
27# while being agnostic to the stream implementation
28from reg import GroupInfo, TypeInfo, EnumInfo
29
30VK_CEREAL_FLAG_HOST = 1
31VK_CEREAL_FLAG_GUEST = 2
32VK_CEREAL_FLAG_ALL = VK_CEREAL_FLAG_GUEST | VK_CEREAL_FLAG_HOST
33
34SUPPORTED_FEATURES = [
35    "VK_VERSION_1_0",
36    "VK_VERSION_1_1",
37    "VK_VERSION_1_2",
38    "VK_VERSION_1_3",
39    # Instance extensions
40    "VK_KHR_get_physical_device_properties2",
41    "VK_KHR_sampler_ycbcr_conversion",
42    "VK_KHR_external_semaphore_capabilities",
43    "VK_KHR_external_memory_capabilities",
44    "VK_KHR_external_fence_capabilities",
45    "VK_EXT_debug_utils",
46    # Device extensions
47    "VK_KHR_storage_buffer_storage_class",
48    "VK_KHR_vulkan_memory_model",
49    "VK_KHR_buffer_device_address",
50    "VK_KHR_maintenance1",
51    "VK_KHR_maintenance2",
52    "VK_KHR_maintenance3",
53    "VK_KHR_bind_memory2",
54    "VK_KHR_dedicated_allocation",
55    "VK_KHR_get_memory_requirements2",
56    "VK_KHR_sampler_ycbcr_conversion",
57    "VK_KHR_shader_float16_int8",
58    "VK_AMD_gpu_shader_half_float",
59    "VK_NV_shader_subgroup_partitioned",
60    "VK_KHR_shader_subgroup_extended_types",
61    "VK_EXT_provoking_vertex",
62    "VK_EXT_line_rasterization",
63    "VK_EXT_transform_feedback",
64    "VK_EXT_primitive_topology_list_restart",
65    "VK_EXT_index_type_uint8",
66    "VK_EXT_load_store_op_none",
67    "VK_EXT_swapchain_colorspace",
68    "VK_EXT_custom_border_color",
69    "VK_EXT_shader_stencil_export",
70    "VK_KHR_image_format_list",
71    "VK_KHR_incremental_present",
72    "VK_KHR_pipeline_executable_properties",
73    "VK_EXT_queue_family_foreign",
74    "VK_EXT_scalar_block_layout",
75    "VK_KHR_external_semaphore",
76    "VK_KHR_external_semaphore_fd",
77    "VK_KHR_external_memory",
78    "VK_KHR_external_fence",
79    "VK_KHR_external_fence_fd",
80    "VK_EXT_device_memory_report",
81    "VK_KHR_create_renderpass2",
82    "VK_KHR_imageless_framebuffer",
83    "VK_KHR_descriptor_update_template",
84    "VK_EXT_depth_clip_enable",
85    # see aosp/2736079 + b/268351352
86    "VK_EXT_swapchain_maintenance1",
87    "VK_KHR_maintenance5",
88    "VK_EXT_host_image_copy",
89    "VK_EXT_image_compression_control",
90    "VK_EXT_image_compression_control_swapchain",
91    # VK1.3 extensions: see b/298704840
92    "VK_KHR_copy_commands2",
93    "VK_KHR_dynamic_rendering",
94    "VK_KHR_format_feature_flags2",
95    "VK_KHR_maintenance4",
96    "VK_KHR_shader_integer_dot_product",
97    "VK_KHR_shader_non_semantic_info",
98    "VK_KHR_shader_terminate_invocation",
99    "VK_KHR_synchronization2",
100    "VK_KHR_zero_initialize_workgroup_memory",
101    "VK_EXT_4444_formats",
102    "VK_EXT_extended_dynamic_state",
103    "VK_EXT_extended_dynamic_state2",
104    "VK_EXT_image_robustness",
105    "VK_EXT_inline_uniform_block",
106    "VK_EXT_pipeline_creation_cache_control",
107    "VK_EXT_pipeline_creation_feedback",
108    "VK_EXT_private_data",
109    "VK_EXT_shader_demote_to_helper_invocation",
110    "VK_EXT_subgroup_size_control",
111    "VK_EXT_texel_buffer_alignment",
112    "VK_EXT_texture_compression_astc_hdr",
113    "VK_EXT_tooling_info",
114    "VK_EXT_ycbcr_2plane_444_formats",
115    # Host dispatch
116    "VK_EXT_debug_utils",
117    "VK_KHR_surface",
118    "VK_KHR_swapchain",
119    "VK_KHR_xcb_surface",
120    "VK_KHR_win32_surface",
121    "VK_EXT_metal_surface",
122    "VK_MVK_moltenvk",
123    "VK_KHR_external_semaphore_win32",
124    "VK_KHR_external_memory_win32",
125    "VK_KHR_external_memory_fd",
126    # Android
127    "VK_ANDROID_native_buffer",
128    "VK_ANDROID_external_memory_android_hardware_buffer",
129    "VK_KHR_android_surface",
130    # Custom
131    "VK_GOOGLE_gfxstream",
132    # Used in tests without proper support checks
133    "VK_EXT_graphics_pipeline_library",
134    # Used by guest ANGLE
135    "VK_EXT_vertex_attribute_divisor",
136    # QNX
137    "VK_QNX_external_memory_screen_buffer",
138    # b/320855472 Chrome
139    "VK_EXT_fragment_density_map",
140]
141
142HOST_MODULES = ["goldfish_vk_extension_structs", "goldfish_vk_marshaling",
143                "goldfish_vk_reserved_marshaling", "goldfish_vk_deepcopy",
144                "goldfish_vk_dispatch", "goldfish_vk_transform", "VkDecoder",
145                "VkDecoderSnapshot", "VkSubDecoder"]
146
147# By default, the all wrappers are run all on all features.  In certain cases,
148# we wish run wrappers when the module requires it. For example, `VK_GOOGLE_gfxstream`
149# shouldn't generate a function table entry since it's an internal interface.
150SUPPORTED_MODULES = {
151    "VK_EXT_debug_utils": ["goldfish_vk_dispatch"],
152    "VK_KHR_surface": ["goldfish_vk_dispatch"],
153    "VK_KHR_xcb_surface": ["goldfish_vk_dispatch"],
154    "VK_KHR_win32_surface": ["goldfish_vk_dispatch"],
155    "VK_EXT_metal_surface": ["goldfish_vk_dispatch"],
156    # VK_MVK_moltenvk doesn't generate a generate dispatch entry for some reason, but should. The
157    # lack of this extension doesn't cause any build failtures though.
158    "VK_MVK_moltenvk": ["goldfish_vk_dispatch"],
159    "VK_KHR_external_semaphore_win32" : ["goldfish_vk_dispatch"],
160    "VK_KHR_external_memory_win32" : ["goldfish_vk_dispatch"],
161    "VK_KHR_external_memory_fd": ["goldfish_vk_dispatch"],
162    "VK_QNX_external_memory_screen_buffer": ["goldfish_vk_dispatch"],
163    "VK_ANDROID_external_memory_android_hardware_buffer": ["func_table"],
164    "VK_KHR_android_surface": ["func_table"],
165    "VK_EXT_swapchain_maintenance1" : HOST_MODULES,
166    "VK_KHR_swapchain" : HOST_MODULES,
167}
168
169REQUIRED_TYPES = {
170    "int",
171    "uint16_t",
172    "int64_t",
173    "double",
174    "VkPresentScalingFlagsEXT",
175    "VkPresentGravityFlagsEXT",
176}
177
178copyrightHeader = """// Copyright (C) 2018 The Android Open Source Project
179// Copyright (C) 2018 Google Inc.
180//
181// Licensed under the Apache License, Version 2.0 (the "License");
182// you may not use this file except in compliance with the License.
183// You may obtain a copy of the License at
184//
185// http://www.apache.org/licenses/LICENSE-2.0
186//
187// Unless required by applicable law or agreed to in writing, software
188// distributed under the License is distributed on an "AS IS" BASIS,
189// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190// See the License for the specific language governing permissions and
191// limitations under the License.
192"""
193
194# We put the long generated commands in a separate paragraph, so that the formatter won't mess up
195# with other texts.
196autogeneratedHeaderTemplate = """
197// Autogenerated module %s
198//
199// %s
200//
201// Please do not modify directly;
202// re-run gfxstream-protocols/scripts/generate-vulkan-sources.sh,
203// or directly from Python by defining:
204// VULKAN_REGISTRY_XML_DIR : Directory containing vk.xml
205// VULKAN_REGISTRY_SCRIPTS_DIR : Directory containing genvk.py
206// CEREAL_OUTPUT_DIR: Where to put the generated sources.
207//
208// python3 $VULKAN_REGISTRY_SCRIPTS_DIR/genvk.py -registry $VULKAN_REGISTRY_XML_DIR/vk.xml cereal -o $CEREAL_OUTPUT_DIR
209//
210"""
211namespaceBegin ="""
212namespace gfxstream {
213namespace vk {\n
214"""
215
216namespaceEnd = """
217}  // namespace vk
218}  // namespace gfxstream
219"""
220
221def banner_command(argv):
222    """Return sanitized command-line description.
223       |argv| must be a list of command-line parameters, e.g. sys.argv.
224       Return a string corresponding to the command, with platform-specific
225       paths removed."""
226
227    def makePosixRelative(someArg):
228        if os.path.exists(someArg):
229            return str(PurePosixPath(Path(os.path.relpath(someArg))))
230        return someArg
231
232    return ' '.join(map(makePosixRelative, argv))
233
234def envGetOrDefault(key, default=None):
235    if key in os.environ:
236        return os.environ[key]
237    print("envGetOrDefault: notfound: %s" % key)
238    return default
239
240# ---- methods overriding base class ----
241# beginFile(genOpts)
242# endFile()
243# beginFeature(interface, emit)
244# endFeature()
245# genType(typeinfo,name)
246# genStruct(typeinfo,name)
247# genGroup(groupinfo,name)
248# genEnum(enuminfo, name)
249# genCmd(cmdinfo)
250class CerealGenerator(OutputGenerator):
251
252    """Generate serialization code"""
253    def __init__(self, errFile = sys.stderr,
254                       warnFile = sys.stderr,
255                       diagFile = sys.stdout):
256        OutputGenerator.__init__(self, errFile, warnFile, diagFile)
257
258        self.typeInfo = cereal.VulkanTypeInfo(self)
259
260        self.modules = {}
261        self.protos = {}
262        self.moduleList = []
263        self.protoList = []
264
265        self.wrappers = []
266
267        self.codegen = cereal.CodeGen()
268        self.featureSupported = False
269        self.supportedModules = None
270
271        self.guestBaseLibDirPrefix = "aemu/base"
272        self.baseLibDirPrefix = "aemu/base"
273        self.utilsHeaderDirPrefix = "utils"
274
275        # The cereal variant should be an environmental variable of one of
276        # the following:
277        #    - "guest"
278        #    - "host"
279        #    - "both"
280        cerealVariant = envGetOrDefault("CEREAL_VARIANT", "both")
281        if cerealVariant == "guest":
282          self.cerealFlags = VK_CEREAL_FLAG_GUEST
283        elif cerealVariant == "host":
284          self.cerealFlags = VK_CEREAL_FLAG_HOST
285        else:
286          self.cerealFlags = VK_CEREAL_FLAG_ALL
287
288        # THe host always needs all possible guest struct definitions, while the guest only needs
289        # platform sepcific headers.
290        self.hostCommonExtraVulkanHeaders = '#include "vk_android_native_buffer_gfxstream.h"'
291
292        encoderInclude = f"""
293#include "{self.guestBaseLibDirPrefix}/AndroidHealthMonitor.h"
294#include "goldfish_vk_private_defs.h"
295#include <memory>
296
297namespace gfxstream {{
298namespace guest {{
299class IOStream;
300}}  // namespace guest
301}}  // namespace gfxstream
302"""
303        encoderImplInclude = f"""
304#include "EncoderDebug.h"
305#include "Resources.h"
306#include "ResourceTracker.h"
307#include "Validation.h"
308#include "%s.h"
309#include "gfxstream/guest/IOStream.h"
310
311#include "{self.guestBaseLibDirPrefix}/AlignedBuf.h"
312#include "{self.guestBaseLibDirPrefix}/BumpPool.h"
313#include "{self.guestBaseLibDirPrefix}/synchronization/AndroidLock.h"
314
315#include <cutils/properties.h>
316
317#include "goldfish_vk_marshaling_guest.h"
318#include "goldfish_vk_reserved_marshaling_guest.h"
319#include "goldfish_vk_deepcopy_guest.h"
320#include "goldfish_vk_counting_guest.h"
321#include "goldfish_vk_private_defs.h"
322#include "goldfish_vk_transform_guest.h"
323
324#include <memory>
325#include <optional>
326#include <unordered_map>
327#include <string>
328#include <vector>
329
330""" % VULKAN_STREAM_TYPE_GUEST
331
332        functableImplInclude = """
333#include "VkEncoder.h"
334#include "../OpenglSystemCommon/HostConnection.h"
335#include "ResourceTracker.h"
336#include "gfxstream_vk_entrypoints.h"
337#include "gfxstream_vk_private.h"
338
339#include "goldfish_vk_private_defs.h"
340
341#include <log/log.h>
342#include <cstring>
343
344// Stuff we are not going to use but if included,
345// will cause compile errors. These are Android Vulkan
346// required extensions, but the approach will be to
347// implement them completely on the guest side.
348#undef VK_KHR_android_surface
349#if defined(LINUX_GUEST_BUILD) || defined(__Fuchsia__)
350#undef VK_ANDROID_native_buffer
351#endif
352"""
353        marshalIncludeGuest = """
354#include "goldfish_vk_marshaling_guest.h"
355#include "goldfish_vk_private_defs.h"
356#include "%s.h"
357
358// Stuff we are not going to use but if included,
359// will cause compile errors. These are Android Vulkan
360// required extensions, but the approach will be to
361// implement them completely on the guest side.
362#undef VK_KHR_android_surface
363#undef VK_ANDROID_external_memory_android_hardware_buffer
364""" % VULKAN_STREAM_TYPE_GUEST
365
366        reservedmarshalIncludeGuest = """
367#include "goldfish_vk_marshaling_guest.h"
368#include "goldfish_vk_private_defs.h"
369#include "%s.h"
370
371// Stuff we are not going to use but if included,
372// will cause compile errors. These are Android Vulkan
373// required extensions, but the approach will be to
374// implement them completely on the guest side.
375#undef VK_KHR_android_surface
376#undef VK_ANDROID_external_memory_android_hardware_buffer
377""" % VULKAN_STREAM_TYPE_GUEST
378
379        reservedmarshalImplIncludeGuest = """
380#include "Resources.h"
381"""
382
383        vulkanStreamIncludeHost = f"""
384{self.hostCommonExtraVulkanHeaders}
385#include "goldfish_vk_private_defs.h"
386
387#include "%s.h"
388#include "{self.baseLibDirPrefix}/files/StreamSerializing.h"
389""" % VULKAN_STREAM_TYPE
390
391        poolInclude = f"""
392{self.hostCommonExtraVulkanHeaders}
393#include "goldfish_vk_private_defs.h"
394#include "{self.baseLibDirPrefix}/BumpPool.h"
395using android::base::Allocator;
396using android::base::BumpPool;
397"""
398        transformIncludeGuest = """
399#include "goldfish_vk_private_defs.h"
400"""
401        transformInclude = f"""
402{self.hostCommonExtraVulkanHeaders}
403#include "goldfish_vk_private_defs.h"
404#include "goldfish_vk_extension_structs.h"
405"""
406        transformImplIncludeGuest = """
407#include "ResourceTracker.h"
408"""
409        transformImplInclude = """
410#include "VkDecoderGlobalState.h"
411"""
412        deepcopyInclude = """
413#include "vk_util.h"
414"""
415        poolIncludeGuest = f"""
416#include "goldfish_vk_private_defs.h"
417#include "{self.guestBaseLibDirPrefix}/BumpPool.h"
418using gfxstream::guest::Allocator;
419using gfxstream::guest::BumpPool;
420// Stuff we are not going to use but if included,
421// will cause compile errors. These are Android Vulkan
422// required extensions, but the approach will be to
423// implement them completely on the guest side.
424#undef VK_KHR_android_surface
425#undef VK_ANDROID_external_memory_android_hardware_buffer
426"""
427        dispatchHeaderDefs = f"""
428{self.hostCommonExtraVulkanHeaders}
429#include "goldfish_vk_private_defs.h"
430namespace gfxstream {{
431namespace vk {{
432
433struct VulkanDispatch;
434
435}} // namespace vk
436}} // namespace gfxstream
437using DlOpenFunc = void* (void);
438using DlSymFunc = void* (void*, const char*);
439"""
440
441        extensionStructsInclude = f"""
442{self.hostCommonExtraVulkanHeaders}
443#include "goldfish_vk_private_defs.h"
444#include "host-common/GfxstreamFatalError.h"
445"""
446
447        extensionStructsIncludeGuest = """
448#include "vk_platform_compat.h"
449#include "goldfish_vk_private_defs.h"
450// Stuff we are not going to use but if included,
451// will cause compile errors. These are Android Vulkan
452// required extensions, but the approach will be to
453// implement them completely on the guest side.
454#undef VK_KHR_android_surface
455#undef VK_ANDROID_external_memory_android_hardware_buffer
456"""
457        commonCerealImplIncludes = """
458#include "goldfish_vk_extension_structs.h"
459#include "goldfish_vk_private_defs.h"
460#include <string.h>
461"""
462        commonCerealIncludesGuest = """
463#include "vk_platform_compat.h"
464"""
465        commonCerealImplIncludesGuest = """
466#include "goldfish_vk_extension_structs_guest.h"
467#include "goldfish_vk_private_defs.h"
468
469#include <cstring>
470"""
471        countingIncludes = """
472#include "vk_platform_compat.h"
473#include "goldfish_vk_private_defs.h"
474"""
475
476        dispatchImplIncludes = """
477#include <stdio.h>
478#include <stdlib.h>
479#include <string.h>
480"""
481
482        decoderSnapshotHeaderIncludes = f"""
483#include <memory>
484#include "{self.utilsHeaderDirPrefix}/GfxApiLogger.h"
485#include "{self.baseLibDirPrefix}/HealthMonitor.h"
486#include "goldfish_vk_private_defs.h"
487"""
488        decoderSnapshotImplIncludes = f"""
489#include "VulkanHandleMapping.h"
490#include "VkDecoderGlobalState.h"
491#include "VkReconstruction.h"
492
493#include "{self.baseLibDirPrefix}/synchronization/Lock.h"
494"""
495
496        decoderHeaderIncludes = f"""
497#include "VkDecoderContext.h"
498#include "host/ProcessResources.h"
499
500#include <memory>
501
502namespace android {{
503namespace base {{
504class BumpPool;
505}} // namespace android
506}} // namespace base
507
508"""
509
510        decoderImplIncludes = f"""
511#include "common/goldfish_vk_marshaling.h"
512#include "common/goldfish_vk_reserved_marshaling.h"
513#include "goldfish_vk_private_defs.h"
514#include "common/goldfish_vk_transform.h"
515
516#include "{self.baseLibDirPrefix}/BumpPool.h"
517#include "{self.baseLibDirPrefix}/system/System.h"
518#include "{self.baseLibDirPrefix}/Tracing.h"
519#include "{self.baseLibDirPrefix}/Metrics.h"
520#include "render-utils/IOStream.h"
521#include "host/FrameBuffer.h"
522#include "host-common/feature_control.h"
523#include "host-common/GfxstreamFatalError.h"
524#include "host-common/logging.h"
525
526#include "VkDecoderGlobalState.h"
527#include "VkDecoderSnapshot.h"
528
529#include "VulkanDispatch.h"
530#include "%s.h"
531
532#include <functional>
533#include <optional>
534#include <unordered_map>
535""" % VULKAN_STREAM_TYPE
536
537        def createVkExtensionStructureTypePreamble(extensionName: str) -> str:
538            return f"""
539#define {extensionName}_ENUM(type,id) \
540    ((type)(1000000000 + (1000 * ({extensionName}_NUMBER - 1)) + (id)))
541"""
542        self.guest_encoder_tag = "guest_encoder"
543        self.host_tag = "host"
544
545        default_guest_abs_encoder_destination = \
546            os.path.join(
547                os.getcwd(),
548                "..", "..",
549                "device", "generic", "goldfish-opengl",
550                "system", "vulkan_enc")
551        self.guest_abs_encoder_destination = \
552            envGetOrDefault("GFXSTREAM_GUEST_ENCODER_DIR",
553                            default_guest_abs_encoder_destination)
554
555        default_host_abs_decoder_destination = \
556            os.path.join(
557                os.getcwd(),
558                "android", "android-emugl", "host",
559                "libs", "libOpenglRender", "vulkan")
560        self.host_abs_decoder_destination = \
561            envGetOrDefault("GFXSTREAM_HOST_DECODER_DIR",
562                            default_host_abs_decoder_destination)
563        #self.host_script_destination = envGetOrDefault("GFXSTREAM_SCRIPTS_DIR")
564        #assert(self.host_script_destination is not None)
565
566        if self.cerealFlags & VK_CEREAL_FLAG_GUEST:
567            self.addGuestEncoderModule(
568                "VkEncoder",
569                extraHeader = encoderInclude,
570                extraImpl = encoderImplInclude)
571
572            self.addGuestEncoderModule("goldfish_vk_extension_structs_guest",
573                                       extraHeader=extensionStructsIncludeGuest)
574            self.addGuestEncoderModule("goldfish_vk_marshaling_guest",
575                                       extraHeader=commonCerealIncludesGuest + marshalIncludeGuest,
576                                       extraImpl=commonCerealImplIncludesGuest)
577            self.addGuestEncoderModule("goldfish_vk_reserved_marshaling_guest",
578                                       extraHeader=commonCerealIncludesGuest + reservedmarshalIncludeGuest,
579                                       extraImpl=commonCerealImplIncludesGuest + reservedmarshalImplIncludeGuest)
580            self.addGuestEncoderModule("goldfish_vk_deepcopy_guest",
581                                       extraHeader=commonCerealIncludesGuest + poolIncludeGuest,
582                                       extraImpl=commonCerealImplIncludesGuest + deepcopyInclude)
583            self.addGuestEncoderModule("goldfish_vk_counting_guest",
584                                       extraHeader=countingIncludes,
585                                       extraImpl=commonCerealImplIncludesGuest)
586            self.addGuestEncoderModule("goldfish_vk_transform_guest",
587                                       extraHeader=commonCerealIncludesGuest + transformIncludeGuest,
588                                       extraImpl=commonCerealImplIncludesGuest + transformImplIncludeGuest)
589            self.addGuestEncoderModule(
590                "vulkan_gfxstream_structure_type", headerOnly=True, suppressFeatureGuards=True,
591                moduleName="vulkan_gfxstream_structure_type_guest", useNamespace=False,
592                suppressVulkanHeaders=True,
593                extraHeader=createVkExtensionStructureTypePreamble('VK_GOOGLE_GFXSTREAM'))
594
595            self.addGuestEncoderModule("func_table", extraImpl=functableImplInclude, implOnly = True,
596                                    useNamespace = False)
597
598            self.addWrapper(cereal.VulkanEncoder, "VkEncoder")
599            self.addWrapper(cereal.VulkanExtensionStructs, "goldfish_vk_extension_structs_guest", variant = "guest")
600            self.addWrapper(cereal.VulkanMarshaling, "goldfish_vk_marshaling_guest", variant = "guest")
601            self.addWrapper(cereal.VulkanReservedMarshaling, "goldfish_vk_reserved_marshaling_guest", variant = "guest")
602            self.addWrapper(cereal.VulkanDeepcopy, "goldfish_vk_deepcopy_guest")
603            self.addWrapper(cereal.VulkanCounting, "goldfish_vk_counting_guest")
604            self.addWrapper(cereal.VulkanTransform, "goldfish_vk_transform_guest")
605            self.addWrapper(cereal.VulkanFuncTable, "func_table")
606            self.addWrapper(cereal.VulkanGfxstreamStructureType,
607                            "vulkan_gfxstream_structure_type_guest")
608
609        if self.cerealFlags & VK_CEREAL_FLAG_HOST:
610            self.addCppModule("common", "goldfish_vk_extension_structs",
611                           extraHeader=extensionStructsInclude)
612            self.addCppModule("common", "goldfish_vk_marshaling",
613                           extraHeader=vulkanStreamIncludeHost,
614                           extraImpl=commonCerealImplIncludes)
615            self.addCppModule("common", "goldfish_vk_reserved_marshaling",
616                           extraHeader=vulkanStreamIncludeHost,
617                           extraImpl=commonCerealImplIncludes)
618            self.addCppModule("common", "goldfish_vk_deepcopy",
619                           extraHeader=poolInclude,
620                           extraImpl=commonCerealImplIncludes + deepcopyInclude)
621            self.addCppModule("common", "goldfish_vk_dispatch",
622                           extraHeader=dispatchHeaderDefs,
623                           extraImpl=dispatchImplIncludes)
624            self.addCppModule("common", "goldfish_vk_transform",
625                           extraHeader=transformInclude,
626                           extraImpl=transformImplInclude)
627            self.addHostModule("VkDecoder",
628                               extraHeader=decoderHeaderIncludes,
629                               extraImpl=decoderImplIncludes,
630                               useNamespace=False)
631            self.addHostModule("VkDecoderSnapshot",
632                               extraHeader=decoderSnapshotHeaderIncludes,
633                               extraImpl=decoderSnapshotImplIncludes,
634                               useNamespace=False)
635            self.addHostModule("VkSubDecoder",
636                               extraHeader="",
637                               extraImpl="",
638                               useNamespace=False,
639                               implOnly=True)
640
641            #self.addModule(cereal.PyScript(self.host_tag, "vulkan_printer", customAbsDir=Path(
642            #    self.host_script_destination) / "print_gfx_logs"), moduleName="ApiLogDecoder")
643            self.addHostModule(
644                "vulkan_gfxstream_structure_type", headerOnly=True, suppressFeatureGuards=True,
645                moduleName="vulkan_gfxstream_structure_type_host", useNamespace=False,
646                suppressVulkanHeaders=True,
647                extraHeader=createVkExtensionStructureTypePreamble('VK_GOOGLE_GFXSTREAM'))
648            self.addHostModule(
649                "vk_android_native_buffer_structure_type", headerOnly=True, suppressFeatureGuards=True,
650                useNamespace=False, suppressVulkanHeaders=True,
651                extraHeader=createVkExtensionStructureTypePreamble('VK_ANDROID_NATIVE_BUFFER'))
652
653            self.addWrapper(cereal.VulkanExtensionStructs, "goldfish_vk_extension_structs", variant = "host")
654            self.addWrapper(cereal.VulkanMarshaling, "goldfish_vk_marshaling")
655            self.addWrapper(cereal.VulkanReservedMarshaling, "goldfish_vk_reserved_marshaling", variant = "host")
656            self.addWrapper(cereal.VulkanDeepcopy, "goldfish_vk_deepcopy")
657            self.addWrapper(cereal.VulkanDispatch, "goldfish_vk_dispatch")
658            self.addWrapper(cereal.VulkanTransform, "goldfish_vk_transform", resourceTrackerTypeName="VkDecoderGlobalState")
659            self.addWrapper(cereal.VulkanDecoder, "VkDecoder")
660            self.addWrapper(cereal.VulkanDecoderSnapshot, "VkDecoderSnapshot")
661            self.addWrapper(cereal.VulkanSubDecoder, "VkSubDecoder")
662            self.addWrapper(cereal.ApiLogDecoder, "ApiLogDecoder")
663            self.addWrapper(cereal.VulkanGfxstreamStructureType, "vulkan_gfxstream_structure_type_host")
664            self.addWrapper(cereal.VulkanAndroidNativeBufferStructureType,
665                            "vk_android_native_buffer_structure_type")
666
667    def addGuestEncoderModule(
668            self, basename, extraHeader="", extraImpl="", useNamespace=True, headerOnly=False,
669            suppressFeatureGuards=False, moduleName=None, suppressVulkanHeaders=False, implOnly=False):
670        if not os.path.exists(self.guest_abs_encoder_destination):
671            print("Path [%s] not found (guest encoder path), skipping" % self.guest_abs_encoder_destination)
672            return
673        self.addCppModule(self.guest_encoder_tag, basename, extraHeader=extraHeader,
674                       extraImpl=extraImpl, customAbsDir=self.guest_abs_encoder_destination,
675                       useNamespace=useNamespace, implOnly=implOnly, headerOnly=headerOnly,
676                       suppressFeatureGuards=suppressFeatureGuards, moduleName=moduleName,
677                       suppressVulkanHeaders=suppressVulkanHeaders)
678
679    def addHostModule(
680            self, basename, extraHeader="", extraImpl="", useNamespace=True, implOnly=False,
681            suppress=False, headerOnly=False, suppressFeatureGuards=False, moduleName=None,
682            suppressVulkanHeaders=False):
683        if not os.path.exists(self.host_abs_decoder_destination):
684            print("Path [%s] not found (host encoder path), skipping" %
685                  self.host_abs_decoder_destination)
686            return
687        if not suppressVulkanHeaders:
688            extraHeader = self.hostCommonExtraVulkanHeaders + '\n' + extraHeader
689        self.addCppModule(
690            self.host_tag, basename, extraHeader=extraHeader, extraImpl=extraImpl,
691            customAbsDir=self.host_abs_decoder_destination, useNamespace=useNamespace,
692            implOnly=implOnly, suppress=suppress, headerOnly=headerOnly,
693            suppressFeatureGuards=suppressFeatureGuards, moduleName=moduleName,
694            suppressVulkanHeaders=suppressVulkanHeaders)
695
696    def addModule(self, module, moduleName=None):
697        if moduleName is None:
698            moduleName = module.basename
699        self.moduleList.append(moduleName)
700        self.modules[moduleName] = module
701
702    def addCppModule(
703            self, directory, basename, extraHeader="", extraImpl="", customAbsDir=None,
704            useNamespace=True, implOnly=False, suppress=False, headerOnly=False,
705            suppressFeatureGuards=False, moduleName=None, suppressVulkanHeaders=False):
706        module = cereal.Module(
707            directory, basename, customAbsDir=customAbsDir, suppress=suppress, implOnly=implOnly,
708            headerOnly=headerOnly, suppressFeatureGuards=suppressFeatureGuards)
709        self.addModule(module, moduleName=moduleName)
710        module.headerPreamble = copyrightHeader
711        module.headerPreamble += \
712                autogeneratedHeaderTemplate % \
713                (basename, "(header) generated by %s" % banner_command(sys.argv))
714
715        module.headerPreamble += "#pragma once\n"
716        if (not suppressVulkanHeaders):
717            module.headerPreamble += "#include <vulkan/vulkan.h>\n"
718            module.headerPreamble += '#include "vulkan_gfxstream.h"\n'
719            module.headerPreamble += '#include "vk_android_native_buffer_gfxstream.h"\n'
720        module.headerPreamble += extraHeader + '\n'
721        if useNamespace:
722            module.headerPreamble += namespaceBegin
723
724        module.implPreamble = copyrightHeader
725        module.implPreamble += \
726                autogeneratedHeaderTemplate % \
727                (basename, "(impl) generated by %s" % \
728                    banner_command(sys.argv))
729        if not implOnly:
730            module.implPreamble += '\n#include "%s.h"' % \
731                (basename)
732
733        module.implPreamble += extraImpl
734
735        if useNamespace:
736            module.implPreamble += namespaceBegin
737            module.implPostamble += namespaceEnd
738            module.headerPostamble += namespaceEnd
739
740    def addWrapper(self, moduleType, moduleName, **kwargs):
741        if moduleName not in self.modules:
742            print(f'Unknown module: {moduleName}. All known modules are: {", ".join(self.modules)}.')
743            return
744        self.wrappers.append(
745            (moduleType(
746                self.modules[moduleName],
747                self.typeInfo, **kwargs),
748             moduleName)
749            )
750
751    def forEachModule(self, func):
752        for moduleName in self.moduleList:
753            func(self.modules[moduleName])
754
755    def forEachWrapper(self, func, supportedModules):
756        for wrapper in self.wrappers:
757            if supportedModules is None:
758                func(wrapper[0])
759            elif wrapper[1] in supportedModules:
760                func(wrapper[0])
761
762## Overrides####################################################################
763
764    def beginFile(self, genOpts):
765        OutputGenerator.beginFile(self, genOpts)
766
767        self.forEachModule(lambda m: m.begin(self.genOpts.directory))
768        self.forEachWrapper(lambda w: w.onBegin(), None)
769
770    def endFile(self):
771        OutputGenerator.endFile(self)
772
773        self.typeInfo.onEnd()
774
775        self.forEachWrapper(lambda w: w.onEnd(), None)
776        self.forEachModule(lambda m: m.end())
777
778    def beginFeature(self, interface, emit):
779        # Start processing in superclass
780        OutputGenerator.beginFeature(self, interface, emit)
781
782        for supportedFeature in SUPPORTED_FEATURES:
783            if self.featureName == supportedFeature:
784                self.featureSupported = True
785
786        if self.featureSupported == False:
787            return
788
789        self.supportedModules = SUPPORTED_MODULES.get(self.featureName)
790        self.typeInfo.onBeginFeature(self.featureName, self.featureType)
791
792        self.forEachModule(
793            lambda m: m.appendHeader("#ifdef %s\n" % self.featureName)
794            if isinstance(m, cereal.Module) and not m.suppressFeatureGuards else None)
795        self.forEachModule(
796            lambda m: m.appendImpl("#ifdef %s\n" % self.featureName)
797            if isinstance(m, cereal.Module) and not m.suppressFeatureGuards else None)
798        self.forEachWrapper(lambda w: w.onBeginFeature(self.featureName, self.featureType), self.supportedModules)
799        # functable needs to understand the feature type (device vs instance) of each cmd
800        for features in interface.findall('require'):
801            for c in features.findall('command'):
802                self.forEachWrapper(lambda w: w.onFeatureNewCmd(c.get('name')), self.supportedModules)
803
804    def endFeature(self):
805        # Finish processing in superclass
806        OutputGenerator.endFeature(self)
807
808        if self.featureSupported == False:
809            return
810
811        self.featureSupported = False
812
813        self.typeInfo.onEndFeature()
814
815        self.forEachModule(lambda m: m.appendHeader("#endif\n") if isinstance(
816            m, cereal.Module) and not m.suppressFeatureGuards else None)
817        self.forEachModule(lambda m: m.appendImpl("#endif\n") if isinstance(
818            m, cereal.Module) and not m.suppressFeatureGuards else None)
819        self.forEachWrapper(lambda w: w.onEndFeature(), self.supportedModules)
820
821    def genType(self, typeinfo: TypeInfo, name, alias):
822        OutputGenerator.genType(self, typeinfo, name, alias)
823
824        # Maybe this check can be removed if we refactor other things inside
825        # the cereal subdirectory.
826        if self.featureSupported == False and name in REQUIRED_TYPES:
827            self.typeInfo.onGenType(typeinfo, name, alias)
828            return
829
830        if self.featureSupported == False:
831            return
832
833        self.typeInfo.onGenType(typeinfo, name, alias)
834        self.forEachWrapper(lambda w: w.onGenType(typeinfo, name, alias), self.supportedModules)
835
836    def genStruct(self, typeinfo, typeName, alias):
837        OutputGenerator.genStruct(self, typeinfo, typeName, alias)
838        if self.featureSupported == False:
839            return
840
841        self.typeInfo.onGenStruct(typeinfo, typeName, alias)
842        self.forEachWrapper(lambda w: w.onGenStruct(typeinfo, typeName, alias), self.supportedModules)
843
844    def genGroup(self, groupinfo: GroupInfo, groupName, alias = None):
845        OutputGenerator.genGroup(self, groupinfo, groupName, alias)
846        if self.featureSupported == False:
847            return
848
849        self.typeInfo.onGenGroup(groupinfo, groupName, alias)
850        self.forEachWrapper(lambda w: w.onGenGroup(groupinfo, groupName, alias), self.supportedModules)
851
852    def genEnum(self, enuminfo: EnumInfo, name, alias):
853        OutputGenerator.genEnum(self, enuminfo, name, alias)
854        if self.featureSupported == False:
855            return
856        self.typeInfo.onGenEnum(enuminfo, name, alias)
857        self.forEachWrapper(lambda w: w.onGenEnum(enuminfo, name, alias), self.supportedModules)
858
859    def genCmd(self, cmdinfo, name, alias):
860        OutputGenerator.genCmd(self, cmdinfo, name, alias)
861        if self.featureSupported == False:
862            return
863
864        self.typeInfo.onGenCmd(cmdinfo, name, alias)
865        self.forEachWrapper(lambda w: w.onGenCmd(cmdinfo, name, alias), self.supportedModules)
866