SDL_gpu_shadercross: Add DirectXShaderCompiler git submodule (#49)

From 933e058bc2f442461b4358b3fc2e896c34775478 Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
Date: Thu, 7 Nov 2024 02:12:57 +0100
Subject: [PATCH] Add DirectXShaderCompiler git submodule (#49)

---------

Co-authored-by: cosmonaut <evan@moonside.games>
---
 .github/workflows/main.yml                    |  47 ++++--
 .gitignore                                    |   1 +
 .gitmodules                                   |   9 ++
 CMakeLists.txt                                | 148 ++++++++++--------
 ...nload-prebuilt-DirectXShaderCompiler.cmake |  47 ++++++
 cmake/FindDirectXShaderCompiler.cmake         |  60 +++++++
 cmake/SDL3_gpu_shadercrossConfig.cmake.in     |  33 +++-
 cmake/sdl3-gpu-shadercross.pc.in              |   2 +-
 external/DirectXShaderCompiler                |   1 +
 external/SPIRV-Headers                        |   1 +
 external/SPIRV-Tools                          |   1 +
 src/SDL_gpu_shadercross.c                     |  76 ++++-----
 12 files changed, 292 insertions(+), 134 deletions(-)
 create mode 100644 build-scripts/download-prebuilt-DirectXShaderCompiler.cmake
 create mode 100644 cmake/FindDirectXShaderCompiler.cmake
 create mode 160000 external/DirectXShaderCompiler
 create mode 160000 external/SPIRV-Headers
 create mode 160000 external/SPIRV-Tools

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index dedba3d..656ae17 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -16,12 +16,11 @@ jobs:
       fail-fast: false
       matrix:
         platform:
-          - { name: Windows (MSVC),                os: windows-2019, shell: sh, msvc: true, artifact: 'SDL3_gpu_shadercross-VC-x64' }
-          - { name: Windows (mingw64),             os: windows-latest, shell: 'msys2 {0}', msystem: mingw64, msys-env: mingw-w64-x86_64, artifact: 'SDL3_gpu_shadercross-mingw64' }
-          - { name: Ubuntu 20.04,                  os: ubuntu-20.04,   shell: sh, artifact: 'SDL3_gpu_shadercross-linux-x64' }
-          - { name: Steam Linux Runtime (Sniper),  os: ubuntu-latest,  shell: sh, artifact: 'SDL3_gpu_shadercross-slrsniper', container: 'registry.gitlab.steamos.cloud/steamrt/sniper/sdk:beta' }
-          - { name: macOS,                         os: macos-latest,   shell: sh, artifact: 'SDL3_gpu_shadercross-macos-x64' }
-
+          - { name: Windows (MSVC),                os: windows-2019,   build-spirv-cross: true,  vendored: false, shell: sh, msvc: true, artifact: 'SDL3_gpu_shadercross-VC-x64' }
+          - { name: Windows (mingw64),             os: windows-latest, build-spirv-cross: false, vendored: false, shell: 'msys2 {0}', msystem: mingw64, msys-env: mingw-w64-x86_64, artifact: 'SDL3_gpu_shadercross-mingw64' }
+          - { name: Ubuntu 22.04,                  os: ubuntu-22.04,   build-spirv-cross: true,  vendored: false, shell: sh, artifact: 'SDL3_gpu_shadercross-linux-x64' }
+          - { name: Steam Linux Runtime (Sniper),  os: ubuntu-latest,  build-spirv-cross: false,  vendored: true, shell: sh, artifact: 'SDL3_gpu_shadercross-slrsniper', container: 'registry.gitlab.steamos.cloud/steamrt/sniper/sdk:beta' }
+          - { name: macOS,                         os: macos-latest,   build-spirv-cross: true,  vendored: true,  shell: sh, artifact: 'SDL3_gpu_shadercross-macos-arm64' }
 
     steps:
       - uses: actions/checkout@v4
@@ -43,6 +42,7 @@ jobs:
             ${{ matrix.platform.msys-env }}-cmake
             ${{ matrix.platform.msys-env }}-gcc
             ${{ matrix.platform.msys-env }}-ninja
+            ${{ (!matrix.platform.vendored && format('{0}-spirv-cross', matrix.platform.msys-env)) || '' }}
       - name: Set up SDL
         id: sdl
         uses: libsdl-org/setup-sdl@main
@@ -58,7 +58,7 @@ jobs:
           # patchelf is needed to fix the runpath of libSDL3.so.0
           wget https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0-x86_64.tar.gz
           tar xf patchelf-0.18.0-x86_64.tar.gz ./bin/patchelf
-          echo "$PWD/bin" >>$GITHUB_PATH
+          echo "${PWD}/bin" >>$GITHUB_PATH
 
           # libxrandr-dev is needed by vulkan-loader
           sudo apt-get update -y
@@ -69,18 +69,39 @@ jobs:
           # bison is needed by vkd3d
           brew install bison
           echo "/opt/homebrew/opt/bison/bin" >>$GITHUB_PATH
+      - name: Download DirectXShaderCompiler binaries
+        if: ${{ !matrix.platform.vendored && runner.os != 'macOS' }}
+        run: |
+          cmake -P build-scripts/download-prebuilt-DirectXShaderCompiler.cmake
+          echo "DirectXShaderCompiler_ROOT=${PWD}/external/DirectXShaderCompiler-binaries" >>${GITHUB_ENV}
+      - name: Build SPIRV-Cross
+        if: ${{ matrix.platform.build-spirv-cross }}
+        run: |
+          cmake -S external/SPIRV-Cross -B spirv_cross_build -GNinja \
+            -DCMAKE_BUILD_TYPE=Release \
+            -DSPIRV_CROSS_SHARED=ON \
+            -DSPIRV_CROSS_STATIC=ON \
+            -DCMAKE_INSTALL_PREFIX=${PWD}/spirv_cross_prefix
+          cmake --build spirv_cross_build
+          cmake --install spirv_cross_build
 
+          spirv_cross_prefix=${PWD}/spirv_cross_prefix
+          if test "x${{ (matrix.platform.msvc && 'msvc') || '' }}" = "xmsvc"; then
+            spirv_cross_prefix=$(cygpath -w "${spirv_cross_prefix}")
+          fi
+          joiner="${{ (runner.os == 'Windows' && ';') || ':' }}"
+          echo "spirv_cross_c_shared_ROOT=${spirv_cross_prefix}${joiner}${spirv_cross_prefix}/share/spirv_cross_c_shared" >>${GITHUB_ENV}
       - name: Configure (CMake)
         run: |
           cmake -S . -B build -GNinja \
             -DCMAKE_BUILD_TYPE=Release \
             -DSDLGPUSHADERCROSS_SHARED=ON \
             -DSDLGPUSHADERCROSS_STATIC=ON \
-            -DSDLGPUSHADERCROSS_VENDORED=ON \
+            -DSDLGPUSHADERCROSS_VENDORED=${{ matrix.platform.vendored }} \
             -DSDLGPUSHADERCROSS_CLI=ON \
             -DSDLGPUSHADERCROSS_WERROR=ON \
             -DSDLGPUSHADERCROSS_INSTALL=ON \
-            -DSDLGPUSHADERCROSS_INSTALL_DEPS=ON \
+            -DSDLGPUSHADERCROSS_INSTALL_RUNTIME=ON \
             -DSDLGPUSHADERCROSS_INSTALL_CPACK=ON \
             -DCMAKE_INSTALL_PREFIX="${PWD}/prefix"
 
@@ -88,12 +109,12 @@ jobs:
         id: build
         run: |
           cmake --build build --config Release --parallel --verbose
-
       - name: Install (CMake)
         id: install
         if: ${{ always() && steps.build.outcome == 'success' }}
         run: |
           cmake --install build/ --config Release
+          echo "SDL3_gpu_shadercross_ROOT=${PWD}/prefix" >>${GITHUB_ENV}
       - name: Package (CPack)
         id: package
         if: ${{ always() && steps.build.outcome == 'success' }}
@@ -103,10 +124,8 @@ jobs:
       - name: Verify CMake configuration files
         if: ${{ always() && steps.install.outcome == 'success' }}
         run: |
-          cmake -S cmake/test -B cmake_config_build \
-            -DCMAKE_BUILD_TYPE=Release \
-            -DCMAKE_PREFIX_PATH="${PWD}/prefix" \
-            -GNinja
+          cmake -S cmake/test -B cmake_config_build -GNinja \
+            -DCMAKE_BUILD_TYPE=Release
           cmake --build cmake_config_build --verbose
 
       - uses: actions/upload-artifact@v4
diff --git a/.gitignore b/.gitignore
index 567609b..5dd143f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 build/
+/external/DirectXShaderCompiler-binaries
diff --git a/.gitmodules b/.gitmodules
index 3dea3c4..cdfea88 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,12 @@
 [submodule "spirv-cross"]
 	path = external/SPIRV-Cross
 	url = https://github.com/KhronosGroup/SPIRV-Cross.git
+[submodule "spirv-headers"]
+	path = external/SPIRV-Headers
+	url = https://github.com/KhronosGroup/SPIRV-Headers.git
+[submodule "spirv-tools"]
+	path = external/SPIRV-Tools
+	url = https://github.com/KhronosGroup/SPIRV-Tools.git
+[submodule "DirectXShaderCompiler"]
+	path = external/DirectXShaderCompiler
+	url = https://github.com/microsoft/DirectXShaderCompiler.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4311604..ee61f15 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,6 +13,8 @@ set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
 
 project(SDL3_gpu_shadercross LANGUAGES C VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}")
 
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
 include(CMakeDependentOption)
 include("${CMAKE_CURRENT_LIST_DIR}/cmake/PrivateSdlFunctions.cmake")
 include("${CMAKE_CURRENT_LIST_DIR}/cmake/sdlcpu.cmake")
@@ -33,19 +35,23 @@ endif()
 # Options
 option(SDLGPUSHADERCROSS_SHARED "Build shared SDL_gpu_shadercross library" ${SDLGPUSHADERCROSS_SHARED_DEFAULT})
 option(SDLGPUSHADERCROSS_STATIC "Build static SDL_gpu_shadercross library" ${SDLGPUSHADERCROSS_STATIC_DEFAULT})
-option(SDLGPUSHADERCROSS_LINK_STATIC "Link to static library variants of dependencies" OFF)
+option(SDLGPUSHADERCROSS_SPIRVCROSS_SHARED "Link to shared library variants of dependencies" ON)
 option(SDLGPUSHADERCROSS_VENDORED "Use vendored dependencies" OFF)
 option(SDLGPUSHADERCROSS_CLI "Build command line executable" ON)
 cmake_dependent_option(SDLGPUSHADERCROSS_CLI_STATIC "Link CLI with static libraries" OFF "SDLGPUSHADERCROSS_CLI;SDLGPUSHADERCROSS_STATIC;TARGET SDL3::SDL3-static" OFF)
 option(SDLGPUSHADERCROSS_WERROR "Enable Werror" OFF)
 option(SDLGPUSHADERCROSS_INSTALL "Enable installation" OFF)
 cmake_dependent_option(SDLGPUSHADERCROSS_INSTALL_CPACK "Enable CPack installation" OFF "SDLGPUSHADERCROSS_INSTALL" OFF)
-cmake_dependent_option(SDLGPUSHADERCROSS_INSTALL_DEPS "Download, build and install optional dependencies" OFF "SDLGPUSHADERCROSS_INSTALL" OFF)
+cmake_dependent_option(SDLGPUSHADERCROSS_INSTALL_RUNTIME "Download, build and install runtime dependencies" OFF "SDLGPUSHADERCROSS_INSTALL" OFF)
 
 sdl_calculate_derived_version_variables(${MAJOR_VERSION} ${MINOR_VERSION} ${MICRO_VERSION})
 SDL_DetectTargetCPUArchitectures(SDL_CPU_NAMES)
 SDL_DetectCMakePlatform()
 
+if(SDLGPUSHADERCROSS_INSTALL)
+	include(GNUInstallDirs)
+endif()
+
 if(NOT SDLGPUSHADERCROSS_SHARED AND NOT SDLGPUSHADERCROSS_STATIC)
 	message(FATAL_ERROR "SDLGPUSHADERCROSS_SHARED and SDLGPUSHADERCROSS_STATIC cannot be both disabled")
 endif()
@@ -60,18 +66,20 @@ if(NOT MSVC)
 	add_compile_options(-pedantic) # -Wno-strict-aliasing
 endif()
 
+set(spirv_static_targets spirv-cross-c spirv-cross-glsl spirv-cross-hlsl spirv-cross-msl spirv-cross-cpp spirv-cross-reflect spirv-cross-core)
+
 set(pc_requires )
 set(install_extra_targets )
 if(SDLGPUSHADERCROSS_VENDORED)
 	set(SPIRV_CROSS_SKIP_INSTALL ON)
 	set(SPIRV_CROSS_CLI OFF)
 	set(SPIRV_CROSS_ENABLE_TESTS OFF)
-	if(SDLGPUSHADERCROSS_LINK_STATIC)
-		set(SPIRV_CROSS_SHARED OFF)
-		set(SPIRV_CROSS_STATIC ON)
-	else()
+	if(SDLGPUSHADERCROSS_SPIRVCROSS_SHARED)
 		set(SPIRV_CROSS_SHARED ON)
 		set(SPIRV_CROSS_STATIC OFF)
+	else()
+		set(SPIRV_CROSS_SHARED OFF)
+		set(SPIRV_CROSS_STATIC ON)
 	endif()
 
 	sdl_check_project_in_subfolder(external/SPIRV-Cross SPIRV-Cross SDLGPUSHADERCROSS_VENDORED)
@@ -79,36 +87,58 @@ if(SDLGPUSHADERCROSS_VENDORED)
 	set(CMAKE_POSITION_INDEPENDENT_CODE ON)
 	add_subdirectory(external/SPIRV-Cross EXCLUDE_FROM_ALL)
 
-	if(SDLGPUSHADERCROSS_LINK_STATIC)
+	if(SDLGPUSHADERCROSS_SPIRVCROSS_SHARED)
+		list(APPEND install_extra_targets spirv-cross-c-shared)
+		list(APPEND pc_requires "spirv-cross-c-shared")
+	else()
 		enable_language(CXX)
 		if(SDLGPUSHADERCROSS_STATIC)
-			list(APPEND install_extra_targets spirv-cross-c)
-			list(APPEND pc_requires "spirv-cross-c")
-			set(spirv_extra_targets spirv-cross-glsl spirv-cross-hlsl spirv-cross-msl spirv-cross-cpp spirv-cross-reflect spirv-cross-core)
-			foreach(extra IN LISTS spirv_extra_targets)
+			foreach(extra IN LISTS spirv_static_targets)
 				if(TARGET ${extra})
 					list(APPEND install_extra_targets ${extra})
 					list(APPEND pc_requires "${extra}")
 				endif()
 			endforeach()
 		endif()
-	else()
-		list(APPEND install_extra_targets spirv-cross-c-shared)
-		list(APPEND pc_requires "spirv-cross-c-shared")
 	endif()
+
+	sdl_check_project_in_subfolder(external/SPIRV-Headers SPIRV-Headers SDLGPUSHADERCROSS_VENDORED)
+	add_subdirectory(external/SPIRV-Headers EXCLUDE_FROM_ALL)
+	sdl_check_project_in_subfolder(external/SPIRV-Tools SPIRV-Tools SDLGPUSHADERCROSS_VENDORED)
+	add_subdirectory(external/SPIRV-Tools EXCLUDE_FROM_ALL)
+
+	sdl_check_project_in_subfolder(external/DirectXShaderCompiler DirectXShaderCompiler SDLGPUSHADERCROSS_VENDORED)
+	if(MINGW)
+		set(CMAKE_C_COMPILER_ARCHITECTURE_ID "${SDL_CPU_NAMES}")
+	endif()
+	set(DXC_COVERAGE OFF)
+	set(HLSL_INCLUDE_TESTS OFF)
+	set(LLVM_INCLUDE_TESTS OFF)
+	include(external/DirectXShaderCompiler/cmake/caches/PredefinedParams.cmake)
+	add_subdirectory(external/DirectXShaderCompiler EXCLUDE_FROM_ALL)
+	add_library(DirectXShaderCompiler::dxcompiler ALIAS dxcompiler)
+	add_library(DirectXShaderCompiler::dxil ALIAS dxildll)
+	list(APPEND install_extra_targets dxcompiler dxildll)
+	add_dependencies(dxcompiler dxildll)
 else()
-	if(SDLGPUSHADERCROSS_LINK_STATIC)
-		enable_language(CXX)
-		find_package(spirv_cross_core QUIET)
-		find_package(spirv_cross_glsl QUIET)
-		find_package(spirv_cross_hlsl QUIET)
-		find_package(spirv_cross_msl QUIET)
-		find_package(spirv_cross_cpp QUIET)
-		find_package(spirv_cross_reflect QUIET)
-		find_package(spirv_cross_c REQUIRED)
+	if(SDLGPUSHADERCROSS_SPIRVCROSS_SHARED)
+		if(NOT TARGET spirv_cross_c_shared)
+			find_package(spirv_cross_c_shared REQUIRED)
+		endif()
 	else()
-		find_package(spirv_cross_c_shared REQUIRED)
+		enable_language(CXX)
+		if(NOT TARGET spirv_cross_c)
+			find_package(spirv_cross_core QUIET)
+			find_package(spirv_cross_glsl QUIET)
+			find_package(spirv_cross_hlsl QUIET)
+			find_package(spirv_cross_msl QUIET)
+			find_package(spirv_cross_cpp QUIET)
+			find_package(spirv_cross_reflect QUIET)
+			find_package(spirv_cross_c REQUIRED)
+		endif()
 	endif()
+
+	find_package(DirectXShaderCompiler REQUIRED)
 endif()
 
 # Source lists
@@ -178,12 +208,13 @@ foreach(target IN LISTS SDL3_gpu_shadercross_targets)
 	sdl_add_warning_options(${target} WARNING_AS_ERROR ${SDLGPUSHADERCROSS_WERROR})
 	target_compile_features(${target} PRIVATE c_std_99)
 
-	if(SDLGPUSHADERCROSS_LINK_STATIC)
-		target_link_libraries(${target} PRIVATE spirv-cross-c)
-	else()
+	if(SDLGPUSHADERCROSS_SPIRVCROSS_SHARED)
 		target_link_libraries(${target} PRIVATE spirv-cross-c-shared)
+	else()
+		target_link_libraries(${target} PRIVATE spirv-cross-c)
 	endif()
-	if(SDLGPUSHADERCROSS_LINK_STATIC)
+	target_link_libraries(${target} PRIVATE DirectXShaderCompiler::dxcompiler)
+	if(NOT SDLGPUSHADERCROSS_SPIRVCROSS_SHARED)
 		# spirv-cross uses C++
 		set_property(TARGET ${target} PROPERTY LINKER_LANGUAGE CXX)
 	endif()
@@ -212,7 +243,6 @@ if(SDLGPUSHADERCROSS_CLI)
 endif()
 
 if(SDLGPUSHADERCROSS_INSTALL)
-	include(GNUInstallDirs)
 	if(WIN32 AND NOT MINGW)
 		set(INSTALL_CMAKEDIR_ROOT_DEFAULT "cmake")
 	else()
@@ -288,18 +318,27 @@ if(SDLGPUSHADERCROSS_INSTALL)
 		DESTINATION "${SDLGPUSHADERCROSS_INSTALL_CMAKEDIR}"
 		COMPONENT devel
 	)
+	if(NOT SDLGPUSHADERCROSS_VENDORED)
+		install(
+			FILES
+				"cmake/sdlcpu.cmake"
+				"cmake/FindDirectXShaderCompiler.cmake"
+			DESTINATION "${SDLGPUSHADERCROSS_INSTALL_CMAKEDIR}"
+			COMPONENT devel
+		)
+	endif()
 
 	file(RELATIVE_PATH SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG "${CMAKE_INSTALL_PREFIX}/${SDLGPUSHADERCROSS_PKGCONFIG_INSTALLDIR}" "${CMAKE_INSTALL_PREFIX}")
 	string(REGEX REPLACE "[/]+$" "" SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG "${SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG}")
 	set(SDL_PKGCONFIG_PREFIX "\${pcfiledir}/${SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG}")
 	if(NOT SDLGPUSHADERCROSS_VENDORED)
-		if(SDLGPUSHADERCROSS_LINK_STATIC)
-			set(PC_REQUIRES "spirv-cross-c")
-		else()
+		if(SDLGPUSHADERCROSS_SPIRVCROSS_SHARED)
 			set(PC_REQUIRES "spirv-cross-c-shared")
+		else()
+			set(PC_REQUIRES "spirv-cross-c")
 		endif()
 	endif()
-	set(PC_LIBS "")
+	set(PC_LIBS "-ldxcompiler")
 	configure_file(cmake/sdl3-gpu-shadercross.pc.in sdl3-gpu-shadercross.pc @ONLY)
 
 	# Always install sdl3-gpu-shadercross.pc file: libraries might be different between config modes
@@ -330,7 +369,7 @@ set(DXC_LINUX_X64_HASH "SHA256=b58725ac191df0686994fb9d54d27ee8dd3f180b023d56273
 set(DXC_WINDOWS_X86_X64_ARM64_URL "https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.8.2407/dxc_2024_07_31.zip")
 set(DXC_WINDOWS_X86_X64_ARM64_HASH "SHA256=e2627f004f0f9424d8c71ea1314d04f38c5a5096884ae9217f1f18bd320267b5")
 
-if(SDLGPUSHADERCROSS_INSTALL_DEPS)
+if(SDLGPUSHADERCROSS_INSTALL_RUNTIME)
 	set(chmod_0755 OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
 	if(APPLE)
 		set(rpath_origin "@executable_path")
@@ -338,6 +377,13 @@ if(SDLGPUSHADERCROSS_INSTALL_DEPS)
 		set(rpath_origin "\$ORIGIN")
 	endif()
 
+	if(NOT SDLGPUSHADERCROSS_VENDORED)
+		install(IMPORTED_RUNTIME_ARTIFACTS DirectXShaderCompiler::dxcompiler DirectXShaderCompiler::dxil RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
+		if(SDLGPUSHADERCROSS_SPIRVCROSS_SHARED)
+			install(IMPORTED_RUNTIME_ARTIFACTS spirv-cross-c-shared RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
+		endif()
+	endif()
+
 	if(TARGET shadercross)
 		file(RELATIVE_PATH bin_to_lib "${CMAKE_INSTALL_FULL_BINDIR}" "${CMAKE_INSTALL_FULL_LIBDIR}")
 		set_property(TARGET shadercross PROPERTY INSTALL_RPATH "${rpath_origin}/${bin_to_lib}")
@@ -347,41 +393,7 @@ if(SDLGPUSHADERCROSS_INSTALL_DEPS)
 	if(SDLGPUSHADERCROSS_CLI AND NOT SDLGPUSHADERCROSS_CLI_STATIC)
 		install(IMPORTED_RUNTIME_ARTIFACTS SDL3::SDL3-shared RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
 	endif()
-
-	# Download and install prebuilt dxil and dxcompiler shared libraries
 	include(ExternalProject)
-	if(LINUX AND SDL_CPU_X64)
-		ExternalProject_Add(dxc
-			URL					"${DXC_LINUX_X64_URL}"
-			URL_HASH			"${DXC_LINUX_X64_HASH}"
-			DOWNLOAD_EXTRACT_TIMESTAMP "1"
-			CONFIGURE_COMMAND 	""
-			BUILD_COMMAND	 	""
-			INSTALL_COMMAND	 	""
-		)
-		ExternalProject_Get_property(dxc SOURCE_DIR)
-		install(FILES "${SOURCE_DIR}/lib/libdxcompiler.so" "${SOURCE_DIR}/lib/libdxil.so" DESTINATION "${CMAKE_INSTALL_LIBDIR}" PERMISSIONS ${chmod_0755})
-		install(FILES "${SOURCE_DIR}/LICENSE-LLVM.txt" "${SOURCE_DIR}/LICENSE-MS.txt" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/licenses/dxc")
-	elseif(WINDOWS AND (SDL_CPU_ARM64 OR SDL_CPU_X86 OR SDL_CPU_X64))
-		ExternalProject_Add(dxc
-			URL					"${DXC_WINDOWS_X86_X64_ARM64_URL}"
-			URL_HASH			"${DXC_WINDOWS_X86_X64_ARM64_HASH}"
-			DOWNLOAD_EXTRACT_TIMESTAMP "1"
-			CONFIGURE_COMMAND 	""
-			BUILD_COMMAND	 	""
-			INSTALL_COMMAND	 	""
-		)
-		if(SDL_CPU_ARM64)
-			set(arch_dir "arm64")
-		elseif(SDL_CPU_X86)
-			set(arch_dir "x86")
-		elseif(SDL_CPU_X64)
-			set(arch_dir "x64")
-		endif()
-		ExternalProject_Get_property(dxc SOURCE_DIR)
-		install(FILES "${SOURCE_DIR}/bin/${arch_dir}/dxcompiler.dll" "${SOURCE_DIR}/bin/${arch_dir}/dxil.dll" DESTINATION "${CMAKE_INSTALL_BINDIR}" PERMISSIONS ${chmod_0755})
-		install(FILES "${SOURCE_DIR}/LICENSE-LLVM.txt" "${SOURCE_DIR}/LICENSE-MS.txt" "${SOURCE_DIR}/LICENSE-MIT.txt" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/licenses/dxc")
-	endif()
 
 	if(NOT WIN32)
 		ExternalProject_Add(spirv_headers
diff --git a/build-scripts/download-prebuilt-DirectXShaderCompiler.cmake b/build-scripts/download-prebuilt-DirectXShaderCompiler.cmake
new file mode 100644
index 0000000..31463ec
--- /dev/null
+++ b/build-scripts/download-prebuilt-DirectXShaderCompiler.cmake
@@ -0,0 +1,47 @@
+set(DXC_LINUX_X64_URL "https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.8.2407/linux_dxc_2024_07_31.x86_64.tar.gz")
+set(DXC_LINUX_X64_HASH "SHA256=b58725ac191df0686994fb9d54d27ee8dd3f180b023d562733112a499ea1195c")
+set(DXC_WINDOWS_X86_X64_ARM64_URL "https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.8.2407/dxc_2024_07_31.zip")
+set(DXC_WINDOWS_X86_X64_ARM64_HASH "SHA256=e2627f004f0f9424d8c71ea1314d04f38c5a5096884ae9217f1f18bd320267b5")
+
+get_filename_component(EXTERNAL_PATH "${CMAKE_CURRENT_LIST_DIR}/../external" ABSOLUTE)
+set(DXC_ROOT "${EXTERNAL_PATH}/DirectXShaderCompiler-binaries")
+
+set(DOWNLOAD_LINUX ON)
+set(DOWNLOAD_WINDOWS ON)
+if(DEFINED CMAKE_SYSTEM_NAME)
+    if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
+        set(DOWNLOAD_Linux OFF)
+    endif()
+    if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows")
+        set(DOWNLOAD_WINDOWS OFF)
+    endif()
+endif()
+
+if(DOWNLOAD_LINUX)
+    include(FetchContent)
+    FetchContent_Populate(
+        dxc_linux
+        URL  "${DXC_LINUX_X64_URL}"
+        URL_HASH  "${DXC_LINUX_X64_HASH}"
+        SOURCE_DIR "${DXC_ROOT}/linux"
+    )
+endif()
+
+if(DOWNLOAD_WINDOWS)
+    include(FetchContent)
+    FetchContent_Populate(
+        dxc_windows
+        URL  "${DXC_WINDOWS_X86_X64_ARM64_URL}"
+        URL_HASH  "${DXC_WINDOWS_X86_X64_ARM64_HASH}"
+        SOURCE_DIR "${DXC_ROOT}/windows"
+    )
+endif()
+
+message("To make use of the prebuilt DirectXShaderCompiler libraries, configure with:")
+message("")
+message("  -DSDLGPUSHADERCROSS_VENDORED=OFF")
+message("")
+message("and")
+message("")
+message("  -DDirectXShaderCompiler_ROOT=\"${DXC_ROOT}\"")
+message("")
diff --git a/cmake/FindDirectXShaderCompiler.cmake b/cmake/FindDirectXShaderCompiler.cmake
new file mode 100644
index 0000000..788805c
--- /dev/null
+++ b/cmake/FindDirectXShaderCompiler.cmake
@@ -0,0 +1,60 @@
+set(required_vars)
+
+if(WIN32)
+    find_path(DirectXShaderCompiler_INCLUDE_PATH NAMES "dxcapi.h" PATH_SUFFIXES "inc" "windows/inc" HINTS ${DirectXShaderCompiler_ROOT})
+    if(SDL_CPU_ARM64)
+        set(extra_bin_suffix "bin/arm64" "windows/bin/arm64")
+        set(extra_lib_suffix "lib/arm64" "windows/lib/arm64")
+    elseif(SDL_CPU_X86)
+        set(extra_bin_suffix "bin/x86" "windows/bin/x86")
+        set(extra_lib_suffix "lib/x86" "windows/lib/x86")
+    elseif(SDL_CPU_X64)
+        set(extra_bin_suffix "bin/x64" "windows/bin/x64")
+        set(extra_lib_suffix "lib/x64" "windows/lib/x64")
+    endif()
+    find_file(DirectXShaderCompiler_dxcompiler_BINARY NAMES "dxcompiler.dll" PATH_SUFFIXES "bin" ${extra_bin_suffix} HINTS ${DirectXShaderCompiler_ROOT})
+    find_library(DirectXShaderCompiler_dxcompiler_LIBRARY NAMES "dxcompiler" "dxcompiler.lib" PATH_SUFFIXES "lib" ${extra_lib_suffix} HINTS ${DirectXShaderCompiler_ROOT})
+    find_file(DirectXShaderCompiler_dxil_BINARY NAMES "dxil.dll" PATH_SUFFIXES "bin" ${extra_bin_suffix} HINTS ${DirectXShaderCompiler_ROOT})
+    set(required_vars
+        DirectXShaderCompiler_INCLUDE_PATH
+        DirectXShaderCompiler_dxcompiler_BINARY
+        DirectXShaderCompiler_dxcompiler_LIBRARY
+        DirectXShaderCompiler_dxil_BINARY
+    )
+else()
+    find_path(DirectXShaderCompiler_INCLUDE_PATH NAMES "dxcapi.h" PATH_SUFFIXES "include" "include/dxc" "linux/include" "linux/include/dxc")
+    find_library(DirectXShaderCompiler_dxcompiler_LIBRARY NAMES "dxcompiler" PATH_SUFFIXES "lib" "linux/lib" HINTS ${DirectXShaderCompiler_ROOT})
+    find_library(DirectXShaderCompiler_dxil_LIBRARY NAMES "dxil" PATH_SUFFIXES "lib" "linux/lib" HINTS ${DirectXShaderCompiler_ROOT})
+    set(required_vars
+        DirectXShaderCompiler_INCLUDE_PATH
+        DirectXShaderCompiler_dxcompiler_LIBRARY
+        DirectXShaderCompiler_dxil_LIBRARY
+    )
+endif()
+
+include(FindPackageHandleStandardArgs)
+
+find_package_handle_standard_args(DirectXShaderCompiler
+    REQUIRED_VARS ${required_vars}
+)
+
+if(DirectXShaderCompiler_FOUND)
+    if(NOT TARGET DirectXShaderCompiler::dxcompiler)
+        add_library(DirectXShaderCompiler::dxcompiler IMPORTED SHARED)
+        set_property(TARGET DirectXShaderCompiler::dxcompiler PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${DirectXShaderCompiler_INCLUDE_PATH}")
+        if(WIN32)
+            set_property(TARGET DirectXShaderCompiler::dxcompiler PROPERTY IMPORTED_LOCATION "${DirectXShaderCompiler_dxcompiler_BINARY}")
+            set_property(TARGET DirectXShaderCompiler::dxcompiler PROPERTY IMPORTED_IMPLIB "${DirectXShaderCompiler_dxcompiler_LIBRARY}")
+        else()
+            set_property(TARGET DirectXShaderCompiler::dxcompiler PROPERTY IMPORTED_LOCATION "${DirectXShaderCompiler_dxcompiler_LIBRARY}")
+        endif()
+    endif()
+    if(NOT TARGET DirectXShaderCompiler::dxil)
+        add_library(DirectXShaderCompiler::dxil IMPORTED SHARED)
+        if(WIN32)
+            set_property(TARGET DirectXShaderCompiler::dxil PROPERTY IMPORTED_LOCATION "${DirectXShaderCompiler_dxil_BINARY}")
+        else()
+            set_property(TARGET DirectXShaderCompiler::dxil PROPERTY IMPORTED_LOCATION "${DirectXShaderCompiler_dxil_LIBRARY}")
+        endif()
+    endif()
+endif()
diff --git a/cmake/SDL3_gpu_shadercrossConfig.cmake.in b/cmake/SDL3_gpu_shadercrossConfig.cmake.in
index 9604323..846316c 100644
--- a/cmake/SDL3_gpu_shadercrossConfig.cmake.in
+++ b/cmake/SDL3_gpu_shadercrossConfig.cmake.in
@@ -6,11 +6,16 @@ set_package_properties(SDL3_gpu_shadercross PROPERTIES
     DESCRIPTION "Support SPIR-V and HLSL on various backends"
 )
 
+@PACKAGE_INIT@
+
+set(SDLGPUSHADERCROSS_VENDORED          @SDLGPUSHADERCROSS_VENDORED@)
+set(SDLGPUSHADERCROSS_SPIRVCROSS_SHARED @SDLGPUSHADERCROSS_SPIRVCROSS_SHARED@)
+
 set(SDL3_gpu_shadercross_FOUND ON)
 
-set(SDL3_gpu_SHADERCROSS_REQUIRED_VERSION  @SDL_REQUIRED_VERSION@)
+set(SDL3_gpu_SHADERCROSS_REQUIRED_VERSION @SDL_REQUIRED_VERSION@)
 
-if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL3_gpu_shadercross-vendored-targets.cmake")
+if(SDLGPUSHADERCROSS_VENDORED)
     include("${CMAKE_CURRENT_LIST_DIR}/SDL3_gpu_shadercross-vendored-targets.cmake")
 endif()
 
@@ -22,6 +27,29 @@ endif()
 
 set(SDL3_gpu_shadercross_SDL3_gpu_shadercross-static FALSE)
 if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL3_gpu_shadercross-static-targets.cmake")
+    if(NOT SDLGPUSHADERCROSS_VENDORED)
+        set(original_cmake_module_path "${CMAKE_MODULE_PATH}")
+        include(CMakeFindDependencyMacro)
+
+        if(SDLGPUSHADERCROSS_SPIRVCROSS_SHARED)
+            find_dependency(spirv_cross_c_shared REQUIRED)
+        else()
+            find_package(spirv_cross_core QUIET)
+            find_package(spirv_cross_glsl QUIET)
+            find_package(spirv_cross_hlsl QUIET)
+            find_package(spirv_cross_msl QUIET)
+            find_package(spirv_cross_cpp QUIET)
+            find_package(spirv_cross_reflect QUIET)
+            find_package(spirv_cross_c)
+        endif()
+
+        list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
+        include("${CMAKE_CURRENT_LIST_DIR}/sdlcpu.cmake")
+        SDL_DetectTargetCPUArchitectures(SDL_CPU_NAMES)
+        find_dependency(DirectXShaderCompiler)
+
+        set(CMAKE_MODULE_PATH "${original_cmake_module_path}")
+    endif()
     include("${CMAKE_CURRENT_LIST_DIR}/SDL3_gpu_shadercross-static-targets.cmake")
     set(SDL3_gpu_shadercross_SDL3_gpu_shadercross-static_FOUND TRUE)
 endif()
@@ -45,5 +73,4 @@ if(NOT TARGET SDL3_gpu_shadercross::SDL3_gpu_shadercross)
     endif()
 endif()
 
-@PACKAGE_INIT@
 check_required_components(SDL3_gpu_shadercross)
diff --git a/cmake/sdl3-gpu-shadercross.pc.in b/cmake/sdl3-gpu-shadercross.pc.in
index a61fbf0..65944c7 100644
--- a/cmake/sdl3-gpu-shadercross.pc.in
+++ b/cmake/sdl3-gpu-shadercross.pc.in
@@ -7,7 +7,7 @@ Name: @PROJECT_NAME@
 Description: Support SPIR-V and HLSL on various backends
 Version: @PROJECT_VERSION@
 Requires: sdl3 >= @SDL_REQUIRED_VERSION@
-Libs: -L${libdir} -lSDL3_gpu_shadercross
+Libs: -L${libdir} -Wl,-rpath,${libdir} -Wl,--enable-new-dtags -lSDL3_gpu_shadercross
 Requires.private: @PC_REQUIRES@
 Libs.private: @PC_LIBS@
 Cflags: -I${includedir}
diff --git a/external/DirectXShaderCompiler b/external/DirectXShaderCompiler
new file mode 160000
index 0000000..ac36a79
--- /dev/null
+++ b/external/DirectXShaderCompiler
@@ -0,0 +1 @@
+Subproject commit ac36a797d3470e8ee906b98457a59270d01db30d
diff --git a/external/SPIRV-Headers b/external/SPIRV-Headers
new file mode 160000
index 0000000..cb6b2c3
--- /dev/null
+++ b/external/SPIRV-Headers
@@ -0,0 +1 @@
+Subproject commit cb6b2c32dbfc3257c1e9142a116fe9ee3d9b80a2
diff --git a/external/SPIRV-Tools b/external/SPIRV-Tools
new file mode 160000
index 0000000..0243356
--- /dev/null
+++ b/external/SPIRV-Tools
@@ -0,0 +1 @@
+Subproject commit 02433568af277324e6d7fe4582b663f14165c563
diff --git a/src/SDL_gpu_shadercross.c b/src/SDL_gpu_shadercross.c
index 170356f..2be9df8 100644
--- a/src/SDL_gpu_shadercross.c
+++ b/src/SDL_gpu_shadercross.c
@@ -50,7 +50,6 @@ typedef void IDxcIncludeHandler; /* hack, unused */
 #ifdef DXCOMPILER_DLL
 #undef DXCOMPILER_DLL
 #endif
-#if defined(_WIN32)
 #if defined(_GAMING_XBOX_SCARLETT)
 #define DXCOMPILER_DLL "dxcompiler_xs.dll"
 #elif defined(_GAMING_XBOX_XBOXONE)
@@ -58,22 +57,6 @@ typedef void IDxcIncludeHandler; /* hack, unused */
 #else
 #define DXCOMPILER_DLL "dxcompiler.dll"
 #endif
-#elif defined(__APPLE__)
-#define DXCOMPILER_DLL "libdxcompiler.dylib"
-#else
-#define DXCOMPILER_DLL "libdxcompiler.so"
-#endif
-
-#ifdef DXIL_DLL
-#undef DXIL_DLL
-#endif
-#if defined(_WIN32)
-#define DXIL_DLL "dxil.dll"
-#elif defined(__APPLE__)
-#define DXIL_DLL "libdxil.dylib"
-#else
-#define DXIL_DLL "libdxil.so"
-#endif
 
 /* Unlike vkd3d-utils, libdxcompiler.so does not use msabi */
 #if !defined(_WIN32)
@@ -276,14 +259,16 @@ struct IDxcCompiler3
 /* *INDENT-ON* */ // clang-format on
 
 /* DXCompiler */
+#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
 static SDL_SharedObject *dxcompiler_dll = NULL;
-
+static DxcCreateInstanceProc SDL_DxcCreateInstance = NULL;
 typedef HRESULT(__stdcall *DxcCreateInstanceProc)(
     REFCLSID rclsid,
     REFIID riid,
     LPVOID *ppv);
-
-static DxcCreateInstanceProc SDL_DxcCreateInstance = NULL;
+#else
+HRESULT DxcCreateInstance(REFCLSID rclsid, REFIID riid, LPVOID *ppv);
+#endif
 
 static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
     const char *hlslSource,
@@ -312,9 +297,22 @@ static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
     /* Non-static DxcInstance, since the functions we call on it are not thread-safe */
     IDxcCompiler3 *dxcInstance = NULL;
 
-    SDL_DxcCreateInstance(&CLSID_DxcCompiler,
-                          IID_IDxcCompiler3,
-                          (void **)&dxcInstance);
+    #if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
+    if (SDL_DxcCreateInstance == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "DxcCreateInstance function not loaded. Did you forget to call Init?");
+        return NULL;
+    }
+    SDL_DxcCreateInstance(
+        &CLSID_DxcCompiler,
+        IID_IDxcCompiler3,
+        (void **)&dxcInstance);
+    #else
+    DxcCreateInstance(
+        &CLSID_DxcCompiler,
+        IID_IDxcCompiler3,
+        (void **)&dxcInstance);
+    #endif
+
     if (dxcInstance == NULL) {
         return NULL;
     }
@@ -338,7 +336,7 @@ static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
         args[argCount++] = (LPCWSTR)L"-spirv";
     }
 
-#ifdef _GAMING_XBOX
+#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
     args[argCount++] = L"-D__XBOX_DISABLE_PRECOMPILE=1";
 #endif
 
@@ -1547,22 +1545,8 @@ SDL_GPUComputePipeline *SDL_ShaderCross_CompileComputePipelineFromSPIRV(
 
 bool SDL_ShaderCross_Init(void)
 {
+    #if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
     dxcompiler_dll = SDL_LoadObject(DXCOMPILER_DLL);
-    if (dxcompiler_dll != NULL) {
-#ifndef _GAMING_XBOX
-        /* Try to load DXIL, we don't need it directly but if it doesn't exist the code will not be 

(Patch may be truncated, please check the link at the top of this post.)