├── .github ├── actions │ └── setup-ninja │ │ └── action.yml └── workflows │ └── main.yml ├── .gitignore ├── .gitmodules ├── .vscode └── settings.json ├── .wikiheaders-options ├── CMakeLists.txt ├── LICENSE.txt ├── README.txt ├── VisualC-GDK ├── SDL_shadercross.sln └── SDL_shadercross.vcxproj ├── build-scripts ├── download-prebuilt-DirectXShaderCompiler.cmake ├── test-versioning.sh └── wikiheaders.pl ├── cmake ├── CPackProjectConfig.cmake.in ├── FindDirectXShaderCompiler.cmake ├── GetGitRevisionDescription.cmake ├── GetGitRevisionDescription.cmake.in ├── PrivateSdlFunctions.cmake ├── SDL3_shadercrossConfig.cmake.in ├── sdl3-shadercross.pc.in ├── sdlcpu.cmake ├── sdlmanpages.cmake ├── sdlplatform.cmake └── test │ ├── CMakeLists.txt │ └── main.c ├── external ├── Get-GitModules.ps1 └── download.sh ├── include └── SDL3_shadercross │ └── SDL_shadercross.h └── src ├── SDL_shadercross.c ├── SDL_shadercross.sym ├── cli.c └── version.rc /.github/actions/setup-ninja/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Setup ninja' 2 | description: 'Download ninja and add it to the PATH environment variable' 3 | inputs: 4 | version: 5 | description: 'Ninja version' 6 | default: '1.12.1' 7 | runs: 8 | using: 'composite' 9 | steps: 10 | - name: 'Calculate variables' 11 | id: calc 12 | shell: sh 13 | run: | 14 | case "${{ runner.os }}-${{ runner.arch }}" in 15 | "Linux-X86" | "Linux-X64") 16 | archive="ninja-linux.zip" 17 | ;; 18 | "Linux-ARM64") 19 | archive="ninja-linux-aarch64.zip" 20 | ;; 21 | "macOS-X86" | "macOS-X64" | "macOS-ARM64") 22 | archive="ninja-mac.zip" 23 | ;; 24 | "Windows-X86" | "Windows-X64") 25 | archive="ninja-win.zip" 26 | ;; 27 | "Windows-ARM64") 28 | archive="ninja-winarm64.zip" 29 | ;; 30 | *) 31 | echo "Unsupported ${{ runner.os }}-${{ runner.arch }}" 32 | exit 1; 33 | ;; 34 | esac 35 | echo "archive=${archive}" >> ${GITHUB_OUTPUT} 36 | echo "cache-key=${archive}-${{ inputs.version }}-${{ runner.os }}-${{ runner.arch }}" >> ${GITHUB_OUTPUT} 37 | - name: 'Restore cached ${{ steps.calc.outputs.archive }}' 38 | id: cache-restore 39 | uses: actions/cache/restore@v4 40 | with: 41 | path: '${{ runner.temp }}/${{ steps.calc.outputs.archive }}' 42 | key: ${{ steps.calc.outputs.cache-key }} 43 | - name: 'Download ninja ${{ inputs.version }} for ${{ runner.os }} (${{ runner.arch }})' 44 | if: ${{ (!steps.cache-restore.outputs.cache-hit || steps.cache-restore.outputs.cache-hit == 'false') }} 45 | shell: pwsh 46 | run: | 47 | Invoke-WebRequest "https://github.com/ninja-build/ninja/releases/download/v${{ inputs.version }}/${{ steps.calc.outputs.archive }}" -OutFile "${{ runner.temp }}/${{ steps.calc.outputs.archive }}" 48 | - name: 'Cache ${{ steps.calc.outputs.archive }}' 49 | if: ${{ (!steps.cache-restore.outputs.cache-hit || steps.cache-restore.outputs.cache-hit == 'false') }} 50 | uses: actions/cache/save@v4 51 | with: 52 | path: '${{ runner.temp }}/${{ steps.calc.outputs.archive }}' 53 | key: ${{ steps.calc.outputs.cache-key }} 54 | - name: 'Extract ninja' 55 | shell: pwsh 56 | run: | 57 | 7z "-o${{ runner.temp }}/ninja-${{ inputs.version }}-${{ runner.arch }}" x "${{ runner.temp }}/${{ steps.calc.outputs.archive }}" 58 | - name: 'Set output variables' 59 | id: final 60 | shell: pwsh 61 | run: | 62 | echo "${{ runner.temp }}/ninja-${{ inputs.version }}-${{ runner.arch }}" >> $env:GITHUB_PATH 63 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | Build: 7 | name: ${{ matrix.platform.name }} 8 | runs-on: ${{ matrix.platform.os }} 9 | container: ${{ matrix.platform.container }} 10 | 11 | defaults: 12 | run: 13 | shell: ${{ matrix.platform.shell }} 14 | 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | platform: 19 | - { name: Windows (MSVC), os: windows-2019, build-spirv-cross: true, vendored: false, shell: sh, msvc: true, artifact: 'SDL3_shadercross-VC-x64' } 20 | - { 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_shadercross-mingw64' } 21 | - { name: Ubuntu 22.04, os: ubuntu-22.04, build-spirv-cross: true, vendored: false, shell: sh, artifact: 'SDL3_shadercross-linux-x64' } 22 | - { name: Steam Linux Runtime (Sniper), os: ubuntu-latest, build-spirv-cross: false, vendored: true, shell: sh, artifact: 'SDL3_shadercross-slrsniper', container: 'registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest' } 23 | - { name: macOS, os: macos-latest, build-spirv-cross: true, vendored: true, shell: sh, artifact: 'SDL3_shadercross-macos-arm64', cmake-arguments: '-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DCMAKE_C_FLAGS="-mmacosx-version-min=11.0" -DCMAKE_CXX_FLAGS="-mmacosx-version-min=11.0"' } 24 | 25 | steps: 26 | - uses: actions/checkout@v4 27 | with: 28 | submodules: recursive 29 | - name: Set up Ninja 30 | uses: ./.github/actions/setup-ninja 31 | if: ${{ !contains(matrix.platform.shell, 'msys2') && !contains(matrix.platform.container, 'steamrt') }} 32 | - uses: ilammy/msvc-dev-cmd@v1 33 | if: ${{ matrix.platform.msvc }} 34 | with: 35 | arch: x64 36 | - name: Set up MSYS2 37 | if: ${{ matrix.platform.shell == 'msys2 {0}' }} 38 | uses: msys2/setup-msys2@v2 39 | with: 40 | msystem: ${{ matrix.platform.msystem }} 41 | install: >- 42 | ${{ matrix.platform.msys-env }}-cmake 43 | ${{ matrix.platform.msys-env }}-gcc 44 | ${{ matrix.platform.msys-env }}-ninja 45 | ${{ (!matrix.platform.vendored && format('{0}-spirv-cross', matrix.platform.msys-env)) || '' }} 46 | - name: Set up SDL 47 | id: sdl 48 | uses: libsdl-org/setup-sdl@main 49 | with: 50 | cmake-arguments: ${{ matrix.platform.cmake-arguments }} 51 | cmake-generator: Ninja 52 | version: 3-head 53 | sdl-test: true 54 | shell: ${{ matrix.platform.shell }} 55 | discriminator: ${{ matrix.platform.artifact }} 56 | - name: Install Linux requirements 57 | if: ${{ contains(matrix.platform.os, 'ubuntu') }} 58 | run: | 59 | # patchelf is needed to fix the runpath of libSDL3.so.0 60 | wget https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0-x86_64.tar.gz 61 | tar xf patchelf-0.18.0-x86_64.tar.gz ./bin/patchelf 62 | echo "${PWD}/bin" >>$GITHUB_PATH 63 | 64 | # libxrandr-dev is needed by vulkan-loader 65 | # libjson-perl is a (build-time) dependency of vkd3d 3.16+ 66 | sudo apt-get update -y 67 | sudo apt-get install -y patchelf libxrandr-dev libjson-perl 68 | - name: Install macOS requirements 69 | if: ${{ runner.os == 'macOS' }} 70 | run: | 71 | # bison is needed by vkd3d 72 | # perl-json is needed by vkd3d 1.16+ 73 | brew install bison cpanm 74 | echo "/opt/homebrew/opt/bison/bin" >>$GITHUB_PATH 75 | cpanm install JSON 76 | - name: Download DirectXShaderCompiler binaries 77 | if: ${{ !matrix.platform.vendored && runner.os != 'macOS' }} 78 | run: | 79 | cmake -P build-scripts/download-prebuilt-DirectXShaderCompiler.cmake 80 | echo "DirectXShaderCompiler_ROOT=${PWD}/external/DirectXShaderCompiler-binaries" >>${GITHUB_ENV} 81 | - name: Build SPIRV-Cross 82 | if: ${{ matrix.platform.build-spirv-cross }} 83 | run: | 84 | cmake -S external/SPIRV-Cross -B spirv_cross_build -GNinja \ 85 | -DCMAKE_BUILD_TYPE=Release \ 86 | -DSPIRV_CROSS_SHARED=ON \ 87 | -DSPIRV_CROSS_STATIC=ON \ 88 | -DCMAKE_INSTALL_PREFIX=${PWD}/spirv_cross_prefix \ 89 | ${{ matrix.platform.cmake-arguments }} 90 | cmake --build spirv_cross_build 91 | cmake --install spirv_cross_build 92 | 93 | spirv_cross_prefix=${PWD}/spirv_cross_prefix 94 | if test "x${{ (matrix.platform.msvc && 'msvc') || '' }}" = "xmsvc"; then 95 | spirv_cross_prefix=$(cygpath -w "${spirv_cross_prefix}") 96 | fi 97 | joiner="${{ (runner.os == 'Windows' && ';') || ':' }}" 98 | echo "spirv_cross_c_shared_ROOT=${spirv_cross_prefix}${joiner}${spirv_cross_prefix}/share/spirv_cross_c_shared" >>${GITHUB_ENV} 99 | - name: Configure (CMake) 100 | run: | 101 | cmake -S . -B build -GNinja \ 102 | -DCMAKE_BUILD_TYPE=Release \ 103 | -DSDLSHADERCROSS_SHARED=ON \ 104 | -DSDLSHADERCROSS_STATIC=ON \ 105 | -DSDLSHADERCROSS_VENDORED=${{ matrix.platform.vendored }} \ 106 | -DSDLSHADERCROSS_CLI=ON \ 107 | -DSDLSHADERCROSS_WERROR=ON \ 108 | -DSDLSHADERCROSS_INSTALL=ON \ 109 | -DSDLSHADERCROSS_INSTALL_RUNTIME=ON \ 110 | -DSDLSHADERCROSS_INSTALL_CPACK=ON \ 111 | -DSDLSHADERCROSS_INSTALL_MAN=ON \ 112 | -DCMAKE_INSTALL_PREFIX="${PWD}/prefix" \ 113 | ${{ matrix.platform.cmake-arguments }} 114 | 115 | - name: Build (CMake) 116 | id: build 117 | run: | 118 | cmake --build build --config Release --parallel --verbose 119 | - name: Install (CMake) 120 | id: install 121 | if: ${{ always() && steps.build.outcome == 'success' }} 122 | run: | 123 | cmake --install build/ --config Release 124 | echo "SDL3_shadercross_ROOT=${PWD}/prefix" >>${GITHUB_ENV} 125 | - name: Package (CPack) 126 | id: package 127 | if: ${{ always() && steps.build.outcome == 'success' }} 128 | run: | 129 | cmake --build build/ --target package 130 | 131 | - name: Verify CMake configuration files 132 | if: ${{ always() && steps.install.outcome == 'success' }} 133 | run: | 134 | cmake -S cmake/test -B cmake_config_build -GNinja \ 135 | -DCMAKE_BUILD_TYPE=Release \ 136 | ${{ matrix.platform.cmake-arguments }} 137 | cmake --build cmake_config_build --verbose 138 | 139 | - uses: actions/upload-artifact@v4 140 | if: ${{ always() && steps.package.outcome == 'success' }} 141 | with: 142 | if-no-files-found: error 143 | name: ${{ matrix.platform.artifact }} 144 | path: build/dist/SDL* 145 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | /external/DirectXShaderCompiler-binaries 3 | dxc_linux-build 4 | dxc_linux-subbuild 5 | dxc_windows-build 6 | dxc_windows-subbuild 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "spirv-cross"] 2 | path = external/SPIRV-Cross 3 | url = https://github.com/KhronosGroup/SPIRV-Cross.git 4 | branch = main 5 | [submodule "spirv-headers"] 6 | path = external/SPIRV-Headers 7 | url = https://github.com/KhronosGroup/SPIRV-Headers.git 8 | branch = main 9 | [submodule "spirv-tools"] 10 | path = external/SPIRV-Tools 11 | url = https://github.com/KhronosGroup/SPIRV-Tools.git 12 | branch = main 13 | [submodule "DirectXShaderCompiler"] 14 | path = external/DirectXShaderCompiler 15 | url = https://github.com/microsoft/DirectXShaderCompiler.git 16 | branch = main 17 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "sdl_shadercross.h": "c", 4 | "iterator": "c", 5 | "initializer_list": "c", 6 | "utility": "c", 7 | "xutility": "c" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.wikiheaders-options: -------------------------------------------------------------------------------- 1 | projectfullname = SDL_shadercross 2 | projectshortname = SDL_shadercross 3 | incsubdir = include/SDL3_shadercross 4 | wikisubdir = SDL_shadercross 5 | apiprefixregex = SDL_ShaderCross_ 6 | mainincludefname = SDL3_shadercross/SDL_shadercross.h 7 | versionfname = include/SDL3_shadercross/SDL_shadercross.h 8 | versionmajorregex = \A\#define\s+SDL_SHADERCROSS_MAJOR_VERSION\s+(\d+)\Z 9 | versionminorregex = \A\#define\s+SDL_SHADERCROSS_MINOR_VERSION\s+(\d+)\Z 10 | versionmicroregex = \A\#define\s+SDL_SHADERCROSS_MICRO_VERSION\s+(\d+)\Z 11 | selectheaderregex = \ASDL_shadercross\.h\Z 12 | projecturl = https://libsdl.org/projects/SDL_shadercross 13 | wikiurl = https://wiki.libsdl.org/SDL_shadercross 14 | bugreporturl = https://github.com/libsdl-org/sdlwiki/issues/new 15 | warn_about_missing = 0 16 | wikipreamble = (This function is part of SDL_shadercross, a separate library from SDL.) 17 | wikiheaderfiletext = Defined in [](https://github.com/libsdl-org/SDL_shadercross/blob/main/include/SDL3_shadercross/%fname%) 18 | manpageheaderfiletext = Defined in SDL3_shadercross/%fname% 19 | quickrefenabled = 1 20 | quickreftitle = SDL3_shadercross API Quick Reference 21 | quickrefurl = https://libsdl.org/ 22 | quickrefdesc = The latest version of this document can be found at https://wiki.libsdl.org/SDL3_shadercross/QuickReference 23 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake Project for SDL3_shadercross - Simple DirectMedia Layer Shader Cross Compiler 2 | # Written by @thatcosmonaut 3 | cmake_minimum_required(VERSION 3.22) 4 | 5 | # Version 6 | set(MAJOR_VERSION 3) 7 | set(MINOR_VERSION 0) 8 | set(MICRO_VERSION 0) 9 | set(SDL_REQUIRED_VERSION "3.1.3") 10 | 11 | # option() honors normal variables. 12 | set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) 13 | 14 | project(SDL3_shadercross LANGUAGES C VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}") 15 | 16 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 17 | 18 | include(CMakeDependentOption) 19 | include("${CMAKE_CURRENT_LIST_DIR}/cmake/GetGitRevisionDescription.cmake") 20 | include("${CMAKE_CURRENT_LIST_DIR}/cmake/PrivateSdlFunctions.cmake") 21 | include("${CMAKE_CURRENT_LIST_DIR}/cmake/sdlcpu.cmake") 22 | include("${CMAKE_CURRENT_LIST_DIR}/cmake/sdlplatform.cmake") 23 | include("${CMAKE_CURRENT_LIST_DIR}/cmake/sdlmanpages.cmake") 24 | 25 | if(NOT TARGET SDL3::SDL3-static) 26 | find_package(SDL3 ${SDL_REQUIRED_VERSION}) 27 | endif() 28 | 29 | if(BUILD_SHARED_LIBS) 30 | set(SDLSHADERCROSS_SHARED_DEFAULT ON) 31 | set(SDLSHADERCROSS_STATIC_DEFAULT OFF) 32 | else() 33 | set(SDLSHADERCROSS_SHARED_DEFAULT OFF) 34 | set(SDLSHADERCROSS_STATIC_DEFAULT ON) 35 | endif() 36 | 37 | # Options 38 | option(SDLSHADERCROSS_DXC "Enable HLSL compilation via DXC" ON) 39 | option(SDLSHADERCROSS_SHARED "Build shared SDL_shadercross library" ${SDLSHADERCROSS_SHARED_DEFAULT}) 40 | option(SDLSHADERCROSS_STATIC "Build static SDL_shadercross library" ${SDLSHADERCROSS_STATIC_DEFAULT}) 41 | option(SDLSHADERCROSS_SPIRVCROSS_SHARED "Link to shared library variants of dependencies" ON) 42 | option(SDLSHADERCROSS_VENDORED "Use vendored dependencies" OFF) 43 | option(SDLSHADERCROSS_CLI "Build command line executable" ON) 44 | cmake_dependent_option(SDLSHADERCROSS_CLI_STATIC "Link CLI with static libraries" OFF "SDLSHADERCROSS_CLI;SDLSHADERCROSS_STATIC;TARGET SDL3::SDL3-static" OFF) 45 | cmake_dependent_option(SDLSHADERCROSS_CLI_LEAKCHECK "Check shadercross for memory leaks" OFF "SDLSHADERCROSS_CLI;TARGET SDL3::SDL3_test" OFF) 46 | option(SDLSHADERCROSS_WERROR "Enable Werror" OFF) 47 | option(SDLSHADERCROSS_INSTALL "Enable installation" OFF) 48 | cmake_dependent_option(SDLSHADERCROSS_INSTALL_CPACK "Enable CPack installation" OFF "SDLSHADERCROSS_INSTALL" OFF) 49 | cmake_dependent_option(SDLSHADERCROSS_INSTALL_MAN "Install man pages for SDL3_shadercross" OFF "SDLSHADERCROSS_INSTALL" OFF) 50 | cmake_dependent_option(SDLSHADERCROSS_INSTALL_RUNTIME "Download, build and install runtime dependencies" OFF "SDLSHADERCROSS_INSTALL" OFF) 51 | 52 | sdl_calculate_derived_version_variables(${MAJOR_VERSION} ${MINOR_VERSION} ${MICRO_VERSION}) 53 | SDL_DetectTargetCPUArchitectures(SDL_CPU_NAMES) 54 | SDL_DetectCMakePlatform() 55 | 56 | if(SDLSHADERCROSS_INSTALL) 57 | include(GNUInstallDirs) 58 | endif() 59 | 60 | if(NOT SDLSHADERCROSS_SHARED AND NOT SDLSHADERCROSS_STATIC) 61 | message(FATAL_ERROR "SDLSHADERCROSS_SHARED and SDLSHADERCROSS_STATIC cannot be both disabled") 62 | endif() 63 | 64 | # Platform Flags 65 | if(APPLE) 66 | set(CMAKE_MACOSX_RPATH ON) 67 | set(CMAKE_OSX_DEPLOYMENT_TARGET 11.0) 68 | endif() 69 | 70 | if(NOT MSVC) 71 | add_compile_options(-pedantic) # -Wno-strict-aliasing 72 | endif() 73 | 74 | 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) 75 | 76 | set(pc_requires ) 77 | set(vendored_targets ) 78 | if(SDLSHADERCROSS_VENDORED) 79 | set(SPIRV_CROSS_SKIP_INSTALL ON) 80 | set(SPIRV_CROSS_CLI OFF) 81 | set(SPIRV_CROSS_ENABLE_TESTS OFF) 82 | if(SDLSHADERCROSS_SPIRVCROSS_SHARED) 83 | set(SPIRV_CROSS_SHARED ON) 84 | set(SPIRV_CROSS_STATIC OFF) 85 | else() 86 | set(SPIRV_CROSS_SHARED OFF) 87 | set(SPIRV_CROSS_STATIC ON) 88 | endif() 89 | 90 | sdl_check_project_in_subfolder(external/SPIRV-Cross SPIRV-Cross SDLSHADERCROSS_VENDORED) 91 | set(SPIRV_CROSS_ENABLE_TESTS ON) 92 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) 93 | add_subdirectory(external/SPIRV-Cross EXCLUDE_FROM_ALL) 94 | 95 | if(SDLSHADERCROSS_SPIRVCROSS_SHARED) 96 | list(APPEND vendored_targets spirv-cross-c-shared) 97 | list(APPEND pc_requires "spirv-cross-c-shared") 98 | else() 99 | enable_language(CXX) 100 | if(SDLSHADERCROSS_STATIC) 101 | foreach(extra IN LISTS spirv_static_targets) 102 | if(TARGET ${extra}) 103 | list(APPEND vendored_targets ${extra}) 104 | list(APPEND pc_requires "${extra}") 105 | endif() 106 | endforeach() 107 | endif() 108 | endif() 109 | 110 | sdl_check_project_in_subfolder(external/SPIRV-Headers SPIRV-Headers SDLSHADERCROSS_VENDORED) 111 | add_subdirectory(external/SPIRV-Headers EXCLUDE_FROM_ALL) 112 | sdl_check_project_in_subfolder(external/SPIRV-Tools SPIRV-Tools SDLSHADERCROSS_VENDORED) 113 | add_subdirectory(external/SPIRV-Tools EXCLUDE_FROM_ALL) 114 | 115 | sdl_check_project_in_subfolder(external/DirectXShaderCompiler DirectXShaderCompiler SDLSHADERCROSS_VENDORED) 116 | if(MINGW) 117 | set(CMAKE_C_COMPILER_ARCHITECTURE_ID "${SDL_CPU_NAMES}") 118 | endif() 119 | 120 | if(SDLSHADERCROSS_DXC) 121 | # LLVM dependencies of dxc does not support building as a shared library 122 | set(BUILD_SHARED_LIBS OFF) 123 | # Enabling HLSL_ENABLE_DEBUG_ITERATORS blocks DirectXShaderCompiler from adding /D_ITERATOR_DEBUG_LEVEL=0 124 | set(HLSL_ENABLE_DEBUG_ITERATORS ON) 125 | set(DXC_COVERAGE OFF) 126 | set(HLSL_INCLUDE_TESTS OFF) 127 | set(LLVM_INCLUDE_TESTS OFF) 128 | set(HLSL_DISABLE_SOURCE_GENERATION TRUE) 129 | include(external/DirectXShaderCompiler/cmake/caches/PredefinedParams.cmake) 130 | add_subdirectory(external/DirectXShaderCompiler EXCLUDE_FROM_ALL) 131 | add_library(DirectXShaderCompiler::dxcompiler ALIAS dxcompiler) 132 | add_library(DirectXShaderCompiler::dxil ALIAS dxildll) 133 | list(APPEND vendored_targets dxcompiler dxildll) 134 | add_dependencies(dxcompiler dxildll) 135 | endif() 136 | 137 | export(TARGETS ${vendored_targets} NAMESPACE "SDL3_shadercross::" FILE "SDL3_shadercross-vendored-targets.cmake") 138 | else() 139 | if(SDLSHADERCROSS_SPIRVCROSS_SHARED) 140 | if(NOT TARGET spirv_cross_c_shared) 141 | find_package(spirv_cross_c_shared REQUIRED) 142 | endif() 143 | else() 144 | enable_language(CXX) 145 | if(NOT TARGET spirv_cross_c) 146 | find_package(spirv_cross_core QUIET) 147 | find_package(spirv_cross_glsl QUIET) 148 | find_package(spirv_cross_hlsl QUIET) 149 | find_package(spirv_cross_msl QUIET) 150 | find_package(spirv_cross_cpp QUIET) 151 | find_package(spirv_cross_reflect QUIET) 152 | find_package(spirv_cross_c REQUIRED) 153 | endif() 154 | endif() 155 | 156 | if(SDLSHADERCROSS_DXC) 157 | set(DirectXShaderCompiler_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/external/DirectXShaderCompiler-binaries") 158 | find_package(DirectXShaderCompiler REQUIRED) 159 | endif() 160 | endif() 161 | 162 | # Source lists 163 | set(SOURCE_FILES 164 | # Public Headers 165 | include/SDL3_shadercross/SDL_shadercross.h 166 | # Source Files 167 | src/SDL_shadercross.c 168 | ) 169 | 170 | set(SDL3_shadercross_targets) 171 | if(SDLSHADERCROSS_SHARED) 172 | list(APPEND SDL3_shadercross_targets SDL3_shadercross-shared) 173 | if(NOT TARGET SDL3::Headers OR NOT TARGET SDL3::SDL3-shared) 174 | find_package(SDL3 ${SDL_REQUIRED_VERSION} REQUIRED COMPONENTS Headers SDL3-shared) 175 | endif() 176 | 177 | add_library(SDL3_shadercross-shared SHARED ${SOURCE_FILES}) 178 | add_library(SDL3_shadercross::SDL3_shadercross ALIAS SDL3_shadercross-shared) 179 | 180 | set_property(TARGET SDL3_shadercross-shared PROPERTY DEFINE_SYMBOL DLL_EXPORT) 181 | sdl_target_link_option_version_file(SDL3_shadercross-shared "${CMAKE_CURRENT_SOURCE_DIR}/src/SDL_shadercross.sym") 182 | sdl_target_link_options_no_undefined(SDL3_shadercross-shared) 183 | 184 | # Build flags 185 | if(WIN32) 186 | target_sources(SDL3_shadercross-shared PRIVATE "src/version.rc") 187 | set_property(TARGET SDL3_shadercross-shared PROPERTY PREFIX "") 188 | endif() 189 | 190 | # SDL3_shadercross folders as includes, for other targets to consume 191 | target_include_directories(SDL3_shadercross-shared PUBLIC "$") 192 | target_include_directories(SDL3_shadercross-shared PUBLIC "$") 193 | 194 | # Soname 195 | set_target_properties(SDL3_shadercross-shared PROPERTIES 196 | OUTPUT_NAME "SDL3_shadercross" 197 | SOVERSION "${SO_VERSION_MAJOR}" 198 | VERSION "${SO_VERSION}" 199 | ) 200 | 201 | target_link_libraries(SDL3_shadercross-shared PRIVATE 202 | SDL3::SDL3-shared 203 | ) 204 | export(TARGETS SDL3_shadercross-shared NAMESPACE "SDL3_shadercross::" FILE "SDL3_shadercross-shared-targets.cmake") 205 | endif() 206 | 207 | 208 | if(SDLSHADERCROSS_STATIC) 209 | list(APPEND SDL3_shadercross_targets SDL3_shadercross-static) 210 | if(NOT TARGET SDL3::Headers) 211 | find_package(SDL3 ${SDL_REQUIRED_VERSION} REQUIRED COMPONENTS Headers) 212 | endif() 213 | 214 | add_library(SDL3_shadercross-static STATIC ${SOURCE_FILES}) 215 | add_library(SDL3_shadercross::SDL3_shadercross-static ALIAS SDL3_shadercross-static) 216 | 217 | if(NOT MSVC) 218 | set_property(TARGET SDL3_shadercross-static PROPERTY OUTPUT_NAME "SDL3_shadercross") 219 | endif() 220 | 221 | # SDL3_shadercross folders as includes, for other targets to consume 222 | target_include_directories(SDL3_shadercross-static PUBLIC "$") 223 | target_include_directories(SDL3_shadercross-static PUBLIC "$") 224 | 225 | target_link_libraries(SDL3_shadercross-static PUBLIC 226 | SDL3::Headers 227 | ) 228 | export(TARGETS SDL3_shadercross-static NAMESPACE "SDL3_shadercross::" FILE "SDL3_shadercross-static-targets.cmake") 229 | endif() 230 | 231 | # Copy dependencies of SDL3_shadercross-config.cmake to build directory. 232 | # This allows usage of the package without installation. 233 | file(COPY 234 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdlcpu.cmake" 235 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindDirectXShaderCompiler.cmake" 236 | DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") 237 | 238 | foreach(target IN LISTS SDL3_shadercross_targets) 239 | sdl_add_warning_options(${target} WARNING_AS_ERROR ${SDLSHADERCROSS_WERROR}) 240 | target_compile_features(${target} PRIVATE c_std_99) 241 | 242 | if(SDLSHADERCROSS_DXC) 243 | add_compile_definitions(SDL_SHADERCROSS_DXC) 244 | endif() 245 | 246 | if(SDLSHADERCROSS_SPIRVCROSS_SHARED) 247 | target_link_libraries(${target} PRIVATE spirv-cross-c-shared) 248 | else() 249 | target_link_libraries(${target} PRIVATE spirv-cross-c) 250 | endif() 251 | if(SDLSHADERCROSS_DXC) 252 | target_link_libraries(${target} PRIVATE DirectXShaderCompiler::dxcompiler) 253 | endif() 254 | if(NOT SDLSHADERCROSS_SPIRVCROSS_SHARED) 255 | # spirv-cross uses C++ 256 | set_property(TARGET ${target} PROPERTY LINKER_LANGUAGE CXX) 257 | endif() 258 | endforeach() 259 | 260 | if(NOT TARGET SDL3_shadercross::SDL3_shadercross) 261 | if(TARGET SDL3_shadercross-shared) 262 | add_library(SDL3_shadercross::SDL3_shadercross ALIAS SDL3_shadercross-shared) 263 | else() 264 | add_library(SDL3_shadercross::SDL3_shadercross ALIAS SDL3_shadercross-static) 265 | endif() 266 | endif() 267 | 268 | if(SDLSHADERCROSS_CLI) 269 | add_executable(shadercross src/cli.c) 270 | sdl_add_warning_options(shadercross WARNING_AS_ERROR ${SDLSHADERCROSS_WERROR}) 271 | sdl_target_link_options_no_undefined(shadercross) 272 | 273 | if(SDLSHADERCROSS_CLI_LEAKCHECK) 274 | target_link_libraries(shadercross PRIVATE SDL3::SDL3_test) 275 | target_compile_definitions(shadercross PRIVATE LEAKCHECK) 276 | endif() 277 | if(SDLSHADERCROSS_CLI_STATIC) 278 | target_link_libraries(shadercross PRIVATE SDL3_shadercross::SDL3_shadercross-static) 279 | target_link_libraries(shadercross PRIVATE SDL3::SDL3-static) 280 | else() 281 | if(NOT TARGET SDL3::SDL3) 282 | find_package(SDL3 ${SDL_REQUIRED_VERSION} REQUIRED CONFIG COMPONENTS SDL3) 283 | endif() 284 | target_link_libraries(shadercross PRIVATE SDL3_shadercross::SDL3_shadercross) 285 | target_link_libraries(shadercross PRIVATE SDL3::SDL3) 286 | endif() 287 | endif() 288 | 289 | if(SDLSHADERCROSS_INSTALL) 290 | if(WIN32 AND NOT MINGW) 291 | set(INSTALL_CMAKEDIR_ROOT_DEFAULT "cmake") 292 | else() 293 | set(INSTALL_CMAKEDIR_ROOT_DEFAULT "${CMAKE_INSTALL_LIBDIR}/cmake") 294 | endif() 295 | set(SDLSHADERCROSS_INSTALL_CMAKEDIR_ROOT "${INSTALL_CMAKEDIR_ROOT_DEFAULT}" CACHE STRING "Root folder where to install SDL3_shadercross cmake related files (SDL3_shadercross subfolder for MSVC projects)") 296 | set(SDLSHADERCROSS_PKGCONFIG_INSTALLDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig") 297 | 298 | if(WIN32 AND NOT MINGW) 299 | set(SDLSHADERCROSS_INSTALL_CMAKEDIR "${SDLSHADERCROSS_INSTALL_CMAKEDIR_ROOT}") 300 | else() 301 | set(SDLSHADERCROSS_INSTALL_CMAKEDIR "${SDLSHADERCROSS_INSTALL_CMAKEDIR_ROOT}/SDL3_shadercross") 302 | endif() 303 | 304 | if(TARGET SDL3_shadercross-shared) 305 | install(TARGETS SDL3_shadercross-shared EXPORT SDL3_shadercross-shared-export 306 | ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel 307 | LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT library 308 | RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT library 309 | ) 310 | install(EXPORT SDL3_shadercross-shared-export 311 | FILE SDL3_shadercross-shared-targets.cmake 312 | NAMESPACE SDL3_shadercross:: 313 | DESTINATION "${SDLSHADERCROSS_INSTALL_CMAKEDIR}" 314 | COMPONENT devel 315 | ) 316 | endif() 317 | if(TARGET SDL3_shadercross-static) 318 | install(TARGETS SDL3_shadercross-static EXPORT SDL3_shadercross-static-export 319 | ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel 320 | LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT library 321 | ) 322 | install(EXPORT SDL3_shadercross-static-export 323 | FILE SDL3_shadercross-static-targets.cmake 324 | NAMESPACE SDL3_shadercross:: 325 | DESTINATION "${SDLSHADERCROSS_INSTALL_CMAKEDIR}" 326 | COMPONENT devel 327 | ) 328 | endif() 329 | if(vendored_targets) 330 | install(TARGETS ${vendored_targets} EXPORT SDL3_shadercross-vendored 331 | ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel 332 | RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT library 333 | LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT library 334 | ) 335 | install(EXPORT SDL3_shadercross-vendored 336 | FILE SDL3_shadercross-vendored-targets.cmake 337 | NAMESPACE SDL3_shadercross::vendored:: 338 | DESTINATION "${SDLSHADERCROSS_INSTALL_CMAKEDIR}" 339 | COMPONENT devel 340 | ) 341 | endif() 342 | install( 343 | FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/SDL3_shadercross/SDL_shadercross.h" 344 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/SDL3_shadercross" COMPONENT DEVEL 345 | ) 346 | if(SDLSHADERCROSS_CLI) 347 | install(TARGETS shadercross RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") 348 | endif() 349 | 350 | include(CMakePackageConfigHelpers) 351 | configure_package_config_file(cmake/SDL3_shadercrossConfig.cmake.in SDL3_shadercrossConfig.cmake 352 | NO_SET_AND_CHECK_MACRO 353 | INSTALL_DESTINATION "${SDLSHADERCROSS_INSTALL_CMAKEDIR}" 354 | ) 355 | write_basic_package_version_file("${PROJECT_BINARY_DIR}/SDL3_shadercrossConfigVersion.cmake" 356 | COMPATIBILITY AnyNewerVersion 357 | ) 358 | install( 359 | FILES 360 | "${CMAKE_CURRENT_BINARY_DIR}/SDL3_shadercrossConfig.cmake" 361 | "${CMAKE_CURRENT_BINARY_DIR}/SDL3_shadercrossConfigVersion.cmake" 362 | DESTINATION "${SDLSHADERCROSS_INSTALL_CMAKEDIR}" 363 | COMPONENT devel 364 | ) 365 | if(NOT SDLSHADERCROSS_VENDORED) 366 | install( 367 | FILES 368 | "cmake/sdlcpu.cmake" 369 | "cmake/FindDirectXShaderCompiler.cmake" 370 | DESTINATION "${SDLSHADERCROSS_INSTALL_CMAKEDIR}" 371 | COMPONENT devel 372 | ) 373 | endif() 374 | 375 | if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") 376 | set(INCLUDEDIR_FOR_PKG_CONFIG "${CMAKE_INSTALL_INCLUDEDIR}") 377 | else() 378 | set(INCLUDEDIR_FOR_PKG_CONFIG "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") 379 | endif() 380 | if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") 381 | set(LIBDIR_FOR_PKG_CONFIG "${CMAKE_INSTALL_LIBDIR}") 382 | else() 383 | set(LIBDIR_FOR_PKG_CONFIG "\${prefix}/${CMAKE_INSTALL_LIBDIR}") 384 | endif() 385 | 386 | file(RELATIVE_PATH SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG "${CMAKE_INSTALL_PREFIX}/${SDLSHADERCROSS_PKGCONFIG_INSTALLDIR}" "${CMAKE_INSTALL_PREFIX}") 387 | string(REGEX REPLACE "[/]+$" "" SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG "${SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG}") 388 | set(SDL_PKGCONFIG_PREFIX "\${pcfiledir}/${SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG}") 389 | if(NOT SDLSHADERCROSS_VENDORED) 390 | if(SDLSHADERCROSS_SPIRVCROSS_SHARED) 391 | set(PC_REQUIRES "spirv-cross-c-shared") 392 | else() 393 | set(PC_REQUIRES "spirv-cross-c") 394 | endif() 395 | endif() 396 | set(PC_LIBS "-ldxcompiler") 397 | configure_file(cmake/sdl3-shadercross.pc.in sdl3-shadercross.pc @ONLY) 398 | 399 | # Always install sdl3-shadercross.pc file: libraries might be different between config modes 400 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sdl3-shadercross.pc" 401 | DESTINATION "${SDLSHADERCROSS_PKGCONFIG_INSTALLDIR}" COMPONENT devel) 402 | 403 | install(FILES "LICENSE.txt" 404 | DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/licenses/${PROJECT_NAME}" 405 | COMPONENT library 406 | ) 407 | if(SDLSHADERCROSS_INSTALL_CPACK) 408 | if(MSVC) 409 | set(CPACK_GENERATOR "ZIP") 410 | else() 411 | set(CPACK_GENERATOR "TGZ") 412 | endif() 413 | configure_file(cmake/CPackProjectConfig.cmake.in CPackProjectConfig.cmake @ONLY) 414 | set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/CPackProjectConfig.cmake") 415 | # CPACK_SOURCE_PACKAGE_FILE_NAME must end with "-src" (so we can block creating a source archive) 416 | set(CPACK_SOURCE_PACKAGE_FILE_NAME "SDL3_shadercross-${PROJECT_VERSION}-src") 417 | set(CPACK_PACKAGE_DIRECTORY "${CMAKE_BINARY_DIR}/dist") 418 | include(CPack) 419 | endif() 420 | endif() 421 | 422 | if(SDLSHADERCROSS_INSTALL_MAN) 423 | sdl_get_git_revision_hash(SDLSHADERCROSS_REVISION) 424 | SDL_generate_manpages( 425 | HEADERS_DIR "${PROJECT_SOURCE_DIR}/include/SDL3_shadercross" 426 | SYMBOL "SDL_ShaderCross_Init" 427 | WIKIHEADERS_PL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build-scripts/wikiheaders.pl" 428 | REVISION "${SDLSHADERCROSS_REVISION}" 429 | ) 430 | endif() 431 | 432 | set(DXC_LINUX_X64_URL "https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.8.2407/linux_dxc_2024_07_31.x86_64.tar.gz") 433 | set(DXC_LINUX_X64_HASH "SHA256=b58725ac191df0686994fb9d54d27ee8dd3f180b023d562733112a499ea1195c") 434 | set(DXC_WINDOWS_X86_X64_ARM64_URL "https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.8.2407/dxc_2024_07_31.zip") 435 | set(DXC_WINDOWS_X86_X64_ARM64_HASH "SHA256=e2627f004f0f9424d8c71ea1314d04f38c5a5096884ae9217f1f18bd320267b5") 436 | 437 | if(SDLSHADERCROSS_INSTALL_RUNTIME) 438 | set(chmod_0755 OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) 439 | if(APPLE) 440 | set(rpath_origin "@executable_path") 441 | else() 442 | set(rpath_origin "\$ORIGIN") 443 | endif() 444 | 445 | if(NOT SDLSHADERCROSS_VENDORED) 446 | if(SDLSHADERCROSS_DXC) 447 | install(IMPORTED_RUNTIME_ARTIFACTS DirectXShaderCompiler::dxcompiler DirectXShaderCompiler::dxil RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") 448 | endif() 449 | if(SDLSHADERCROSS_SPIRVCROSS_SHARED) 450 | install(IMPORTED_RUNTIME_ARTIFACTS spirv-cross-c-shared RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") 451 | if(WIN32) 452 | install(CODE " 453 | set(CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM \"windows+pe\") 454 | set(CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL \"$,dumpbin,objdump>\") 455 | set(CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND \"${CMAKE_OBJDUMP}\") 456 | file(GET_RUNTIME_DEPENDENCIES 457 | RESOLVED_DEPENDENCIES_VAR resolved 458 | UNRESOLVED_DEPENDENCIES_VAR unresolved 459 | DIRECTORIES \"$\" \"${CMAKE_INSTALL_PREFIX}${CMAKE_INSTALL_BINDIR}\" 460 | LIBRARIES \"$\" 461 | POST_EXCLUDE_REGEXES \".*[sS][yY][sS][tT][eE][mM]32.*\" \".*[aA][pP][iI]-[mM][sS].*\" \".*[aA][pP][iI]-[eE][xX][tT].*\" 462 | ) 463 | file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/bin\" TYPE SHARED_LIBRARY FILES \${resolved}) 464 | ") 465 | endif() 466 | endif() 467 | endif() 468 | 469 | if(TARGET shadercross) 470 | file(RELATIVE_PATH bin_to_lib "${CMAKE_INSTALL_FULL_BINDIR}" "${CMAKE_INSTALL_FULL_LIBDIR}") 471 | set_property(TARGET shadercross PROPERTY INSTALL_RPATH "${rpath_origin}/${bin_to_lib}") 472 | endif() 473 | 474 | # Install SDL3 475 | if(SDLSHADERCROSS_CLI AND NOT SDLSHADERCROSS_CLI_STATIC) 476 | install(IMPORTED_RUNTIME_ARTIFACTS SDL3::SDL3-shared RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") 477 | endif() 478 | include(ExternalProject) 479 | 480 | if(NOT WIN32) 481 | set(configure_CFLAGS "${CMAKE_C_FLAGS}") 482 | if(APPLE) 483 | foreach(osx_arch IN LISTS CMAKE_OSX_ARCHITECTURES) 484 | string(APPEND configure_CFLAGS " -arch ${osx_arch}") 485 | endforeach() 486 | endif() 487 | string(REPLACE ";" "$" genex_CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}") 488 | 489 | ExternalProject_Add(spirv_headers 490 | GIT_REPOSITORY "https://github.com/KhronosGroup/SPIRV-Headers.git" 491 | GIT_TAG "main" 492 | CMAKE_ARGS "-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_INSTALL_LIBDIR=lib" "-DCMAKE_INSTALL_BINDIR=bin" "-DCMAKE_INSTALL_PREFIX=" "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}" "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DCMAKE_OSX_ARCHITECTURES=${genex_CMAKE_OSX_ARCHITECTURES}" "-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}" 493 | BUILD_COMMAND "${CMAKE_COMMAND}" "--build" "" --config "Release" 494 | INSTALL_COMMAND "${CMAKE_COMMAND}" "--install" "" --config "Release" 495 | ) 496 | ExternalProject_Get_property(spirv_headers INSTALL_DIR) 497 | set(spirv_headers_install_dir "${INSTALL_DIR}") 498 | 499 | ExternalProject_Add(vulkan_headers 500 | GIT_REPOSITORY "https://github.com/KhronosGroup/Vulkan-Headers" 501 | GIT_TAG "main" 502 | CMAKE_ARGS "-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_INSTALL_LIBDIR=lib" "-DCMAKE_INSTALL_BINDIR=bin" "-DCMAKE_INSTALL_PREFIX=" "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}" "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DCMAKE_OSX_ARCHITECTURES=${genex_CMAKE_OSX_ARCHITECTURES}" "-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}" 503 | BUILD_COMMAND "${CMAKE_COMMAND}" "--build" "" --config "Release" 504 | INSTALL_COMMAND "${CMAKE_COMMAND}" "--install" "" --config "Release" 505 | ) 506 | ExternalProject_Get_property(vulkan_headers INSTALL_DIR) 507 | set(vulkan_headers_install_dir "${INSTALL_DIR}") 508 | 509 | ExternalProject_Add(vulkan_loader 510 | DEPENDS spirv_headers vulkan_headers 511 | GIT_REPOSITORY "https://github.com/KhronosGroup/Vulkan-Loader.git" 512 | GIT_TAG "main" 513 | CMAKE_ARGS "-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_INSTALL_LIBDIR=lib" "-DCMAKE_INSTALL_BINDIR=bin" "-DCMAKE_INSTALL_PREFIX=" "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}" "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DCMAKE_OSX_ARCHITECTURES=${genex_CMAKE_OSX_ARCHITECTURES}" "-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}" "-DCMAKE_PREFIX_PATH=${vulkan_headers_install_dir}" 514 | BUILD_COMMAND "${CMAKE_COMMAND}" "--build" "" --config "Release" 515 | INSTALL_COMMAND "${CMAKE_COMMAND}" "--install" "" --config "Release" 516 | ) 517 | ExternalProject_Get_property(vulkan_loader INSTALL_DIR) 518 | set(vulkan_loader_install_dir "${INSTALL_DIR}") 519 | 520 | find_package(BISON REQUIRED) 521 | ExternalProject_Add(vkd3d 522 | DEPENDS spirv_headers vulkan_headers vulkan_loader 523 | URL "https://dl.winehq.org/vkd3d/source/vkd3d-1.16.tar.xz" 524 | URL_HASH "SHA256=b4aef432ba1b533465b959d0e1bd22fac4610b7e178c95b3ff153854ef0f4136" 525 | DOWNLOAD_EXTRACT_TIMESTAMP "1" 526 | CONFIGURE_COMMAND "sh" "/configure" "--prefix=" "--enable-tests=no" "--enable-demos=no" "--disable-doxygen-doc" "CFLAGS=-I${spirv_headers_install_dir}/include -I${vulkan_headers_install_dir}/include -I${vulkan_loader_install_dir}/include ${configure_CFLAGS}" "LDFLAGS=-L${vulkan_loader_install_dir}/lib" "BISON=${BISON_EXECUTABLE}" 527 | BUILD_COMMAND "make" 528 | INSTALL_COMMAND "make" "install" 529 | ) 530 | ExternalProject_Get_property(vkd3d SOURCE_DIR) 531 | ExternalProject_Get_property(vkd3d INSTALL_DIR) 532 | install(DIRECTORY "${INSTALL_DIR}/lib/" DESTINATION "${CMAKE_INSTALL_LIBDIR}" FILES_MATCHING PATTERN "*.so*" PERMISSIONS ${chmod_0755}) 533 | install(DIRECTORY "${INSTALL_DIR}/lib/" DESTINATION "${CMAKE_INSTALL_LIBDIR}" FILES_MATCHING PATTERN "*.dylib*" PERMISSIONS ${chmod_0755}) 534 | install(FILES "${SOURCE_DIR}/COPYING" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/licenses/vkd3d") 535 | endif() 536 | if(LINUX) 537 | find_program(PATCHELF_BIN NAMES "patchelf" REQUIRED) 538 | install(CODE "file(GLOB so_paths \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/*so*\")\n foreach(so_path \${so_paths})\n if(NOT IS_SYMLINK \${so_path})\n message(STATUS \"Adding \\\"\$ORIGIN\\\" to RPATH of \${so_path}\")\n execute_process(COMMAND ${PATCHELF_BIN} \"\${so_path}\" --add-rpath \"\$ORIGIN\")\n endif()\n endforeach()") 539 | elseif(APPLE) 540 | find_program(INT_BIN NAMES "install_name_tool" REQUIRED) 541 | install(CODE "file(GLOB so_paths \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/*dylib*\")\n foreach(so_path \${so_paths})\n if(NOT IS_SYMLINK \${so_path})\n message(STATUS \"Adding \\\"\@loader_path\\\" to RPATH of \${so_path}\")\n execute_process(COMMAND ${INT_BIN} \"\${so_path}\" -add_rpath \"\@loader_path\")\n endif()\n endforeach()") 542 | endif() 543 | endif() 544 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2024 Sam Lantinga 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 2. Altered source versions must be plainly marked as such, and must not be 16 | misrepresented as being the original software. 17 | 3. This notice may not be removed or altered from any source distribution. 18 | 19 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | SDL_shadercross 2 | 3 | This is a library for translating shaders to different formats, intended for use with SDL's GPU API. 4 | It takes SPIRV or HLSL as the source and outputs DXBC, DXIL, SPIRV, MSL, or HLSL. 5 | 6 | This library can perform runtime translation and conveniently returns compiled SDL GPU shader objects from HLSL or SPIRV source. 7 | This library also provides a command line interface for offline translation of shaders. 8 | 9 | For SPIRV translation, this library depends on SPIRV-Cross: https://github.com/KhronosGroup/SPIRV-Cross 10 | spirv-cross-c-shared.dll (or your platform's equivalent) can be obtained in the Vulkan SDK: https://vulkan.lunarg.com/ 11 | For compiling to DXIL, dxcompiler.dll and dxil.dll (or your platform's equivalent) are required. 12 | DXIL dependencies can be obtained here: https://github.com/microsoft/DirectXShaderCompiler/releases 13 | It is strongly recommended that you ship SPIRV-Cross and DXIL dependencies along with your application. 14 | For compiling to DXBC, d3dcompiler_47 is shipped with Windows. Other platforms require vkd3d-utils. 15 | 16 | This library is under the zlib license, see LICENSE.txt for details. 17 | -------------------------------------------------------------------------------- /VisualC-GDK/SDL_shadercross.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.32630.194 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{DE5CE1BB-2DF1-4AC8-8259-0786F17E885E}") = "SDL3_shadercross", "SDL_shadercross.vcxproj", "{983B31A7-C73E-4FE7-8602-59A00DB2E2BA}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL3", "..\..\SDL\VisualC-GDK\SDL\SDL.vcxproj", "{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Gaming.Xbox.Scarlett.x64 = Debug|Gaming.Xbox.Scarlett.x64 13 | Debug|Gaming.Xbox.XboxOne.x64 = Debug|Gaming.Xbox.XboxOne.x64 14 | Profile|Gaming.Xbox.Scarlett.x64 = Profile|Gaming.Xbox.Scarlett.x64 15 | Profile|Gaming.Xbox.XboxOne.x64 = Profile|Gaming.Xbox.XboxOne.x64 16 | Release|Gaming.Xbox.Scarlett.x64 = Release|Gaming.Xbox.Scarlett.x64 17 | Release|Gaming.Xbox.XboxOne.x64 = Release|Gaming.Xbox.XboxOne.x64 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {983B31A7-C73E-4FE7-8602-59A00DB2E2BA}.Debug|Gaming.Xbox.Scarlett.x64.ActiveCfg = Debug|Gaming.Xbox.Scarlett.x64 21 | {983B31A7-C73E-4FE7-8602-59A00DB2E2BA}.Debug|Gaming.Xbox.Scarlett.x64.Build.0 = Debug|Gaming.Xbox.Scarlett.x64 22 | {983B31A7-C73E-4FE7-8602-59A00DB2E2BA}.Debug|Gaming.Xbox.XboxOne.x64.ActiveCfg = Debug|Gaming.Xbox.XboxOne.x64 23 | {983B31A7-C73E-4FE7-8602-59A00DB2E2BA}.Debug|Gaming.Xbox.XboxOne.x64.Build.0 = Debug|Gaming.Xbox.XboxOne.x64 24 | {983B31A7-C73E-4FE7-8602-59A00DB2E2BA}.Profile|Gaming.Xbox.Scarlett.x64.ActiveCfg = Profile|Gaming.Xbox.Scarlett.x64 25 | {983B31A7-C73E-4FE7-8602-59A00DB2E2BA}.Profile|Gaming.Xbox.Scarlett.x64.Build.0 = Profile|Gaming.Xbox.Scarlett.x64 26 | {983B31A7-C73E-4FE7-8602-59A00DB2E2BA}.Profile|Gaming.Xbox.XboxOne.x64.ActiveCfg = Profile|Gaming.Xbox.XboxOne.x64 27 | {983B31A7-C73E-4FE7-8602-59A00DB2E2BA}.Profile|Gaming.Xbox.XboxOne.x64.Build.0 = Profile|Gaming.Xbox.XboxOne.x64 28 | {983B31A7-C73E-4FE7-8602-59A00DB2E2BA}.Release|Gaming.Xbox.Scarlett.x64.ActiveCfg = Release|Gaming.Xbox.Scarlett.x64 29 | {983B31A7-C73E-4FE7-8602-59A00DB2E2BA}.Release|Gaming.Xbox.Scarlett.x64.Build.0 = Release|Gaming.Xbox.Scarlett.x64 30 | {983B31A7-C73E-4FE7-8602-59A00DB2E2BA}.Release|Gaming.Xbox.XboxOne.x64.ActiveCfg = Release|Gaming.Xbox.XboxOne.x64 31 | {983B31A7-C73E-4FE7-8602-59A00DB2E2BA}.Release|Gaming.Xbox.XboxOne.x64.Build.0 = Release|Gaming.Xbox.XboxOne.x64 32 | {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|Gaming.Xbox.Scarlett.x64.ActiveCfg = Debug|Gaming.Xbox.Scarlett.x64 33 | {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|Gaming.Xbox.Scarlett.x64.Build.0 = Debug|Gaming.Xbox.Scarlett.x64 34 | {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|Gaming.Xbox.XboxOne.x64.ActiveCfg = Debug|Gaming.Xbox.XboxOne.x64 35 | {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|Gaming.Xbox.XboxOne.x64.Build.0 = Debug|Gaming.Xbox.XboxOne.x64 36 | {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Profile|Gaming.Xbox.Scarlett.x64.ActiveCfg = Profile|Gaming.Xbox.Scarlett.x64 37 | {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Profile|Gaming.Xbox.Scarlett.x64.Build.0 = Profile|Gaming.Xbox.Scarlett.x64 38 | {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Profile|Gaming.Xbox.XboxOne.x64.ActiveCfg = Profile|Gaming.Xbox.XboxOne.x64 39 | {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Profile|Gaming.Xbox.XboxOne.x64.Build.0 = Profile|Gaming.Xbox.XboxOne.x64 40 | {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|Gaming.Xbox.Scarlett.x64.ActiveCfg = Release|Gaming.Xbox.Scarlett.x64 41 | {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|Gaming.Xbox.Scarlett.x64.Build.0 = Release|Gaming.Xbox.Scarlett.x64 42 | {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|Gaming.Xbox.XboxOne.x64.ActiveCfg = Release|Gaming.Xbox.XboxOne.x64 43 | {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|Gaming.Xbox.XboxOne.x64.Build.0 = Release|Gaming.Xbox.XboxOne.x64 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {0B42B3D0-337B-4E5E-96BA-2BB97FAE6842} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /VisualC-GDK/SDL_shadercross.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Gaming.Xbox.Scarlett.x64 7 | 8 | 9 | Profile 10 | Gaming.Xbox.Scarlett.x64 11 | 12 | 13 | Release 14 | Gaming.Xbox.Scarlett.x64 15 | 16 | 17 | Release 18 | Gaming.Xbox.XboxOne.x64 19 | 20 | 21 | Profile 22 | Gaming.Xbox.XboxOne.x64 23 | 24 | 25 | Debug 26 | Gaming.Xbox.XboxOne.x64 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | {81ce8daf-ebb2-4761-8e45-b71abcca8c68} 45 | 46 | 47 | 48 | SDL3_shadercross 49 | {983b31a7-c73e-4fe7-8602-59a00db2e2ba} 50 | SDL_shadercross 51 | en-US 52 | Win32Proj 53 | 54 | 15.0 55 | Native 56 | x64 57 | 58 | 59 | 60 | DynamicLibrary 61 | false 62 | true 63 | Unicode 64 | false 65 | false 66 | $(DefaultPlatformToolset) 67 | 68 | 69 | DynamicLibrary 70 | false 71 | true 72 | Unicode 73 | false 74 | false 75 | $(DefaultPlatformToolset) 76 | 77 | 78 | DynamicLibrary 79 | false 80 | true 81 | Unicode 82 | false 83 | false 84 | $(DefaultPlatformToolset) 85 | 86 | 87 | DynamicLibrary 88 | false 89 | true 90 | Unicode 91 | false 92 | false 93 | $(DefaultPlatformToolset) 94 | 95 | 96 | DynamicLibrary 97 | true 98 | Unicode 99 | false 100 | false 101 | $(DefaultPlatformToolset) 102 | 103 | 104 | DynamicLibrary 105 | true 106 | Unicode 107 | false 108 | false 109 | $(DefaultPlatformToolset) 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 | $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) 135 | $(Console_SdkLibPath) 136 | $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) 137 | ..\..\SDL\include;..\external\SPIRV-Headers\include\spirv;..\external\SPIRV-Cross;..\include;$(Console_SdkIncludeRoot) 138 | $(Console_SdkRoot)bin;$(Console_SdkToolPath);$(ExecutablePath) 139 | false 140 | 141 | 142 | $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) 143 | $(Console_SdkLibPath) 144 | $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) 145 | ..\..\SDL\include;..\external\SPIRV-Headers\include\spirv;..\external\SPIRV-Cross;..\include;$(Console_SdkIncludeRoot) 146 | $(Console_SdkRoot)bin;$(Console_SdkToolPath);$(ExecutablePath) 147 | false 148 | 149 | 150 | $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) 151 | $(Console_SdkLibPath) 152 | $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) 153 | ..\..\SDL\include;..\external\SPIRV-Headers\include\spirv;..\external\SPIRV-Cross;..\include;$(Console_SdkIncludeRoot) 154 | $(Console_SdkRoot)bin;$(Console_SdkToolPath);$(ExecutablePath) 155 | false 156 | 157 | 158 | $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) 159 | $(Console_SdkLibPath) 160 | $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) 161 | ..\..\SDL\include;..\external\SPIRV-Headers\include\spirv;..\external\SPIRV-Cross;..\include;$(Console_SdkIncludeRoot) 162 | $(Console_SdkRoot)bin;$(Console_SdkToolPath);$(ExecutablePath) 163 | false 164 | 165 | 166 | $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) 167 | $(Console_SdkLibPath) 168 | $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) 169 | ..\..\SDL\include;..\external\SPIRV-Headers\include\spirv;..\external\SPIRV-Cross;..\include;$(Console_SdkIncludeRoot) 170 | $(Console_SdkRoot)bin;$(Console_SdkToolPath);$(ExecutablePath) 171 | true 172 | 173 | 174 | $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) 175 | $(Console_SdkLibPath) 176 | $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) 177 | ..\..\SDL\include;..\external\SPIRV-Headers\include\spirv;..\external\SPIRV-Cross;..\include;$(Console_SdkIncludeRoot) 178 | $(Console_SdkRoot)bin;$(Console_SdkToolPath);$(ExecutablePath) 179 | true 180 | 181 | 182 | 183 | dxcompiler_x.lib;$(Console_Libs);%(XboxExtensionsDependencies);%(AdditionalDependencies) 184 | true 185 | Windows 186 | true 187 | true 188 | 189 | 190 | MaxSpeed 191 | SDL_SHADERCROSS_DXC;SPIRV_CROSS_C_API_HLSL;SPIRV_CROSS_C_API_GLSL;DLL_EXPORT;NDEBUG;_LIB;%(PreprocessorDefinitions) 192 | Level4 193 | true 194 | true 195 | /Zc:__cplusplus %(AdditionalOptions) 196 | 197 | 198 | 199 | 200 | dxcompiler_xs.lib;$(Console_Libs);%(XboxExtensionsDependencies);%(AdditionalDependencies) 201 | true 202 | Windows 203 | true 204 | true 205 | 206 | 207 | MaxSpeed 208 | SDL_SHADERCROSS_DXC;SPIRV_CROSS_C_API_HLSL;SPIRV_CROSS_C_API_GLSL;DLL_EXPORT;NDEBUG;_LIB;%(PreprocessorDefinitions) 209 | Level4 210 | true 211 | true 212 | /Zc:__cplusplus %(AdditionalOptions) 213 | 214 | 215 | 216 | 217 | dxcompiler_x.lib;$(Console_Libs);%(XboxExtensionsDependencies);%(AdditionalDependencies) 218 | true 219 | Windows 220 | true 221 | true 222 | 223 | 224 | MaxSpeed 225 | SDL_SHADERCROSS_DXC;SPIRV_CROSS_C_API_HLSL;SPIRV_CROSS_C_API_GLSL;DLL_EXPORT;NDEBUG;_LIB;PROFILE;%(PreprocessorDefinitions) 226 | Level4 227 | true 228 | true 229 | /Zc:__cplusplus %(AdditionalOptions) 230 | 231 | 232 | 233 | 234 | dxcompiler_xs.lib;$(Console_Libs);%(XboxExtensionsDependencies);%(AdditionalDependencies) 235 | true 236 | Windows 237 | true 238 | true 239 | 240 | 241 | MaxSpeed 242 | SDL_SHADERCROSS_DXC;SPIRV_CROSS_C_API_HLSL;SPIRV_CROSS_C_API_GLSL;DLL_EXPORT;NDEBUG;_LIB;PROFILE;%(PreprocessorDefinitions) 243 | Level4 244 | true 245 | true 246 | /Zc:__cplusplus %(AdditionalOptions) 247 | 248 | 249 | 250 | 251 | dxcompiler_x.lib;$(Console_Libs);%(XboxExtensionsDependencies);%(AdditionalDependencies) 252 | Windows 253 | true 254 | 255 | 256 | false 257 | Level4 258 | Disabled 259 | SDL_SHADERCROSS_DXC;SPIRV_CROSS_C_API_HLSL;SPIRV_CROSS_C_API_GLSL;DLL_EXPORT;_DEBUG;_LIB;%(PreprocessorDefinitions) 260 | /Zc:__cplusplus %(AdditionalOptions) 261 | 262 | 263 | 264 | 265 | dxcompiler_xs.lib;$(Console_Libs);%(XboxExtensionsDependencies);%(AdditionalDependencies) 266 | Windows 267 | true 268 | 269 | 270 | false 271 | Level4 272 | Disabled 273 | SDL_SHADERCROSS_DXC;SPIRV_CROSS_C_API_HLSL;SPIRV_CROSS_C_API_GLSL;DLL_EXPORT;_DEBUG;_LIB;%(PreprocessorDefinitions) 274 | /Zc:__cplusplus %(AdditionalOptions) 275 | 276 | 277 | 278 | 279 | 280 | 281 | -------------------------------------------------------------------------------- /build-scripts/download-prebuilt-DirectXShaderCompiler.cmake: -------------------------------------------------------------------------------- 1 | set(DXC_LINUX_X64_URL "https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.8.2502/linux_dxc_2025_02_20.x86_64.tar.gz") 2 | set(DXC_LINUX_X64_HASH "SHA256=e0580d90dbf6053a783ddd8d5153285f0606e5deaad17a7a6452f03acdf88c71") 3 | set(DXC_WINDOWS_X86_X64_ARM64_URL "https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.8.2502/dxc_2025_02_20.zip") 4 | set(DXC_WINDOWS_X86_X64_ARM64_HASH "SHA256=70b1913a1bfce4a3e1a5311d16246f4ecdf3a3e613abec8aa529e57668426f85") 5 | 6 | get_filename_component(EXTERNAL_PATH "${CMAKE_CURRENT_LIST_DIR}/../external" ABSOLUTE) 7 | if(NOT DEFINED DXC_ROOT) 8 | set(DXC_ROOT "${EXTERNAL_PATH}/DirectXShaderCompiler-binaries") 9 | endif() 10 | 11 | set(DOWNLOAD_LINUX ON) 12 | set(DOWNLOAD_WINDOWS ON) 13 | if(DEFINED CMAKE_SYSTEM_NAME) 14 | if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") 15 | set(DOWNLOAD_LINUX OFF) 16 | endif() 17 | if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") 18 | set(DOWNLOAD_WINDOWS OFF) 19 | endif() 20 | endif() 21 | 22 | if(DOWNLOAD_LINUX) 23 | include(FetchContent) 24 | FetchContent_Populate( 25 | dxc_linux 26 | URL "${DXC_LINUX_X64_URL}" 27 | URL_HASH "${DXC_LINUX_X64_HASH}" 28 | SOURCE_DIR "${DXC_ROOT}/linux" 29 | ) 30 | endif() 31 | 32 | if(DOWNLOAD_WINDOWS) 33 | include(FetchContent) 34 | FetchContent_Populate( 35 | dxc_windows 36 | URL "${DXC_WINDOWS_X86_X64_ARM64_URL}" 37 | URL_HASH "${DXC_WINDOWS_X86_X64_ARM64_HASH}" 38 | SOURCE_DIR "${DXC_ROOT}/windows" 39 | ) 40 | endif() 41 | 42 | message("To make use of the prebuilt DirectXShaderCompiler libraries, configure with:") 43 | message("") 44 | message(" -DSDLSHADERCROSS_VENDORED=OFF") 45 | message("") 46 | message("and") 47 | message("") 48 | message(" -DDirectXShaderCompiler_ROOT=\"${DXC_ROOT}\"") 49 | message("") 50 | -------------------------------------------------------------------------------- /build-scripts/test-versioning.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2022 Collabora Ltd. 3 | # SPDX-License-Identifier: Zlib 4 | 5 | set -eu 6 | 7 | cd `dirname $0`/.. 8 | 9 | # Needed so sed doesn't report illegal byte sequences on macOS 10 | export LC_CTYPE=C 11 | 12 | header=include/SDL3_shadercross/SDL_shadercross.h 13 | ref_major=$(sed -ne 's/^#define SDL_SHADERCROSS_MAJOR_VERSION *//p' $header) 14 | ref_minor=$(sed -ne 's/^#define SDL_SHADERCROSS_MINOR_VERSION *//p' $header) 15 | ref_micro=$(sed -ne 's/^#define SDL_SHADERCROSS_MICRO_VERSION *//p' $header) 16 | ref_version="${ref_major}.${ref_minor}.${ref_micro}" 17 | 18 | tests=0 19 | failed=0 20 | 21 | ok () { 22 | tests=$(( tests + 1 )) 23 | echo "ok - $*" 24 | } 25 | 26 | not_ok () { 27 | tests=$(( tests + 1 )) 28 | echo "not ok - $*" 29 | failed=1 30 | } 31 | 32 | major=$(sed -ne 's/^set(MAJOR_VERSION \([0-9]*\))$/\1/p' CMakeLists.txt) 33 | minor=$(sed -ne 's/^set(MINOR_VERSION \([0-9]*\))$/\1/p' CMakeLists.txt) 34 | micro=$(sed -ne 's/^set(MICRO_VERSION \([0-9]*\))$/\1/p' CMakeLists.txt) 35 | ref_sdl_req=$(sed -ne 's/^set(SDL_REQUIRED_VERSION \([0-9.]*\))$/\1/p' CMakeLists.txt) 36 | version="${major}.${minor}.${micro}" 37 | 38 | if [ "$ref_version" = "$version" ]; then 39 | ok "CMakeLists.txt $version" 40 | else 41 | not_ok "CMakeLists.txt $version disagrees with SDL_shadercross.h $ref_version" 42 | fi 43 | 44 | for rcfile in src/version.rc; do 45 | tuple=$(sed -ne 's/^ *FILEVERSION *//p' "$rcfile" | tr -d '\r') 46 | ref_tuple="${ref_major},${ref_minor},${ref_micro},0" 47 | 48 | if [ "$ref_tuple" = "$tuple" ]; then 49 | ok "$rcfile FILEVERSION $tuple" 50 | else 51 | not_ok "$rcfile FILEVERSION $tuple disagrees with SDL_shadercross.h $ref_tuple" 52 | fi 53 | 54 | tuple=$(sed -ne 's/^ *PRODUCTVERSION *//p' "$rcfile" | tr -d '\r') 55 | 56 | if [ "$ref_tuple" = "$tuple" ]; then 57 | ok "$rcfile PRODUCTVERSION $tuple" 58 | else 59 | not_ok "$rcfile PRODUCTVERSION $tuple disagrees with SDL_shadercross.h $ref_tuple" 60 | fi 61 | 62 | tuple=$(sed -Ene 's/^ *VALUE "FileVersion", "([0-9, ]*)\\0"\r?$/\1/p' "$rcfile" | tr -d '\r') 63 | ref_tuple="${ref_major}, ${ref_minor}, ${ref_micro}, 0" 64 | 65 | if [ "$ref_tuple" = "$tuple" ]; then 66 | ok "$rcfile FileVersion $tuple" 67 | else 68 | not_ok "$rcfile FileVersion $tuple disagrees with SDL_shadercross.h $ref_tuple" 69 | fi 70 | 71 | tuple=$(sed -Ene 's/^ *VALUE "ProductVersion", "([0-9, ]*)\\0"\r?$/\1/p' "$rcfile" | tr -d '\r') 72 | 73 | if [ "$ref_tuple" = "$tuple" ]; then 74 | ok "$rcfile ProductVersion $tuple" 75 | else 76 | not_ok "$rcfile ProductVersion $tuple disagrees with SDL_shadercross.h $ref_tuple" 77 | fi 78 | done 79 | 80 | echo "1..$tests" 81 | exit "$failed" 82 | -------------------------------------------------------------------------------- /cmake/CPackProjectConfig.cmake.in: -------------------------------------------------------------------------------- 1 | if(CPACK_PACKAGE_FILE_NAME MATCHES ".*-src$") 2 | message(FATAL_ERROR "Creating source archives is not supported.") 3 | endif() 4 | 5 | set(PROJECT_NAME "@PROJECT_NAME@") 6 | set(PROJECT_VERSION "@PROJECT_VERSION@") 7 | set(PROJECT_SOURCE_DIR "@PROJECT_SOURCE_DIR@") 8 | set(SDL_CMAKE_PLATFORM "@SDL_CMAKE_PLATFORM@") 9 | set(SDL_CPU_NAMES "@SDL_CPU_NAMES@") 10 | list(SORT SDL_CPU_NAMES) 11 | 12 | string(TOLOWER "${SDL_CMAKE_PLATFORM}" SDL_CMAKE_PLATFORM) 13 | string(TOLOWER "${SDL_CPU_NAMES}" SDL_CPU_NAMES) 14 | if(lower_sdl_cmake_platform STREQUAL lower_sdl_cpu_names) 15 | set(SDL_CPU_NAMES_WITH_DASHES) 16 | endif() 17 | 18 | string(REPLACE ";" "-" SDL_CPU_NAMES_WITH_DASHES "${SDL_CPU_NAMES}") 19 | if(SDL_CPU_NAMES_WITH_DASHES) 20 | set(SDL_CPU_NAMES_WITH_DASHES "-${SDL_CPU_NAMES_WITH_DASHES}") 21 | endif() 22 | 23 | set(MSVC @MSVC@) 24 | set(MINGW @MINGW@) 25 | if(MSVC) 26 | set(SDL_CMAKE_PLATFORM "${SDL_CMAKE_PLATFORM}-VC") 27 | elseif(MINGW) 28 | set(SDL_CMAKE_PLATFORM "${SDL_CMAKE_PLATFORM}-mingw") 29 | endif() 30 | 31 | set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-${SDL_CMAKE_PLATFORM}${SDL_CPU_NAMES_WITH_DASHES}") 32 | 33 | if(CPACK_GENERATOR STREQUAL "DragNDrop") 34 | set(CPACK_DMG_VOLUME_NAME "@PROJECT_NAME@ @PROJECT_VERSION@") 35 | # FIXME: use pre-built/create .DS_Store through AppleScript (CPACK_DMG_DS_STORE/CPACK_DMG_DS_STORE_SETUP_SCRIPT) 36 | set(CPACK_DMG_DS_STORE "${PROJECT_SOURCE_DIR}/Xcode/SDL/pkg-support/resources/SDL_DS_Store") 37 | endif() 38 | -------------------------------------------------------------------------------- /cmake/FindDirectXShaderCompiler.cmake: -------------------------------------------------------------------------------- 1 | set(required_vars) 2 | 3 | if(WIN32) 4 | find_path(DirectXShaderCompiler_INCLUDE_PATH NAMES "dxcapi.h" PATH_SUFFIXES "inc" "windows/inc" HINTS ${DirectXShaderCompiler_ROOT}) 5 | if(SDL_CPU_ARM64) 6 | set(extra_bin_suffix "bin/arm64" "windows/bin/arm64") 7 | set(extra_lib_suffix "lib/arm64" "windows/lib/arm64") 8 | elseif(SDL_CPU_X86) 9 | set(extra_bin_suffix "bin/x86" "windows/bin/x86") 10 | set(extra_lib_suffix "lib/x86" "windows/lib/x86") 11 | elseif(SDL_CPU_X64) 12 | set(extra_bin_suffix "bin/x64" "windows/bin/x64") 13 | set(extra_lib_suffix "lib/x64" "windows/lib/x64") 14 | endif() 15 | find_file(DirectXShaderCompiler_dxcompiler_BINARY NAMES "dxcompiler.dll" PATH_SUFFIXES "bin" ${extra_bin_suffix} HINTS ${DirectXShaderCompiler_ROOT}) 16 | find_library(DirectXShaderCompiler_dxcompiler_LIBRARY NAMES "dxcompiler" "dxcompiler.lib" PATH_SUFFIXES "lib" ${extra_lib_suffix} HINTS ${DirectXShaderCompiler_ROOT}) 17 | find_file(DirectXShaderCompiler_dxil_BINARY NAMES "dxil.dll" PATH_SUFFIXES "bin" ${extra_bin_suffix} HINTS ${DirectXShaderCompiler_ROOT}) 18 | set(required_vars 19 | DirectXShaderCompiler_INCLUDE_PATH 20 | DirectXShaderCompiler_dxcompiler_BINARY 21 | DirectXShaderCompiler_dxcompiler_LIBRARY 22 | DirectXShaderCompiler_dxil_BINARY 23 | ) 24 | else() 25 | find_path(DirectXShaderCompiler_INCLUDE_PATH NAMES "dxcapi.h" PATH_SUFFIXES "include" "include/dxc" "linux/include" "linux/include/dxc") 26 | find_library(DirectXShaderCompiler_dxcompiler_LIBRARY NAMES "dxcompiler" PATH_SUFFIXES "lib" "linux/lib" HINTS ${DirectXShaderCompiler_ROOT}) 27 | find_library(DirectXShaderCompiler_dxil_LIBRARY NAMES "dxil" PATH_SUFFIXES "lib" "linux/lib" HINTS ${DirectXShaderCompiler_ROOT}) 28 | set(required_vars 29 | DirectXShaderCompiler_INCLUDE_PATH 30 | DirectXShaderCompiler_dxcompiler_LIBRARY 31 | DirectXShaderCompiler_dxil_LIBRARY 32 | ) 33 | endif() 34 | 35 | include(FindPackageHandleStandardArgs) 36 | 37 | find_package_handle_standard_args(DirectXShaderCompiler 38 | REQUIRED_VARS ${required_vars} 39 | ) 40 | 41 | if(DirectXShaderCompiler_FOUND) 42 | if(NOT TARGET DirectXShaderCompiler::dxcompiler) 43 | add_library(DirectXShaderCompiler::dxcompiler IMPORTED SHARED) 44 | set_property(TARGET DirectXShaderCompiler::dxcompiler PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${DirectXShaderCompiler_INCLUDE_PATH}") 45 | if(WIN32) 46 | set_property(TARGET DirectXShaderCompiler::dxcompiler PROPERTY IMPORTED_LOCATION "${DirectXShaderCompiler_dxcompiler_BINARY}") 47 | set_property(TARGET DirectXShaderCompiler::dxcompiler PROPERTY IMPORTED_IMPLIB "${DirectXShaderCompiler_dxcompiler_LIBRARY}") 48 | else() 49 | set_property(TARGET DirectXShaderCompiler::dxcompiler PROPERTY IMPORTED_LOCATION "${DirectXShaderCompiler_dxcompiler_LIBRARY}") 50 | endif() 51 | endif() 52 | if(NOT TARGET DirectXShaderCompiler::dxil) 53 | add_library(DirectXShaderCompiler::dxil IMPORTED SHARED) 54 | if(WIN32) 55 | set_property(TARGET DirectXShaderCompiler::dxil PROPERTY IMPORTED_LOCATION "${DirectXShaderCompiler_dxil_BINARY}") 56 | else() 57 | set_property(TARGET DirectXShaderCompiler::dxil PROPERTY IMPORTED_LOCATION "${DirectXShaderCompiler_dxil_LIBRARY}") 58 | endif() 59 | endif() 60 | endif() 61 | -------------------------------------------------------------------------------- /cmake/GetGitRevisionDescription.cmake: -------------------------------------------------------------------------------- 1 | # - Returns a version string from Git 2 | # 3 | # These functions force a re-configure on each git commit so that you can 4 | # trust the values of the variables in your build system. 5 | # 6 | # get_git_head_revision( [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR]) 7 | # 8 | # Returns the refspec and sha hash of the current head revision 9 | # 10 | # git_describe( [ ...]) 11 | # 12 | # Returns the results of git describe on the source tree, and adjusting 13 | # the output so that it tests false if an error occurs. 14 | # 15 | # git_describe_working_tree( [ ...]) 16 | # 17 | # Returns the results of git describe on the working tree (--dirty option), 18 | # and adjusting the output so that it tests false if an error occurs. 19 | # 20 | # git_get_exact_tag( [ ...]) 21 | # 22 | # Returns the results of git describe --exact-match on the source tree, 23 | # and adjusting the output so that it tests false if there was no exact 24 | # matching tag. 25 | # 26 | # git_local_changes() 27 | # 28 | # Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes. 29 | # Uses the return code of "git diff-index --quiet HEAD --". 30 | # Does not regard untracked files. 31 | # 32 | # Requires CMake 2.6 or newer (uses the 'function' command) 33 | # 34 | # Original Author: 35 | # 2009-2020 Ryan Pavlik 36 | # http://academic.cleardefinition.com 37 | # 38 | # Copyright 2009-2013, Iowa State University. 39 | # Copyright 2013-2020, Ryan Pavlik 40 | # Copyright 2013-2020, Contributors 41 | # SPDX-License-Identifier: BSL-1.0 42 | # Distributed under the Boost Software License, Version 1.0. 43 | # (See accompanying file LICENSE_1_0.txt or copy at 44 | # http://www.boost.org/LICENSE_1_0.txt) 45 | 46 | if(__get_git_revision_description) 47 | return() 48 | endif() 49 | set(__get_git_revision_description YES) 50 | 51 | # We must run the following at "include" time, not at function call time, 52 | # to find the path to this module rather than the path to a calling list file 53 | get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) 54 | 55 | # Function _git_find_closest_git_dir finds the next closest .git directory 56 | # that is part of any directory in the path defined by _start_dir. 57 | # The result is returned in the parent scope variable whose name is passed 58 | # as variable _git_dir_var. If no .git directory can be found, the 59 | # function returns an empty string via _git_dir_var. 60 | # 61 | # Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and 62 | # neither foo nor bar contain a file/directory .git. This will return 63 | # C:/bla/.git 64 | # 65 | function(_git_find_closest_git_dir _start_dir _git_dir_var) 66 | set(cur_dir "${_start_dir}") 67 | set(git_dir "${_start_dir}/.git") 68 | while(NOT EXISTS "${git_dir}") 69 | # .git dir not found, search parent directories 70 | set(git_previous_parent "${cur_dir}") 71 | get_filename_component(cur_dir "${cur_dir}" DIRECTORY) 72 | if(cur_dir STREQUAL git_previous_parent) 73 | # We have reached the root directory, we are not in git 74 | set(${_git_dir_var} 75 | "" 76 | PARENT_SCOPE) 77 | return() 78 | endif() 79 | set(git_dir "${cur_dir}/.git") 80 | endwhile() 81 | set(${_git_dir_var} 82 | "${git_dir}" 83 | PARENT_SCOPE) 84 | endfunction() 85 | 86 | function(get_git_head_revision _refspecvar _hashvar) 87 | _git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR) 88 | 89 | if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR") 90 | set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE) 91 | else() 92 | set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE) 93 | endif() 94 | if(NOT "${GIT_DIR}" STREQUAL "") 95 | file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}" 96 | "${GIT_DIR}") 97 | if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR) 98 | # We've gone above the CMake root dir. 99 | set(GIT_DIR "") 100 | endif() 101 | endif() 102 | if("${GIT_DIR}" STREQUAL "") 103 | set(${_refspecvar} 104 | "GITDIR-NOTFOUND" 105 | PARENT_SCOPE) 106 | set(${_hashvar} 107 | "GITDIR-NOTFOUND" 108 | PARENT_SCOPE) 109 | return() 110 | endif() 111 | 112 | # Check if the current source dir is a git submodule or a worktree. 113 | # In both cases .git is a file instead of a directory. 114 | # 115 | if(NOT IS_DIRECTORY ${GIT_DIR}) 116 | # The following git command will return a non empty string that 117 | # points to the super project working tree if the current 118 | # source dir is inside a git submodule. 119 | # Otherwise the command will return an empty string. 120 | # 121 | execute_process( 122 | COMMAND "${GIT_EXECUTABLE}" rev-parse 123 | --show-superproject-working-tree 124 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 125 | OUTPUT_VARIABLE out 126 | ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) 127 | if(NOT "${out}" STREQUAL "") 128 | # If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule 129 | file(READ ${GIT_DIR} submodule) 130 | string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE 131 | ${submodule}) 132 | string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE) 133 | get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) 134 | get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} 135 | ABSOLUTE) 136 | set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD") 137 | else() 138 | # GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree 139 | file(READ ${GIT_DIR} worktree_ref) 140 | # The .git directory contains a path to the worktree information directory 141 | # inside the parent git repo of the worktree. 142 | # 143 | string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir 144 | ${worktree_ref}) 145 | string(STRIP ${git_worktree_dir} git_worktree_dir) 146 | _git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR) 147 | set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD") 148 | endif() 149 | else() 150 | set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD") 151 | endif() 152 | set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") 153 | if(NOT EXISTS "${GIT_DATA}") 154 | file(MAKE_DIRECTORY "${GIT_DATA}") 155 | endif() 156 | 157 | if(NOT EXISTS "${HEAD_SOURCE_FILE}") 158 | return() 159 | endif() 160 | set(HEAD_FILE "${GIT_DATA}/HEAD") 161 | configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY) 162 | 163 | configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" 164 | "${GIT_DATA}/grabRef.cmake" @ONLY) 165 | include("${GIT_DATA}/grabRef.cmake") 166 | 167 | set(${_refspecvar} 168 | "${HEAD_REF}" 169 | PARENT_SCOPE) 170 | set(${_hashvar} 171 | "${HEAD_HASH}" 172 | PARENT_SCOPE) 173 | endfunction() 174 | 175 | function(git_describe _var) 176 | if(NOT GIT_FOUND) 177 | find_package(Git QUIET) 178 | endif() 179 | get_git_head_revision(refspec hash) 180 | if(NOT GIT_FOUND) 181 | set(${_var} 182 | "GIT-NOTFOUND" 183 | PARENT_SCOPE) 184 | return() 185 | endif() 186 | if(NOT hash) 187 | set(${_var} 188 | "HEAD-HASH-NOTFOUND" 189 | PARENT_SCOPE) 190 | return() 191 | endif() 192 | 193 | # TODO sanitize 194 | #if((${ARGN}" MATCHES "&&") OR 195 | # (ARGN MATCHES "||") OR 196 | # (ARGN MATCHES "\\;")) 197 | # message("Please report the following error to the project!") 198 | # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") 199 | #endif() 200 | 201 | #message(STATUS "Arguments to execute_process: ${ARGN}") 202 | 203 | execute_process( 204 | COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN} 205 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 206 | RESULT_VARIABLE res 207 | OUTPUT_VARIABLE out 208 | ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) 209 | if(NOT res EQUAL 0) 210 | set(out "${out}-${res}-NOTFOUND") 211 | endif() 212 | 213 | set(${_var} 214 | "${out}" 215 | PARENT_SCOPE) 216 | endfunction() 217 | 218 | function(git_describe_working_tree _var) 219 | if(NOT GIT_FOUND) 220 | find_package(Git QUIET) 221 | endif() 222 | if(NOT GIT_FOUND) 223 | set(${_var} 224 | "GIT-NOTFOUND" 225 | PARENT_SCOPE) 226 | return() 227 | endif() 228 | 229 | execute_process( 230 | COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN} 231 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 232 | RESULT_VARIABLE res 233 | OUTPUT_VARIABLE out 234 | ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) 235 | if(NOT res EQUAL 0) 236 | set(out "${out}-${res}-NOTFOUND") 237 | endif() 238 | 239 | set(${_var} 240 | "${out}" 241 | PARENT_SCOPE) 242 | endfunction() 243 | 244 | function(git_get_exact_tag _var) 245 | git_describe(out --exact-match ${ARGN}) 246 | set(${_var} 247 | "${out}" 248 | PARENT_SCOPE) 249 | endfunction() 250 | 251 | function(git_local_changes _var) 252 | if(NOT GIT_FOUND) 253 | find_package(Git QUIET) 254 | endif() 255 | get_git_head_revision(refspec hash) 256 | if(NOT GIT_FOUND) 257 | set(${_var} 258 | "GIT-NOTFOUND" 259 | PARENT_SCOPE) 260 | return() 261 | endif() 262 | if(NOT hash) 263 | set(${_var} 264 | "HEAD-HASH-NOTFOUND" 265 | PARENT_SCOPE) 266 | return() 267 | endif() 268 | 269 | execute_process( 270 | COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD -- 271 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 272 | RESULT_VARIABLE res 273 | OUTPUT_VARIABLE out 274 | ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) 275 | if(res EQUAL 0) 276 | set(${_var} 277 | "CLEAN" 278 | PARENT_SCOPE) 279 | else() 280 | set(${_var} 281 | "DIRTY" 282 | PARENT_SCOPE) 283 | endif() 284 | endfunction() 285 | -------------------------------------------------------------------------------- /cmake/GetGitRevisionDescription.cmake.in: -------------------------------------------------------------------------------- 1 | # 2 | # Internal file for GetGitRevisionDescription.cmake 3 | # 4 | # Requires CMake 2.6 or newer (uses the 'function' command) 5 | # 6 | # Original Author: 7 | # 2009-2010 Ryan Pavlik 8 | # http://academic.cleardefinition.com 9 | # Iowa State University HCI Graduate Program/VRAC 10 | # 11 | # Copyright 2009-2012, Iowa State University 12 | # Copyright 2011-2015, Contributors 13 | # Distributed under the Boost Software License, Version 1.0. 14 | # (See accompanying file LICENSE_1_0.txt or copy at 15 | # http://www.boost.org/LICENSE_1_0.txt) 16 | # SPDX-License-Identifier: BSL-1.0 17 | 18 | set(HEAD_HASH) 19 | 20 | file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) 21 | 22 | string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) 23 | if(HEAD_CONTENTS MATCHES "ref") 24 | # named branch 25 | string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") 26 | if(EXISTS "@GIT_DIR@/${HEAD_REF}") 27 | configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) 28 | else() 29 | configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) 30 | file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) 31 | if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") 32 | set(HEAD_HASH "${CMAKE_MATCH_1}") 33 | endif() 34 | endif() 35 | else() 36 | # detached HEAD 37 | configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) 38 | endif() 39 | 40 | if(NOT HEAD_HASH) 41 | file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) 42 | string(STRIP "${HEAD_HASH}" HEAD_HASH) 43 | endif() 44 | -------------------------------------------------------------------------------- /cmake/PrivateSdlFunctions.cmake: -------------------------------------------------------------------------------- 1 | # This file is shared amongst SDL_image/SDL_mixer/SDL_ttf 2 | 3 | include(CheckCCompilerFlag) 4 | include(CheckCSourceCompiles) 5 | include(CMakePushCheckState) 6 | 7 | macro(sdl_calculate_derived_version_variables MAJOR MINOR MICRO) 8 | set(SO_VERSION_MAJOR "0") 9 | set(SO_VERSION_MINOR "${MINOR_VERSION}") 10 | set(SO_VERSION_MICRO "${MICRO_VERSION}") 11 | set(SO_VERSION "${SO_VERSION_MAJOR}.${SO_VERSION_MINOR}.${SO_VERSION_MICRO}") 12 | 13 | if(MINOR MATCHES "[02468]$") 14 | math(EXPR DYLIB_COMPAT_VERSION_MAJOR "100 * ${MINOR} + 1") 15 | set(DYLIB_COMPAT_VERSION_MINOR "0") 16 | math(EXPR DYLIB_CURRENT_VERSION_MAJOR "${DYLIB_COMPAT_VERSION_MAJOR}") 17 | set(DYLIB_CURRENT_VERSION_MINOR "${MICRO}") 18 | else() 19 | math(EXPR DYLIB_COMPAT_VERSION_MAJOR "100 * ${MINOR} + ${MICRO} + 1") 20 | set(DYLIB_COMPAT_VERSION_MINOR "0") 21 | math(EXPR DYLIB_CURRENT_VERSION_MAJOR "${DYLIB_COMPAT_VERSION_MAJOR}") 22 | set(DYLIB_CURRENT_VERSION_MINOR "0") 23 | endif() 24 | set(DYLIB_COMPAT_VERSION_MICRO "0") 25 | set(DYLIB_CURRENT_VERSION_MICRO "0") 26 | 27 | set(DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION_MAJOR}.${DYLIB_CURRENT_VERSION_MINOR}.${DYLIB_CURRENT_VERSION_MICRO}") 28 | set(DYLIB_COMPAT_VERSION "${DYLIB_COMPAT_VERSION_MAJOR}.${DYLIB_COMPAT_VERSION_MINOR}.${DYLIB_COMPAT_VERSION_MICRO}") 29 | endmacro() 30 | 31 | function(read_absolute_symlink DEST PATH) 32 | file(READ_SYMLINK "${PATH}" p) 33 | if(NOT IS_ABSOLUTE "${p}") 34 | get_filename_component(pdir "${PATH}" DIRECTORY) 35 | set(p "${pdir}/${p}") 36 | endif() 37 | get_filename_component(p "${p}" ABSOLUTE) 38 | set("${DEST}" "${p}" PARENT_SCOPE) 39 | endfunction() 40 | 41 | function(win32_implib_identify_dll DEST IMPLIB) 42 | cmake_parse_arguments(ARGS "NOTFATAL" "" "" ${ARGN}) 43 | if(CMAKE_DLLTOOL) 44 | execute_process( 45 | COMMAND "${CMAKE_DLLTOOL}" --identify "${IMPLIB}" 46 | RESULT_VARIABLE retcode 47 | OUTPUT_VARIABLE stdout 48 | ERROR_VARIABLE stderr) 49 | if(NOT retcode EQUAL 0) 50 | if(NOT ARGS_NOTFATAL) 51 | message(FATAL_ERROR "${CMAKE_DLLTOOL} failed.") 52 | else() 53 | set("${DEST}" "${DEST}-NOTFOUND" PARENT_SCOPE) 54 | return() 55 | endif() 56 | endif() 57 | string(STRIP "${stdout}" result) 58 | set(${DEST} "${result}" PARENT_SCOPE) 59 | elseif(MSVC) 60 | get_filename_component(CMAKE_C_COMPILER_DIRECTORY "${CMAKE_C_COMPILER}" DIRECTORY CACHE) 61 | find_program(CMAKE_DUMPBIN NAMES dumpbin PATHS "${CMAKE_C_COMPILER_DIRECTORY}") 62 | if(CMAKE_DUMPBIN) 63 | execute_process( 64 | COMMAND "${CMAKE_DUMPBIN}" "-headers" "${IMPLIB}" 65 | RESULT_VARIABLE retcode 66 | OUTPUT_VARIABLE stdout 67 | ERROR_VARIABLE stderr) 68 | if(NOT retcode EQUAL 0) 69 | if(NOT ARGS_NOTFATAL) 70 | message(FATAL_ERROR "dumpbin failed.") 71 | else() 72 | set(${DEST} "${DEST}-NOTFOUND" PARENT_SCOPE) 73 | return() 74 | endif() 75 | endif() 76 | string(REGEX MATCH "DLL name[ ]+:[ ]+([^\n]+)\n" match "${stdout}") 77 | if(NOT match) 78 | if(NOT ARGS_NOTFATAL) 79 | message(FATAL_ERROR "dumpbin did not find any associated dll for ${IMPLIB}.") 80 | else() 81 | set(${DEST} "${DEST}-NOTFOUND" PARENT_SCOPE) 82 | return() 83 | endif() 84 | endif() 85 | set(result "${CMAKE_MATCH_1}") 86 | set(${DEST} "${result}" PARENT_SCOPE) 87 | else() 88 | message(FATAL_ERROR "Cannot find dumpbin, please set CMAKE_DUMPBIN cmake variable") 89 | endif() 90 | else() 91 | if(NOT ARGS_NOTFATAL) 92 | message(FATAL_ERROR "Don't know how to identify dll from import library. Set CMAKE_DLLTOOL (for mingw) or CMAKE_DUMPBIN (for MSVC)") 93 | else() 94 | set(${DEST} "${DEST}-NOTFOUND") 95 | endif() 96 | endif() 97 | endfunction() 98 | 99 | function(get_actual_target) 100 | set(dst "${ARGV0}") 101 | set(target "${${dst}}") 102 | set(input "${target}") 103 | get_target_property(alias "${target}" ALIASED_TARGET) 104 | while(alias) 105 | set(target "${alias}") 106 | get_target_property(alias "${target}" ALIASED_TARGET) 107 | endwhile() 108 | message(DEBUG "get_actual_target(\"${input}\") -> \"${target}\"") 109 | set("${dst}" "${target}" PARENT_SCOPE) 110 | endfunction() 111 | 112 | function(target_get_dynamic_library DEST TARGET) 113 | set(result) 114 | if(DEFINED ${DEST}) 115 | if(NOT EXISTS "${${DEST}}") 116 | message(FATAL_ERROR "${DEST}=${${DEST}} does not exist") 117 | endif() 118 | get_filename_component(filename ${${DEST}} NAME) 119 | set(${DEST} ${filename} PARENT_SCOPE) 120 | else() 121 | get_actual_target(TARGET) 122 | if(WIN32) 123 | # Use the target dll of the import library 124 | set(props_to_check IMPORTED_IMPLIB) 125 | if(CMAKE_BUILD_TYPE) 126 | list(APPEND props_to_check IMPORTED_IMPLIB_${CMAKE_BUILD_TYPE}) 127 | endif() 128 | list(APPEND props_to_check IMPORTED_LOCATION) 129 | if(CMAKE_BUILD_TYPE) 130 | list(APPEND props_to_check IMPORTED_LOCATION_${CMAKE_BUILD_TYPE}) 131 | endif() 132 | foreach (config_type ${CMAKE_CONFIGURATION_TYPES} RELEASE DEBUG RELWITHDEBINFO MINSIZEREL) 133 | list(APPEND props_to_check IMPORTED_IMPLIB_${config_type}) 134 | list(APPEND props_to_check IMPORTED_LOCATION_${config_type}) 135 | endforeach() 136 | 137 | foreach(prop_to_check ${props_to_check}) 138 | if(NOT result) 139 | get_target_property(propvalue "${TARGET}" ${prop_to_check}) 140 | if(propvalue AND EXISTS "${propvalue}") 141 | win32_implib_identify_dll(result "${propvalue}" NOTFATAL) 142 | endif() 143 | endif() 144 | endforeach() 145 | else() 146 | # 1. find the target library a file might be symbolic linking to 147 | # 2. find all other files in the same folder that symolic link to it 148 | # 3. sort all these files, and select the 1st item on Linux, and last on Macos 149 | set(location_properties IMPORTED_LOCATION) 150 | if(CMAKE_BUILD_TYPE) 151 | list(APPEND location_properties IMPORTED_LOCATION_${CMAKE_BUILD_TYPE}) 152 | endif() 153 | foreach (config_type ${CMAKE_CONFIGURATION_TYPES} RELEASE DEBUG RELWITHDEBINFO MINSIZEREL) 154 | list(APPEND location_properties IMPORTED_LOCATION_${config_type}) 155 | endforeach() 156 | if(APPLE) 157 | set(valid_shared_library_regex "\\.[0-9]+\\.dylib$") 158 | else() 159 | set(valid_shared_library_regex "\\.so\\.([0-9.]+)?[0-9]") 160 | endif() 161 | foreach(location_property ${location_properties}) 162 | if(NOT result) 163 | get_target_property(library_path "${TARGET}" ${location_property}) 164 | message(DEBUG "get_target_property(${TARGET} ${location_propert}) -> ${library_path}") 165 | if(EXISTS "${library_path}") 166 | get_filename_component(library_path "${library_path}" ABSOLUTE) 167 | while (IS_SYMLINK "${library_path}") 168 | read_absolute_symlink(library_path "${library_path}") 169 | endwhile() 170 | message(DEBUG "${TARGET} -> ${library_path}") 171 | get_filename_component(libdir "${library_path}" DIRECTORY) 172 | file(GLOB subfiles "${libdir}/*") 173 | set(similar_files "${library_path}") 174 | foreach(subfile ${subfiles}) 175 | if(IS_SYMLINK "${subfile}") 176 | read_absolute_symlink(subfile_target "${subfile}") 177 | while(IS_SYMLINK "${subfile_target}") 178 | read_absolute_symlink(subfile_target "${subfile_target}") 179 | endwhile() 180 | get_filename_component(subfile_target "${subfile_target}" ABSOLUTE) 181 | if(subfile_target STREQUAL library_path AND subfile MATCHES "${valid_shared_library_regex}") 182 | list(APPEND similar_files "${subfile}") 183 | endif() 184 | endif() 185 | endforeach() 186 | list(SORT similar_files) 187 | message(DEBUG "files that are similar to \"${library_path}\"=${similar_files}") 188 | if(APPLE) 189 | list(REVERSE similar_files) 190 | endif() 191 | list(GET similar_files 0 item) 192 | get_filename_component(result "${item}" NAME) 193 | endif() 194 | endif() 195 | endforeach() 196 | endif() 197 | if(result) 198 | string(TOLOWER "${result}" result_lower) 199 | if(WIN32 OR OS2) 200 | if(NOT result_lower MATCHES ".*dll") 201 | message(FATAL_ERROR "\"${result}\" is not a .dll library") 202 | endif() 203 | elseif(APPLE) 204 | if(NOT result_lower MATCHES ".*dylib.*") 205 | message(FATAL_ERROR "\"${result}\" is not a .dylib shared library") 206 | endif() 207 | else() 208 | if(NOT result_lower MATCHES ".*so.*") 209 | message(FATAL_ERROR "\"${result}\" is not a .so shared library") 210 | endif() 211 | endif() 212 | else() 213 | get_target_property(target_type ${TARGET} TYPE) 214 | if(target_type MATCHES "SHARED_LIBRARY|MODULE_LIBRARY") 215 | # OK 216 | elseif(target_type MATCHES "STATIC_LIBRARY|OBJECT_LIBRARY|INTERFACE_LIBRARY|EXECUTABLE") 217 | message(SEND_ERROR "${TARGET} is not a shared library, but has type=${target_type}") 218 | else() 219 | message(WARNING "Unable to extract dynamic library from target=${TARGET}, type=${target_type}.") 220 | endif() 221 | # TARGET_SONAME_FILE is not allowed for DLL target platforms. 222 | if(WIN32) 223 | set(result "$") 224 | else() 225 | set(result "$") 226 | endif() 227 | endif() 228 | set(${DEST} ${result} PARENT_SCOPE) 229 | endif() 230 | endfunction() 231 | 232 | function(sdl_check_project_in_subfolder relative_subfolder name vendored_option) 233 | cmake_parse_arguments(ARG "" "FILE" "" ${ARGN}) 234 | if(NOT ARG_FILE) 235 | set(ARG_FILE "CMakeLists.txt") 236 | endif() 237 | if(NOT EXISTS "${PROJECT_SOURCE_DIR}/${relative_subfolder}/${ARG_FILE}") 238 | message(FATAL_ERROR "Could not find ${ARG_FILE} for ${name} in ${relative_subfolder}.\n" 239 | "Run the download script in the external folder, or re-configure with -D${vendored_option}=OFF to use system packages.") 240 | endif() 241 | endfunction() 242 | 243 | macro(sdl_check_linker_flag flag var) 244 | # FIXME: Use CheckLinkerFlag module once cmake minimum version >= 3.18 245 | cmake_push_check_state(RESET) 246 | set(CMAKE_REQUIRED_LINK_OPTIONS "${flag}") 247 | check_c_source_compiles("int main() { return 0; }" ${var} FAIL_REGEX "(unsupported|syntax error|unrecognized option)") 248 | cmake_pop_check_state() 249 | endmacro() 250 | 251 | function(SDL_detect_linker) 252 | if(CMAKE_VERSION VERSION_LESS 3.29) 253 | if(NOT DEFINED SDL_CMAKE_C_COMPILER_LINKER_ID) 254 | execute_process(COMMAND ${CMAKE_LINKER} -v OUTPUT_VARIABLE LINKER_OUTPUT ERROR_VARIABLE LINKER_OUTPUT) 255 | string(REGEX REPLACE "[\r\n]" " " LINKER_OUTPUT "${LINKER_OUTPUT}") 256 | if(LINKER_OUTPUT MATCHES ".*Microsoft.*") 257 | set(linker MSVC) 258 | else() 259 | set(linker GNUlike) 260 | endif() 261 | message(STATUS "Linker identification: ${linker}") 262 | set(SDL_CMAKE_C_COMPILER_LINKER_ID "${linker}" CACHE STRING "Linker identification") 263 | mark_as_advanced(SDL_CMAKE_C_COMPILER_LINKER_ID) 264 | endif() 265 | set(CMAKE_C_COMPILER_LINKER_ID "${SDL_CMAKE_C_COMPILER_LINKER_ID}" PARENT_SCOPE) 266 | endif() 267 | endfunction() 268 | 269 | function(check_linker_support_version_script VAR) 270 | SDL_detect_linker() 271 | if(CMAKE_C_COMPILER_LINKER_ID MATCHES "^(MSVC)$") 272 | set(LINKER_SUPPORTS_VERSION_SCRIPT FALSE) 273 | else() 274 | cmake_push_check_state(RESET) 275 | file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.sym" "n_0 {\n global:\n func;\n local: *;\n};\n") 276 | list(APPEND CMAKE_REQUIRED_LINK_OPTIONS "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/dummy.sym") 277 | check_c_source_compiles("int func(void) {return 0;} int main(int argc,char*argv[]){(void)argc;(void)argv;return func();}" LINKER_SUPPORTS_VERSION_SCRIPT FAIL_REGEX "(unsupported|syntax error|unrecognized option)") 278 | cmake_pop_check_state() 279 | endif() 280 | set(${VAR} "${LINKER_SUPPORTS_VERSION_SCRIPT}" PARENT_SCOPE) 281 | endfunction() 282 | 283 | function(sdl_target_link_options_no_undefined TARGET) 284 | if(NOT MSVC AND NOT CMAKE_SYSTEM_NAME MATCHES ".*OpenBSD.*") 285 | if(CMAKE_C_COMPILER_ID MATCHES "AppleClang") 286 | target_link_options(${TARGET} PRIVATE "-Wl,-undefined,error") 287 | else() 288 | sdl_check_linker_flag("-Wl,--no-undefined" HAVE_WL_NO_UNDEFINED) 289 | if(HAVE_WL_NO_UNDEFINED AND NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") AND WIN32)) 290 | target_link_options(${TARGET} PRIVATE "-Wl,--no-undefined") 291 | endif() 292 | endif() 293 | endif() 294 | endfunction() 295 | 296 | function(sdl_target_link_option_version_file TARGET VERSION_SCRIPT) 297 | check_linker_support_version_script(HAVE_WL_VERSION_SCRIPT) 298 | if(HAVE_WL_VERSION_SCRIPT) 299 | target_link_options(${TARGET} PRIVATE "-Wl,--version-script=${VERSION_SCRIPT}") 300 | set_property(TARGET ${TARGET} APPEND PROPERTY LINK_DEPENDS "${VERSION_SCRIPT}") 301 | else() 302 | if(LINUX OR ANDROID) 303 | message(FATAL_ERROR "Linker does not support '-Wl,--version-script=xxx.sym'. This is required on the current host platform.") 304 | endif() 305 | endif() 306 | endfunction() 307 | 308 | function(sdl_add_warning_options TARGET) 309 | cmake_parse_arguments(ARGS "" "WARNING_AS_ERROR" "" ${ARGN}) 310 | if(MSVC) 311 | target_compile_options(${TARGET} PRIVATE /W2) 312 | else() 313 | target_compile_options(${TARGET} PRIVATE -Wall -Wextra) 314 | endif() 315 | if(ARGS_WARNING_AS_ERROR) 316 | if(MSVC) 317 | target_compile_options(${TARGET} PRIVATE /WX) 318 | else() 319 | target_compile_options(${TARGET} PRIVATE -Werror) 320 | endif() 321 | endif() 322 | endfunction() 323 | 324 | function(sdl_no_deprecated_errors TARGET) 325 | check_c_compiler_flag(-Wno-error=deprecated-declarations HAVE_WNO_ERROR_DEPRECATED_DECLARATIONS) 326 | if(HAVE_WNO_ERROR_DEPRECATED_DECLARATIONS) 327 | target_compile_options(${TARGET} PRIVATE "-Wno-error=deprecated-declarations") 328 | endif() 329 | endfunction() 330 | 331 | function(sdl_get_git_revision_hash VARNAME) 332 | set("${VARNAME}" "" CACHE STRING "${PROJECT_NAME} revision") 333 | set(revision "${${VARNAME}}") 334 | if(NOT revision) 335 | if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION.txt") 336 | # If VERSION.txt exists, it contains the SDL version 337 | file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION.txt" revision_version) 338 | string(STRIP "${revision_version}" revision_version) 339 | else() 340 | # If VERSION.txt does not exist, use git to calculate a version 341 | git_describe(revision_version) 342 | if(NOT revision_version) 343 | set(revision_version "${PROJECT_VERSION}-no-vcs") 344 | endif() 345 | endif() 346 | set(revision "${revision_version}") 347 | endif() 348 | set("${VARNAME}" "${revision}" PARENT_SCOPE) 349 | endfunction() 350 | 351 | function(SDL_install_pdb TARGET DIRECTORY) 352 | get_property(type TARGET ${TARGET} PROPERTY TYPE) 353 | if(type MATCHES "^(SHARED_LIBRARY|EXECUTABLE)$") 354 | install(FILES $ DESTINATION "${DIRECTORY}" OPTIONAL) 355 | elseif(type STREQUAL "STATIC_LIBRARY") 356 | # FIXME: Use $= @SDL_REQUIRED_VERSION@ 10 | Libs: -L${libdir} -lSDL3_shadercross 11 | Requires.private: @PC_REQUIRES@ 12 | Libs.private: @PC_LIBS@ 13 | Cflags: -I${includedir} 14 | -------------------------------------------------------------------------------- /cmake/sdlcpu.cmake: -------------------------------------------------------------------------------- 1 | function(SDL_DetectTargetCPUArchitectures DETECTED_ARCHS) 2 | 3 | set(known_archs EMSCRIPTEN ARM32 ARM64 ARM64EC LOONGARCH64 POWERPC32 POWERPC64 X86 X64) 4 | 5 | if(APPLE AND CMAKE_OSX_ARCHITECTURES) 6 | foreach(known_arch IN LISTS known_archs) 7 | set(SDL_CPU_${known_arch} "0") 8 | endforeach() 9 | set(detected_archs) 10 | foreach(osx_arch IN LISTS CMAKE_OSX_ARCHITECTURES) 11 | if(osx_arch STREQUAL "x86_64") 12 | set(SDL_CPU_X64 "1") 13 | list(APPEND detected_archs "X64") 14 | elseif(osx_arch STREQUAL "arm64") 15 | set(SDL_CPU_ARM64 "1") 16 | list(APPEND detected_archs "ARM64") 17 | endif() 18 | endforeach() 19 | set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) 20 | return() 21 | endif() 22 | 23 | set(detected_archs) 24 | foreach(known_arch IN LISTS known_archs) 25 | if(SDL_CPU_${known_arch}) 26 | list(APPEND detected_archs "${known_arch}") 27 | endif() 28 | endforeach() 29 | 30 | if(detected_archs) 31 | set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) 32 | return() 33 | endif() 34 | 35 | set(arch_check_ARM32 "defined(__arm__) || defined(_M_ARM)") 36 | set(arch_check_ARM64 "defined(__aarch64__) || defined(_M_ARM64)") 37 | set(arch_check_ARM64EC "defined(_M_ARM64EC)") 38 | set(arch_check_EMSCRIPTEN "defined(__EMSCRIPTEN__)") 39 | set(arch_check_LOONGARCH64 "defined(__loongarch64)") 40 | set(arch_check_POWERPC32 "(defined(__PPC__) || defined(__powerpc__)) && !defined(__powerpc64__)") 41 | set(arch_check_POWERPC64 "defined(__PPC64__) || defined(__powerpc64__)") 42 | set(arch_check_X86 "defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) ||defined( __i386) || defined(_M_IX86)") 43 | set(arch_check_X64 "(defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC)") 44 | 45 | set(src_vars "") 46 | set(src_main "") 47 | foreach(known_arch IN LISTS known_archs) 48 | set(detected_${known_arch} "0") 49 | 50 | string(APPEND src_vars " 51 | #if ${arch_check_${known_arch}} 52 | #define ARCH_${known_arch} \"1\" 53 | #else 54 | #define ARCH_${known_arch} \"0\" 55 | #endif 56 | const char *arch_${known_arch} = \"INFO<${known_arch}=\" ARCH_${known_arch} \">\"; 57 | ") 58 | string(APPEND src_main " 59 | result += arch_${known_arch}[argc];") 60 | endforeach() 61 | 62 | set(src_arch_detect "${src_vars} 63 | int main(int argc, char *argv[]) { 64 | (void)argv; 65 | int result = 0; 66 | ${src_main} 67 | return result; 68 | }") 69 | 70 | if(CMAKE_C_COMPILER) 71 | set(ext ".c") 72 | elseif(CMAKE_CXX_COMPILER) 73 | set(ext ".cpp") 74 | else() 75 | enable_language(C) 76 | set(ext ".c") 77 | endif() 78 | set(path_src_arch_detect "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/SDL_detect_arch${ext}") 79 | file(WRITE "${path_src_arch_detect}" "${src_arch_detect}") 80 | set(path_dir_arch_detect "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/SDL_detect_arch") 81 | set(path_bin_arch_detect "${path_dir_arch_detect}/bin") 82 | 83 | set(detected_archs) 84 | 85 | set(msg "Detecting Target CPU Architecture") 86 | message(STATUS "${msg}") 87 | 88 | include(CMakePushCheckState) 89 | 90 | set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") 91 | 92 | cmake_push_check_state(RESET) 93 | try_compile(SDL_CPU_CHECK_ALL 94 | "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/SDL_detect_arch" 95 | SOURCES "${path_src_arch_detect}" 96 | COPY_FILE "${path_bin_arch_detect}" 97 | ) 98 | cmake_pop_check_state() 99 | if(NOT SDL_CPU_CHECK_ALL) 100 | message(STATUS "${msg} - ") 101 | message(WARNING "Failed to compile source detecting the target CPU architecture") 102 | else() 103 | set(re "INFO<([A-Z0-9]+)=([01])>") 104 | file(STRINGS "${path_bin_arch_detect}" infos REGEX "${re}") 105 | 106 | foreach(info_arch_01 IN LISTS infos) 107 | string(REGEX MATCH "${re}" A "${info_arch_01}") 108 | if(NOT "${CMAKE_MATCH_1}" IN_LIST known_archs) 109 | message(WARNING "Unknown architecture: \"${CMAKE_MATCH_1}\"") 110 | continue() 111 | endif() 112 | set(arch "${CMAKE_MATCH_1}") 113 | set(arch_01 "${CMAKE_MATCH_2}") 114 | set(detected_${arch} "${arch_01}") 115 | endforeach() 116 | 117 | foreach(known_arch IN LISTS known_archs) 118 | if(detected_${known_arch}) 119 | list(APPEND detected_archs ${known_arch}) 120 | endif() 121 | endforeach() 122 | endif() 123 | 124 | if(detected_archs) 125 | foreach(known_arch IN LISTS known_archs) 126 | set("SDL_CPU_${known_arch}" "${detected_${known_arch}}" CACHE BOOL "Detected architecture ${known_arch}") 127 | endforeach() 128 | message(STATUS "${msg} - ${detected_archs}") 129 | else() 130 | include(CheckCSourceCompiles) 131 | cmake_push_check_state(RESET) 132 | foreach(known_arch IN LISTS known_archs) 133 | if(NOT detected_archs) 134 | set(cache_variable "SDL_CPU_${known_arch}") 135 | set(test_src " 136 | int main(int argc, char *argv[]) { 137 | #if ${arch_check_${known_arch}} 138 | return 0; 139 | #else 140 | choke 141 | #endif 142 | } 143 | ") 144 | check_c_source_compiles("${test_src}" "${cache_variable}") 145 | if(${cache_variable}) 146 | set(SDL_CPU_${known_arch} "1" CACHE BOOL "Detected architecture ${known_arch}") 147 | set(detected_archs ${known_arch}) 148 | else() 149 | set(SDL_CPU_${known_arch} "0" CACHE BOOL "Detected architecture ${known_arch}") 150 | endif() 151 | endif() 152 | endforeach() 153 | cmake_pop_check_state() 154 | endif() 155 | set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) 156 | endfunction() 157 | -------------------------------------------------------------------------------- /cmake/sdlmanpages.cmake: -------------------------------------------------------------------------------- 1 | include(CMakeParseArguments) 2 | include(GNUInstallDirs) 3 | 4 | function(SDL_generate_manpages) 5 | cmake_parse_arguments(ARG "" "RESULT_VARIABLE;NAME;BUILD_DOCDIR;HEADERS_DIR;SOURCE_DIR;SYMBOL;OPTION_FILE;WIKIHEADERS_PL_PATH;REVISION" "" ${ARGN}) 6 | 7 | set(wikiheaders_extra_args) 8 | 9 | if(NOT ARG_NAME) 10 | set(ARG_NAME "${PROJECT_NAME}") 11 | endif() 12 | 13 | if(NOT ARG_SOURCE_DIR) 14 | set(ARG_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 15 | endif() 16 | 17 | if(NOT ARG_OPTION_FILE) 18 | set(ARG_OPTION_FILE "${PROJECT_SOURCE_DIR}/.wikiheaders-options") 19 | endif() 20 | 21 | if(NOT ARG_HEADERS_DIR) 22 | message(FATAL_ERROR "Missing required HEADERS_DIR argument") 23 | endif() 24 | 25 | # FIXME: get rid of SYMBOL and let the perl script figure out the dependencies 26 | if(NOT ARG_SYMBOL) 27 | message(FATAL_ERROR "Missing required SYMBOL argument") 28 | endif() 29 | 30 | if(ARG_REVISION) 31 | list(APPEND wikiheaders_extra_args "--rev=${ARG_REVISION}") 32 | endif() 33 | 34 | if(NOT ARG_BUILD_DOCDIR) 35 | set(ARG_BUILD_DOCDIR "${CMAKE_CURRENT_BINARY_DIR}/docs") 36 | endif() 37 | set(BUILD_WIKIDIR "${ARG_BUILD_DOCDIR}/wiki") 38 | set(BUILD_MANDIR "${ARG_BUILD_DOCDIR}/man") 39 | 40 | find_package(Perl) 41 | file(GLOB HEADER_FILES "${ARG_HEADERS_DIR}/*.h") 42 | 43 | set(result FALSE) 44 | 45 | if(PERL_FOUND AND EXISTS "${ARG_WIKIHEADERS_PL_PATH}") 46 | add_custom_command( 47 | OUTPUT "${BUILD_WIKIDIR}/${ARG_SYMBOL}.md" 48 | COMMAND "${CMAKE_COMMAND}" -E make_directory "${BUILD_WIKIDIR}" 49 | COMMAND "${PERL_EXECUTABLE}" "${ARG_WIKIHEADERS_PL_PATH}" "${ARG_SOURCE_DIR}" "${BUILD_WIKIDIR}" "--options=${ARG_OPTION_FILE}" --copy-to-wiki ${wikiheaders_extra_args} 50 | DEPENDS ${HEADER_FILES} "${ARG_WIKIHEADERS_PL_PATH}" "${ARG_OPTION_FILE}" 51 | COMMENT "Generating ${ARG_NAME} wiki markdown files" 52 | ) 53 | add_custom_command( 54 | OUTPUT "${BUILD_MANDIR}/man3/${ARG_SYMBOL}.3" 55 | COMMAND "${PERL_EXECUTABLE}" "${ARG_WIKIHEADERS_PL_PATH}" "${ARG_SOURCE_DIR}" "${BUILD_WIKIDIR}" "--options=${ARG_OPTION_FILE}" "--manpath=${BUILD_MANDIR}" --copy-to-manpages ${wikiheaders_extra_args} 56 | DEPENDS "${BUILD_WIKIDIR}/${ARG_SYMBOL}.md" "${ARG_WIKIHEADERS_PL_PATH}" "${ARG_OPTION_FILE}" 57 | COMMENT "Generating ${ARG_NAME} man pages" 58 | ) 59 | add_custom_target(${ARG_NAME}-docs ALL DEPENDS "${BUILD_MANDIR}/man3/${ARG_SYMBOL}.3") 60 | 61 | install(DIRECTORY "${BUILD_MANDIR}/" DESTINATION "${CMAKE_INSTALL_MANDIR}") 62 | set(result TRUE) 63 | endif() 64 | 65 | if(ARG_RESULT_VARIABLE) 66 | set(${ARG_RESULT_VARIABLE} ${result} PARENT_SCOPE) 67 | endif() 68 | endfunction() 69 | -------------------------------------------------------------------------------- /cmake/sdlplatform.cmake: -------------------------------------------------------------------------------- 1 | macro(SDL_DetectCMakePlatform) 2 | set(SDL_CMAKE_PLATFORM ) 3 | # Get the platform 4 | if(WIN32) 5 | set(SDL_CMAKE_PLATFORM Windows) 6 | elseif(PSP) 7 | set(SDL_CMAKE_PLATFORM psp) 8 | elseif(APPLE) 9 | if(CMAKE_SYSTEM_NAME MATCHES ".*Darwin.*") 10 | set(SDL_CMAKE_PLATFORM Darwin) 11 | elseif(CMAKE_SYSTEM_NAME MATCHES ".*MacOS.*") 12 | set(SDL_CMAKE_PLATFORM MacosX) 13 | elseif(CMAKE_SYSTEM_NAME MATCHES ".*tvOS.*") 14 | set(SDL_CMAKE_PLATFORM tvOS) 15 | elseif(CMAKE_SYSTEM_NAME MATCHES ".*iOS.*") 16 | set(SDL_CMAKE_PLATFORM iOS) 17 | endif() 18 | elseif(CMAKE_SYSTEM_NAME MATCHES "Haiku.*") 19 | set(SDL_CMAKE_PLATFORM Haiku) 20 | elseif(NINTENDO_3DS) 21 | set(SDL_CMAKE_PLATFORM n3ds) 22 | elseif(PS2) 23 | set(SDL_CMAKE_PLATFORM ps2) 24 | elseif(VITA) 25 | set(SDL_CMAKE_PLATFORM Vita) 26 | elseif(CMAKE_SYSTEM_NAME MATCHES ".*Linux") 27 | set(SDL_CMAKE_PLATFORM Linux) 28 | elseif(CMAKE_SYSTEM_NAME MATCHES "kFreeBSD.*") 29 | set(SDL_CMAKE_PLATFORM FreeBSD) 30 | elseif(CMAKE_SYSTEM_NAME MATCHES "kNetBSD.*|NetBSD.*") 31 | set(SDL_CMAKE_PLATFORM NetBSD) 32 | elseif(CMAKE_SYSTEM_NAME MATCHES "kOpenBSD.*|OpenBSD.*") 33 | set(SDL_CMAKE_PLATFORM OpenBSD) 34 | elseif(CMAKE_SYSTEM_NAME MATCHES ".*GNU.*") 35 | set(SDL_CMAKE_PLATFORM GNU) 36 | elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSDI.*") 37 | set(SDL_CMAKE_PLATFORM BSDi) 38 | elseif(CMAKE_SYSTEM_NAME MATCHES "DragonFly.*|FreeBSD") 39 | set(SDL_CMAKE_PLATFORM FreeBSD) 40 | elseif(CMAKE_SYSTEM_NAME MATCHES "SYSV5.*") 41 | set(SDL_CMAKE_PLATFORM SYSV5) 42 | elseif(CMAKE_SYSTEM_NAME MATCHES "Solaris.*|SunOS.*") 43 | set(SDL_CMAKE_PLATFORM Solaris) 44 | elseif(CMAKE_SYSTEM_NAME MATCHES "HP-UX.*") 45 | set(SDL_CMAKE_PLATFORM HPUX) 46 | elseif(CMAKE_SYSTEM_NAME MATCHES "AIX.*") 47 | set(SDL_CMAKE_PLATFORM AIX) 48 | elseif(CMAKE_SYSTEM_NAME MATCHES "Minix.*") 49 | set(SDL_CMAKE_PLATFORM Minix) 50 | elseif(CMAKE_SYSTEM_NAME MATCHES "Android.*") 51 | set(SDL_CMAKE_PLATFORM Android) 52 | elseif(CMAKE_SYSTEM_NAME MATCHES "Emscripten.*") 53 | set(SDL_CMAKE_PLATFORM Emscripten) 54 | elseif(CMAKE_SYSTEM_NAME MATCHES "QNX.*") 55 | set(SDL_CMAKE_PLATFORM QNX) 56 | elseif(CMAKE_SYSTEM_NAME MATCHES "BeOS.*") 57 | message(FATAL_ERROR "BeOS support has been removed as of SDL 2.0.2.") 58 | endif() 59 | 60 | if(SDL_CMAKE_PLATFORM) 61 | string(TOUPPER "${SDL_CMAKE_PLATFORM}" _upper_platform) 62 | set(${_upper_platform} TRUE) 63 | else() 64 | set(SDL_CMAKE_PLATFORM} "unknown") 65 | endif() 66 | endmacro() 67 | 68 | function(SDL_DetectCPUArchitecture) 69 | set(sdl_cpu_names) 70 | if(APPLE AND CMAKE_OSX_ARCHITECTURES) 71 | foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES}) 72 | if(osx_arch STREQUAL "x86_64") 73 | list(APPEND sdl_cpu_names "x64") 74 | elseif(osx_arch STREQUAL "arm64") 75 | list(APPEND sdl_cpu_names "arm64") 76 | endif() 77 | endforeach() 78 | endif() 79 | 80 | set(sdl_known_archs x64 x86 arm64 arm32 emscripten powerpc64 powerpc32 loongarch64) 81 | if(NOT sdl_cpu_names) 82 | set(found FALSE) 83 | foreach(sdl_known_arch ${sdl_known_archs}) 84 | if(NOT found) 85 | string(TOUPPER "${sdl_known_arch}" sdl_known_arch_upper) 86 | set(var_name "SDL_CPU_${sdl_known_arch_upper}") 87 | check_cpu_architecture(${sdl_known_arch} ${var_name}) 88 | if(${var_name}) 89 | list(APPEND sdl_cpu_names ${sdl_known_arch}) 90 | set(found TRUE) 91 | endif() 92 | endif() 93 | endforeach() 94 | endif() 95 | 96 | foreach(sdl_known_arch ${sdl_known_archs}) 97 | string(TOUPPER "${sdl_known_arch}" sdl_known_arch_upper) 98 | set(var_name "SDL_CPU_${sdl_known_arch_upper}") 99 | if(sdl_cpu_names MATCHES "(^|;)${sdl_known_arch}($|;)") # FIXME: use if(IN_LIST) 100 | set(${var_name} 1 PARENT_SCOPE) 101 | else() 102 | set(${var_name} 0 PARENT_SCOPE) 103 | endif() 104 | endforeach() 105 | set(SDL_CPU_NAMES ${sdl_cpu_names} PARENT_SCOPE) 106 | endfunction() 107 | -------------------------------------------------------------------------------- /cmake/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This cmake build script is meant for verifying the various CMake configuration script. 2 | 3 | cmake_minimum_required(VERSION 3.12) 4 | project(sdl_test LANGUAGES C) 5 | 6 | cmake_policy(SET CMP0074 NEW) 7 | 8 | # Override CMAKE_FIND_ROOT_PATH_MODE to allow search for SDL3 outside of sysroot 9 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER) 10 | 11 | include(FeatureSummary) 12 | 13 | option(TEST_SHARED "Test linking to shared SDL3_shadercross library" ON) 14 | add_feature_info("TEST_SHARED" TEST_SHARED "Test linking with shared library") 15 | 16 | option(TEST_STATIC "Test linking to static SDL3_shadercross library" ON) 17 | add_feature_info("TEST_STATIC" TEST_STATIC "Test linking with static library") 18 | 19 | if(ANDROID) 20 | macro(add_executable NAME) 21 | set(args ${ARGN}) 22 | list(REMOVE_ITEM args WIN32) 23 | add_library(${NAME} SHARED ${args}) 24 | unset(args) 25 | endmacro() 26 | endif() 27 | 28 | if(TEST_SHARED) 29 | find_package(SDL3 REQUIRED CONFIG COMPONENTS SDL3) 30 | find_package(SDL3_shadercross REQUIRED CONFIG) 31 | add_executable(main_shared main.c) 32 | target_link_libraries(main_shared PRIVATE SDL3_shadercross::SDL3_shadercross-shared SDL3::SDL3) 33 | endif() 34 | 35 | if(TEST_STATIC) 36 | find_package(SDL3 REQUIRED CONFIG COMPONENTS SDL3) 37 | # some static vendored libraries use c++ (enable CXX after `find_package` might show a warning) 38 | enable_language(CXX) 39 | find_package(SDL3_shadercross REQUIRED CONFIG) 40 | add_executable(main_static main.c) 41 | target_link_libraries(main_static PRIVATE SDL3_shadercross::SDL3_shadercross-static SDL3::SDL3) 42 | endif() 43 | 44 | feature_summary(WHAT ALL) 45 | -------------------------------------------------------------------------------- /cmake/test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | if (!SDL_Init(0)) { 6 | SDL_Log("SDL_Init failed (%s)", SDL_GetError()); 7 | return 1; 8 | } 9 | if (!SDL_ShaderCross_Init()) { 10 | SDL_Log("SDL_ShaderCross_Init failed (%s)", SDL_GetError()); 11 | return 1; 12 | } 13 | SDL_ShaderCross_Quit(); 14 | SDL_Quit(); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /external/Get-GitModules.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Downloads the Git modules specified in ../.gitmodules 4 | 5 | .DESCRIPTION 6 | Parses and downloads the Github repositories specified in the .gitmodules file 7 | 8 | .EXAMPLE 9 | PS> .\Get-GitModules.ps1 10 | < Downloads and parses the repositories in the .gitmodules file. > 11 | #> 12 | 13 | #------- Variables ------------------------------------------------------------- 14 | [String] $PathRegex = "path\s*=\s*(?.*)" 15 | [String] $URLRegex = "url\s*=\s*(?.*)" 16 | [String] $BranchRegex = "branch\s*=\s*(?.*)" 17 | 18 | #------- Script ---------------------------------------------------------------- 19 | foreach ($Line in Get-Content $PSScriptRoot\..\.gitmodules) { 20 | if ($Line -match $PathRegex) { 21 | $Match = Select-String -InputObject $Line -Pattern $PathRegex 22 | $Path = $Match.Matches[0].Groups[1].Value 23 | } 24 | elseif ($Line -match $URLRegex) { 25 | $Match = Select-String -InputObject $Line -Pattern $URLRegex 26 | $URL = $Match.Matches[0].Groups[1].Value 27 | } 28 | elseif ($Line -match $BranchRegex) { 29 | $Match = Select-String -InputObject $Line -Pattern $BranchRegex 30 | $Branch = $Match.Matches[0].Groups[1].Value 31 | 32 | Write-Host "git clone --filter=blob:none $URL $Path -b $Branch --recursive" ` 33 | -ForegroundColor Blue 34 | git clone --filter=blob:none $URL $PSScriptRoot/../$Path -b $Branch --recursive 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /external/download.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | ARGUMENTS="$*" 6 | 7 | cd $(dirname "$0")/.. 8 | cat .gitmodules | \ 9 | while true; do 10 | read module || break 11 | read line; set -- $line 12 | path=$3 13 | read line; set -- $line 14 | url=$3 15 | read line; set -- $line 16 | branch=$3 17 | git clone --filter=blob:none $url $path -b $branch --recursive $ARGUMENTS 18 | done 19 | -------------------------------------------------------------------------------- /include/SDL3_shadercross/SDL_shadercross.h: -------------------------------------------------------------------------------- 1 | /* 2 | Simple DirectMedia Layer Shader Cross Compiler 3 | Copyright (C) 2024 Sam Lantinga 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | #ifndef SDL_SHADERCROSS_H 23 | #define SDL_SHADERCROSS_H 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | /* Set up for C function definitions, even when using C++ */ 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | /** 35 | * Printable format: "%d.%d.%d", MAJOR, MINOR, MICRO 36 | */ 37 | #define SDL_SHADERCROSS_MAJOR_VERSION 3 38 | #define SDL_SHADERCROSS_MINOR_VERSION 0 39 | #define SDL_SHADERCROSS_MICRO_VERSION 0 40 | 41 | typedef enum SDL_ShaderCross_IOVarType { 42 | SDL_SHADERCROSS_IOVAR_TYPE_UNKNOWN, 43 | SDL_SHADERCROSS_IOVAR_TYPE_INT8, 44 | SDL_SHADERCROSS_IOVAR_TYPE_UINT8, 45 | SDL_SHADERCROSS_IOVAR_TYPE_INT16, 46 | SDL_SHADERCROSS_IOVAR_TYPE_UINT16, 47 | SDL_SHADERCROSS_IOVAR_TYPE_INT32, 48 | SDL_SHADERCROSS_IOVAR_TYPE_UINT32, 49 | SDL_SHADERCROSS_IOVAR_TYPE_INT64, 50 | SDL_SHADERCROSS_IOVAR_TYPE_UINT64, 51 | SDL_SHADERCROSS_IOVAR_TYPE_FLOAT16, 52 | SDL_SHADERCROSS_IOVAR_TYPE_FLOAT32, 53 | SDL_SHADERCROSS_IOVAR_TYPE_FLOAT64 54 | } SDL_ShaderCross_IOVarType; 55 | 56 | typedef enum SDL_ShaderCross_ShaderStage 57 | { 58 | SDL_SHADERCROSS_SHADERSTAGE_VERTEX, 59 | SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT, 60 | SDL_SHADERCROSS_SHADERSTAGE_COMPUTE 61 | } SDL_ShaderCross_ShaderStage; 62 | 63 | typedef struct SDL_ShaderCross_IOVarMetadata { 64 | char *name; /**< The UTF-8 name of the variable. */ 65 | Uint32 location; /**< The location of the variable. */ 66 | Uint32 offset; /**< The byte offset of the variable. */ 67 | SDL_ShaderCross_IOVarType vector_type; /**< The vector type of the variable. */ 68 | Uint32 vector_size; /**< The number of components in the vector type of the variable. */ 69 | } SDL_ShaderCross_IOVarMetadata; 70 | 71 | typedef struct SDL_ShaderCross_GraphicsShaderMetadata 72 | { 73 | Uint32 num_samplers; /**< The number of samplers defined in the shader. */ 74 | Uint32 num_storage_textures; /**< The number of storage textures defined in the shader. */ 75 | Uint32 num_storage_buffers; /**< The number of storage buffers defined in the shader. */ 76 | Uint32 num_uniform_buffers; /**< The number of uniform buffers defined in the shader. */ 77 | Uint32 num_inputs; /**< The number of inputs defined in the shader. */ 78 | SDL_ShaderCross_IOVarMetadata *inputs; /**< The inputs defined in the shader. */ 79 | Uint32 num_outputs; /**< The number of outputs defined in the shader. */ 80 | SDL_ShaderCross_IOVarMetadata *outputs; /**< The outputs defined in the shader. */ 81 | } SDL_ShaderCross_GraphicsShaderMetadata; 82 | 83 | typedef struct SDL_ShaderCross_ComputePipelineMetadata 84 | { 85 | Uint32 num_samplers; /**< The number of samplers defined in the shader. */ 86 | Uint32 num_readonly_storage_textures; /**< The number of readonly storage textures defined in the shader. */ 87 | Uint32 num_readonly_storage_buffers; /**< The number of readonly storage buffers defined in the shader. */ 88 | Uint32 num_readwrite_storage_textures; /**< The number of read-write storage textures defined in the shader. */ 89 | Uint32 num_readwrite_storage_buffers; /**< The number of read-write storage buffers defined in the shader. */ 90 | Uint32 num_uniform_buffers; /**< The number of uniform buffers defined in the shader. */ 91 | Uint32 threadcount_x; /**< The number of threads in the X dimension. */ 92 | Uint32 threadcount_y; /**< The number of threads in the Y dimension. */ 93 | Uint32 threadcount_z; /**< The number of threads in the Z dimension. */ 94 | } SDL_ShaderCross_ComputePipelineMetadata; 95 | 96 | typedef struct SDL_ShaderCross_SPIRV_Info 97 | { 98 | const Uint8 *bytecode; /**< The SPIRV bytecode. */ 99 | size_t bytecode_size; /**< The length of the SPIRV bytecode. */ 100 | const char *entrypoint; /**< The entry point function name for the shader in UTF-8. */ 101 | SDL_ShaderCross_ShaderStage shader_stage; /**< The shader stage to transpile the shader with. */ 102 | bool enable_debug; /**< Allows debug info to be emitted when relevant. Can be useful for graphics debuggers like RenderDoc. */ 103 | const char *name; /**< A UTF-8 name to associate with the shader. Optional, can be NULL. */ 104 | 105 | SDL_PropertiesID props; /**< A properties ID for extensions. Should be 0 if no extensions are needed. */ 106 | } SDL_ShaderCross_SPIRV_Info; 107 | 108 | #define SDL_SHADERCROSS_PROP_SPIRV_PSSL_COMPATIBILITY "SDL.shadercross.spirv.pssl.compatibility" 109 | 110 | #define SDL_SHADERCROSS_PROP_SPIRV_MSL_VERSION "SDL.shadercross.spirv.msl.version" 111 | 112 | typedef struct SDL_ShaderCross_HLSL_Define 113 | { 114 | char *name; /**< The define name. */ 115 | char *value; /**< An optional value for the define. Can be NULL. */ 116 | } SDL_ShaderCross_HLSL_Define; 117 | 118 | typedef struct SDL_ShaderCross_HLSL_Info 119 | { 120 | const char *source; /**< The HLSL source code for the shader. */ 121 | const char *entrypoint; /**< The entry point function name for the shader in UTF-8. */ 122 | const char *include_dir; /**< The include directory for shader code. Optional, can be NULL. */ 123 | SDL_ShaderCross_HLSL_Define *defines; /**< An array of defines. Optional, can be NULL. If not NULL, must be terminated with a fully NULL define struct. */ 124 | SDL_ShaderCross_ShaderStage shader_stage; /**< The shader stage to compile the shader with. */ 125 | bool enable_debug; /**< Allows debug info to be emitted when relevant. Can be useful for graphics debuggers like RenderDoc. */ 126 | const char *name; /**< A UTF-8 name to associate with the shader. Optional, can be NULL. */ 127 | 128 | SDL_PropertiesID props; /**< A properties ID for extensions. Should be 0 if no extensions are needed. */ 129 | } SDL_ShaderCross_HLSL_Info; 130 | 131 | /** 132 | * Initializes SDL_shadercross 133 | * 134 | * \threadsafety This should only be called once, from a single thread. 135 | * \returns true on success, false otherwise. 136 | */ 137 | extern SDL_DECLSPEC bool SDLCALL SDL_ShaderCross_Init(void); 138 | /** 139 | * De-initializes SDL_shadercross 140 | * 141 | * \threadsafety This should only be called once, from a single thread. 142 | */ 143 | extern SDL_DECLSPEC void SDLCALL SDL_ShaderCross_Quit(void); 144 | 145 | /** 146 | * Get the supported shader formats that SPIRV cross-compilation can output 147 | * 148 | * \threadsafety It is safe to call this function from any thread. 149 | * \returns GPU shader formats supported by SPIRV cross-compilation. 150 | */ 151 | extern SDL_DECLSPEC SDL_GPUShaderFormat SDLCALL SDL_ShaderCross_GetSPIRVShaderFormats(void); 152 | 153 | /** 154 | * Transpile to MSL code from SPIRV code. 155 | * 156 | * You must SDL_free the returned string once you are done with it. 157 | * 158 | * \param info a struct describing the shader to transpile. 159 | * \returns an SDL_malloc'd string containing MSL code. 160 | */ 161 | extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_TranspileMSLFromSPIRV( 162 | const SDL_ShaderCross_SPIRV_Info *info); 163 | 164 | /** 165 | * Transpile to HLSL code from SPIRV code. 166 | * 167 | * You must SDL_free the returned string once you are done with it. 168 | * 169 | * \param info a struct describing the shader to transpile. 170 | * \returns an SDL_malloc'd string containing HLSL code. 171 | */ 172 | extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_TranspileHLSLFromSPIRV( 173 | const SDL_ShaderCross_SPIRV_Info *info); 174 | 175 | /** 176 | * Compile DXBC bytecode from SPIRV code. 177 | * 178 | * You must SDL_free the returned buffer once you are done with it. 179 | * 180 | * \param info a struct describing the shader to transpile. 181 | * \param size filled in with the bytecode buffer size. 182 | * \returns an SDL_malloc'd buffer containing DXBC bytecode. 183 | */ 184 | extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXBCFromSPIRV( 185 | const SDL_ShaderCross_SPIRV_Info *info, 186 | size_t *size); 187 | 188 | /** 189 | * Compile DXIL bytecode from SPIRV code. 190 | * 191 | * You must SDL_free the returned buffer once you are done with it. 192 | * 193 | * \param info a struct describing the shader to transpile. 194 | * \param size filled in with the bytecode buffer size. 195 | * \returns an SDL_malloc'd buffer containing DXIL bytecode. 196 | */ 197 | extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXILFromSPIRV( 198 | const SDL_ShaderCross_SPIRV_Info *info, 199 | size_t *size); 200 | 201 | /** 202 | * Compile an SDL GPU shader from SPIRV code. If your shader source is HLSL, you should obtain SPIR-V bytecode from SDL_ShaderCross_CompileSPIRVFromHLSL(). 203 | * 204 | * \param device the SDL GPU device. 205 | * \param info a struct describing the shader to transpile. 206 | * \param metadata a struct describing shader metadata. Can be obtained from SDL_ShaderCross_ReflectGraphicsSPIRV(). 207 | * \param props a properties object filled in with extra shader metadata. 208 | * \returns a compiled SDL_GPUShader. 209 | * 210 | * \threadsafety It is safe to call this function from any thread. 211 | */ 212 | extern SDL_DECLSPEC SDL_GPUShader * SDLCALL SDL_ShaderCross_CompileGraphicsShaderFromSPIRV( 213 | SDL_GPUDevice *device, 214 | const SDL_ShaderCross_SPIRV_Info *info, 215 | const SDL_ShaderCross_GraphicsShaderMetadata *metadata, 216 | SDL_PropertiesID props); 217 | 218 | /** 219 | * Compile an SDL GPU compute pipeline from SPIRV code. If your shader source is HLSL, you should obtain SPIR-V bytecode from SDL_ShaderCross_CompileSPIRVFromHLSL(). 220 | * 221 | * \param device the SDL GPU device. 222 | * \param info a struct describing the shader to transpile. 223 | * \param metadata a struct describing shader metadata. Can be obtained from SDL_ShaderCross_ReflectComputeSPIRV(). 224 | * \param props a properties object filled in with extra shader metadata. 225 | * \returns a compiled SDL_GPUComputePipeline. 226 | * 227 | * \threadsafety It is safe to call this function from any thread. 228 | */ 229 | extern SDL_DECLSPEC SDL_GPUComputePipeline * SDLCALL SDL_ShaderCross_CompileComputePipelineFromSPIRV( 230 | SDL_GPUDevice *device, 231 | const SDL_ShaderCross_SPIRV_Info *info, 232 | const SDL_ShaderCross_ComputePipelineMetadata *metadata, 233 | SDL_PropertiesID props); 234 | 235 | /** 236 | * Reflect graphics shader info from SPIRV code. If your shader source is HLSL, you should obtain SPIR-V bytecode from SDL_ShaderCross_CompileSPIRVFromHLSL(). This must be freed with SDL_free() when you are done with the metadata. 237 | * 238 | * \param bytecode the SPIRV bytecode. 239 | * \param bytecode_size the length of the SPIRV bytecode. 240 | * \param props a properties object filled in with extra shader metadata, provided by the user. 241 | * \returns A metadata struct on success, NULL otherwise. The struct must be free'd when it is no longer needed. 242 | * 243 | * \threadsafety It is safe to call this function from any thread. 244 | */ 245 | extern SDL_DECLSPEC SDL_ShaderCross_GraphicsShaderMetadata * SDLCALL SDL_ShaderCross_ReflectGraphicsSPIRV( 246 | const Uint8 *bytecode, 247 | size_t bytecode_size, 248 | SDL_PropertiesID props); 249 | 250 | /** 251 | * Reflect compute pipeline info from SPIRV code. If your shader source is HLSL, you should obtain SPIR-V bytecode from SDL_ShaderCross_CompileSPIRVFromHLSL(). This must be freed with SDL_free() when you are done with the metadata. 252 | * 253 | * \param bytecode the SPIRV bytecode. 254 | * \param bytecode_size the length of the SPIRV bytecode. 255 | * \param props a properties object filled in with extra shader metadata, provided by the user. 256 | * \returns A metadata struct on success, NULL otherwise. 257 | * 258 | * \threadsafety It is safe to call this function from any thread. 259 | */ 260 | extern SDL_DECLSPEC SDL_ShaderCross_ComputePipelineMetadata * SDLCALL SDL_ShaderCross_ReflectComputeSPIRV( 261 | const Uint8 *bytecode, 262 | size_t bytecode_size, 263 | SDL_PropertiesID props); 264 | 265 | /** 266 | * Get the supported shader formats that HLSL cross-compilation can output 267 | * 268 | * \returns GPU shader formats supported by HLSL cross-compilation. 269 | * 270 | * \threadsafety It is safe to call this function from any thread. 271 | */ 272 | extern SDL_DECLSPEC SDL_GPUShaderFormat SDLCALL SDL_ShaderCross_GetHLSLShaderFormats(void); 273 | 274 | /** 275 | * Compile to DXBC bytecode from HLSL code via a SPIRV-Cross round trip. 276 | * 277 | * You must SDL_free the returned buffer once you are done with it. 278 | * 279 | * \param info a struct describing the shader to transpile. 280 | * \param size filled in with the bytecode buffer size. 281 | * \returns an SDL_malloc'd buffer containing DXBC bytecode. 282 | * 283 | * \threadsafety It is safe to call this function from any thread. 284 | */ 285 | extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXBCFromHLSL( 286 | const SDL_ShaderCross_HLSL_Info *info, 287 | size_t *size); 288 | 289 | /** 290 | * Compile to DXIL bytecode from HLSL code via a SPIRV-Cross round trip. 291 | * 292 | * You must SDL_free the returned buffer once you are done with it. 293 | * 294 | * \param info a struct describing the shader to transpile. 295 | * \param size filled in with the bytecode buffer size. 296 | * \returns an SDL_malloc'd buffer containing DXIL bytecode. 297 | * 298 | * \threadsafety It is safe to call this function from any thread. 299 | */ 300 | extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXILFromHLSL( 301 | const SDL_ShaderCross_HLSL_Info *info, 302 | size_t *size); 303 | 304 | /** 305 | * Compile to SPIRV bytecode from HLSL code. 306 | * 307 | * You must SDL_free the returned buffer once you are done with it. 308 | * 309 | * \param info a struct describing the shader to transpile. 310 | * \param size filled in with the bytecode buffer size. 311 | * \returns an SDL_malloc'd buffer containing SPIRV bytecode. 312 | * 313 | * \threadsafety It is safe to call this function from any thread. 314 | */ 315 | extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileSPIRVFromHLSL( 316 | const SDL_ShaderCross_HLSL_Info *info, 317 | size_t *size); 318 | 319 | #ifdef __cplusplus 320 | } 321 | #endif 322 | #include 323 | 324 | #endif /* SDL_SHADERCROSS_H */ 325 | -------------------------------------------------------------------------------- /src/SDL_shadercross.sym: -------------------------------------------------------------------------------- 1 | SDL3_shadercross_0.0.0 { 2 | global: 3 | SDL_ShaderCross_Init; 4 | SDL_ShaderCross_Quit; 5 | SDL_ShaderCross_GetSPIRVShaderFormats; 6 | SDL_ShaderCross_TranspileMSLFromSPIRV; 7 | SDL_ShaderCross_TranspileHLSLFromSPIRV; 8 | SDL_ShaderCross_CompileDXBCFromSPIRV; 9 | SDL_ShaderCross_CompileDXILFromSPIRV; 10 | SDL_ShaderCross_CompileGraphicsShaderFromSPIRV; 11 | SDL_ShaderCross_CompileComputePipelineFromSPIRV; 12 | SDL_ShaderCross_GetHLSLShaderFormats; 13 | SDL_ShaderCross_CompileDXBCFromHLSL; 14 | SDL_ShaderCross_CompileDXILFromHLSL; 15 | SDL_ShaderCross_CompileSPIRVFromHLSL; 16 | SDL_ShaderCross_ReflectGraphicsSPIRV; 17 | SDL_ShaderCross_ReflectComputeSPIRV; 18 | local: *; 19 | }; 20 | -------------------------------------------------------------------------------- /src/cli.c: -------------------------------------------------------------------------------- 1 | /* 2 | Simple DirectMedia Layer Shader Cross Compiler 3 | Copyright (C) 2024 Sam Lantinga 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #ifdef LEAKCHECK 26 | #include 27 | #endif 28 | 29 | // We can emit HLSL and JSON as a destination, so let's redefine the shader format enum. 30 | typedef enum ShaderCross_DestinationFormat { 31 | SHADERFORMAT_INVALID, 32 | SHADERFORMAT_SPIRV, 33 | SHADERFORMAT_DXBC, 34 | SHADERFORMAT_DXIL, 35 | SHADERFORMAT_MSL, 36 | SHADERFORMAT_HLSL, 37 | SHADERFORMAT_JSON 38 | } ShaderCross_ShaderFormat; 39 | 40 | void print_help(void) 41 | { 42 | int column_width = 32; 43 | SDL_Log("Usage: shadercross [options]"); 44 | SDL_Log("Required options:\n"); 45 | SDL_Log(" %-*s %s", column_width, "-s | --source ", "Source language format. May be inferred from the filename. Values: [SPIRV, HLSL]"); 46 | SDL_Log(" %-*s %s", column_width, "-d | --dest ", "Destination format. May be inferred from the filename. Values: [DXBC, DXIL, MSL, SPIRV, HLSL, JSON]"); 47 | SDL_Log(" %-*s %s", column_width, "-t | --stage ", "Shader stage. May be inferred from the filename. Values: [vertex, fragment, compute]"); 48 | SDL_Log(" %-*s %s", column_width, "-e | --entrypoint ", "Entrypoint function name. Default: \"main\"."); 49 | SDL_Log(" %-*s %s", column_width, "-o | --output ", "Output file."); 50 | SDL_Log("\n"); 51 | SDL_Log("Optional options:\n"); 52 | SDL_Log(" %-*s %s", column_width, "-I | --include ", "HLSL include directory. Only used with HLSL source."); 53 | SDL_Log(" %-*s %s", column_width, "-D[=]", "HLSL define. Only used with HLSL source. Can be repeated."); 54 | SDL_Log(" %-*s %s", column_width, "", "If = is omitted the define will be treated as equal to 1."); 55 | SDL_Log(" %-*s %s", column_width, "--msl-version ", "Target MSL version. Only used when transpiling to MSL. The default is 1.2.0."); 56 | SDL_Log(" %-*s %s", column_width, "-g | --debug", "Generate debug information when possible. Shaders are valid only when graphics debuggers are attached."); 57 | SDL_Log(" %-*s %s", column_width, "-p | --pssl", "Generate PSSL-compatible shader. Destination format should be HLSL."); 58 | } 59 | 60 | static const char* io_var_type_to_string(SDL_ShaderCross_IOVarType io_var_type, Uint32 vector_size) 61 | { 62 | switch (io_var_type) { 63 | case SDL_SHADERCROSS_IOVAR_TYPE_INT8: 64 | switch (vector_size) { 65 | case 1: return "byte"; 66 | case 2: return "byte2"; 67 | case 3: return "byte3"; 68 | case 4: return "byte4"; 69 | default: break; 70 | } 71 | break; 72 | case SDL_SHADERCROSS_IOVAR_TYPE_UINT8: 73 | switch (vector_size) { 74 | case 1: return "ubyte"; 75 | case 2: return "ubyte2"; 76 | case 3: return "ubyte3"; 77 | case 4: return "ubyte4"; 78 | default: break; 79 | } 80 | break; 81 | case SDL_SHADERCROSS_IOVAR_TYPE_INT16: 82 | switch (vector_size) { 83 | case 1: return "short"; 84 | case 2: return "short2"; 85 | case 3: return "short3"; 86 | case 4: return "short4"; 87 | default: break; 88 | } 89 | break; 90 | case SDL_SHADERCROSS_IOVAR_TYPE_UINT16: 91 | switch (vector_size) { 92 | case 1: return "ushort"; 93 | case 2: return "ushort2"; 94 | case 3: return "ushort3"; 95 | case 4: return "ushort4"; 96 | default: break; 97 | } 98 | break; 99 | case SDL_SHADERCROSS_IOVAR_TYPE_INT32: 100 | switch (vector_size) { 101 | case 1: return "int"; 102 | case 2: return "int2"; 103 | case 3: return "int3"; 104 | case 4: return "int4"; 105 | default: break; 106 | } 107 | break; 108 | case SDL_SHADERCROSS_IOVAR_TYPE_UINT32: 109 | switch (vector_size) { 110 | case 1: return "uint"; 111 | case 2: return "uint2"; 112 | case 3: return "uint3"; 113 | case 4: return "uint4"; 114 | default: break; 115 | } 116 | break; 117 | case SDL_SHADERCROSS_IOVAR_TYPE_INT64: 118 | switch (vector_size) { 119 | case 1: return "long"; 120 | case 2: return "long2"; 121 | case 3: return "long3"; 122 | case 4: return "long4"; 123 | default: break; 124 | } 125 | break; 126 | case SDL_SHADERCROSS_IOVAR_TYPE_UINT64: 127 | switch (vector_size) { 128 | case 1: return "ulong"; 129 | case 2: return "ulong2"; 130 | case 3: return "ulong3"; 131 | case 4: return "ulong4"; 132 | default: break; 133 | } 134 | break; 135 | case SDL_SHADERCROSS_IOVAR_TYPE_FLOAT16: 136 | switch (vector_size) { 137 | case 1: return "half"; 138 | case 2: return "half2"; 139 | case 3: return "half3"; 140 | case 4: return "half4"; 141 | default: break; 142 | } 143 | break; 144 | case SDL_SHADERCROSS_IOVAR_TYPE_FLOAT32: 145 | switch (vector_size) { 146 | case 1: return "float"; 147 | case 2: return "float2"; 148 | case 3: return "float3"; 149 | case 4: return "float4"; 150 | default: break; 151 | } 152 | break; 153 | case SDL_SHADERCROSS_IOVAR_TYPE_FLOAT64: 154 | switch (vector_size) { 155 | case 1: return "double"; 156 | case 2: return "double2"; 157 | case 3: return "double3"; 158 | case 4: return "double4"; 159 | default: break; 160 | } 161 | break; 162 | case SDL_SHADERCROSS_IOVAR_TYPE_UNKNOWN: 163 | default: break; 164 | } 165 | 166 | SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Unknown IO variable type: vector_type=%u vector_size=%u", io_var_type, vector_size); 167 | return "unknown"; 168 | } 169 | 170 | void write_graphics_reflect_json(SDL_IOStream *outputIO, SDL_ShaderCross_GraphicsShaderMetadata *info) 171 | { 172 | SDL_IOprintf( 173 | outputIO, 174 | "{ \"samplers\": %u, \"storage_textures\": %u, \"storage_buffers\": %u, \"uniform_buffers\": %u, ", 175 | info->num_samplers, 176 | info->num_storage_textures, 177 | info->num_storage_buffers, 178 | info->num_uniform_buffers 179 | ); 180 | 181 | SDL_IOprintf(outputIO, "\"inputs\": ["); 182 | for (Uint32 i = 0; i < info->num_inputs; i++) { 183 | const SDL_ShaderCross_IOVarMetadata* input = &info->inputs[i]; 184 | SDL_IOprintf(outputIO, "{ \"name\": \"%s\", \"type\": \"%s\", \"location\": %u, \"offset\": %u }%s", 185 | input->name, 186 | io_var_type_to_string(input->vector_type, input->vector_size), 187 | input->location, 188 | input->offset, 189 | i + 1 < info->num_inputs ? ", " : "" 190 | ); 191 | } 192 | SDL_IOprintf(outputIO, "], "); 193 | 194 | SDL_IOprintf(outputIO, "\"outputs\": ["); 195 | for (Uint32 i = 0; i < info->num_outputs; i++) { 196 | const SDL_ShaderCross_IOVarMetadata* output = &info->outputs[i]; 197 | SDL_IOprintf(outputIO, "{ \"name\": \"%s\", \"type\": \"%s\", \"location\": %u, \"offset\": %u }%s", 198 | output->name, 199 | io_var_type_to_string(output->vector_type, output->vector_size), 200 | output->location, 201 | output->offset, 202 | i + 1 < info->num_outputs ? ", " : "" 203 | ); 204 | } 205 | SDL_IOprintf(outputIO, "] }\n"); 206 | } 207 | 208 | void write_compute_reflect_json(SDL_IOStream *outputIO, SDL_ShaderCross_ComputePipelineMetadata *info) 209 | { 210 | SDL_IOprintf( 211 | outputIO, 212 | "{ \"samplers\": %u, \"readonly_storage_textures\": %u, \"readonly_storage_buffers\": %u, \"readwrite_storage_textures\": %u, \"readwrite_storage_buffers\": %u, \"uniform_buffers\": %u, \"threadcount_x\": %u, \"threadcount_y\": %u, \"threadcount_z\": %u }\n", 213 | info->num_samplers, 214 | info->num_readonly_storage_textures, 215 | info->num_readonly_storage_buffers, 216 | info->num_readwrite_storage_textures, 217 | info->num_readwrite_storage_buffers, 218 | info->num_uniform_buffers, 219 | info->threadcount_x, 220 | info->threadcount_y, 221 | info->threadcount_z 222 | ); 223 | } 224 | 225 | int main(int argc, char *argv[]) 226 | { 227 | bool sourceValid = false; 228 | bool destinationValid = false; 229 | bool stageValid = false; 230 | 231 | bool spirvSource = false; 232 | ShaderCross_ShaderFormat destinationFormat = SHADERFORMAT_INVALID; 233 | SDL_ShaderCross_ShaderStage shaderStage = SDL_SHADERCROSS_SHADERSTAGE_VERTEX; 234 | char *outputFilename = NULL; 235 | char *entrypointName = "main"; 236 | char *includeDir = NULL; 237 | 238 | char *filename = NULL; 239 | size_t fileSize = 0; 240 | void *fileData = NULL; 241 | bool accept_optionals = true; 242 | 243 | SDL_ShaderCross_HLSL_Define *defines = NULL; 244 | size_t numDefines = 0; 245 | 246 | bool enableDebug = false; 247 | char *mslVersion = NULL; 248 | 249 | bool psslCompat = false; 250 | 251 | #ifdef LEAKCHECK 252 | SDLTest_TrackAllocations(); 253 | #endif 254 | 255 | for (int i = 1; i < argc; i += 1) { 256 | char *arg = argv[i]; 257 | 258 | if (accept_optionals && arg[0] == '-') { 259 | if (SDL_strcmp(arg, "-h") == 0 || SDL_strcmp(arg, "--help") == 0) { 260 | print_help(); 261 | return 0; 262 | } else if (SDL_strcmp(arg, "-s") == 0 || SDL_strcmp(arg, "--source") == 0) { 263 | if (i + 1 >= argc) { 264 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s requires an argument", arg); 265 | print_help(); 266 | return 1; 267 | } 268 | i += 1; 269 | if (SDL_strcasecmp(argv[i], "spirv") == 0) { 270 | spirvSource = true; 271 | sourceValid = true; 272 | } else if (SDL_strcasecmp(argv[i], "hlsl") == 0) { 273 | spirvSource = false; 274 | sourceValid = true; 275 | } else { 276 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unrecognized source input %s, source must be SPIRV or HLSL!", argv[i]); 277 | print_help(); 278 | return 1; 279 | } 280 | } else if (SDL_strcmp(arg, "-d") == 0 || SDL_strcmp(arg, "--dest") == 0) { 281 | if (i + 1 >= argc) { 282 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s requires an argument", arg); 283 | print_help(); 284 | return 1; 285 | } 286 | i += 1; 287 | if (SDL_strcasecmp(argv[i], "DXBC") == 0) { 288 | destinationFormat = SHADERFORMAT_DXBC; 289 | destinationValid = true; 290 | } else if (SDL_strcasecmp(argv[i], "DXIL") == 0) { 291 | destinationFormat = SHADERFORMAT_DXIL; 292 | destinationValid = true; 293 | } else if (SDL_strcasecmp(argv[i], "MSL") == 0) { 294 | destinationFormat = SHADERFORMAT_MSL; 295 | destinationValid = true; 296 | } else if (SDL_strcasecmp(argv[i], "SPIRV") == 0) { 297 | destinationFormat = SHADERFORMAT_SPIRV; 298 | destinationValid = true; 299 | } else if (SDL_strcasecmp(argv[i], "HLSL") == 0) { 300 | destinationFormat = SHADERFORMAT_HLSL; 301 | destinationValid = true; 302 | } else if (SDL_strcasecmp(argv[i], "JSON") == 0) { 303 | destinationFormat = SHADERFORMAT_JSON; 304 | destinationValid = true; 305 | } else { 306 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unrecognized destination input %s, destination must be DXBC, DXIL, MSL or SPIRV!", argv[i]); 307 | print_help(); 308 | return 1; 309 | } 310 | } else if (SDL_strcmp(arg, "-t") == 0 || SDL_strcmp(arg, "--stage") == 0) { 311 | if (i + 1 >= argc) { 312 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s requires an argument", arg); 313 | print_help(); 314 | return 1; 315 | } 316 | i += 1; 317 | if (SDL_strcasecmp(argv[i], "vertex") == 0) { 318 | shaderStage = SDL_SHADERCROSS_SHADERSTAGE_VERTEX; 319 | stageValid = true; 320 | } else if (SDL_strcasecmp(argv[i], "fragment") == 0) { 321 | shaderStage = SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT; 322 | stageValid = true; 323 | } else if (SDL_strcasecmp(argv[i], "compute") == 0) { 324 | shaderStage = SDL_SHADERCROSS_SHADERSTAGE_COMPUTE; 325 | stageValid = true; 326 | } else { 327 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unrecognized shader stage input %s, must be vertex, fragment, or compute.", argv[i]); 328 | print_help(); 329 | return 1; 330 | } 331 | } else if (SDL_strcmp(arg, "-e") == 0 || SDL_strcmp(arg, "--entrypoint") == 0) { 332 | if (i + 1 >= argc) { 333 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s requires an argument", arg); 334 | print_help(); 335 | return 1; 336 | } 337 | i += 1; 338 | entrypointName = argv[i]; 339 | } else if (SDL_strcmp(arg, "-I") == 0 || SDL_strcmp(arg, "--include") == 0) { 340 | if (includeDir) { 341 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "'%s' can only be used once", arg); 342 | print_help(); 343 | return 1; 344 | } 345 | if (i + 1 >= argc) { 346 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s requires an argument", arg); 347 | print_help(); 348 | return 1; 349 | } 350 | i += 1; 351 | includeDir = argv[i]; 352 | } else if (SDL_strcmp(arg, "-o") == 0 || SDL_strcmp(arg, "--output") == 0) { 353 | if (i + 1 >= argc) { 354 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s requires an argument", arg); 355 | print_help(); 356 | return 1; 357 | } 358 | i += 1; 359 | outputFilename = argv[i]; 360 | } else if (SDL_strncmp(argv[i], "-D", SDL_strlen("-D")) == 0) { 361 | numDefines += 1; 362 | defines = SDL_realloc(defines, sizeof(SDL_ShaderCross_HLSL_Define) * numDefines); 363 | char *equalSign = SDL_strchr(argv[i], '='); 364 | if (equalSign != NULL) { 365 | defines[numDefines - 1].value = equalSign + 1; 366 | size_t len = defines[numDefines - 1].value - argv[i] - 2; 367 | defines[numDefines - 1].name = SDL_malloc(len); 368 | SDL_utf8strlcpy(defines[numDefines - 1].name, (const char *)argv[i] + 2, len); 369 | } else { // no '=' was found 370 | defines[numDefines - 1].value = NULL; 371 | size_t len = SDL_utf8strlen(argv[i]) + 1 - 2; 372 | defines[numDefines - 1].name = SDL_malloc(len); 373 | SDL_utf8strlcpy(defines[numDefines - 1].name, (const char *)argv[i] + 2, len); 374 | } 375 | } else if (SDL_strcmp(arg, "--msl-version") == 0) { 376 | if (i + 1 >= argc) { 377 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s requires an argument", arg); 378 | print_help(); 379 | return 1; 380 | } 381 | i += 1; 382 | mslVersion = argv[i]; 383 | } else if (SDL_strcmp(argv[i], "-g") == 0 || SDL_strcmp(arg, "--debug") == 0) { 384 | enableDebug = true; 385 | } else if (SDL_strcmp(arg, "-p") == 0 || SDL_strcmp(arg, "--pssl") == 0) { 386 | psslCompat = true; 387 | } else if (SDL_strcmp(arg, "--") == 0) { 388 | accept_optionals = false; 389 | } else { 390 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s: Unknown argument: %s", argv[0], arg); 391 | print_help(); 392 | return 1; 393 | } 394 | } else if (!filename) { 395 | filename = arg; 396 | } else { 397 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s: Unknown argument: %s", argv[0], arg); 398 | print_help(); 399 | return 1; 400 | } 401 | } 402 | if (!filename) { 403 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s: missing input path", argv[0]); 404 | print_help(); 405 | return 1; 406 | } 407 | if (!outputFilename) { 408 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s: missing output path", argv[0]); 409 | print_help(); 410 | return 1; 411 | } 412 | fileData = SDL_LoadFile(filename, &fileSize); 413 | if (fileData == NULL) { 414 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid file (%s)", SDL_GetError()); 415 | return 1; 416 | } 417 | 418 | if (!SDL_ShaderCross_Init()) 419 | { 420 | SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s", "Failed to initialize shadercross!"); 421 | return 1; 422 | } 423 | 424 | if (!sourceValid) { 425 | if (SDL_strstr(filename, ".spv")) { 426 | spirvSource = true; 427 | } else if (SDL_strstr(filename, ".hlsl")) { 428 | spirvSource = false; 429 | } else { 430 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Could not infer source format!"); 431 | print_help(); 432 | return 1; 433 | } 434 | } 435 | 436 | if (!destinationValid) { 437 | if (SDL_strstr(outputFilename, ".dxbc")) { 438 | destinationFormat = SHADERFORMAT_DXBC; 439 | } else if (SDL_strstr(outputFilename, ".dxil")) { 440 | destinationFormat = SHADERFORMAT_DXIL; 441 | } else if (SDL_strstr(outputFilename, ".msl")) { 442 | destinationFormat = SHADERFORMAT_MSL; 443 | } else if (SDL_strstr(outputFilename, ".spv")) { 444 | destinationFormat = SHADERFORMAT_SPIRV; 445 | } else if (SDL_strstr(outputFilename, ".hlsl")) { 446 | destinationFormat = SHADERFORMAT_HLSL; 447 | } else if (SDL_strstr(outputFilename, ".json")) { 448 | destinationFormat = SHADERFORMAT_JSON; 449 | } else { 450 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Could not infer destination format!"); 451 | print_help(); 452 | return 1; 453 | } 454 | } 455 | 456 | if (!stageValid) { 457 | if (SDL_strcasestr(filename, ".vert")) { 458 | shaderStage = SDL_SHADERCROSS_SHADERSTAGE_VERTEX; 459 | } else if (SDL_strcasestr(filename, ".frag")) { 460 | shaderStage = SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT; 461 | } else if (SDL_strcasestr(filename, ".comp")) { 462 | shaderStage = SDL_SHADERCROSS_SHADERSTAGE_COMPUTE; 463 | } else { 464 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not infer shader stage from filename!"); 465 | print_help(); 466 | return 1; 467 | } 468 | } 469 | 470 | SDL_IOStream *outputIO = SDL_IOFromFile(outputFilename, "w"); 471 | 472 | if (outputIO == NULL) { 473 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", SDL_GetError()); 474 | return 1; 475 | } 476 | 477 | size_t bytecodeSize; 478 | int result = 0; 479 | 480 | // null-terminate the defines array 481 | if (defines != NULL) { 482 | defines = SDL_realloc(defines, sizeof(SDL_ShaderCross_HLSL_Define) * (numDefines + 1)); 483 | defines[numDefines].name = NULL; 484 | defines[numDefines].value = NULL; 485 | } 486 | 487 | if (spirvSource) { 488 | SDL_ShaderCross_SPIRV_Info spirvInfo; 489 | spirvInfo.bytecode = fileData; 490 | spirvInfo.bytecode_size = fileSize; 491 | spirvInfo.entrypoint = entrypointName; 492 | spirvInfo.shader_stage = shaderStage; 493 | spirvInfo.enable_debug = enableDebug; 494 | spirvInfo.name = filename; 495 | spirvInfo.props = SDL_CreateProperties(); 496 | if (mslVersion) { 497 | SDL_SetStringProperty(spirvInfo.props, SDL_SHADERCROSS_PROP_SPIRV_MSL_VERSION, mslVersion); 498 | } 499 | 500 | if (psslCompat) { 501 | SDL_SetBooleanProperty(spirvInfo.props, SDL_SHADERCROSS_PROP_SPIRV_PSSL_COMPATIBILITY, true); 502 | } 503 | 504 | switch (destinationFormat) { 505 | case SHADERFORMAT_DXBC: { 506 | Uint8 *buffer = SDL_ShaderCross_CompileDXBCFromSPIRV( 507 | &spirvInfo, 508 | &bytecodeSize); 509 | if (buffer == NULL) { 510 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile DXBC from SPIR-V: %s", SDL_GetError()); 511 | result = 1; 512 | } else { 513 | SDL_WriteIO(outputIO, buffer, bytecodeSize); 514 | SDL_free(buffer); 515 | } 516 | break; 517 | } 518 | 519 | case SHADERFORMAT_DXIL: { 520 | Uint8 *buffer = SDL_ShaderCross_CompileDXILFromSPIRV( 521 | &spirvInfo, 522 | &bytecodeSize); 523 | if (buffer == NULL) { 524 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile DXIL from SPIR-V: %s", SDL_GetError()); 525 | result = 1; 526 | } else { 527 | SDL_WriteIO(outputIO, buffer, bytecodeSize); 528 | SDL_free(buffer); 529 | } 530 | break; 531 | } 532 | 533 | case SHADERFORMAT_MSL: { 534 | char *buffer = SDL_ShaderCross_TranspileMSLFromSPIRV( 535 | &spirvInfo); 536 | if (buffer == NULL) { 537 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to transpile MSL from SPIR-V: %s", SDL_GetError()); 538 | result = 1; 539 | } else { 540 | SDL_IOprintf(outputIO, "%s", buffer); 541 | SDL_free(buffer); 542 | } 543 | break; 544 | } 545 | 546 | case SHADERFORMAT_HLSL: { 547 | char *buffer = SDL_ShaderCross_TranspileHLSLFromSPIRV( 548 | &spirvInfo); 549 | if (buffer == NULL) { 550 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to transpile HLSL from SPIRV: %s", SDL_GetError()); 551 | result = 1; 552 | } else { 553 | SDL_IOprintf(outputIO, "%s", buffer); 554 | SDL_free(buffer); 555 | } 556 | break; 557 | } 558 | 559 | case SHADERFORMAT_SPIRV: { 560 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Input and output are both SPIRV. Did you mean to do that?"); 561 | result = 1; 562 | break; 563 | } 564 | 565 | case SHADERFORMAT_JSON: { 566 | if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_COMPUTE) { 567 | SDL_ShaderCross_ComputePipelineMetadata *info = SDL_ShaderCross_ReflectComputeSPIRV( 568 | fileData, 569 | fileSize, 570 | 0); 571 | if (info) { 572 | write_compute_reflect_json(outputIO, info); 573 | SDL_free(info); 574 | } else { 575 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to reflect SPIRV: %s", SDL_GetError()); 576 | result = 1; 577 | } 578 | } else { 579 | SDL_ShaderCross_GraphicsShaderMetadata *info = SDL_ShaderCross_ReflectGraphicsSPIRV( 580 | fileData, 581 | fileSize, 582 | 0); 583 | if (info) { 584 | write_graphics_reflect_json(outputIO, info); 585 | SDL_free(info); 586 | } else { 587 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to reflect SPIRV: %s", SDL_GetError()); 588 | result = 1; 589 | } 590 | } 591 | break; 592 | } 593 | 594 | case SHADERFORMAT_INVALID: { 595 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Destination format not provided!"); 596 | result = 1; 597 | break; 598 | } 599 | } 600 | 601 | SDL_DestroyProperties(spirvInfo.props); 602 | } else { 603 | SDL_ShaderCross_HLSL_Info hlslInfo; 604 | hlslInfo.source = fileData; 605 | hlslInfo.entrypoint = entrypointName; 606 | hlslInfo.include_dir = includeDir; 607 | hlslInfo.defines = defines; 608 | hlslInfo.shader_stage = shaderStage; 609 | hlslInfo.enable_debug = enableDebug; 610 | hlslInfo.name = filename; 611 | hlslInfo.props = 0; 612 | 613 | switch (destinationFormat) { 614 | case SHADERFORMAT_DXBC: { 615 | Uint8 *buffer = SDL_ShaderCross_CompileDXBCFromHLSL( 616 | &hlslInfo, 617 | &bytecodeSize); 618 | if (buffer == NULL) { 619 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile DXBC from HLSL: %s", SDL_GetError()); 620 | result = 1; 621 | } else { 622 | SDL_WriteIO(outputIO, buffer, bytecodeSize); 623 | SDL_free(buffer); 624 | } 625 | break; 626 | } 627 | 628 | case SHADERFORMAT_DXIL: { 629 | Uint8 *buffer = SDL_ShaderCross_CompileDXILFromHLSL( 630 | &hlslInfo, 631 | &bytecodeSize); 632 | if (buffer == NULL) { 633 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile DXIL from HLSL: %s", SDL_GetError()); 634 | result = 1; 635 | } else { 636 | SDL_WriteIO(outputIO, buffer, bytecodeSize); 637 | SDL_free(buffer); 638 | } 639 | break; 640 | } 641 | 642 | // TODO: Should we have TranspileMSLFromHLSL? 643 | case SHADERFORMAT_MSL: { 644 | void *spirv = SDL_ShaderCross_CompileSPIRVFromHLSL( 645 | &hlslInfo, 646 | &bytecodeSize); 647 | if (spirv == NULL) { 648 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to transpile MSL from HLSL: %s", SDL_GetError()); 649 | result = 1; 650 | } else { 651 | SDL_ShaderCross_SPIRV_Info spirvInfo; 652 | spirvInfo.bytecode = spirv; 653 | spirvInfo.bytecode_size = bytecodeSize; 654 | spirvInfo.entrypoint = entrypointName; 655 | spirvInfo.shader_stage = shaderStage; 656 | spirvInfo.enable_debug = enableDebug; 657 | spirvInfo.props = SDL_CreateProperties(); 658 | if (mslVersion) { 659 | SDL_SetStringProperty(spirvInfo.props, SDL_SHADERCROSS_PROP_SPIRV_MSL_VERSION, mslVersion); 660 | } 661 | char *buffer = SDL_ShaderCross_TranspileMSLFromSPIRV( 662 | &spirvInfo); 663 | if (buffer == NULL) { 664 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to transpile MSL from HLSL: %s", SDL_GetError()); 665 | result = 1; 666 | } else { 667 | SDL_IOprintf(outputIO, "%s", buffer); 668 | SDL_free(spirv); 669 | SDL_free(buffer); 670 | } 671 | SDL_DestroyProperties(spirvInfo.props); 672 | } 673 | break; 674 | } 675 | 676 | case SHADERFORMAT_SPIRV: { 677 | Uint8 *buffer = SDL_ShaderCross_CompileSPIRVFromHLSL( 678 | &hlslInfo, 679 | &bytecodeSize); 680 | if (buffer == NULL) { 681 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile SPIR-V From HLSL: %s", SDL_GetError()); 682 | result = 1; 683 | } else { 684 | SDL_WriteIO(outputIO, buffer, bytecodeSize); 685 | SDL_free(buffer); 686 | } 687 | break; 688 | } 689 | 690 | case SHADERFORMAT_HLSL: { 691 | void *spirv = SDL_ShaderCross_CompileSPIRVFromHLSL( 692 | &hlslInfo, 693 | &bytecodeSize); 694 | 695 | if (spirv == NULL) { 696 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile HLSL to SPIRV: %s", SDL_GetError()); 697 | result = 1; 698 | break; 699 | } 700 | 701 | SDL_ShaderCross_SPIRV_Info spirvInfo; 702 | spirvInfo.bytecode = spirv; 703 | spirvInfo.bytecode_size = bytecodeSize; 704 | spirvInfo.entrypoint = entrypointName; 705 | spirvInfo.shader_stage = shaderStage; 706 | spirvInfo.enable_debug = enableDebug; 707 | spirvInfo.props = SDL_CreateProperties(); 708 | 709 | if (psslCompat) { 710 | SDL_SetBooleanProperty(spirvInfo.props, SDL_SHADERCROSS_PROP_SPIRV_PSSL_COMPATIBILITY, true); 711 | } 712 | 713 | char *buffer = SDL_ShaderCross_TranspileHLSLFromSPIRV( 714 | &spirvInfo); 715 | 716 | if (buffer == NULL) { 717 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to transpile HLSL from SPIRV: %s", SDL_GetError()); 718 | result = 1; 719 | break; 720 | } 721 | 722 | SDL_IOprintf(outputIO, "%s", buffer); 723 | SDL_free(spirv); 724 | SDL_free(buffer); 725 | SDL_DestroyProperties(spirvInfo.props); 726 | break; 727 | } 728 | 729 | case SHADERFORMAT_JSON: { 730 | void *spirv = SDL_ShaderCross_CompileSPIRVFromHLSL( 731 | &hlslInfo, 732 | &bytecodeSize); 733 | 734 | if (spirv == NULL) { 735 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile HLSL to SPIRV: %s", SDL_GetError()); 736 | result = 1; 737 | break; 738 | } 739 | 740 | if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_COMPUTE) { 741 | SDL_ShaderCross_ComputePipelineMetadata *info = SDL_ShaderCross_ReflectComputeSPIRV( 742 | spirv, 743 | bytecodeSize, 744 | 0); 745 | SDL_free(spirv); 746 | 747 | if (info) { 748 | write_compute_reflect_json(outputIO, info); 749 | SDL_free(info); 750 | } else { 751 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to reflect SPIRV: %s", SDL_GetError()); 752 | result = 1; 753 | } 754 | } else { 755 | SDL_ShaderCross_GraphicsShaderMetadata *info = SDL_ShaderCross_ReflectGraphicsSPIRV( 756 | spirv, 757 | bytecodeSize, 758 | 0); 759 | SDL_free(spirv); 760 | 761 | if (info) { 762 | write_graphics_reflect_json(outputIO, info); 763 | SDL_free(info); 764 | } else { 765 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to reflect SPIRV: %s", SDL_GetError()); 766 | result = 1; 767 | } 768 | } 769 | 770 | break; 771 | } 772 | 773 | case SHADERFORMAT_INVALID: { 774 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Destination format not provided!"); 775 | result = 1; 776 | break; 777 | } 778 | } 779 | } 780 | 781 | SDL_CloseIO(outputIO); 782 | SDL_free(fileData); 783 | for (Uint32 i = 0; i < numDefines; i += 1) { 784 | SDL_free(defines[i].name); 785 | } 786 | SDL_free(defines); 787 | SDL_ShaderCross_Quit(); 788 | SDL_Quit(); 789 | 790 | #ifdef LEAKCHECK 791 | SDLTest_LogAllocations(); 792 | #endif 793 | 794 | return result; 795 | } 796 | -------------------------------------------------------------------------------- /src/version.rc: -------------------------------------------------------------------------------- 1 | 2 | #include "winresrc.h" 3 | 4 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 5 | 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Version 9 | // 10 | 11 | VS_VERSION_INFO VERSIONINFO 12 | FILEVERSION 3,0,0,0 13 | PRODUCTVERSION 3,0,0,0 14 | FILEFLAGSMASK 0x3fL 15 | FILEFLAGS 0x0L 16 | FILEOS 0x40004L 17 | FILETYPE 0x2L 18 | FILESUBTYPE 0x0L 19 | BEGIN 20 | BLOCK "StringFileInfo" 21 | BEGIN 22 | BLOCK "040904b0" 23 | BEGIN 24 | VALUE "CompanyName", "\0" 25 | VALUE "FileDescription", "SDL_shadercross\0" 26 | VALUE "FileVersion", "3, 0, 0, 0\0" 27 | VALUE "InternalName", "SDL_shadercross\0" 28 | VALUE "LegalCopyright", "Copyright (C) 2024 Sam Lantinga\0" 29 | VALUE "OriginalFilename", "SDL3_shadercross.dll\0" 30 | VALUE "ProductName", "Simple DirectMedia Layer\0" 31 | VALUE "ProductVersion", "3, 0, 0, 0\0" 32 | END 33 | END 34 | BLOCK "VarFileInfo" 35 | BEGIN 36 | VALUE "Translation", 0x409, 1200 37 | END 38 | END 39 | --------------------------------------------------------------------------------