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