-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
981 lines (902 loc) · 37.4 KB
/
Copy pathCMakeLists.txt
File metadata and controls
981 lines (902 loc) · 37.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
cmake_minimum_required(VERSION 3.16)
project(Gfx VERSION 1.0.0 LANGUAGES C CXX)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Detect Emscripten
if(EMSCRIPTEN)
message(STATUS "Building for Emscripten/WebAssembly")
set(BUILD_FOR_WEB TRUE)
# Force options for web builds
set(BUILD_VULKAN_BACKEND OFF CACHE BOOL "Vulkan not available on web" FORCE)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Static libraries for web" FORCE)
set(ENABLE_ASAN OFF CACHE BOOL "Sanitizers not supported on web" FORCE)
set(ENABLE_UBSAN OFF CACHE BOOL "Sanitizers not supported on web" FORCE)
set(ENABLE_TSAN OFF CACHE BOOL "Sanitizers not supported on web" FORCE)
else()
set(BUILD_FOR_WEB FALSE)
endif()
# Options
option(BUILD_EXAMPLES "Build example applications" ON)
option(BUILD_TESTS "Build test suite" ON)
option(BUILD_CPP_WRAPPER "Build C++ wrapper library" ON)
option(BUILD_VULKAN_BACKEND "Build Vulkan backend" ON)
option(BUILD_WEBGPU_BACKEND "Build WebGPU backend" ON)
option(BUILD_SHARED_LIBS "Build shared libraries instead of static" ON)
option(ENABLE_ASAN "Enable Address Sanitizer" OFF)
option(ENABLE_UBSAN "Enable Undefined Behavior Sanitizer" OFF)
option(ENABLE_TSAN "Enable Thread Sanitizer" OFF)
option(BUILD_HEADLESS "Build without windowing system support (no surface creation)" OFF)
# Sanitizers (Clang/GCC only). ASan and TSan are mutually exclusive; UBSan combines with either.
if(ENABLE_ASAN AND ENABLE_TSAN)
message(FATAL_ERROR "ENABLE_ASAN and ENABLE_TSAN are mutually exclusive")
endif()
# Apply the enabled sanitizers to a first-party target (libraries, tests, examples). Vendored
# third_party code is intentionally left uninstrumented. No-op on MSVC and when none are enabled.
function(gfx_apply_sanitizers target)
if(MSVC)
return()
endif()
set(_sanitizers "")
if(ENABLE_ASAN)
list(APPEND _sanitizers address)
endif()
if(ENABLE_UBSAN)
list(APPEND _sanitizers undefined)
endif()
if(ENABLE_TSAN)
list(APPEND _sanitizers thread)
endif()
if(_sanitizers)
string(REPLACE ";" "," _flags "${_sanitizers}")
target_compile_options(${target} PRIVATE -fsanitize=${_flags} -fno-omit-frame-pointer -g)
target_link_options(${target} PRIVATE -fsanitize=${_flags})
endif()
endfunction()
# Platform-specific libraries
if(BUILD_HEADLESS)
# Headless builds don't need windowing libraries
set(PLATFORM_LIBS "")
message(STATUS "Headless build: skipping windowing system libraries")
elseif(BUILD_FOR_WEB)
# Web builds don't need platform libraries
set(PLATFORM_LIBS "")
set(GFX_HAS_EMSCRIPTEN ON)
elseif(ANDROID)
# Android-specific libraries
find_library(ANDROID_LIBRARY android)
find_library(LOG_LIBRARY log)
set(PLATFORM_LIBS ${ANDROID_LIBRARY} ${LOG_LIBRARY})
set(GFX_HAS_ANDROID ON)
# 16KB page size compatibility (Android 15+, NDK r27+)
add_link_options("-Wl,-z,max-page-size=16384")
elseif(WIN32)
set(PLATFORM_LIBS user32 gdi32)
set(GFX_HAS_WIN32 ON)
elseif(IOS)
# iOS-specific frameworks
find_library(UIKIT_LIBRARY UIKit)
find_library(FOUNDATION_LIBRARY Foundation)
find_library(QUARTZCORE_LIBRARY QuartzCore)
set(PLATFORM_LIBS ${UIKIT_LIBRARY} ${FOUNDATION_LIBRARY} ${QUARTZCORE_LIBRARY})
set(GFX_HAS_UIKIT ON)
elseif(APPLE)
# macOS-specific frameworks
find_library(COCOA_LIBRARY Cocoa)
find_library(IOKIT_LIBRARY IOKit)
find_library(COREVIDEO_LIBRARY CoreVideo)
set(PLATFORM_LIBS ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY})
set(GFX_HAS_COCOA ON)
elseif(UNIX)
# Options to allow parent project to restrict windowing system detection
option(GFX_ENABLE_X11 "Enable X11 windowing support" ON)
option(GFX_ENABLE_XCB "Enable XCB windowing support" ON)
option(GFX_ENABLE_WAYLAND "Enable Wayland windowing support" ON)
# Try to find available windowing systems (all optional)
if(GFX_ENABLE_X11)
find_package(X11)
endif()
# Only use pkg-config if available (for XCB and Wayland detection)
find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
if(GFX_ENABLE_XCB)
pkg_check_modules(XCB xcb)
endif()
if(GFX_ENABLE_WAYLAND)
pkg_check_modules(WAYLAND_CLIENT wayland-client)
endif()
endif()
# Build list of platform libraries based on what's available
set(PLATFORM_LIBS "")
if(X11_FOUND AND GFX_ENABLE_X11)
list(APPEND PLATFORM_LIBS ${X11_LIBRARIES})
set(GFX_HAS_X11 ON)
message(STATUS "Found X11 windowing support")
endif()
if(XCB_FOUND AND GFX_ENABLE_XCB)
list(APPEND PLATFORM_LIBS ${XCB_LIBRARIES})
set(GFX_HAS_XCB ON)
message(STATUS "Found XCB windowing support")
endif()
if(WAYLAND_CLIENT_FOUND AND GFX_ENABLE_WAYLAND)
list(APPEND PLATFORM_LIBS ${WAYLAND_CLIENT_LIBRARIES})
set(GFX_HAS_WAYLAND ON)
message(STATUS "Found Wayland windowing support")
endif()
# Warn if no windowing system found
if(NOT GFX_HAS_X11 AND NOT GFX_HAS_XCB AND NOT GFX_HAS_WAYLAND)
message(WARNING "No windowing system found (X11, XCB, or Wayland). Consider using -DBUILD_HEADLESS=ON")
endif()
else()
message(ERROR "Unknown configuration.")
endif()
# Vulkan
if(BUILD_VULKAN_BACKEND AND NOT BUILD_FOR_WEB)
# Don't use find_package(Vulkan) - we'll use Dawn's bundled Vulkan headers
# Just find the Vulkan loader library and glslc compiler
# Find Vulkan loader library manually
if(IOS)
# For iOS simulator, determine the correct architecture
# Check the actual SDK path, not just the name, since CMAKE_OSX_SYSROOT can be inconsistent
string(TOLOWER "${CMAKE_OSX_SYSROOT}" SYSROOT_LOWER)
if(SYSROOT_LOWER MATCHES "simulator" OR CMAKE_OSX_SYSROOT MATCHES "Simulator")
set(IOS_ARCH "ios-arm64_x86_64-simulator")
else()
set(IOS_ARCH "ios-arm64")
endif()
message(STATUS "iOS build detected, architecture: ${IOS_ARCH}")
message(STATUS "CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT}")
message(STATUS "VULKAN_SDK: $ENV{VULKAN_SDK}")
# Try to find the MoltenVK static library in the xcframework
# VULKAN_SDK typically points to macOS subdirectory already
set(MOLTENVK_XCFRAMEWORK_PATH "$ENV{VULKAN_SDK}/lib/MoltenVK.xcframework/${IOS_ARCH}/libMoltenVK.a")
message(STATUS "Checking for MoltenVK at: ${MOLTENVK_XCFRAMEWORK_PATH}")
if(EXISTS "${MOLTENVK_XCFRAMEWORK_PATH}")
set(Vulkan_LIBRARY "${MOLTENVK_XCFRAMEWORK_PATH}")
message(STATUS "Found MoltenVK at: ${Vulkan_LIBRARY}")
else()
# Try alternative paths
find_library(Vulkan_LIBRARY
NAMES MoltenVK libMoltenVK.a
HINTS
"$ENV{VULKAN_SDK}/macOS/lib/MoltenVK.xcframework/${IOS_ARCH}"
"$ENV{VULKAN_SDK}/iOS/lib/MoltenVK.xcframework/${IOS_ARCH}/MoltenVK.framework"
"$ENV{VULKAN_SDK}/iOS/lib"
NO_DEFAULT_PATH
)
if(NOT Vulkan_LIBRARY)
# Fallback to standard paths
find_library(Vulkan_LIBRARY
NAMES MoltenVK
HINTS ENV VULKAN_SDK
PATH_SUFFIXES iOS/lib iOS/static
)
endif()
endif()
elseif(APPLE)
# macOS SDK path structure: $ENV{VULKAN_SDK}/macOS/lib
find_library(Vulkan_LIBRARY
NAMES MoltenVK vulkan
HINTS
ENV VULKAN_SDK
PATH_SUFFIXES macOS/lib lib
)
else()
find_library(Vulkan_LIBRARY
NAMES vulkan vulkan-1
HINTS
ENV VULKAN_SDK
PATH_SUFFIXES lib
)
endif()
if(NOT Vulkan_LIBRARY)
message(FATAL_ERROR "Vulkan loader library not found. Please install Vulkan SDK.")
endif()
# Find glslc shader compiler (comes with Vulkan SDK)
find_program(GLSLC_EXECUTABLE
NAMES glslc
HINTS
ENV VULKAN_SDK
PATH_SUFFIXES bin
)
if(GLSLC_EXECUTABLE)
message(STATUS "Found glslc: ${GLSLC_EXECUTABLE}")
else()
message(WARNING "glslc not found - shaders will not be compiled automatically")
endif()
endif()
# WebGPU (Dawn)
if(BUILD_WEBGPU_BACKEND)
# Check for Dawn in multiple locations (submodule, environment, or custom path)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/third_party/dawn/CMakeLists.txt")
set(DAWN_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/third_party/dawn")
message(STATUS "Using Dawn from submodule: ${DAWN_ROOT}")
elseif(DEFINED ENV{DAWN_ROOT} AND EXISTS "$ENV{DAWN_ROOT}/CMakeLists.txt")
set(DAWN_ROOT "$ENV{DAWN_ROOT}")
message(STATUS "Using Dawn from environment variable: ${DAWN_ROOT}")
elseif(DEFINED DAWN_ROOT AND EXISTS "${DAWN_ROOT}/CMakeLists.txt")
message(STATUS "Using Dawn from CMake variable: ${DAWN_ROOT}")
else()
message(FATAL_ERROR "Dawn not found. Please either:\n"
" 1. Initialize submodule: git submodule update --init\n"
" 2. Set DAWN_ROOT environment variable\n"
" 3. Pass -DDAWN_ROOT=/path/to/dawn to CMake")
endif()
if(EXISTS "${DAWN_ROOT}/CMakeLists.txt")
message(STATUS "Adding Dawn from: ${DAWN_ROOT}")
# Save our BUILD_SHARED_LIBS setting
set(GFX_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
# Dawn build options - Dawn requires BUILD_SHARED_LIBS=OFF
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
set(DAWN_FETCH_DEPENDENCIES ON CACHE BOOL "" FORCE)
set(DAWN_BUILD_SAMPLES OFF CACHE BOOL "" FORCE)
set(DAWN_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
set(DAWN_USE_GLFW OFF CACHE BOOL "" FORCE)
# Enable SPIR-V support in Tint (required for native WebGPU)
if(NOT BUILD_FOR_WEB)
set(TINT_BUILD_SPV_READER ON CACHE BOOL "Enable SPIR-V reader for WebGPU backend" FORCE)
set(TINT_BUILD_SPV_WRITER ON CACHE BOOL "Enable SPIR-V writer for WebGPU backend" FORCE)
endif()
# Platform-specific Dawn options
if(BUILD_FOR_WEB)
set(DAWN_ENABLE_VULKAN OFF CACHE BOOL "" FORCE)
set(DAWN_USE_X11 OFF CACHE BOOL "" FORCE)
set(DAWN_USE_WAYLAND OFF CACHE BOOL "" FORCE)
set(DAWN_ENABLE_METAL OFF CACHE BOOL "" FORCE)
set(DAWN_ENABLE_D3D11 OFF CACHE BOOL "" FORCE)
set(DAWN_ENABLE_D3D12 OFF CACHE BOOL "" FORCE)
else()
set(DAWN_ENABLE_VULKAN ON CACHE BOOL "" FORCE) # Enable Vulkan for native rendering
if(GFX_HAS_X11 OR GFX_HAS_XCB)
set(DAWN_USE_X11 ON CACHE BOOL "" FORCE)
else()
set(DAWN_USE_X11 OFF CACHE BOOL "" FORCE)
endif()
if(GFX_HAS_WAYLAND)
set(DAWN_USE_WAYLAND ON CACHE BOOL "" FORCE)
else()
set(DAWN_USE_WAYLAND OFF CACHE BOOL "" FORCE)
endif()
if(GFX_HAS_COCOA OR GFX_HAS_UIKIT)
set(DAWN_ENABLE_METAL ON CACHE BOOL "" FORCE)
endif()
if(GFX_HAS_WIN32)
set(DAWN_ENABLE_D3D11 ON CACHE BOOL "" FORCE)
set(DAWN_ENABLE_D3D12 ON CACHE BOOL "" FORCE)
endif()
endif()
set(TINT_BUILD_CMD_TOOLS ON CACHE BOOL "" FORCE)
# Suppress warnings from third-party code (Dawn and its dependencies)
set(GFX_SAVED_C_FLAGS "${CMAKE_C_FLAGS}")
set(GFX_SAVED_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
if(NOT MSVC)
# Suppress all warnings including compiler flag warnings
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w -Wno-unused-command-line-argument")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w -Wno-unused-command-line-argument")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W0")
endif()
add_subdirectory(${DAWN_ROOT} ${CMAKE_BINARY_DIR}/dawn EXCLUDE_FROM_ALL)
# Restore warning flags for our code
set(CMAKE_C_FLAGS "${GFX_SAVED_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${GFX_SAVED_CXX_FLAGS}")
# Restore our BUILD_SHARED_LIBS setting
set(BUILD_SHARED_LIBS ${GFX_BUILD_SHARED_LIBS} CACHE BOOL "" FORCE)
set(WEBGPU_INCLUDE_DIR "${DAWN_ROOT}/include")
set(WEBGPU_FOUND TRUE)
message(STATUS "WebGPU enabled via Dawn subdirectory")
message(STATUS "WebGPU include dir: ${WEBGPU_INCLUDE_DIR}")
else()
message(WARNING "Dawn directory not found at ${DAWN_ROOT} - WebGPU backend will be disabled")
set(BUILD_WEBGPU_BACKEND OFF)
endif()
endif()
# Vulkan Memory Allocator (VMA) - header-only library for efficient GPU memory management
if(BUILD_VULKAN_BACKEND AND NOT BUILD_FOR_WEB)
include(FetchContent)
FetchContent_Declare(
VulkanMemoryAllocator
GIT_REPOSITORY https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
GIT_TAG v3.3.0
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(VulkanMemoryAllocator)
set(VMA_INCLUDE_DIR "${vulkanmemoryallocator_SOURCE_DIR}/include")
message(STATUS "VMA include dir: ${VMA_INCLUDE_DIR}")
endif()
# Google Test
if(BUILD_TESTS)
if(BUILD_WEBGPU_BACKEND AND WEBGPU_FOUND)
# Use GoogleTest from Dawn's third_party directory
set(GTEST_INCLUDE_DIR "${DAWN_ROOT}/third_party/googletest/googletest/include")
set(GMOCK_INCLUDE_DIR "${DAWN_ROOT}/third_party/googletest/googlemock/include")
message(STATUS "Using GoogleTest from Dawn: ${GTEST_INCLUDE_DIR}")
else()
# Fetch GoogleTest if Dawn is not available
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.14.0
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
endif()
enable_testing()
include(GoogleTest)
endif()
# C API Library (implemented in C++)
set(GFX_C_SOURCES
gfx/include/gfx/gfx.h
gfx/src/GfxImpl.cpp
gfx/src/backend/IBackend.h
gfx/src/backend/Factory.cpp
gfx/src/backend/Manager.cpp
gfx/src/common/Logger.cpp
gfx/src/util/Utils.cpp
)
if(BUILD_VULKAN_BACKEND)
list(APPEND GFX_C_SOURCES
gfx/src/backend/vulkan/Backend.cpp
# Components
gfx/src/backend/vulkan/component/SystemComponent.cpp
gfx/src/backend/vulkan/component/PresentationComponent.cpp
gfx/src/backend/vulkan/component/ResourceComponent.cpp
gfx/src/backend/vulkan/component/RenderComponent.cpp
gfx/src/backend/vulkan/component/ComputeComponent.cpp
gfx/src/backend/vulkan/component/CommandComponent.cpp
gfx/src/backend/vulkan/component/SyncComponent.cpp
gfx/src/backend/vulkan/component/QueryComponent.cpp
# Converters and validators
gfx/src/backend/vulkan/converter/Conversions.cpp
gfx/src/backend/vulkan/validator/Validations.cpp
# System
gfx/src/backend/vulkan/core/system/Instance.cpp
gfx/src/backend/vulkan/core/system/Adapter.cpp
gfx/src/backend/vulkan/core/system/Device.cpp
gfx/src/backend/vulkan/core/system/Queue.cpp
# Resource
gfx/src/backend/vulkan/core/resource/Buffer.cpp
gfx/src/backend/vulkan/core/resource/Texture.cpp
gfx/src/backend/vulkan/core/resource/TextureView.cpp
gfx/src/backend/vulkan/core/resource/Sampler.cpp
gfx/src/backend/vulkan/core/resource/Shader.cpp
gfx/src/backend/vulkan/core/resource/BindGroup.cpp
gfx/src/backend/vulkan/core/resource/BindGroupLayout.cpp
# Render
gfx/src/backend/vulkan/core/render/RenderPipeline.cpp
gfx/src/backend/vulkan/core/render/RenderPass.cpp
gfx/src/backend/vulkan/core/render/Framebuffer.cpp
# Compute
gfx/src/backend/vulkan/core/compute/ComputePipeline.cpp
# Command
gfx/src/backend/vulkan/core/command/CommandEncoder.cpp
gfx/src/backend/vulkan/core/command/RenderPassEncoder.cpp
gfx/src/backend/vulkan/core/command/ComputePassEncoder.cpp
# Sync
gfx/src/backend/vulkan/core/sync/Semaphore.cpp
gfx/src/backend/vulkan/core/sync/Fence.cpp
# Query
gfx/src/backend/vulkan/core/query/QuerySet.cpp
# Presentation
gfx/src/backend/vulkan/core/presentation/Swapchain.cpp
gfx/src/backend/vulkan/core/presentation/Surface.cpp
# Util
gfx/src/backend/vulkan/core/util/CommandExecutor.cpp
gfx/src/backend/vulkan/core/util/Utils.cpp
gfx/src/backend/vulkan/core/util/VmaImpl.cpp
gfx/src/backend/vulkan/core/util/VmaAllocator.cpp
)
endif()
if(BUILD_WEBGPU_BACKEND)
list(APPEND GFX_C_SOURCES
gfx/src/backend/webgpu/Backend.cpp
gfx/src/backend/webgpu/converter/Conversions.cpp
gfx/src/backend/webgpu/validator/Validations.cpp
# Components
gfx/src/backend/webgpu/component/SystemComponent.cpp
gfx/src/backend/webgpu/component/PresentationComponent.cpp
gfx/src/backend/webgpu/component/ResourceComponent.cpp
gfx/src/backend/webgpu/component/RenderComponent.cpp
gfx/src/backend/webgpu/component/ComputeComponent.cpp
gfx/src/backend/webgpu/component/CommandComponent.cpp
gfx/src/backend/webgpu/component/SyncComponent.cpp
gfx/src/backend/webgpu/component/QueryComponent.cpp
# System
gfx/src/backend/webgpu/core/system/Instance.cpp
gfx/src/backend/webgpu/core/system/Adapter.cpp
gfx/src/backend/webgpu/core/system/Device.cpp
gfx/src/backend/webgpu/core/system/Queue.cpp
# Resources
gfx/src/backend/webgpu/core/resource/Buffer.cpp
gfx/src/backend/webgpu/core/resource/Texture.cpp
gfx/src/backend/webgpu/core/resource/TextureView.cpp
gfx/src/backend/webgpu/core/resource/Sampler.cpp
gfx/src/backend/webgpu/core/resource/Shader.cpp
gfx/src/backend/webgpu/core/resource/BindGroup.cpp
gfx/src/backend/webgpu/core/resource/BindGroupLayout.cpp
# Render
gfx/src/backend/webgpu/core/render/RenderPipeline.cpp
gfx/src/backend/webgpu/core/render/RenderPass.cpp
gfx/src/backend/webgpu/core/render/Framebuffer.cpp
# Compute
gfx/src/backend/webgpu/core/compute/ComputePipeline.cpp
# Command
gfx/src/backend/webgpu/core/command/CommandEncoder.cpp
gfx/src/backend/webgpu/core/command/RenderPassEncoder.cpp
gfx/src/backend/webgpu/core/command/ComputePassEncoder.cpp
# Sync
gfx/src/backend/webgpu/core/sync/Fence.cpp
gfx/src/backend/webgpu/core/sync/Semaphore.cpp
# Query
gfx/src/backend/webgpu/core/query/QuerySet.cpp
# Presentation
gfx/src/backend/webgpu/core/presentation/Surface.cpp
gfx/src/backend/webgpu/core/presentation/Swapchain.cpp
# Util
gfx/src/backend/webgpu/core/util/Blit.cpp
gfx/src/backend/webgpu/core/util/Utils.cpp
)
endif()
# Create library based on BUILD_SHARED_LIBS option
if(BUILD_SHARED_LIBS)
add_library(gfx SHARED ${GFX_C_SOURCES})
# Set version information for shared library
set_target_properties(gfx PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
)
# Define GFX_BUILDING_DLL when building the shared library
target_compile_definitions(gfx PUBLIC GFX_BUILDING_DLL) # Changed from PRIVATE to PUBLIC
else()
add_library(gfx STATIC ${GFX_C_SOURCES})
# Define GFX_STATIC when building static library so header uses no import/export decorations
target_compile_definitions(gfx PUBLIC GFX_STATIC=1)
endif()
target_include_directories(gfx
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/gfx/include>
$<INSTALL_INTERFACE:include>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/gfx/src
)
# Link Vulkan if available
if(BUILD_VULKAN_BACKEND)
target_link_libraries(gfx PUBLIC ${Vulkan_LIBRARY})
target_compile_definitions(gfx PUBLIC GFX_ENABLE_VULKAN=1)
# VMA include directory
if(VMA_INCLUDE_DIR)
target_include_directories(gfx PUBLIC ${VMA_INCLUDE_DIR})
endif()
# For iOS, MoltenVK requires additional frameworks
if(IOS)
target_link_libraries(gfx PUBLIC
"-framework Metal"
"-framework IOSurface"
"-framework CoreGraphics"
)
# For macOS desktop, link Cocoa, QuartzCore and IOSurface for MoltenVK
elseif(APPLE)
target_link_libraries(gfx PUBLIC
"-framework Metal"
"-framework Cocoa"
"-framework QuartzCore"
"-framework IOSurface"
)
endif()
# Use Dawn's bundled Vulkan headers if WebGPU backend is enabled to avoid version conflicts
if(BUILD_WEBGPU_BACKEND AND TARGET Vulkan::Headers)
target_link_libraries(gfx PUBLIC Vulkan::Headers)
else()
# Fall back to system Vulkan headers if Dawn is not available
find_path(SYSTEM_VULKAN_INCLUDE_DIR vulkan/vulkan.h
HINTS ENV VULKAN_SDK
PATH_SUFFIXES include
)
message(STATUS "SYSTEM_VULKAN_INCLUDE_DIR search result: ${SYSTEM_VULKAN_INCLUDE_DIR}")
if(NOT SYSTEM_VULKAN_INCLUDE_DIR AND IOS)
# For iOS, explicitly check in VULKAN_SDK/include
set(IOS_VULKAN_INCLUDE "$ENV{VULKAN_SDK}/include")
if(EXISTS "${IOS_VULKAN_INCLUDE}/vulkan/vulkan.h")
set(SYSTEM_VULKAN_INCLUDE_DIR "${IOS_VULKAN_INCLUDE}")
message(STATUS "Found iOS Vulkan headers at: ${SYSTEM_VULKAN_INCLUDE_DIR}")
endif()
endif()
if(SYSTEM_VULKAN_INCLUDE_DIR)
target_include_directories(gfx PUBLIC ${SYSTEM_VULKAN_INCLUDE_DIR})
else()
message(FATAL_ERROR "Vulkan headers not found. Please install Vulkan SDK.")
endif()
endif()
endif()
# Link WebGPU if available
if(BUILD_WEBGPU_BACKEND)
# Configure WebGPU for native vs web builds
if(BUILD_FOR_WEB)
# For web builds, use emdawnwebgpu port
target_compile_options(gfx PUBLIC --use-port=emdawnwebgpu)
target_link_options(gfx PUBLIC --use-port=emdawnwebgpu)
target_include_directories(gfx PUBLIC
${CMAKE_BINARY_DIR}/dawn/gen/src/emdawnwebgpu/include # Generated headers first
${WEBGPU_INCLUDE_DIR} # Source headers second
)
else()
# For native builds, link to webgpu_dawn
target_link_libraries(gfx PUBLIC webgpu_dawn)
target_include_directories(gfx PUBLIC
${CMAKE_BINARY_DIR}/dawn/gen/include
${WEBGPU_INCLUDE_DIR}
)
endif()
target_include_directories(gfx PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/include)
target_compile_definitions(gfx PUBLIC GFX_ENABLE_WEBGPU=1)
# Ensure Dawn's generated headers are built first
if(TARGET webgpu_headers_gen)
add_dependencies(gfx webgpu_headers_gen)
endif()
if(TARGET emdawnwebgpu_headers_gen)
add_dependencies(gfx emdawnwebgpu_headers_gen)
endif()
endif()
# Add headless build definition
if(BUILD_HEADLESS)
target_compile_definitions(gfx PUBLIC GFX_HEADLESS_BUILD=1)
endif()
# Add windowing system definitions
if(GFX_HAS_WIN32)
target_compile_definitions(gfx PUBLIC GFX_HAS_WIN32=1)
endif()
if(GFX_HAS_ANDROID)
target_compile_definitions(gfx PUBLIC GFX_HAS_ANDROID=1)
endif()
if(GFX_HAS_COCOA)
target_compile_definitions(gfx PUBLIC GFX_HAS_COCOA=1)
endif()
if(GFX_HAS_UIKIT)
target_compile_definitions(gfx PUBLIC GFX_HAS_UIKIT=1)
endif()
if(GFX_HAS_X11)
target_compile_definitions(gfx PUBLIC GFX_HAS_X11=1)
endif()
if(GFX_HAS_XCB)
target_compile_definitions(gfx PUBLIC GFX_HAS_XCB=1)
endif()
if(GFX_HAS_WAYLAND)
target_compile_definitions(gfx PUBLIC GFX_HAS_WAYLAND=1)
endif()
if(GFX_HAS_EMSCRIPTEN)
target_compile_definitions(gfx PUBLIC GFX_HAS_EMSCRIPTEN=1)
endif()
# Link platform libraries
target_link_libraries(gfx PUBLIC ${PLATFORM_LIBS})
# C++ API Library (optional)
if(BUILD_CPP_WRAPPER)
set(GFX_CPP_SOURCES
gfx_cpp/include/gfx_cpp/gfx.hpp
gfx_cpp/src/GfxImpl.cpp
# Converter
gfx_cpp/src/converter/Conversions.h
gfx_cpp/src/converter/Conversions.cpp
# Utilities
gfx_cpp/src/core/util/HandleExtractor.h
gfx_cpp/src/core/util/HandleExtractor.cpp
gfx_cpp/src/core/util/Utils.h
gfx_cpp/src/core/util/Utils.cpp
# Sync
gfx_cpp/src/core/sync/Fence.h
gfx_cpp/src/core/sync/Fence.cpp
gfx_cpp/src/core/sync/Semaphore.h
gfx_cpp/src/core/sync/Semaphore.cpp
# Query
gfx_cpp/src/core/query/QuerySet.h
gfx_cpp/src/core/query/QuerySet.cpp
# Resources
gfx_cpp/src/core/resource/Buffer.h
gfx_cpp/src/core/resource/Buffer.cpp
gfx_cpp/src/core/resource/Texture.h
gfx_cpp/src/core/resource/Texture.cpp
gfx_cpp/src/core/resource/TextureView.h
gfx_cpp/src/core/resource/TextureView.cpp
gfx_cpp/src/core/resource/Sampler.h
gfx_cpp/src/core/resource/Sampler.cpp
gfx_cpp/src/core/resource/Shader.h
gfx_cpp/src/core/resource/Shader.cpp
gfx_cpp/src/core/resource/BindGroup.h
gfx_cpp/src/core/resource/BindGroup.cpp
gfx_cpp/src/core/resource/BindGroupLayout.h
gfx_cpp/src/core/resource/BindGroupLayout.cpp
# Command
gfx_cpp/src/core/command/CommandEncoder.h
gfx_cpp/src/core/command/CommandEncoder.cpp
gfx_cpp/src/core/command/RenderPassEncoder.h
gfx_cpp/src/core/command/RenderPassEncoder.cpp
gfx_cpp/src/core/command/ComputePassEncoder.h
gfx_cpp/src/core/command/ComputePassEncoder.cpp
# Render
gfx_cpp/src/core/render/RenderPipeline.h
gfx_cpp/src/core/render/RenderPipeline.cpp
gfx_cpp/src/core/render/RenderPass.h
gfx_cpp/src/core/render/RenderPass.cpp
gfx_cpp/src/core/render/Framebuffer.h
gfx_cpp/src/core/render/Framebuffer.cpp
# Compute
gfx_cpp/src/core/compute/ComputePipeline.h
gfx_cpp/src/core/compute/ComputePipeline.cpp
# Presentation
gfx_cpp/src/core/presentation/Surface.h
gfx_cpp/src/core/presentation/Surface.cpp
gfx_cpp/src/core/presentation/Swapchain.h
gfx_cpp/src/core/presentation/Swapchain.cpp
# System
gfx_cpp/src/core/system/Queue.h
gfx_cpp/src/core/system/Queue.cpp
gfx_cpp/src/core/system/Device.h
gfx_cpp/src/core/system/Device.cpp
gfx_cpp/src/core/system/Adapter.h
gfx_cpp/src/core/system/Adapter.cpp
gfx_cpp/src/core/system/Instance.h
gfx_cpp/src/core/system/Instance.cpp
)
# Create library based on BUILD_SHARED_LIBS option
if(BUILD_SHARED_LIBS)
add_library(gfx_cpp SHARED ${GFX_CPP_SOURCES})
# Set version information for shared library
set_target_properties(gfx_cpp PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
# CXX_VISIBILITY_PRESET hidden
# VISIBILITY_INLINES_HIDDEN ON
)
target_compile_definitions(gfx_cpp PUBLIC GFX_CPP_BUILDING_DLL) # Changed from PRIVATE to PUBLIC
else()
add_library(gfx_cpp STATIC ${GFX_CPP_SOURCES})
# Define GFX_CPP_STATIC when building static library
target_compile_definitions(gfx_cpp PUBLIC GFX_CPP_STATIC=1)
endif()
target_include_directories(gfx_cpp
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/gfx_cpp/include>
$<INSTALL_INTERFACE:include>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/gfx_cpp/src
)
target_link_libraries(gfx_cpp PUBLIC gfx) # Link to C API library
# Link Vulkan if available - only headers, not the library (already in gfx)
if(BUILD_VULKAN_BACKEND)
target_compile_definitions(gfx_cpp PUBLIC GFX_ENABLE_VULKAN=1)
# Use Dawn's bundled Vulkan headers if WebGPU backend is enabled to avoid version conflicts
if(BUILD_WEBGPU_BACKEND AND TARGET Vulkan::Headers)
target_link_libraries(gfx_cpp PUBLIC Vulkan::Headers)
endif()
endif()
# Link WebGPU if available
if(BUILD_WEBGPU_BACKEND)
target_link_libraries(gfx_cpp PUBLIC ${WEBGPU_LIBRARY})
# Configure WebGPU headers for native vs web builds
if(BUILD_FOR_WEB)
target_include_directories(gfx_cpp PUBLIC
${CMAKE_BINARY_DIR}/dawn/gen/src/emdawnwebgpu/include # Generated headers first
${WEBGPU_INCLUDE_DIR} # Source headers second
)
else()
target_include_directories(gfx_cpp PUBLIC
${CMAKE_BINARY_DIR}/dawn/gen/include
${WEBGPU_INCLUDE_DIR}
)
endif()
target_compile_definitions(gfx_cpp PUBLIC GFX_ENABLE_WEBGPU=1)
# Ensure Dawn's generated headers are built first
if(TARGET webgpu_headers_gen)
add_dependencies(gfx_cpp webgpu_headers_gen)
endif()
if(TARGET emdawnwebgpu_headers_gen)
add_dependencies(gfx_cpp emdawnwebgpu_headers_gen)
endif()
endif()
# Link platform libraries
target_link_libraries(gfx_cpp PUBLIC ${PLATFORM_LIBS})
# Emscripten-specific configuration
if(BUILD_FOR_WEB)
target_compile_options(gfx_cpp PRIVATE
-sDISABLE_EXCEPTION_CATCHING=0
# -sUSE_GLFW=3
# -sASYNCIFY=1
)
target_link_options(gfx_cpp PUBLIC
--use-port=emdawnwebgpu
-sUSE_GLFW=3
-sASYNCIFY=1
-sALLOW_MEMORY_GROWTH=1
-sDISABLE_EXCEPTION_CATCHING=0
)
endif()
# Compiler flags
if(MSVC)
target_compile_options(gfx_cpp PRIVATE /W4)
else()
target_compile_options(gfx_cpp PRIVATE -Wall -Wextra -Wpedantic -g)
endif()
gfx_apply_sanitizers(gfx_cpp)
endif() # BUILD_CPP_WRAPPER
# C API library compiler flags
if(MSVC)
target_compile_options(gfx PRIVATE /W4)
else()
target_compile_options(gfx PRIVATE -Wall -Wextra -Wpedantic -g)
endif()
gfx_apply_sanitizers(gfx)
# Emscripten-specific configuration for C library
if(BUILD_FOR_WEB)
target_compile_options(gfx PRIVATE
-sDISABLE_EXCEPTION_CATCHING=0
# -sUSE_GLFW=3
# -sASYNCIFY=1
)
target_link_options(gfx PUBLIC
--use-port=emdawnwebgpu
-sUSE_GLFW=3
-sASYNCIFY=1
-sALLOW_MEMORY_GROWTH=1
-sDISABLE_EXCEPTION_CATCHING=0
)
endif()
# Examples
if(BUILD_EXAMPLES)
add_subdirectory(examples)
endif() # BUILD_EXAMPLES
# Add tests
if(BUILD_TESTS AND NOT BUILD_FOR_WEB)
# ========================================================================
# CREATE OBJECT LIBRARY FOR gfx INTERNAL TESTS (when shared library)
# ========================================================================
if(BUILD_SHARED_LIBS)
add_library(gfx_objects OBJECT ${GFX_C_SOURCES})
target_include_directories(gfx_objects
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/gfx/include>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/gfx/src
)
# Apply same configuration as main gfx library
if(BUILD_VULKAN_BACKEND)
target_link_libraries(gfx_objects PUBLIC ${Vulkan_LIBRARY})
target_compile_definitions(gfx_objects PUBLIC GFX_ENABLE_VULKAN=1)
if(VMA_INCLUDE_DIR)
target_include_directories(gfx_objects PUBLIC ${VMA_INCLUDE_DIR})
endif()
if(BUILD_WEBGPU_BACKEND AND TARGET Vulkan::Headers)
target_link_libraries(gfx_objects PUBLIC Vulkan::Headers)
elseif(SYSTEM_VULKAN_INCLUDE_DIR)
target_include_directories(gfx_objects PUBLIC ${SYSTEM_VULKAN_INCLUDE_DIR})
endif()
endif()
if(BUILD_WEBGPU_BACKEND)
# For native builds, link to webgpu_dawn
target_link_libraries(gfx_objects PUBLIC webgpu_dawn)
target_include_directories(gfx_objects PUBLIC
${CMAKE_BINARY_DIR}/dawn/gen/include
${WEBGPU_INCLUDE_DIR}
)
target_include_directories(gfx_objects PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/include)
target_compile_definitions(gfx_objects PUBLIC GFX_ENABLE_WEBGPU=1)
if(TARGET webgpu_headers_gen)
add_dependencies(gfx_objects webgpu_headers_gen)
endif()
if(TARGET emdawnwebgpu_headers_gen)
add_dependencies(gfx_objects emdawnwebgpu_headers_gen)
endif()
endif()
if(BUILD_HEADLESS)
target_compile_definitions(gfx_objects PUBLIC GFX_HEADLESS_BUILD=1)
endif()
if(GFX_HAS_WIN32)
target_compile_definitions(gfx_objects PUBLIC GFX_HAS_WIN32=1)
endif()
if(GFX_HAS_ANDROID)
target_compile_definitions(gfx_objects PUBLIC GFX_HAS_ANDROID=1)
endif()
if(GFX_HAS_COCOA)
target_compile_definitions(gfx_objects PUBLIC GFX_HAS_COCOA=1)
endif()
if(GFX_HAS_UIKIT)
target_compile_definitions(gfx_objects PUBLIC GFX_HAS_UIKIT=1)
endif()
if(GFX_HAS_X11)
target_compile_definitions(gfx_objects PUBLIC GFX_HAS_X11=1)
endif()
if(GFX_HAS_XCB)
target_compile_definitions(gfx_objects PUBLIC GFX_HAS_XCB=1)
endif()
if(GFX_HAS_WAYLAND)
target_compile_definitions(gfx_objects PUBLIC GFX_HAS_WAYLAND=1)
endif()
if(GFX_HAS_EMSCRIPTEN)
target_compile_definitions(gfx_objects PUBLIC GFX_HAS_EMSCRIPTEN=1)
endif()
endif()
# ========================================================================
# CREATE OBJECT LIBRARY FOR gfx_cpp INTERNAL TESTS (when shared library)
# ========================================================================
if(BUILD_CPP_WRAPPER AND BUILD_SHARED_LIBS)
add_library(gfx_cpp_objects OBJECT ${GFX_CPP_SOURCES})
target_include_directories(gfx_cpp_objects
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/gfx_cpp/include>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/gfx_cpp/src
)
# Apply same configuration as main gfx_cpp library
target_compile_definitions(gfx_cpp_objects PRIVATE GFX_CPP_BUILDING_DLL)
target_link_libraries(gfx_cpp_objects PUBLIC gfx)
if(BUILD_VULKAN_BACKEND)
target_compile_definitions(gfx_cpp_objects PUBLIC GFX_ENABLE_VULKAN=1)
if(BUILD_WEBGPU_BACKEND AND TARGET Vulkan::Headers)
target_link_libraries(gfx_cpp_objects PUBLIC Vulkan::Headers)
endif()
endif()
if(BUILD_WEBGPU_BACKEND)
target_link_libraries(gfx_cpp_objects PUBLIC webgpu_dawn)
target_include_directories(gfx_cpp_objects PUBLIC
${CMAKE_BINARY_DIR}/dawn/gen/include
${WEBGPU_INCLUDE_DIR}
)
target_compile_definitions(gfx_cpp_objects PUBLIC GFX_ENABLE_WEBGPU=1)
if(TARGET webgpu_headers_gen)
add_dependencies(gfx_cpp_objects webgpu_headers_gen)
endif()
if(TARGET emdawnwebgpu_headers_gen)
add_dependencies(gfx_cpp_objects emdawnwebgpu_headers_gen)
endif()
endif()
target_link_libraries(gfx_cpp_objects PUBLIC ${PLATFORM_LIBS})
endif()
add_subdirectory(test/gfx)
if(BUILD_CPP_WRAPPER)
add_subdirectory(test/gfx_cpp)
endif()
endif()
# Install targets
if(BUILD_CPP_WRAPPER)
install(TARGETS gfx gfx_cpp
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
)
install(FILES gfx/include/gfx/gfx.h DESTINATION include/gfx)
install(FILES gfx_cpp/include/gfx_cpp/gfx.hpp DESTINATION include/gfx_cpp)
else()
install(TARGETS gfx
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
)
install(FILES gfx/include/gfx/gfx.h DESTINATION include/gfx)
endif()
# Print configuration summary
message(STATUS "")
message(STATUS "Gfx Configuration Summary:")
message(STATUS " Library type: ${BUILD_SHARED_LIBS}")
if(BUILD_SHARED_LIBS)
message(STATUS " Building SHARED libraries")
else()
message(STATUS " Building STATIC libraries")
endif()
message(STATUS " Build examples: ${BUILD_EXAMPLES}")
message(STATUS " Build tests: ${BUILD_TESTS}")
message(STATUS " Build C++ wrapper: ${BUILD_CPP_WRAPPER}")
message(STATUS " Headless build: ${BUILD_HEADLESS}")
message(STATUS " Address Sanitizer: ${ENABLE_ASAN}")
message(STATUS " UB Sanitizer: ${ENABLE_UBSAN}")
message(STATUS " Thread Sanitizer: ${ENABLE_TSAN}")
message(STATUS " Vulkan backend: ${BUILD_VULKAN_BACKEND}")
message(STATUS " WebGPU backend: ${BUILD_WEBGPU_BACKEND}")
if(BUILD_VULKAN_BACKEND)
message(STATUS " Vulkan library: ${Vulkan_LIBRARY}")
endif()
if(BUILD_WEBGPU_BACKEND AND WEBGPU_FOUND)
message(STATUS " WebGPU library: webgpu_dawn (target)")
endif()
message(STATUS "")