pax_global_header00006660000000000000000000000064150022217020014501gustar00rootroot0000000000000052 comment=3362e24c42ab5bf7ad32c0fec64b0a0ddeb2fda1 shaderc-2025.2/000077500000000000000000000000001500222170200132045ustar00rootroot00000000000000shaderc-2025.2/.clang-format000066400000000000000000000001171500222170200155560ustar00rootroot00000000000000--- # Use Google code formatting rules. Language: Cpp BasedOnStyle: Google ... shaderc-2025.2/.github/000077500000000000000000000000001500222170200145445ustar00rootroot00000000000000shaderc-2025.2/.github/workflows/000077500000000000000000000000001500222170200166015ustar00rootroot00000000000000shaderc-2025.2/.github/workflows/autoroll.yml000066400000000000000000000040331500222170200211650ustar00rootroot00000000000000# Copyright 2023 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,s either express or implied. # See the License for the specific language governing permissions and # limitations under the License. name: Update dependencies permissions: contents: read on: schedule: - cron: '0 2 * * *' workflow_dispatch: jobs: update-dependencies: permissions: contents: write pull-requests: write name: Update dependencies runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 # Checkout the depot tools they are needed by roll_deps.sh - name: Checkout depot tools run: git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git - name: Update PATH run: echo "$(pwd)/depot_tools" >> $GITHUB_PATH - name: Download dependencies run: python3 utils/git-sync-deps - name: Setup git user information run: | git config user.name "GitHub Actions[bot]" git config user.email "<>" git checkout -b roll_deps - name: Update dependencies run: | utils/roll-deps if [[ `git diff HEAD..origin/main --name-only | wc -l` == 0 ]]; then echo "changed=false" >> $GITHUB_OUTPUT else echo "changed=true" >> $GITHUB_OUTPUT fi id: update_dependencies - name: Push changes and create PR if: steps.update_dependencies.outputs.changed == 'true' run: | git push --force --set-upstream origin roll_deps gh pr create --label 'kokoro:run' --base main -f || true env: GITHUB_TOKEN: ${{ github.token }} shaderc-2025.2/.gitignore000066400000000000000000000005151500222170200151750ustar00rootroot00000000000000build/ build-*/ out/ *.pyc *.swp compile_commands.json .ycm_extra_conf.py cscope.* third_party/abseil_cpp third_party/effcee third_party/glslang third_party/googletest third_party/re2 third_party/spirv-tools third_party/spirv-headers third_party/spirv-cross third_party/tint android_test/libs android_test/include .DS_Store .vscode/ shaderc-2025.2/AUTHORS000066400000000000000000000004661500222170200142620ustar00rootroot00000000000000# This is the official list of shaderc authors for copyright purposes. # This file is distinct from the CONTRIBUTORS files. # See the latter for an explanation. # Names should be added to this file as: # Name or Organization # The email address is not required for organizations. Google Inc. shaderc-2025.2/Android.mk000066400000000000000000000053661500222170200151270ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ROOT_SHADERC_PATH := $(call my-dir) include $(ROOT_SHADERC_PATH)/third_party/Android.mk include $(ROOT_SHADERC_PATH)/libshaderc_util/Android.mk include $(ROOT_SHADERC_PATH)/libshaderc/Android.mk ALL_LIBS:=libglslang.a \ libshaderc.a \ libshaderc_util.a \ libSPIRV.a \ libSPIRV-Tools.a \ libSPIRV-Tools-opt.a SHADERC_HEADERS=shaderc.hpp shaderc.h env.h status.h visibility.h SHADERC_HEADERS_IN_OUT_DIR=$(foreach H,$(SHADERC_HEADERS),$(NDK_APP_LIBS_OUT)/../include/shaderc/$(H)) define gen_libshaderc_header $(call generate-file-dir,$(NDK_APP_LIBS_OUT)/../include/shaderc/$(1)) $(NDK_APP_LIBS_OUT)/../include/shaderc/$(1) : \ $(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/$(1) $(call host-cp,$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/$(1) \ ,$(NDK_APP_LIBS_OUT)/../include/shaderc/$(1)) endef # Generate headers $(eval $(foreach H,$(SHADERC_HEADERS),$(call gen_libshaderc_header,$(H)))) libshaderc_headers: $(SHADERC_HEADERS_IN_OUT_DIR) .PHONY: libshaderc_headers # Rules for combining library files to form a single libshader_combined.a. # It always goes into $(TARGET_OUT) $(call generate-file-dir,$(TARGET_OUT)/combine.ar) $(TARGET_OUT)/combine.ar: $(TARGET_OUT) $(addprefix $(TARGET_OUT)/, $(ALL_LIBS)) $(file >$(TARGET_OUT)/combine.ar,create libshaderc_combined.a) $(foreach lib,$(ALL_LIBS),$(file >>$(TARGET_OUT)/combine.ar,addlib $(lib))) $(file >>$(TARGET_OUT)/combine.ar,save) $(file >>$(TARGET_OUT)/combine.ar,end) $(TARGET_OUT)/libshaderc_combined.a: $(addprefix $(TARGET_OUT)/, $(ALL_LIBS)) $(TARGET_OUT)/combine.ar @echo "[$(TARGET_ARCH_ABI)] Combine: libshaderc_combined.a <= $(ALL_LIBS)" @cd $(TARGET_OUT) && $(TARGET_AR) -M < combine.ar && cd $(ROOT_SHADERC_PATH) @$(TARGET_STRIP) --strip-debug $(TARGET_OUT)/libshaderc_combined.a $(call generate-file-dir,$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a) $(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a: \ $(TARGET_OUT)/libshaderc_combined.a $(call host-cp,$(TARGET_OUT)/libshaderc_combined.a \ ,$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a) libshaderc_combined: libshaderc_headers \ $(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a shaderc-2025.2/BUILD.gn000066400000000000000000000063261500222170200144000ustar00rootroot00000000000000# Copyright 2018 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import("//build_overrides/build.gni") import("//build_overrides/shaderc.gni") glslang_dir = shaderc_glslang_dir spirv_tools_dir = shaderc_spirv_tools_dir config("shaderc_util_public") { include_dirs = [ "libshaderc_util/include" ] } source_set("shaderc_util_sources") { sources = [ "libshaderc_util/include/libshaderc_util/counting_includer.h", "libshaderc_util/include/libshaderc_util/exceptions.h", "libshaderc_util/include/libshaderc_util/file_finder.h", "libshaderc_util/include/libshaderc_util/format.h", "libshaderc_util/include/libshaderc_util/io_shaderc.h", "libshaderc_util/include/libshaderc_util/message.h", "libshaderc_util/include/libshaderc_util/mutex.h", "libshaderc_util/include/libshaderc_util/resources.h", "libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h", "libshaderc_util/include/libshaderc_util/string_piece.h", "libshaderc_util/include/libshaderc_util/universal_unistd.h", "libshaderc_util/include/libshaderc_util/version_profile.h", "libshaderc_util/src/compiler.cc", "libshaderc_util/src/file_finder.cc", "libshaderc_util/src/io_shaderc.cc", "libshaderc_util/src/message.cc", "libshaderc_util/src/resources.cc", "libshaderc_util/src/shader_stage.cc", "libshaderc_util/src/spirv_tools_wrapper.cc", "libshaderc_util/src/version_profile.cc", ] # Configure Glslang's interface to include HLSL-related entry points. defines = [ "ENABLE_HLSL=1" ] public_configs = [ ":shaderc_util_public" ] deps = [ "${glslang_dir}:glslang_sources", "${spirv_tools_dir}:spvtools", ] if (build_with_chromium) { configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] } } config("shaderc_public") { include_dirs = [ "libshaderc/include" ] if (is_component_build) { defines = [ "SHADERC_SHAREDLIB" ] } } component("libshaderc") { public_configs = [ ":shaderc_public", ":shaderc_util_public", ] defines = [ "SHADERC_IMPLEMENTATION" ] sources = [ "libshaderc/include/shaderc/env.h", "libshaderc/include/shaderc/shaderc.h", "libshaderc/include/shaderc/shaderc.hpp", "libshaderc/include/shaderc/status.h", "libshaderc/include/shaderc/visibility.h", "libshaderc/src/shaderc.cc", "libshaderc/src/shaderc_private.h", ] deps = [ ":shaderc_util_sources", "${spirv_tools_dir}:spvtools", "${spirv_tools_dir}:spvtools_val", "${glslang_dir}:glslang_sources", ] if (build_with_chromium) { configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] } } shaderc-2025.2/CHANGES000066400000000000000000000370261500222170200142070ustar00rootroot00000000000000Revision history for Shaderc v2025.2 - Update dependencies: Glslang, SPIRV-Tools, SPIRV-Headers - Supports BFloat16 floating point types v2025.1 - Update tools and compilers tested: - Clang 13 - GCC 13 - VisualStudio 2022 - CMake 3.31.2 - Python 3.12 - NDK r27c - Skip version numbers to match SPIRV-Tools, to avoid confusion. v2024.4 - Support Vulkan 1.4 v2024.3 - Update dependencies: Glslang, SPRIV-Tools, SPIRV-Headers - SPIRV-Tools is at v2024.4.rc1 - This incorporates a SPIRV-Tools fix which was limiting parallelism. Validator friendly name generation was serializing on a mutex protecting the locale object. - During HLSL compilation or any optimizing compile, don't tell the validator to use "friendly names". This should save time spent in the initial validation step of the optimization recipe. - Adapt test golden results to Glslang changes which reorder decorations by object enum value. - Fix ndk-build library dependencies: libshaderc_util depends on glslang - Use Python 3.12 on Linux CI bots - Fix Python 3.12 warnings for string escapes v2024.2 - Update dependencies: Glslang: top of tree 2024-06-21 SPIRV-Header: top of tree 2024-06-21 SPIRV-Tools: v2024.3.rc1 - Build: - Remove support for VS2017 v2024.1 - Update dependencies - Propagate test/install options to Glslang v2024.0 - Update dependencies - Utilities: - Use Python3 explicitly in utility scripts v2023.8 2024-01-03 - API: Expose rlaxed Vulkan rules from glslang - Update to Glslang 14.0.0 - CMake: - Comply with CMP0148: Use PythonInterp - Use TARGET_OBJECTS to simplify creating the shaderc_shared library. v2023.7 2023-10-12 - Update dependencies - Finish converting build instructions and flags to always use C++17 - Add GitHub CI to test more flows v2023.6 2023-08-09 - Update dependencies, including SPIRV-Tools v2023.4.rc2 v2023.5 2023-07-19 - Update dependencies - Update to Android NDK r25c - Update Android API level for test project (#1333) - For testing, add a dependency on Abseil's C++ library - Fix MSVC runtime library linking in CMake (#1339) v2023.4 2023-05-24 - Refresh Glslang, SPIRV-Tools, SPIRV-Headers - Android.mk: - Require NDK 21d or later - Update scripts for generating the shared library, which should fix Windows - glslc and APIs: - Add options to control mesh shading limits v2023.3 2023-03-17 - Shaderc now requires C++17 - Drop support for VS 2015 - Add glslc option -fpreserve-bindings - Refresh Glslang, SPIRV-Tools v2023.2 2023-01-18 - Update DEPS to pull in SPIRV-Tools bugfix #5049 v2023.1 2023-01-13 - General/Build - Removed support for GCC-based code coverage builds - Update minimum CMake to 3.17.2 - Fix C++20 compatibility: explicitly construct string_piece when comparing to `char*` v2022.4 2022-11-30 - Update to Glslang 11 - Update SPIRV-Tools, SPIRV-Headers dependencies - Add Cmake BUNDLE DESTINATION option for target install - The code coverage build is no longer being tested v2022.3 2022-10-12 - #1264: Implement defaults for SPV_EXT_mesh_shader builtins - Update SPIRV-Tools to v2022.4 v2022.2 2022-08-11 - Require CMake 3.14 or later - Support 16bit types in HLSL, via glslc option -fhlsl-16bit-types and associated library API methods. PR #1251 - Update glslc tests for newer Glslang debug output - Update SPIRV-Tools v2022.3 plus one patch - Update SPIRV-Headers v2022.1 2022-02-03 - Update DEPS to include two fixes on top of SPIRV-Tools v2022.1: - Validator handles Nontemporal image operand - Optimizer handles RayQueryKHR type v2022.0 2022-01-27 - Update to Glslang 11.8.0 v2021.4 2022-01-27 - Support Vulkan 1.3 - Support targeting SPIR-V 1.6, which is the default for Vulkan 1.3 - Updated copyright check: Excludes Glslang generated files when building in source tree - Fix Android.mk rules for building libshaderc_combined, to adapt to more recent NDKs that have removed the GNU binutils. v2021.3 2021-11-11 - Add build switch to disable copyright check - Update DEPS: - SPIRV-Tools v2021.4 - SPIRV-Headers GitHub master 2021-11-11 - Glslang GitHub master 2021-11-11 v2021.2 2021-08-25 - README: Mention Common Lisp bindings (external) - Update DEPS: - SPIRV-Tools v2021.3 - SPIRV-Headers master 2021-08-25 - Glslang GitHub master 2021-08-25 v2021.1 2021-06-21 - Disable --target-env=opengl_compat with an explicit error message - It has been deprecated for a long time. v2021.0 2021-04-21 - Refresh dependencies (in DEPS): - SPIRV-Tools v2021.1 - SPIRV-Headers snapshot 2021-04-21 - Glslang 11.2.0, snapshot 2021-04-21 - Fixes: #1174: Windows Bazel support: rename internal headers io.* to io_shaderc.* v2020.5 2021-02-19 - Refresh dependencies (in DEPS): - SPIRV-Tools v2020.7 + 1 patch - Glslang 11.1.0 - Add option to skip building examples - Fixes: #1153: Improve file+line parsing from Glslang messages v2020.4 2020-12-09 - Removed svpc - Fixed issues with embedders getting duplicate symbols - Converted C-style casts to static_cast - Rolled ahead to fix/pickup Vulkan Raytracing support v2020.3 2020-09-02 - General: - Last release with spvc - Cleaned up issues discovered by Infer - spvc: - Added support for Dawn using deprecated Options constructor - Adding support for the additional fixed sample mask in MSL v2020.2 2020-07-23 - General: - Remove VS2013 support - Support both posix and non-posix MinGW toolchains - Support optionally building Tint tooling for WGSL - Add -h option to glslc, spvc; same as --help - Add source file license checker - BUILD.gn improvements - glslc, libshaderc: - Update to Glslang generator 9 - Add interface to support 16bit types in HLSL - Add glslc hidden experimental option -mfmt=wgsl; requires Tint - spvc: - Add minimum buffer size for Dawn reflection v2020.1 2020-06-09 This is the last version that officially supports VS2013. - General: - Added warning signs about unsupported downloads (#1041) - Added .NET bindings to README.md (#1060) - Only add -fPIC if supported by the compiler. (#1061) - glslc, libshaderc: - Removed Singleton pattern around access to glslang (#1059) - spvc: - Added concept of comparison sampler to API (#1036) - Added support for options.hlsl.nonwritable_uav_texture_as_srv (#1048) - Support forcing storage buffers to be always declared as UAV. (#1076) v2020.0 2020-03-06 - General: - Getting spirv.hpp from SPIRV-Headers instead of not glslang (#992) - Added clarification about status of artifacts in downloads.md (#1012) - glslc, libshaderc: - Added support for new Glslang profile enum, EProfileCount (#973) - Updated user documentation for -S in glslc (#978) - Add documentation for Vulkan 1.2 and SPIR-V 1.5 (#980) - Removed NV_EXTENSIONS conditionals (#1003) - Added support for generating WebGPU SPIR-V to libshaderc (#1021) - Rolled in all DEPS for provisional SPIR-V extensions for raytracing - spvc: - Normalized API behaviour (#967) - Added source_set target for libshaderc_spvc (#976) - Added in support for spvc logging to the terminal (#981) - Internal refactoring to reduce boiler plate in API implementations (#984) - Added newline to logging messages to make them readable (#985) - Added reflection support for Dawn: - storage textures (#1001) - storage texture format (#1005) - texture dimension for storage textures (#1008) - is storage texture declared as multisampled texture (#1011) - Converted compile options to require explicit environments (#1019) - Added knob to control force_zero_initialized_variables in SPIRV-Cross (#1028) v2019.1 2020-01-22 - glslc, libshaderc: - Add -fnan-clamp: Generate code for max and min builtins so that, given a NaN operand, will return the other operand. Similarly, the clamp builtin favours non-NaN operands, as if clamp was implemented as the composition of max and min. - Add -finvert-y - Using SetBeforeHlslLegalization for more relaxed validation rules - Added support for SPIR-V 1.5 - Add --emit-line-directive option - Added support for Vulkan 1.2 - spvc: - Add many options: --flatten-multidimensional-arrays --es --no-es --glsl-emit-push-constant-as-ubo --msl-swizzle-texture-samples --msl-platform=ios|macos --msl-pad-fragment-output --msl-capture-output --msl-domain-lower-left --msl-argument-buffers --msl-discrete-descriptor-set= --hlsl-enable-compat - Reintroduce shaderc_spvc_compile_options_set_shader_model - Added option to inject robust buffer access code - Added support for emitting ToVulkan shaders - Added spirv-opt based IR generation as alternative to built in spirv_cross IR gen - Added API for specifying source and target execution environments - Added option & reflection API methods neede by Dawn - Substantial internal refactoring and code cleanup - Large number of breaking changes to the API - Replaced shaderc_spvc_compile_options_set_shader_model with shaderc_spvc_compile_options_set_hlsl_shader_model - Compiler initialization and shader generation moved into seperate calls - Seperated return codes from shaderc ones - Many small API changes - Improvements to testing - Refactoring and clean up of run_spirv_cross_tests.py - Seperation of expectations into known failures, known invalids, and cases that need investigation - Tweaks and fixes to substantially increase passing cases - Added support for running tests using spvc IR generation - Infrastructure - Update DEPS with cross-verified commits from associated repos. - Add utils/roll-deps - Infrastructure: - Removed Appveyor artifacts link - Improvements and clean up of DEPS rolling scripts - Enabled warnings about implicit fallthrough - Enabled improper semicolon warnings - Restricted -fPIC to platforms that support it - Converted remaining scripts to use Python 3 - Replaced nosetest with unittest - Removed assumptions aabout location of spirv-tools, effcee, and RE2 - Migrated BUILD.gn spirv_cross dependency to local repo - Fixes: - Fix duplicate install paths when using VisualStudio - Fixed BUILD.gn for Chromium, Dawn & Fuchsia - Explicitly enabled HLSL support in glslang - Added installing necessary headers in Android.mk - Removed unsupported Unicode characters - Fixed detection of spirv-headers directory #666: Update Docker file to use Python3 v2019.0 2019-06-04 - Add optional spvc, libshaderc_spvc as wrapper around SPIRV-Cross: - Rejects bad modules by running the SPIR-V validator first - Skips exception-heavy SPIRV-Cross SPIR-V parser - Support NV extensions for shader stages - Require SPIRV-Tools and SPIRV-Headers with SPIR-V 1.4 support Build support: - Use KhronosGroup/glslang instead of google/glslang - Stop running tests on VS 2013 (googletest no longer supports VS2013) - Require Python3 for building - Support Chromium's GN build system - Kokoro build fixes - Cmake build fixes: Only build subdirs if those targets are not yet defined - Use Android.mk from Glslang - Dockerfile gets re2 and effcee sources - Fixes for newer googletest - Add address sanitizer presubmit bot - Generate config files for pkg-config Spvc: - Add option to specify source environment. Spvc will transform from source to target environment if they are different. This only works for WebGPU0 and Vulkan 1.1. Fixes: #499: In HLSL compilation, relax layout and logical pointer validation rules prior to running the legalization recipe. v2018.0 2018-10-01 - Support -fhlsl_functionality1 (also -fhlsl-functionality1) - Support NVIDIA Turing extensions. Requires updated Glslang and SPIRV-Tools. - Use SPIR-V optimization and HLSL legalization recipes from SPIRV-Tools. - Pass target environment into SPIRV-Tools code, e.g. from --target-env vulkan1.1 - Add SONAME=1 property to shared library - Support GN build for Chromium Fixes: #469: Add virtual dtor to classes with virtual functions. #457: Fix writing SPIR-V binaries to standard output on Windows. v2017.2 2018-02-27 - Add a shared library version of libshaderc - Support GLSL 4.6 and ESSL 3.2 - Fail compilation if a resource does not have a binding. - Add options for automatically setting bindings for (uniform) resources that don't have bindings set in shader source. - Add options for automatically setting locations for pipline inputs and outputs. - Add option for using HLSL IO mappings as expressed in source. - Add options for setting resource binding base numbers. - Add option to use HLSL resource register numbers for bindings. - HLSL compilation now defaults to HLSL packing rules. (This change is inherited from Glslang commit 7cca140.) - HLSL compilation runs SPIR-V "legalization" transforms to reduce manipulation of opaque handles (e.g. images), to satisfy Vulkan rules. - Adapt to Glslang generator version numbers: - To 2: a fix for code generation for atomicCounterDecrement. - To 3: change memory barrier semantics masks - To 4: generate more access chains for swizzles - CMake install rules uses GNUInstallDirs. For example, install to lib64 when that is the norm for the target system. v2017.1 2017-03-10 - Add option to automatically assign bindings to uniform variables that don't have an explicit 'binding' layout in the shader source. - Enable NVIDIA extensions by default in GLSL compilation - README mentions language bindings provided by 3rd parties. - README describes the known-good branch on GitHub - Fixed examples in shaderc.h; added C API use to examples/online-compile - Fixes issues: #289: Don't output an object file when compilation fails. #296: Enable use of the CMake in Android Studio. v2016.2 2016-12-13 - Describe Shaderc's level of stability. - Support HLSL compilation, exposing functionality in Glslang. - Supported in C, C++ API - glslc accepts "-x hlsl", and assumes .hlsl files are HLSL. - glslc accepts "-fentry-point=" to set entry point name, overriding default value "main". - Support setting shader resource limits in C, C++ APIs, and in glslc - glslc adds -flimit= - glslc adds --show-limits to display defaults and valid resource limit syntax. - glslc adds "-flimit-file " support to read Glslang resource configuration files, i.e. the output of "glslangValidator -c". - Enable AMD extensions by default in GLSL compilation - Fixes issues: #281: Work around Android build issue with abspath on Windows #283: Increase default maxDrawBuffers to 4, to match Vulkan/GLES3.0 v2016.1 2016-10-12 - C API for assembling now takes an options object - Support compilation options to optimize for size. - Maintain compatibility with recent SPIRV-Tools and Glslang versions. - Update examples. - Build cleanups. - Fixes issues: #238: Fix invocation of python scripts during build v2016.0 2016-07-07 - Adds v. versioning, with "-dev" suffix to indicate work in progress. The intent is to summarize and report functionalities more easily for incorporating into downstream projects. - Summary of functionalities (See the README.md for more details): - Provides libraries and command line tools for generating SPIR-V modules - Supports GLSL source code or SPIR-V assembly as input - Supports SPIR-V binary or assembly text as output - Command line options follow GCC/Clang conventions - Supports various semantics (OpenGL, OpenGL Compatible and Vulkan) - Supports #include - Supports user-defined macros - Supports dependency information dumping shaderc-2025.2/CMakeLists.txt000066400000000000000000000131171500222170200157470ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. cmake_minimum_required(VERSION 3.22.1) project(shaderc) enable_testing() if ("${CMAKE_BUILD_TYPE}" STREQUAL "") message(STATUS "No build type selected, default to Debug") set(CMAKE_BUILD_TYPE "Debug") endif() message(STATUS "Shaderc: build type is \"${CMAKE_BUILD_TYPE}\".") option(SHADERC_ENABLE_WGSL_OUTPUT "Enable WGSL output" OFF) option(SHADERC_SKIP_INSTALL "Skip installation" ${SHADERC_SKIP_INSTALL}) if(NOT ${SHADERC_SKIP_INSTALL}) set(SHADERC_ENABLE_INSTALL ON) endif() option(SHADERC_SKIP_TESTS "Skip building tests" ${SHADERC_SKIP_TESTS}) if(NOT ${SHADERC_SKIP_TESTS}) set(SHADERC_ENABLE_TESTS ON) endif() if(${SHADERC_ENABLE_TESTS}) message(STATUS "Configuring Shaderc to build tests.") else() message(STATUS "Configuring Shaderc to avoid building tests.") endif() option(SHADERC_SKIP_EXAMPLES "Skip building examples" ${SHADERC_SKIP_EXAMPLES}) if(NOT ${SHADERC_SKIP_EXAMPLES}) set(SHADERC_ENABLE_EXAMPLES ON) endif() if(${SHADERC_ENABLE_EXAMPLES}) message(STATUS "Configuring Shaderc to build examples.") else() message(STATUS "Configuring Shaderc to avoid building examples.") endif() option(SHADERC_SKIP_COPYRIGHT_CHECK "Skip copyright check" ${SHADERC_SKIP_COPYRIGHT_CHECK}) if(NOT ${SHADERC_SKIP_COPYRIGHT_CHECK}) set(SHADERC_ENABLE_COPYRIGHT_CHECK ON) endif() if(${SHADERC_ENABLE_COPYRIGHT_CHECK}) message(STATUS "Configuring Shaderc to check copyrights.") else() message(STATUS "Configuring Shaderc to avoid checking copyrights.") endif() option(SHADERC_ENABLE_WERROR_COMPILE "Enable passing -Werror to compiler, if available" ON) set (CMAKE_CXX_STANDARD 17) include(GNUInstallDirs) include(cmake/setup_build.cmake) include(cmake/utils.cmake) include(CheckCXXCompilerFlag) set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS ${DISABLE_EXCEPTIONS} CACHE BOOL "Coupling SPIRV-Cross exception conversion to DISABLE_EXCEPTIONS" FORCE) if(DISABLE_EXCEPTIONS) # Need to set additional values here, since some of the wrapped code occurs in # .h/.hpp files, so maybe included outside of the library. add_definitions(-DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS) endif() # These flags are not supported on Windows and some older version of GCC # that our bots use. # Warning about implicit fallthrough in switch blocks check_cxx_compiler_flag(-Wimplicit-fallthrough COMPILER_SUPPORTS_FALLTHROUGH_WARNING) if (COMPILER_SUPPORTS_FALLTHROUGH_WARNING) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wimplicit-fallthrough") endif() # Warning about extra semi-colons check_cxx_compiler_flag(-Wextra-semi COMPILER_SUPPORTS_EXTRA_SEMI_WARNING) if (COMPILER_SUPPORTS_EXTRA_SEMI_WARNING) add_compile_options("-Wextra-semi") endif() find_package(Python COMPONENTS Interpreter REQUIRED) if (SHADERC_ENABLE_COPYRIGHT_CHECK) add_custom_target(check-copyright ALL ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/utils/add_copyright.py --check WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Check copyright") endif() add_custom_target(add-copyright ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/utils/add_copyright.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Add copyright") if(MSVC) option(SHADERC_ENABLE_SHARED_CRT "Use the shared CRT instead of the static CRT" OFF) if (SHADERC_ENABLE_SHARED_CRT) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") else() set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") endif() endif(MSVC) # Configure subdirectories. # We depend on these for later projects, so they should come first. add_subdirectory(third_party) add_subdirectory(libshaderc_util) add_subdirectory(libshaderc) add_subdirectory(glslc) if(${SHADERC_ENABLE_EXAMPLES}) add_subdirectory(examples) endif() add_custom_target(build-version ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/utils/update_build_version.py ${shaderc_SOURCE_DIR} ${spirv-tools_SOURCE_DIR} ${glslang_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/build-version.inc COMMENT "Update build-version.inc in the Shaderc build directory (if necessary).") function(define_pkg_config_file NAME LIBS) add_custom_target(${NAME}-pkg-config ALL COMMAND ${CMAKE_COMMAND} -DCHANGES_FILE=${CMAKE_CURRENT_SOURCE_DIR}/CHANGES -DTEMPLATE_FILE=${CMAKE_CURRENT_SOURCE_DIR}/cmake/${NAME}.pc.in -DOUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/${NAME}.pc -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR} -DCMAKE_INSTALL_INCLUDEDIR=${CMAKE_INSTALL_INCLUDEDIR} -DLIBS=${LIBS} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/write_pkg_config.cmake DEPENDS "CHANGES" "cmake/${NAME}.pc.in" "cmake/write_pkg_config.cmake") if (SHADERC_ENABLE_INSTALL) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) endif() endfunction() define_pkg_config_file(shaderc -lshaderc_shared) define_pkg_config_file(shaderc_static "-lshaderc ${EXTRA_STATIC_PKGCONFIG_LIBS} -lshaderc_util") define_pkg_config_file(shaderc_combined -lshaderc_combined) shaderc-2025.2/CONTRIBUTING.md000066400000000000000000000025511500222170200154400ustar00rootroot00000000000000Want to contribute? Great! First, read this page (including the small print at the end). Then, have a look at [`DEVELOPMENT.howto.md`](DEVELOPMENT.howto.md), which contains useful info to guide you along the way. ## Before you contribute Before we can use your code, you must sign the [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1) (CLA), which you can do online. The CLA is necessary mainly because you own the copyright to your changes, even after your contribution becomes part of our codebase, so we need your permission to use and distribute your code. We also need to be sure of various other things -- for instance that you'll tell us if you know that your code infringes on other people's patents. You don't have to sign the CLA until after you've submitted your code for review and a member has approved it, but you must do it before we can put your code into our codebase. Before you start working on a larger contribution, you should get in touch with us first through the issue tracker with your idea so that we can help out and possibly guide you. Coordinating up front makes it much easier to avoid frustration later on. ## The small print Contributions made by corporations are covered by a different agreement than the one above, the Software Grant and Corporate Contributor License Agreement. shaderc-2025.2/CONTRIBUTORS000066400000000000000000000015621500222170200150700ustar00rootroot00000000000000# People who have agreed to one of the CLAs and can contribute patches. # The AUTHORS file lists the copyright holders; this file # lists people. For example, Google employees are listed here # but not in AUTHORS, because Google holds the copyright. # # https://developers.google.com/open-source/cla/individual # https://developers.google.com/open-source/cla/corporate # # Names should be added to this file as: # Name Lei Zhang David Neto Andrew Woloszyn Stefanus Du Toit Dejan Mircevski Mark Adams Jason Ekstrand Damien Mabin Qining Lu Jakob Vogel David Yen Adam Chainz Robin Quint shaderc-2025.2/DEPS000066400000000000000000000025201500222170200136610ustar00rootroot00000000000000use_relative_paths = True vars = { 'abseil_git': 'https://github.com/abseil', 'google_git': 'https://github.com/google', 'khronos_git': 'https://github.com/KhronosGroup', 'abseil_revision': '1315c900e1ddbb08a23e06eeb9a06450052ccb5e', 'effcee_revision': '08da24ec245a274fea3a128ba50068f163390565', 'glslang_revision': '697683e6b8871420d7d942b1a2fe233242ab5608', 'googletest_revision': '1d17ea141d2c11b8917d2c7d029f1c4e2b9769b2', 're2_revision': '4a8cee3dd3c3d81b6fe8b867811e193d5819df07', 'spirv_headers_revision': 'aa6cef192b8e693916eb713e7a9ccadf06062ceb', 'spirv_tools_revision': 'a62abcb402009b9ca5975e6167c09f237f630e0e', } deps = { 'third_party/abseil_cpp': Var('abseil_git') + '/abseil-cpp.git@' + Var('abseil_revision'), 'third_party/effcee': Var('google_git') + '/effcee.git@' + Var('effcee_revision'), 'third_party/googletest': Var('google_git') + '/googletest.git@' + Var('googletest_revision'), 'third_party/glslang': Var('khronos_git') + '/glslang.git@' + Var('glslang_revision'), 'third_party/re2': Var('google_git') + '/re2.git@' + Var('re2_revision'), 'third_party/spirv-headers': Var('khronos_git') + '/SPIRV-Headers.git@' + Var('spirv_headers_revision'), 'third_party/spirv-tools': Var('khronos_git') + '/SPIRV-Tools.git@' + Var('spirv_tools_revision'), } shaderc-2025.2/DEVELOPMENT.howto.md000066400000000000000000000050221500222170200164460ustar00rootroot00000000000000Thank you for considering Shaderc development! Please make sure you review [`CONTRIBUTING.md`](CONTRIBUTING.md) for important preliminary info. ## Building Instructions for first-time building can be found in [`README.md`](README.md). Incremental build after a source change can be done using `ninja` (or `cmake --build`) and `ctest` exactly as in the first-time procedure. ## Code reviews (Terminology: we consider everyone with write access to our GitHub repo a project _member_.) All submissions, including submissions by project members, require review. We use GitHub pull requests to facilitate the review process. A submission may be accepted by any project member (other than the submitter), who will then squash the changes into a single commit and cherry-pick them into the repository. Before accepting, there may be some review feedback prompting changes in the submission. You should expect reviewers to strictly insist on the [commenting](https://google.github.io/styleguide/cppguide.html#Comments) guidelines -- in particular, every file, class, method, data member, and global will require a comment. Reviewers will also expect to see test coverage for every code change. _How much_ coverage will be a judgment call on a case-by-case basis, balancing the required effort against the incremental benefit. Coverage will be expected. As a matter of development philosophy, we will strive to engineer the code to make writing tests easy. ## Coding style For our C++ files, we use the [Google C++ style guide](https://google.github.io/styleguide/cppguide.html). (Conveniently, the formatting rules it specifies can be achieved using `clang-format -style=google`.) For our Python files, we use the [Google Python style guide](https://google.github.io/styleguide/pyguide.html). ## Supported platforms We expect Shaderc to always build and test successfully on the platforms listed below. Please keep that in mind when offering contributions. This list will likely grow over time. | Platform | Build Status | |:--------:|:------------:| | Android (ARMv7) | Not Automated | | Linux (x86_64) | [![Linux Build Status](https://travis-ci.org/google/shaderc.svg)](https://travis-ci.org/google/shaderc "Linux Build Status") | | Mac OS X | [![Mac Build Status](https://travis-ci.org/google/shaderc.svg)](https://travis-ci.org/google/shaderc "Mac Build Status") | | Windows (x86_64) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/g6c372blna7vnk1l?svg=true)](https://ci.appveyor.com/project/dneto0/shaderc "Windows Build Status") | shaderc-2025.2/Dockerfile000066400000000000000000000021761500222170200152040ustar00rootroot00000000000000# Copyright 2016 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM alpine MAINTAINER Google Shaderc Team RUN apk add --update \ build-base \ cmake \ git \ ninja \ python3 \ py-pip \ && rm -rf /var/cache/apk/* WORKDIR /root RUN git clone https://github.com/google/shaderc WORKDIR shaderc RUN ./utils/git-sync-deps WORKDIR build RUN cmake -GNinja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr/local \ .. \ && ninja install WORKDIR /root RUN rm -rf shaderc RUN adduser -s /bin/sh -D shaderc USER shaderc VOLUME /code WORKDIR /code CMD ["/bin/sh"] shaderc-2025.2/LICENSE000066400000000000000000000261351500222170200142200ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. shaderc-2025.2/README.md000066400000000000000000000237541500222170200144760ustar00rootroot00000000000000# Shaderc A collection of tools, libraries and tests for shader compilation. At the moment it includes: - [`glslc`](glslc), a command line compiler for GLSL/HLSL to SPIR-V, and - [`libshaderc`](libshaderc), a library API for accessing `glslc` functionality. **Note:** The fact that that `libshaderc` is not named `libshaderc_glslc` is a quirk of history, and a known inconsistency. Changing it would require a significant amount of renaming and breaking of downstream projects, so it is being left as is. `glslc` wraps around core functionality in [glslang][khr-glslang] and [SPIRV-Tools][spirv-tools]. `glslc` and its library aims to to provide: * a command line compiler with GCC- and Clang-like usage, for better integration with build systems * an API where functionality can be added without breaking existing clients * an API supporting standard concurrency patterns across multiple operating systems * increased functionality such as file `#include` support ## Downloads **Note: These binaries are just the artifacts of the builders and have not undergone any QA, thus they should be considered unsupported.** Linux[![Linux Build Status](https://storage.googleapis.com/shaderc/badges/build_status_linux_clang_release.svg)](https://storage.googleapis.com/shaderc/badges/build_link_linux_clang_release.html) MacOS[![MacOS Build Status](https://storage.googleapis.com/shaderc/badges/build_status_macos_clang_release.svg)](https://storage.googleapis.com/shaderc/badges/build_link_macos_clang_release.html) Windows[![Windows Build Status](https://storage.googleapis.com/shaderc/badges/build_status_windows_vs2019_release.svg)](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2019_release.html) [More downloads](downloads.md) ## Status Shaderc has maintained backward compatibility for quite some time, and we don't anticipate any breaking changes. Ongoing enhancements are described in the [CHANGES](CHANGES) file. Shaderc has been shipping in the [Android NDK](https://developer.android.com/ndk/index.html) since version r12b. (The NDK build uses sources from https://android.googlesource.com/platform/external/shaderc/. Those repos are downstream from GitHub.) We currently require r25c. For licensing terms, please see the [`LICENSE`](LICENSE) file. If interested in contributing to this project, please see [`CONTRIBUTING.md`](CONTRIBUTING.md). This is not an official Google product (experimental or otherwise), it is just code that happens to be owned by Google. That may change if Shaderc gains contributions from others. See the [`CONTRIBUTING.md`](CONTRIBUTING.md) file for more information. See also the [`AUTHORS`](AUTHORS) and [`CONTRIBUTORS`](CONTRIBUTORS) files. ## File organization - `android_test/` : a small Android application to verify compilation - `cmake/`: CMake utility functions and configuration for Shaderc - `examples/`: Example programs - `glslc/`: an executable to compile GLSL to SPIR-V - `libshaderc/`: a library for compiling shader strings into SPIR-V - `libshaderc_util/`: a utility library used by multiple shaderc components - `third_party/`: third party open source packages; see below - `utils/`: utility scripts for Shaderc Shaderc depends on glslang, the Khronos reference compiler for GLSL. Shaderc depends on [SPIRV-Tools][spirv-tools] for assembling, disassembling, and transforming SPIR-V binaries. For testing, Shaderc depends on: | Library | URL | Description | | -- | -- | -- | | Googletest | https://github.com/google/googletest | Testing framework | | Effcee | https://github.com/google/effcee | Stateful pattern matcher inspired by LLVM's FileCheck | | RE2 | https://github.com/google/re2 | Regular expression matcher | | Abseil | https://github.com/abseil/abseil-cpp | Common basic utilities in C++ | In the following sections, `$SOURCE_DIR` is the directory you intend to clone Shaderc into. ## Getting and building Shaderc **If you only want prebuilt executables or libraries, see the [Downloads](#downloads) section.** The rest of this section describes how to build Shaderc from sources. Note: Shaderc assumes Glslang supports HLSL compilation. The instructions below assume you're building Glslang from sources, and in a subtree of `shaderc/third_party`. In that scenario, Glslang's HLSL support is automatically enabled. Shaderc also can be built using a Glslang from outside the `shaderc/third_party` tree. In that case you must ensure that that external Glslang is built with HLSL functionality. See Glslang's `ENABLE_HLSL` CMake setting.) 1) Check out the source code: ```sh git clone https://github.com/google/shaderc $SOURCE_DIR cd $SOURCE_DIR ./utils/git-sync-deps ``` **Note:** The [known-good](https://github.com/google/shaderc/tree/known-good) branch of the repository contains a [known_good.json](https://github.com/google/shaderc/blob/known-good/known_good.json) file describing a set of repo URLs and specific commits that have been tested together. This information is updated periodically, and typically matches the latest update of these sources in the development branch of the Android NDK. The `known-good` branch also contains a [update_shaderc.py](https://github.com/google/shaderc/blob/known-good/update_shaderc_sources.py) script that will read the JSON file and checkout those specific commits for you. 2) Ensure you have the requisite tools -- see the tools subsection below. 3) Decide where to place the build output. In the following steps, we'll call it `$BUILD_DIR`. Any new directory should work. We recommend building outside the source tree, but it is also common to build in a (new) subdirectory of `$SOURCE_DIR`, such as `$SOURCE_DIR/build`. 4a) Build (and test) with Ninja on Linux or Windows: ```sh cd $BUILD_DIR cmake -GNinja -DCMAKE_BUILD_TYPE={Debug|Release|RelWithDebInfo} $SOURCE_DIR ninja ctest # optional ``` 4b) Or build (and test) with MSVC on Windows: ```sh cd $BUILD_DIR cmake $SOURCE_DIR cmake --build . --config {Release|Debug|MinSizeRel|RelWithDebInfo} ctest -C {Release|Debug|MinSizeRel|RelWithDebInfo} ``` 4c) Or build with MinGW on Linux for Windows: ```sh cd $BUILD_DIR cmake -GNinja -DCMAKE_BUILD_TYPE={Debug|Release|RelWithDebInfo} $SOURCE_DIR \ -DCMAKE_TOOLCHAIN_FILE=$SOURCE_DIR/cmake/linux-mingw-toolchain.cmake ninja ``` After a successful build, you should have a `glslc` executable somewhere under the `$BUILD_DIR/glslc/` directory, as well as a `libshaderc` library somewhere under the `$BUILD_DIR/libshaderc/` directory. The default behavior on MSVC is to link with the static CRT. If you would like to change this behavior `-DSHADERC_ENABLE_SHARED_CRT` may be passed on the cmake configure line. See [the libshaderc README](libshaderc/README.md) for more on using the library API in your project. ### Tools you'll need For building, testing, and profiling Shaderc, the following tools should be installed regardless of your OS: - A C++17 compiler. Recent versions of Clang, GCC, and MSVC work. - [CMake](http://www.cmake.org/) 3.14 or later: for generating compilation targets. - Shaderc is tested with cmake 3.17.2 - [Python 3](http://www.python.org/): for utility scripts and running the test suite. On Linux, if cross compiling to Windows: - [`mingw`](http://www.mingw.org): A GCC-based cross compiler targeting Windows so that generated executables use the Microsoft C runtime libraries. The MinGW compiler must support C++17. On Windows, the following tools should be installed and available on your path: - Visual Studio 2019 or later. Previous versions of Visual Studio may work but are untested and unsupported. - Git - including the associated tools, Bash, `diff`. Optionally, the following tools may be installed on any OS: - [`asciidoctor`](http://asciidoctor.org/): for generating documentation. - [`pygments.rb`](https://rubygems.org/gems/pygments.rb) required by `asciidoctor` for syntax highlighting. ### Building and running Shaderc using Docker Please make sure you have the Docker engine [installed](https://docs.docker.com/engine/installation/) on your machine. To create a Docker image containing Shaderc command line tools, issue the following command in `${SOURCE_DIR}`: `docker build -t .`. The created image will have all the command line tools installed at `/usr/local` internally, and a data volume mounted at `/code`. Assume `` is `shaderc/shaderc` from now on. To invoke a tool from the above created image in a Docker container: ```bash docker run shaderc/shaderc glslc --version ``` Alternatively, you can mount a host directory (e.g., `example`) containing the shaders you want to manipulate and run different kinds of tools via an interactive shell in the container: ```bash $ docker run -i -t -v `pwd`/example:/code shaderc/shaderc /code $ ls test.vert /code $ glslc -c -o - test.vert | spirv-dis ``` ## Bug tracking We track bugs using GitHub -- click on the "Issues" button on [the project's GitHub page](https://github.com/google/shaderc). ## Bindings Bindings are maintained by third parties, may contain content offered under a different license, and may reference or contain older versions of Shaderc and its dependencies. * **Python:** [pyshaderc][pyshaderc] * **Rust:** [shaderc-rs][shaderc-rs] * **Go:** [gshaderc][gshaderc] * **.NET:** [shaderc.net][shadercdotnet] * **Common Lisp:** [shadercl][shaderccommonlisp] [khr-glslang]: https://github.com/KhronosGroup/glslang [spirv-tools]: https://github.com/KhronosGroup/SPIRV-Tools [spirv-cross]: https://github.com/KhronosGroup/SPIRV-Cross [pyshaderc]: https://github.com/realitix/pyshaderc [shaderc-rs]: https://github.com/google/shaderc-rs [appveyor]: https://ci.appveyor.com/project/dneto0/shaderc [dawn]: https://dawn.googlesource.com/dawn [gshaderc]: https://github.com/celer/gshaderc [shadercdotnet]: https://github.com/jpbruyere/shaderc.net [shaderccommonlisp]: https://github.com/JolifantoBambla/shadercl shaderc-2025.2/android_test/000077500000000000000000000000001500222170200156635ustar00rootroot00000000000000shaderc-2025.2/android_test/Android.mk000066400000000000000000000016551500222170200176030ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_CPP_EXTENSION := .cc .cpp .cxx LOCAL_SRC_FILES:=test.cpp LOCAL_MODULE:=shaderc_test LOCAL_LDLIBS:=-landroid LOCAL_STATIC_LIBRARIES=shaderc android_native_app_glue include $(BUILD_SHARED_LIBRARY) include $(LOCAL_PATH)/../Android.mk $(call import-module,android/native_app_glue) shaderc-2025.2/android_test/jni/000077500000000000000000000000001500222170200164435ustar00rootroot00000000000000shaderc-2025.2/android_test/jni/Android.mk000066400000000000000000000012371500222170200203570ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. LOCAL_PATH := $(call my-dir) include $(LOCAL_PATH)/../Android.mk shaderc-2025.2/android_test/jni/Application.mk000066400000000000000000000014301500222170200212350ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. APP_ABI := all APP_BUILD_SCRIPT := Android.mk APP_STL := c++_static # Vulkan was added at API level 24. # Android NDK 26 will drop support for APIs before 21. APP_PLATFORM := android-24 shaderc-2025.2/android_test/test.cpp000066400000000000000000000016611500222170200173520ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "shaderc/shaderc.hpp" #include void android_main(struct android_app* state) { shaderc::Compiler compiler; const char* test_program = "void main() {}"; compiler.CompileGlslToSpv(test_program, strlen(test_program), shaderc_glsl_vertex_shader, "shader"); } shaderc-2025.2/build_overrides/000077500000000000000000000000001500222170200163655ustar00rootroot00000000000000shaderc-2025.2/build_overrides/build.gni000066400000000000000000000014041500222170200201620ustar00rootroot00000000000000# Copyright 2019 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # These are variables that are overridable by projects that include shaderc. # Set to true when building shaderc as part of Chromium. build_with_chromium = false shaderc-2025.2/build_overrides/shaderc.gni000066400000000000000000000015621500222170200205010ustar00rootroot00000000000000# Copyright 2018 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # These are variables that are overridable by projects that include shaderc. # The path to shaderc dependencies. shaderc_glslang_dir = "//third_party/glslang" shaderc_spirv_tools_dir = "//third_party/spirv-tools" shaderc_spirv_headers_dir = "//third_party/spirv-headers" shaderc-2025.2/cmake/000077500000000000000000000000001500222170200142645ustar00rootroot00000000000000shaderc-2025.2/cmake/linux-mingw-toolchain.cmake000066400000000000000000000027571500222170200215350ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. SET(CMAKE_SYSTEM_NAME Windows) set(MINGW_COMPILER_PREFIX "i686-w64-mingw32" CACHE STRING "What compiler prefix to use for mingw") set(MINGW_SYSROOT "/usr/${MINGW_COMPILER_PREFIX}" CACHE STRING "What sysroot to use for mingw") # Which compilers to use for C and C++ find_program(CMAKE_RC_COMPILER NAMES ${MINGW_COMPILER_PREFIX}-windres) find_program(CMAKE_C_COMPILER NAMES ${MINGW_COMPILER_PREFIX}-gcc-posix ${MINGW_COMPILER_PREFIX}-gcc) find_program(CMAKE_CXX_COMPILER NAMES ${MINGW_COMPILER_PREFIX}-g++-posix ${MINGW_COMPILER_PREFIX}-g++) SET(CMAKE_FIND_ROOT_PATH ${MINGW_SYSROOT}) # Adjust the default behaviour of the FIND_XXX() commands: # Search headers and libraries in the target environment; search # programs in the host environment. set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) shaderc-2025.2/cmake/setup_build.cmake000066400000000000000000000042761500222170200176160ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. if(NOT COMMAND find_host_package) macro(find_host_package) find_package(${ARGN}) endmacro() endif() if(NOT COMMAND find_host_program) macro(find_host_program) find_program(${ARGN}) endmacro() endif() # Find asciidoctor; see shaderc_add_asciidoc() from utils.cmake for # adding documents. find_program(ASCIIDOCTOR_EXE NAMES asciidoctor) if (NOT ASCIIDOCTOR_EXE) message(STATUS "asciidoctor was not found - no documentation will be" " generated") endif() # On Windows, CMake by default compiles with the shared CRT. # Ensure that gmock compiles the same, otherwise failures will occur. if(WIN32) # TODO(awoloszyn): Once we support selecting CRT versions, # make sure this matches correctly. set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) endif(WIN32) if (ANDROID) # For android let's preemptively find the correct packages so that # child projects (glslang, googletest) do not fail to find them. # Tests in glslc and SPIRV-Tools tests require Python 3, or a Python 2 # with the "future" package. Require Python 3 because we can't force # developers to manually install the "future" package. find_host_package(PythonInterp 3 REQUIRED) find_host_package(BISON) else() find_package(Python COMPONENTS Interpreter REQUIRED) endif() option(DISABLE_RTTI "Disable RTTI in builds") if(DISABLE_RTTI) if(UNIX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") endif(UNIX) endif(DISABLE_RTTI) option(DISABLE_EXCEPTIONS "Disables exceptions in builds") if(DISABLE_EXCEPTIONS) if(UNIX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") endif(UNIX) endif(DISABLE_EXCEPTIONS) shaderc-2025.2/cmake/shaderc.pc.in000066400000000000000000000005161500222170200166300ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ Name: shaderc Description: Tools and libraries for Vulkan shader compilation Version: @CURRENT_VERSION@ URL: https://github.com/google/shaderc Libs: -L${libdir} @LIBS@ Cflags: -I${includedir} shaderc-2025.2/cmake/shaderc_combined.pc.in000066400000000000000000000005161500222170200204700ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ Name: shaderc Description: Tools and libraries for Vulkan shader compilation Version: @CURRENT_VERSION@ URL: https://github.com/google/shaderc Libs: -L${libdir} @LIBS@ Cflags: -I${includedir} shaderc-2025.2/cmake/shaderc_static.pc.in000066400000000000000000000005161500222170200201770ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ Name: shaderc Description: Tools and libraries for Vulkan shader compilation Version: @CURRENT_VERSION@ URL: https://github.com/google/shaderc Libs: -L${libdir} @LIBS@ Cflags: -I${includedir} shaderc-2025.2/cmake/utils.cmake000066400000000000000000000162511500222170200164330ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # utility functions function (shaderc_use_gmock TARGET) target_include_directories(${TARGET} PRIVATE ${gmock_SOURCE_DIR}/include ${gtest_SOURCE_DIR}/include) target_link_libraries(${TARGET} PRIVATE gmock gtest_main) endfunction(shaderc_use_gmock) function(shaderc_default_c_compile_options TARGET) if (NOT "${MSVC}") if (SHADERC_ENABLE_WERROR_COMPILE) target_compile_options(${TARGET} PRIVATE -Wall -Werror -fvisibility=hidden) else() target_compile_options(${TARGET} PRIVATE -Wall -fvisibility=hidden) endif() check_cxx_compiler_flag(-fPIC COMPILER_SUPPORTS_PIC) if (NOT "${MINGW}" AND COMPILER_SUPPORTS_PIC) target_compile_options(${TARGET} PRIVATE -fPIC) endif() if (ENABLE_CODE_COVERAGE) # The --coverage option is a synonym for -fprofile-arcs -ftest-coverage # when compiling. target_compile_options(${TARGET} PRIVATE -g -O0 --coverage) # The --coverage option is a synonym for -lgcov when linking for gcc. # For clang, it links in a different library, libclang_rt.profile, which # requires clang to be built with compiler-rt. target_link_libraries(${TARGET} PRIVATE --coverage) endif() if (NOT SHADERC_ENABLE_SHARED_CRT) if (WIN32) # For MinGW cross compile, statically link to the libgcc runtime. # But it still depends on MSVCRT.dll. set_target_properties(${TARGET} PROPERTIES LINK_FLAGS "-static -static-libgcc") endif(WIN32) endif(NOT SHADERC_ENABLE_SHARED_CRT) else() # disable warning C4800: 'int' : forcing value to bool 'true' or 'false' # (performance warning) target_compile_options(${TARGET} PRIVATE /wd4800) endif() endfunction(shaderc_default_c_compile_options) function(shaderc_default_compile_options TARGET) shaderc_default_c_compile_options(${TARGET}) if (NOT "${MSVC}") if (NOT SHADERC_ENABLE_SHARED_CRT) if (WIN32) # For MinGW cross compile, statically link to the C++ runtime. # But it still depends on MSVCRT.dll. set_target_properties(${TARGET} PROPERTIES LINK_FLAGS "-static -static-libgcc -static-libstdc++") endif(WIN32) endif(NOT SHADERC_ENABLE_SHARED_CRT) endif() endfunction(shaderc_default_compile_options) # Build an asciidoc file; additional arguments past the base filename specify # additional dependencies for the file. function(shaderc_add_asciidoc TARGET FILE) if (ASCIIDOCTOR_EXE) set(DEST ${CMAKE_CURRENT_BINARY_DIR}/${FILE}.html) add_custom_command( COMMAND ${ASCIIDOCTOR_EXE} -a toc -o ${DEST} ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.asciidoc DEPENDS ${FILE}.asciidoc ${ARGN} OUTPUT ${DEST}) # Create the target, but the default build target does not depend on it. # Some Asciidoctor installations are mysteriously broken, and it's hard # to detect those cases. Generating HTML is not critical by default. add_custom_target(${TARGET} DEPENDS ${DEST}) endif(ASCIIDOCTOR_EXE) endfunction() # Adds a set of tests. # This function accepts the following parameters: # TEST_PREFIX: a prefix for each test target name # TEST_NAMES: a list of test names where each TEST_NAME has a corresponding # file residing at src/${TEST_NAME}_test.cc # LINK_LIBS: (optional) a list of libraries to be linked to the test target # INCLUDE_DIRS: (optional) a list of include directories to be searched # for header files. function(shaderc_add_tests) if(${SHADERC_ENABLE_TESTS}) cmake_parse_arguments(PARSED_ARGS "" "TEST_PREFIX" "TEST_NAMES;LINK_LIBS;INCLUDE_DIRS" ${ARGN}) if (NOT PARSED_ARGS_TEST_NAMES) message(FATAL_ERROR "Tests must have a target") endif() if (NOT PARSED_ARGS_TEST_PREFIX) message(FATAL_ERROR "Tests must have a prefix") endif() foreach(TARGET ${PARSED_ARGS_TEST_NAMES}) set(TEST_NAME ${PARSED_ARGS_TEST_PREFIX}_${TARGET}_test) add_executable(${TEST_NAME} src/${TARGET}_test.cc) shaderc_default_compile_options(${TEST_NAME}) if (MINGW) target_compile_options(${TEST_NAME} PRIVATE -DSHADERC_DISABLE_THREADED_TESTS) endif() if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") # Disable this warning, which is useless in test code. # Fixes https://github.com/google/shaderc/issues/334 target_compile_options(${TEST_NAME} PRIVATE -Wno-noexcept-type) endif() if (PARSED_ARGS_LINK_LIBS) target_link_libraries(${TEST_NAME} PRIVATE ${PARSED_ARGS_LINK_LIBS}) endif() if (PARSED_ARGS_INCLUDE_DIRS) target_include_directories(${TEST_NAME} PRIVATE ${PARSED_ARGS_INCLUDE_DIRS}) endif() shaderc_use_gmock(${TEST_NAME}) add_test( NAME ${PARSED_ARGS_TEST_PREFIX}_${TARGET} COMMAND ${TEST_NAME}) endforeach() endif(${SHADERC_ENABLE_TESTS}) endfunction(shaderc_add_tests) # Finds all transitive static library dependencies of a given target # including possibly the target itself. # This will skip libraries that were statically linked that were not # built by CMake, for example -lpthread. macro(shaderc_get_transitive_libs target out_list) if (TARGET ${target}) get_target_property(libtype ${target} TYPE) # If this target is a static library, get anything it depends on. if ("${libtype}" STREQUAL "STATIC_LIBRARY") # Get the original library if this is an alias library. This is # to avoid putting both the original library and the alias library # in the list (given we are deduplicating according to target names). # Otherwise, we may pack the same library twice, resulting in # duplicated symbols. get_target_property(aliased_target ${target} ALIASED_TARGET) if (aliased_target) list(INSERT ${out_list} 0 "${aliased_target}") else() list(INSERT ${out_list} 0 "${target}") endif() get_target_property(libs ${target} LINK_LIBRARIES) if (libs) foreach(lib ${libs}) shaderc_get_transitive_libs(${lib} ${out_list}) endforeach() endif() endif() endif() # If we know the location (i.e. if it was made with CMake) then we # can add it to our list. LIST(REMOVE_DUPLICATES ${out_list}) endmacro() # Combines the static library "target" with all of its transitive static # library dependencies into a single static library "new_target". function(shaderc_combine_static_lib new_target target) set(all_libs "") shaderc_get_transitive_libs(${target} all_libs) add_library(${new_target} STATIC) foreach(lib IN LISTS all_libs) target_sources(${new_target} PRIVATE $) endforeach() endfunction() shaderc-2025.2/cmake/write_pkg_config.cmake000066400000000000000000000022421500222170200206060ustar00rootroot00000000000000# Copyright (c) 2017 Pierre Moreau # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # First, retrieve the current version from CHANGES file(STRINGS ${CHANGES_FILE} CHANGES_CONTENT) string( REGEX MATCH "v[0-9]+(.[0-9]+)?(-dev)? [0-9]+-[0-9]+-[0-9]+" FIRST_VERSION_LINE ${CHANGES_CONTENT}) string( REGEX REPLACE "^v([^ ]+) .+$" "\\1" CURRENT_VERSION "${FIRST_VERSION_LINE}") # If this is a development version, replace "-dev" by ".0" as pkg-config nor # CMake support "-dev" in the version. # If it's not a "-dev" version then ensure it ends with ".1" string(REGEX REPLACE "-dev.1" ".0" CURRENT_VERSION "${CURRENT_VERSION}.1") configure_file(${TEMPLATE_FILE} ${OUT_FILE} @ONLY) shaderc-2025.2/downloads.md000066400000000000000000000020421500222170200155160ustar00rootroot00000000000000# Downloads Download the latest builds. **Note: These binaries are just the artifacts of the builders and have not undergone any QA, thus they should be considered unsupported.** ## Release | Windows | Linux | MacOS | | --- | --- | --- | | [MSVC 2019](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2019_release.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_linux_clang_release.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_macos_clang_release.html) | | | [gcc](https://storage.googleapis.com/shaderc/badges/build_link_linux_gcc_release.html) | | ## Debug | Windows | Linux | MacOS | | --- | --- | --- | | [MSVC 2019](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2019_debug.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_linux_clang_debug.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_macos_clang_debug.html) | | | [gcc](https://storage.googleapis.com/shaderc/badges/build_link_linux_gcc_debug.html) | | shaderc-2025.2/examples/000077500000000000000000000000001500222170200150225ustar00rootroot00000000000000shaderc-2025.2/examples/CMakeLists.txt000066400000000000000000000011771500222170200175700ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. add_subdirectory(online-compile) shaderc-2025.2/examples/online-compile/000077500000000000000000000000001500222170200177345ustar00rootroot00000000000000shaderc-2025.2/examples/online-compile/CMakeLists.txt000066400000000000000000000015531500222170200225000ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. add_executable(shaderc-online-compile main.cc) shaderc_default_compile_options(shaderc-online-compile) target_include_directories(shaderc-online-compile PUBLIC ${shaderc_SOURCE_DIR}/libshaderc_util/include) target_link_libraries(shaderc-online-compile PRIVATE shaderc) shaderc-2025.2/examples/online-compile/main.cc000066400000000000000000000143141500222170200211720ustar00rootroot00000000000000// Copyright 2016 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // The program demonstrates basic shader compilation using the Shaderc C++ API. // For clarity, each method is deliberately self-contained. // // Techniques demonstrated: // - Preprocessing GLSL source text // - Compiling a shader to SPIR-V assembly text // - Compliing a shader to a SPIR-V binary module // - Performing optimization with compilation // - Setting basic options: setting a preprocessor symbol. // - Checking compilation status and extracting an error message. #include #include #include #include #include // Returns GLSL shader source text after preprocessing. std::string preprocess_shader(const std::string& source_name, shaderc_shader_kind kind, const std::string& source) { shaderc::Compiler compiler; shaderc::CompileOptions options; // Like -DMY_DEFINE=1 options.AddMacroDefinition("MY_DEFINE", "1"); shaderc::PreprocessedSourceCompilationResult result = compiler.PreprocessGlsl(source, kind, source_name.c_str(), options); if (result.GetCompilationStatus() != shaderc_compilation_status_success) { std::cerr << result.GetErrorMessage(); return ""; } return {result.cbegin(), result.cend()}; } // Compiles a shader to SPIR-V assembly. Returns the assembly text // as a string. std::string compile_file_to_assembly(const std::string& source_name, shaderc_shader_kind kind, const std::string& source, bool optimize = false) { shaderc::Compiler compiler; shaderc::CompileOptions options; // Like -DMY_DEFINE=1 options.AddMacroDefinition("MY_DEFINE", "1"); if (optimize) options.SetOptimizationLevel(shaderc_optimization_level_size); shaderc::AssemblyCompilationResult result = compiler.CompileGlslToSpvAssembly( source, kind, source_name.c_str(), options); if (result.GetCompilationStatus() != shaderc_compilation_status_success) { std::cerr << result.GetErrorMessage(); return ""; } return {result.cbegin(), result.cend()}; } // Compiles a shader to a SPIR-V binary. Returns the binary as // a vector of 32-bit words. std::vector compile_file(const std::string& source_name, shaderc_shader_kind kind, const std::string& source, bool optimize = false) { shaderc::Compiler compiler; shaderc::CompileOptions options; // Like -DMY_DEFINE=1 options.AddMacroDefinition("MY_DEFINE", "1"); if (optimize) options.SetOptimizationLevel(shaderc_optimization_level_size); shaderc::SpvCompilationResult module = compiler.CompileGlslToSpv(source, kind, source_name.c_str(), options); if (module.GetCompilationStatus() != shaderc_compilation_status_success) { std::cerr << module.GetErrorMessage(); return std::vector(); } return {module.cbegin(), module.cend()}; } int main() { const char kShaderSource[] = "#version 310 es\n" "void main() { int x = MY_DEFINE; }\n"; { // Preprocessing auto preprocessed = preprocess_shader( "shader_src", shaderc_glsl_vertex_shader, kShaderSource); std::cout << "Compiled a vertex shader resulting in preprocessed text:" << std::endl << preprocessed << std::endl; } { // Compiling auto assembly = compile_file_to_assembly( "shader_src", shaderc_glsl_vertex_shader, kShaderSource); std::cout << "SPIR-V assembly:" << std::endl << assembly << std::endl; auto spirv = compile_file("shader_src", shaderc_glsl_vertex_shader, kShaderSource); std::cout << "Compiled to a binary module with " << spirv.size() << " words." << std::endl; } { // Compiling with optimizing auto assembly = compile_file_to_assembly("shader_src", shaderc_glsl_vertex_shader, kShaderSource, /* optimize = */ true); std::cout << "Optimized SPIR-V assembly:" << std::endl << assembly << std::endl; auto spirv = compile_file("shader_src", shaderc_glsl_vertex_shader, kShaderSource, /* optimize = */ true); std::cout << "Compiled to an optimized binary module with " << spirv.size() << " words." << std::endl; } { // Error case const char kBadShaderSource[] = "#version 310 es\nint main() { int main_should_be_void; }\n"; std::cout << std::endl << "Compiling a bad shader:" << std::endl; compile_file("bad_src", shaderc_glsl_vertex_shader, kBadShaderSource); } { // Compile using the C API. std::cout << "\n\nCompiling with the C API" << std::endl; // The first example has a compilation problem. The second does not. const char source[2][80] = {"void main() {}", "#version 450\nvoid main() {}"}; shaderc_compiler_t compiler = shaderc_compiler_initialize(); for (int i = 0; i < 2; ++i) { std::cout << " Source is:\n---\n" << source[i] << "\n---\n"; shaderc_compilation_result_t result = shaderc_compile_into_spv( compiler, source[i], std::strlen(source[i]), shaderc_glsl_vertex_shader, "main.vert", "main", nullptr); auto status = shaderc_result_get_compilation_status(result); std::cout << " Result code " << int(status) << std::endl; if (status != shaderc_compilation_status_success) { std::cout << "error: " << shaderc_result_get_error_message(result) << std::endl; } shaderc_result_release(result); } shaderc_compiler_release(compiler); } return 0; } shaderc-2025.2/glslc/000077500000000000000000000000001500222170200143105ustar00rootroot00000000000000shaderc-2025.2/glslc/CMakeLists.txt000066400000000000000000000046521500222170200170570ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. find_package(Threads) add_library(glslc STATIC src/file_compiler.cc src/file_compiler.h src/file.cc src/file.h src/file_includer.cc src/file_includer.h src/resource_parse.h src/resource_parse.cc src/shader_stage.cc src/shader_stage.h src/dependency_info.cc src/dependency_info.h ) shaderc_default_compile_options(glslc) target_include_directories(glslc PUBLIC ${glslang_SOURCE_DIR}) if (SHADERC_ENABLE_WGSL_OUTPUT) if (IS_DIRECTORY "${tint_SOURCE_DIR}/include") target_include_directories(glslc PRIVATE "${tint_SOURCE_DIR}/include") target_include_directories(glslc PRIVATE "${tint_SOURCE_DIR}") endif() # Turn on features in the tint/tint.h header add_definitions(-DTINT_BUILD_SPV_READER=1 -DTINT_BUILD_WGSL_WRITER=1) add_definitions(-DSHADERC_ENABLE_WGSL_OUTPUT=1) endif(SHADERC_ENABLE_WGSL_OUTPUT) target_link_libraries(glslc PRIVATE glslang SPIRV # Glslang libraries $<$:libtint> # Tint libraries, optional shaderc_util shaderc # internal Shaderc libraries ${CMAKE_THREAD_LIBS_INIT}) add_executable(glslc_exe src/main.cc) shaderc_default_compile_options(glslc_exe) target_include_directories(glslc_exe PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/.. ${spirv-tools_SOURCE_DIR}/include) set_target_properties(glslc_exe PROPERTIES OUTPUT_NAME glslc) target_link_libraries(glslc_exe PRIVATE glslc shaderc_util shaderc) add_dependencies(glslc_exe build-version) shaderc_add_tests( TEST_PREFIX glslc LINK_LIBS glslc shaderc_util shaderc TEST_NAMES file resource_parse stage) shaderc_add_asciidoc(glslc_doc_README README) if(SHADERC_ENABLE_INSTALL) install(TARGETS glslc_exe RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}) endif(SHADERC_ENABLE_INSTALL) add_subdirectory(test) shaderc-2025.2/glslc/README.asciidoc000066400000000000000000000652071500222170200167570ustar00rootroot00000000000000= glslc Manual :toc: :toclevels: 3 :numbered: :source-highlighter: pygments == Name `glslc` - A command-line GLSL/HLSL to SPIR-V compiler with Clang-compatible arguments. == Synopsis ---- glslc [--help] glslc [-h] glslc [--show-limits] glslc [-c|-S|-E] [-x ...] [-std=standard] [ ... options for resource bindings ... ] [-fhlsl-16bit-types] [-fhlsl-offsets] [-fhlsl-functionality1] [-fentry-point=] [-fauto-map-locations] [-finvert-y] [-flimit=...] [-flimit-file ] [-fshader-stage=...] [--target-env=...] [--target-spv=...] [-g] [-O0|-Os] [-Idirectory...] [-Dmacroname[=value]...] [-w] [-Werror] [-o outfile] shader... ---- == Description === Input file languages glslc accepts both GLSL/HLSL source and SPIR-V assembly files as inputs. ==== Shader stage specification glslc provides three ways to specify the shader stage of a GLSL source file: `-fshader-stage=`, `#pragma shader_stage()`, and file extension. The `-fshader-stage=` option overrides `#pragma shader_stage()`, which overrides the file extension. Shader stages can be specified by naming a file with an appropriate extension as shown in the following table. `-fshader-stage=` and `#pragma shader_stage()`, on the other hand, enable you to specify shader stages from the command line and within the source file. Possible ``stage``s for them are also listed in the following table. Details about `-fshader-stage=` can be found in <>. [[shader-stage-selection]] .Shader Stage Selection |=== |Shader Stage |Shader File Extension |`` |vertex |`.vert` |`vertex` |fragment |`.frag` |`fragment` |tesselation control |`.tesc` |`tesscontrol` |tesselation evaluation |`.tese` |`tesseval` |geometry |`.geom` |`geometry` |compute |`.comp` |`compute` |=== `#pragma shader_stage()` relies on the `#pragma` preprocessor directive; thus, the token inside `shader_stage()` is not subject to preprocessor macro expansion. It must be exactly one of the ``stage``s in the above table. `#pragma shader_stage()` behaves as follows: * The first `#pragma shader_stage()` directive in a translation unit must precede any non-preprocessor tokens. * If there is more than one `#pragma shader_stage()` directive in the same translation unit, all the ``stage``s specified must be the same. Otherwise, glslc will issue an error. ==== SPIR-V assembly files SPIR-V assembly input files should follow the https://github.com/KhronosGroup/SPIRV-Tools/blob/master/syntax.md[syntax] defined in the https://github.com/KhronosGroup/SPIRV-Tools[SPIRV-Tools] project and have the `.spvasm` extension. Command line options treat SPIR-V assembly files differently; some may ignore them, e.g., `<>`, `<>`, and some may even treat them not as SPIR-V assembly files, e.g., `<>`. [[output-file-naming]] === Output file naming If a name is specified via `-o`, the output file will be given that name. Otherwise, * If a compilation stage selection option is given (`-S` or `-c`), there will be one output file generated per input shader file. The generated output file will end with a file extension that matches the compilation stage, which is `.spvasm` for `-S` and `.spv` for `-c`. The name will depend on the original file's name and extension. ** If the input file has a <>, the output file will be named as by appending the file extension for the compilation stage to the input file's name. E.g., `glslc -c foo.vert` will generate `foo.vert.spv`, and `glslc -S bar.frag` will generate `bar.frag.spvasm`. ** Otherwise, the output file will be named as by replacing the input file's file extension, if any, with the file extension for the compilation stage. E.g., `glslc -c foo` will generate `foo.spv`, and `glslc -S bar.glsl` will generate `bar.spvasm`. * If no compilation stage is selected, the output file will be named `a.spv`. == Command Line Options === Overall Options ==== `--help`, `-h` Option `--help` or `-h` tells the glslc compiler to display all available options and exit. ==== `--show-limits` `--show-limits` shows default resource limits for shader compilation. The syntax is the same as accepted by `-flimit=` and for the contents of the file specified by `-flimit-file`. ==== `-o` `-o` lets you specify the output file's name. It cannot be used when there are multiple files generated. A filename of `-` represents standard output. === Language and Mode Selection Options [[option-finvert-y]] ==== `-finvert-y` Inverts position.Y output in a vertex shader. [[option-flimit]] ==== `-flimit=` `-flimit=` lets you specify resource limits. The argument should be a sequence of limit name, integer value pairs. Tokens should be separated by whitespace. If the same limit is specified several times, only the last setting takes effect. Use `--show-limits` to show the default values, and example syntax. This option affects all compiled shaders. [[option-flimit-file]] ==== `-flimit-file` `-flimit-file ` lets you specify resource limits in a file. The syntax of the file contents is the same as the argument to `-flimit=` and the output of `--show-limits`. This option accepts Glslang resource configuration files, e.g. as emitted by `glslangValidator -c`. This option affects all compiled shaders. [[option-fshader-stage]] ==== `-fshader-stage=` `-fshader-stage=` lets you specify the shader stage for one or more inputs from the command line. Possible values for ```` are listed in the <> table. `-fshader-stage=` behaves as follows: * `-fshader-stage=` sets the shader stage for subsequent input files. It does not affect the stages of any preceding inputs on the command line. * When supplying more than one `-fshader-stage=` argument, the most recent argument preceding an input file applies. * A shader file not ending with <> must have a `-fshader-stage=` argument ahead of it to specify its stage. * If there is a `-fshader-stage=` before a file in which there is a `#pragma shader_stage()` directive, the directive is ignored and the `-fshader-stage=` argument is used instead. * If there is a `-fshader-stage=` before a file with a known shader file extension, the file extension is ignored and the `-fshader-stage=` argument is used instead. [[shader-stage-with-spirv-assembly]] CAUTION: `-fshader-stage=` overrides file extension; that means it should not be used together with SPIR-V assembly files because glslc will treat the given SPIR-V assembly files as GLSL source code of the given shader stage. If you need to supply both SPIR-V assembly files and `-fshader-stage=` on the same command line, please put SPIR-V assembly files ahead of the first `-fshader-stage=`, since `-fshader-stage=` only affects the treatment of subsequent files. ==== `-std=` `-std=` lets you specify a shader version and profile on the command line. ```` can be any valid concatenation of a GLSL version number and profile, e.g., `310es`, `450core`, etc. The profile can be omitted as allowed by GLSL, e.g., `450`. `-std=` behaves as follows: * `-std=` affects the version of all GLSL inputs passed to `glslc`. * `-std=` is ignored for HLSL inputs. * `-std=` overwrites `#version` directives in all input shaders, including those preceding the argument. * If a `-std=` argument specifies a different version from a `#version` directive in an input file, `glslc` will issue a warning. * If multiple `-std=` arguments are specified on the command line, only the last one takes effect. CAUTION: `-std=` does not affect the `#version` directive in the preprocessed output. That is, when `-std=` specifies a version different from the shader source code, the `#version` directive in preprocessed output will still be the one in the source code. But `-std=` does affect the behavior of `#line` directives in the preprocessed output. Behavior of `#line` directives will follow the version specified by `-std=`. ==== `--target-env=` `--target-env=` lets you specify a target environment on the command line. This affects the generation of warnings and errors. The ```` can be one of the following: * `vulkan`: create SPIR-V under Vulkan 1.0 semantics. * `vulkan1.0`: create SPIR-V under Vulkan 1.0 semantics. * `vulkan1.1`: create SPIR-V under Vulkan 1.1 semantics. * `vulkan1.2`: create SPIR-V under Vulkan 1.2 semantics. * `vulkan1.3`: create SPIR-V under Vulkan 1.3 semantics. * `vulkan1.4`: create SPIR-V under Vulkan 1.4 semantics. * `opengl`: create SPIR-V under OpenGL 4.5 semantics. * `opengl4.5`: create SPIR-V under OpenGL 4.5 semantics. Generated code uses SPIR-V 1.0, except for code compiled for Vulkan 1.1, which uses SPIR-V 1.3, and code compiled for Vulkan 1.2, which uses SPIR-V 1.5. If this option is not specified, a default of `vulkan1.0` is used. Note: Support for OpenGL compatibility profile, `opengl_compat`, has been removed. ==== `--target-spv=` `--target-spv=` lets you specify the SPIR-V version to be used by the generated module. The default is to use the highest version of SPIR-V required to be supported by the target environment. The defaults for specific Vulkan target environments are as follows: SPIR-V 1.0 for Vulkan 1.0, SPIR-V 1.3 for Vulkan 1.1, and SPIR-V 1.5 for Vulkan 1.2. The ```` can be one of the following: * `spv1.0` * `spv1.1` * `spv1.2` * `spv1.3` * `spv1.4` * `spv1.5` * `spv1.6` ==== `-x` `-x` lets you specify the language of the input shader files. Valid languages are `glsl` and `hlsl`. If the file extension is `hlsl` then the default language is HLSL. Otherwise the default is 'glsl'. Note: HLSL compilation will use HLSL packing (offset) rules for variables that are vertex shader outputs, and inputs and outputs of both geometry and pixel shaders. [[compilation-stage-selection-options]] === Compilation Stage Selection Options ==== `-c` `-c` tells the glslc compiler to run the preprocessing and compiling stage. Each input shader file results in a SPIR-V binary file; these SPIR-V binary files are named by the rules in the <> section. [[option-cap-e]] ==== `-E` `-E` tells the glslc compiler to run only the preprocessing stage. It overrides `-c` and `-S`. Preprocessed output is written to standard output, while preprocessing errors are written to standard error. If multiple input shader files are given, their preprocessed output are all written to standard output, in the order specified on the command line. glslc will do nothing for SPIR-V assembly files with this option. [[option-cap-s]] ==== `-S` `-S` tells the glslc compiler to run the preprocessing, compiling, and then disassembling stage. It overrides `-c`. Each input shader file results in a SPIR-V assembly file; these SPIR-V assembly files are named by the rules in the <> section. glslc will do nothing for SPIR-V assembly files with this option. ==== No Compilation Stage Selection If none of the above options is given, the glslc compiler will run preprocessing, compiling, and linking stages. WARNING: Linking of multiple input shader files are not supported yet. === Preprocessor Options ==== `-D` `-Dmacroname[=[value]]` lets you define a preprocessor macro before input shader files are preprocessed. If `value` is omitted, the macro is defined with an empty value. ==== `-I` `-Idirectory` or `-I directory` adds the specified directory to the search path for include files. The directory may be an absolute path or a relative path to the current working directory. === Code Generation Options ==== `-g` Requests that the compiler place source-level debug information into the object code, such as identifier names and line numbers. This option restrains `-O` from turning on the strip-debug-info optimization pass. NOTE: Currently this option has no effect. Full functionality depends on glslang support for generating debug info. ==== `-O0`, `-Os` `-O` specifies which optimization level to use: * `-O0` means "no optimization". This level generates the most debuggable code. * `-O` means the default optimization level for better performance. * `-Os` enables optimizations to reduce code size. ==== `-mfmt=` `-mfmt=` selects output format for compilation output in SPIR-V binary code form. Supported options are listed in the <> table. This option is only valid to be used when the compilation output is SPIR-V binary code. Specifying any options listed below when the output is not SPIR-V binary code, like disassembly (with `-S` specified), text (with `-M`, `-MM` or `-E` specified) will trigger an error. [[binary-output-format-options]] .Binary Output Format Options [cols="20%,80%"] |=== |Format option |Description |bin |Output SPIR-V binary code as a sequence of binary 32-bitwords in host native endianness. This is the default format for SPIR-V binary compilation output. |num |Output SPIR-V binary code as a text file containing a list of comma-separated hex numbers. + Example: `glslc -c -mfmt=num main.vert -o output_file.txt` + Content of the output_file.txt: + 0x07230203,0x00010000,0x00080001,0x00000006... |c |Output SPIR-V binary code as a text file containing C-style + initializer list. + This is just wrapping the output of `num` option with curly brackets. + Example: `glslc -c -mfmt=c main.vert -o output_file.txt` + Content of output_file.txt: + {0x07230203, 0x00010000, 0x00080001, 0x00000006...} |=== [[option-fhlsl-16bit-types]] ==== `-fhlsl-16bit-types` Enables 16bit types for HLSL compilation. [[option-fhlsl-offsets]] ==== `-fhlsl-offsets` Use HLSL packing rules instead of GLSL rules when determining offsets of members of blocks. This option is always on when compiling for HLSL. [[option-fhlsl-functionality1]] ==== `-fhlsl-functionality1` Enable extension `SPV_GOOGLE_hlsl_functionality1`, and instructs the compiler to: - Annotate HLSL semantic string decorations on interface objects - Explicitly record the association of a UAV resource with its companion counter buffer. This option can also be spelled with an underscore: `-fhlsl_functionality1`. [[option-fentry-point]] ==== `-fentry-point=` `-fentry-point=` lets you specify the entry point name. This is only significant for HLSL compilation. The default is "main". [[option-fauto-map-locations]] ==== `-fauto-map-locations` For GLSL compilation, option `-fauto-map-locations` directs the compiler to automatically assign location numbers to user-defined stage input and output variables if not explicitly specified by the shader source. For HLSL compilation, this option is on by default. Client APIs normally require adjacent stages to agree on their I/O interface. The compiler only sees one stage at a time, so it is strongly recommended that you avoid relying on this option to assign locations. Instead, an explicit binding number should be specified in the shader source, as follows: * In a GLSL shader, use a `location` layout qualifier: ---- layout(location = 1) in vec4 x; ---- * In an HLSL shader, use a `vk::location` attribute: ---- [[vk::location(1)]] float4 FooShader( [[vk::location(0)]] float4 a, [[vk::location(2)]] float4 b) : COLOR0 { return a + b; } ---- [[option-fpreserve-bindings ==== `-fpreserve-bindings` Directs the optimizer to preserve bindings declarations, even when those bindings are known to be unused. === Warning and Error Options ==== `-w` `-w` suppresses all warning output from `glslc`. Any warning that would have been generated is silently ignored. ==== `-Werror` `-Werror` forces any warning to be treated as an error in `glslc`. This means that all `warning:` messages are shown as `error:` and any warnings will cause a non-zero exit code from `glslc`. If `-w` is specified the warnings generated are suppressed before they are converted to errors. === Dependency Generation Options ==== `-M` or `-MM` `-M` generates *make* dependencies. It outputs a rule suitable for *make* describing the dependencies of the input file. Instead of outputting the result of preprocessing, the preprocessor outputs one *make* rule containing the SPIR-V object file name for that source file, a colon, and the names of all the included files. Unless specified explicitly (with `-MT`), the SPIR-V object file name in the generated *make* rules follows the rules of <> as in `-c` compilation stage. Specifying `-M` implies `-E`, and suppresses warnings with an implicit `-w`. By default the output will be written to stdout, unless `-MF` or `-o` is specified. The dependency info file name can be specified by `-o` and `-MF` options. When both are specified, `-o` option is ignored. Specifying multiple input files is valid when the *make* rules are written to stdout, which means neither `-MF` nor `-o` is specified. When `-o` or `-MF` is specified, only one input file is allowed. `-MM` is an alias for `-M`. E.g., `glslc -M main.vert` will dump `main.vert.spv: main.vert ` to stdout. More examples are listed in <> ==== `-MD` `-MD` tells the glslc compiler to both compile the source and generate *make* dependencies. Dependencies are written to a file whose name is determined as follows: If option `-MF` is specified, use its argument. Otherwise, use the filename formed by appending *.d* to the name of the file containing compilation results. Specifying multiple input files is valid when neither `-MF` nor `-o` is specified. When `-o` or `-MF` is specified, only one input file is allowed. E.g., `glslc -c -MD main.vert` will generate `main.vert.spv` as the SPIR-V object file and `main.vert.spv.d` as the dependency info file. More examples are listed in <> ==== `-MF` `-MF` lets you specify the dependency info file name when used with `-M` or `-MD`. This option is invalid when used with multiple input files. E.g., `glslc -c -MD main.vert -MF dep_info` will generate `main.vert.spv` as the SPIR-V object file and `dep_info` as the dependency info file. ==== `-MT` `-MT` lets you specify the target of the rule emitted by dependency generation when used with `-M` or `-MD`. This option is invalid when used with multiple input files. E.g., `glslc -M main.vert -MT target` will dump following dependency info to stdout: `target: main.vert `. [[dependency-generation-examples]] .Dependency Generation Examples |=== |Command Line Input|Compilation Output File|Dependency Output File|Dependency Info |glslc -M main.vert | | | main.vert.spv: main.vert .2+|glslc -M a.vert b.vert | | | a.vert.spv: a.vert | | | b.vert.spv: b.vert |glslc -M main.vert -o dep_info | | dep_info | main.vert.spv: main.vert |glslc -M main.vert -MF dep_info| | dep_info | main.vert.spv: main.vert |glslc -M main.vert -MT target | | | target: main.vert |glslc -MD main.vert |a.spv |main.vert.spv.d|main.vert.spv: main.vert |glslc -c -MD main.vert |main.vert.spv|main.vert.spv.d|main.vert.spv: main.vert .2+|glslc -c -MD a.vert b.vert | a.vert.spv | a.vert.spv.d | a.vert.spv: a.vert | b.vert.spv | b.vert.spv.d | b.vert.spv: b.vert |glslc -S -MD main.vert |main.vert.spvasm |main.vert.spvasm.d |main.vert.spvasm: main.vert |glslc -c -MD main.vert -MF dep_info |main.vert.spv|dep_info|main.vert.spv: main.vert |glslc -c -MD main.vert -o obj |obj |obj.d |obj: main.vert |glslc -c -MD main.vert -o obj -MF dep_info -MT target|obj|dep_info|target: main.vert |=== === Resource Binding Options [[option-fauto-bind-uniforms]] ==== `-fauto-bind-uniforms` Option `-fauto-bind-uniforms` directs the compiler to automatically assign binding numbers to uniform variables, when an explicit binding is not specified in the shader source. An explicit binding number can be specified in the shader source by using a `binding` layout qualifier. For example: ---- layout(binding = 12) uniform texture2D; ---- [[option-fhlsl-iomap]] ==== `-fhlsl-iomap` Option `-fhlsl-iomap` directs the compiler to use HLSL register assignments as binding values. [[option-fimage-binding-base]] ==== `-fimage-binding-base` Option `-fimage-binding-base [stage] base` sets the lowest automatically assigned binding for images. If a stage is specified, only affects the specified stage. For HLSL, sets one less than the base. [[option-fsampler-binding-base]] ==== `-fsampler-binding-base` Option `-fsampler-binding-base [stage] base` sets the lowest automatically assigned binding for samplers. If a stage is specified, only affects the specified stage. For HLSL, sets one less than the base. [[option-ftexture-binding-base]] ==== `-ftexture-binding-base` Option `-ftexture-binding-base [stage] base` sets the lowest automatically assigned binding for textures. If a stage is specified, only affects the specified stage. For HLSL, sets one less than the base. [[option-fubo-binding-base]] ==== `-fubo-binding-base` Option `-fubo-binding-base [stage] base` sets the lowest automatically assigned binding for Uniform Buffer Objects (GLSL) or Cbuffers (HLSL). If a stage is specified, only affects the specified stage. For HLSL, sets one less than the base. [[option-fcbuffer-binding-base]] ==== `-fcbuffer-binding-base` Option `-fcbuffer-binding-base [stage] base` is the same as `-fubo-binding-base [stage] base`. [[option-fssbo-binding-base]] ==== `-fssbo-binding-base` Option `-fssbo-binding-base [stage] base` sets the lowest automatically assigned binding for Shader Storage Buffer Objects (GLSL). If a stage is specified, only affects the specified stage. This only affects GLSL compilation. [[option-fuav-binding-base]] ==== `-fuav-binding-base` Option `-fuav-binding-base [stage] base` sets one less than the lowest automatically assigned binding for Unordered Access Views (UAV). If a stage is specified, only affects the specified stage. This only affects HLSL compilation. [[option-fregister-set-binding]] ==== `-fresource-set-binding` Option `-fresource-set-binding [stage] ` sets the descriptor set and binding for an HLSL resource, by register name. To specify settings for more registers, append their triples consisting of register name, descriptor set, and binding. Example: ---- # For a texture in register t1, use set 1 binding 0. # For a texture in register t2, use set 1 binding 3 glslc -x hlsl foo.frag -fresource-set-binding t1 1 0 t2 1 3 ---- If a stage is specified, only affects the specified stage. ---- # Same as the previous example, but the settings only apply # to fragment (pixel) shaders. glslc -x hlsl foo.frag -fresource-set-binding frag t1 1 0 t2 1 3 ---- == Divergence from and extensions to GLSL specifications === Source-filename-based `#line` and `\\__FILE__` This section describes how the glslc compiler extends the syntax for the `#line` directive and the `\\__FILE__` macro. By default, the glslc compiler enables the `GL_GOOGLE_cpp_style_line_directive` extension. It will generate this extended syntax in the preprocessed output (obtained via the `-E` option). WARNING: This section is still evolving. Expect changes. GLSL specifications have a notion of source strings. [quote, Section 3.2 of both version 3.30 and 4.50] ____ The source for a single shader is an array of strings of characters from the character set. A single shader is made from the concatenation of these strings. ____ With the above notion, the second parameter to the `#line` directive should be a constant integer expressions representing the source string number. Also the `\\__FILE__` macro will "substitute a decimal integer constant that says which source string number is currently being processed." The glslc compiler implements the standard `#line` and `\\__FILE__` syntax. It also provides an extension, `GL_GOOGLE_cpp_style_line_directive`, to allow source filenames to be used instead of integer source string indices. Specifically, the `#line` directive can have, after macro substitution, one of the following three forms: [source,glsl] ---- #line line-number #line line-number integer-source-string-index #line line-number "source-filename" ---- where `source-filename` can be any combinations of characters except double quotation marks. (Note that according to the GLSL specification, "there are no escape sequences or other uses of the backslash beyond use as the line-continuation character".) And if source-filename-based `#line` is used, the `\\__FILE__` macro expands to a string whose contents are the filename quoted with double quotation marks. The filename is dertermined as the last of * The filename given to the glslc compiler, * The filename argument of the most recent `#line` directive, if any. [[include-directive]] === `#include` The glslc compiler extends GLSL with the include syntax by turning on the `GL_GOOGLE_include_directive` extension. It will preprocess and substitute `#include` directives properly with the following behaviors. WARNING: This section is still evolving. Expect changes. If `#include` directives are used in a shader, there will be an `#extension GL_GOOGLE_include_directive : enable` line generated into the preprocessed output. The `GL_GOOGLE_cpp_style_line_directive` extension is implicitly turned on by the `GL_GOOGLE_include_directive` extension. The file argument to `#include` must be enclosed in double quotes. It must be a relative path, using whatever path separator the OS supports. However, the last path element -- the name of the file itself -- must not contain either '/' or '\', regardless of which path separator is used. This will not be flagged as an error but will instead trigger undefined behavior. For example, let's say there is a file named `f\ilename.vert` on a Unix OS. It is not possible to craft a `#include` that includes that file. Furthermore, it is not possible to escape any characters in a `#include` directive, so the file argument cannot contain any special characters that need escaping in C. The file argument is a relative path that is matched first against the including file's own directory and then against all `-I` arguments in order of their appearance on the command line. If the file cannot be found, `glslc` aborts with an error. shaderc-2025.2/glslc/src/000077500000000000000000000000001500222170200150775ustar00rootroot00000000000000shaderc-2025.2/glslc/src/dependency_info.cc000066400000000000000000000070411500222170200205410ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "dependency_info.h" #include #include #include #include "file.h" #include "libshaderc_util/io_shaderc.h" namespace glslc { DependencyInfoDumpingHandler::DependencyInfoDumpingHandler() : mode_(not_set) {} bool DependencyInfoDumpingHandler::DumpDependencyInfo( std::string compilation_output_file_name, std::string source_file_name, std::string* compilation_output_ptr, const std::unordered_set& dependent_files) { std::string dep_target_label = GetTarget(compilation_output_file_name); std::string dep_file_name = GetDependencyFileName(compilation_output_file_name); // Dump everything to a string stream first, then dump its content to either // a file or compilation output string, depends on current dumping mode. std::stringstream dep_string_stream; // dump target label and the source_file_name. dep_string_stream << dep_target_label << ": " << source_file_name; // dump the dependent file names. for (auto& dependent_file_name : dependent_files) { dep_string_stream << " " << dependent_file_name; } dep_string_stream << std::endl; if (mode_ == dump_as_compilation_output) { compilation_output_ptr->assign(dep_string_stream.str()); } else if (mode_ == dump_as_extra_file) { std::ofstream potential_file_stream_for_dep_info_dump; std::ostream* dep_file_stream = shaderc_util::GetOutputStream( dep_file_name, &potential_file_stream_for_dep_info_dump, &std::cerr); *dep_file_stream << dep_string_stream.str(); if (dep_file_stream->fail()) { std::cerr << "glslc: error: error writing dependent_files info to output " "file: '" << dep_file_name << "'" << std::endl; return false; } } else { // mode_ should not be 'not_set', we should never be here. return false; } return true; } std::string DependencyInfoDumpingHandler::GetTarget( const std::string& compilation_output_file_name) { if (!user_specified_dep_target_label_.empty()) { return user_specified_dep_target_label_; } return compilation_output_file_name; } std::string DependencyInfoDumpingHandler::GetDependencyFileName( const std::string& compilation_output_file_name) { if (!user_specified_dep_file_name_.empty()) { return user_specified_dep_file_name_; } return compilation_output_file_name + ".d"; } bool DependencyInfoDumpingHandler::IsValid(std::string* error_msg_ptr, size_t num_files) { if (DumpingModeNotSet()) { *error_msg_ptr = "to generate dependencies you must specify either -M (-MM) or -MD"; return false; } if (!user_specified_dep_file_name_.empty() || !user_specified_dep_target_label_.empty()) { if (num_files > 1) { *error_msg_ptr = "to specify dependency info file name or dependency info target, " "only one input file is allowed."; return false; } } return true; } } shaderc-2025.2/glslc/src/dependency_info.h000066400000000000000000000136211500222170200204040ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef GLSLC_DEPENDENCY_INFO_H #define GLSLC_DEPENDENCY_INFO_H #include #include #include namespace glslc { // An object to handle everything about dumping dependency info. Internally it // has two valid dumping mode: 1) Dump to extra dependency info files, such as // *.d files. This mode is used when we want to generate dependency info and // also compile. 2) Overwrite the original compilation output and dump // dependency info as compilation output. This mode is used when we do not want // to compile the source code and want the dependency info only. class DependencyInfoDumpingHandler { public: DependencyInfoDumpingHandler(); // Sets the dependency target explicitly. It's the same as the argument to // -MT. void SetTarget(const std::string& target_label) { user_specified_dep_target_label_ = target_label; } // Sets the name of the file where dependency info will be written. void SetDependencyFileName(const std::string& dep_file_name) { user_specified_dep_file_name_ = dep_file_name; } // Dump depdendency info to a) an extra dependency info file, b) an string // which holds the compilation output. The choice depends on the dump // mode of the handler. Returns true if dumping is succeeded, false otherwise. // // The dependency file name and target are deduced based on 1) user // specified dependency file name and target name, 2) the output filename when // the compiler is in 'does not need linking' and 'not preprocessing-only' // mode. It is passed through compilation_output_file_name. // // When the handler is set to dump dependency info as extra dependency info // files, this method will open a file with the dependency file name and write // the dependency info to it. Error messages caused by writing to the file are // emitted to stderr. // // When the handler is set to dump dependency info as compilation output, the // compilation output string, which is passed through compilation_output_ptr, // will be cleared and this method will write dependency info to it. Then the // dependency info should be emitted as normal compilation output. // // If the dump mode is not set when this method is called, return false. bool DumpDependencyInfo(std::string compilation_output_file_name, std::string source_file_name, std::string* compilation_output_ptr, const std::unordered_set& dependent_files); // Sets to always dump dependency info as an extra file, instead of the normal // compilation output. This means the output name specified by -o options // won't be used for the dependency info file. void SetDumpToExtraDependencyInfoFiles() { mode_ = dump_as_extra_file; } // Sets to dump dependency info as normal compilation output. The dependency // info will be either saved in a file with -o option specified file, or, if // no output file name specified, to stdout. void SetDumpAsNormalCompilationOutput() { mode_ = dump_as_compilation_output; } // Returns true if the handler's dumping mode is set to dump dependency info // as extra dependency info files. bool DumpingToExtraDependencyInfoFiles() { return mode_ == dump_as_extra_file; } // Returns true if the handler's dumping mode is set to dump dependency info // as normal compilation output. bool DumpingAsCompilationOutput() { return mode_ == dump_as_compilation_output; } // Returns true if the handler's dumping mode is not set. bool DumpingModeNotSet() { return mode_ == not_set; } // Returns true if the handler is at valid state for dumping dependency info. bool IsValid(std::string* error_msg_ptr, size_t num_files); private: typedef enum { // not_set mode tells that the dumping mode is not set yet, so the handler // is not ready for dumping dependency info. Calling DumpDependencyInfo when // the handler is in this mode will cause failure. not_set = 0, // Dumping dependency info as normal compilation output mode. In this mode, // the dependency info will be dumped as compilation output by overwriting // the string which holds the compilation output. dump_as_compilation_output, // Dumping dependency info as extra dependency info files mode. In this // mode, dependency info will be dumped to a user specified dependency info // file or a *.d file. Compilation output will still be generated along with // the dependency info. dump_as_extra_file, } dump_mode; // Returns the target file label to be used in depdendency info file. If -MT // defined a label, use that string as the label. Otherwise returns the // compilation output filename deduced in 'doesn't need linking' and 'not // preprocessing-only' mode. std::string GetTarget(const std::string& compilation_output_file_name); // Returns the dependency file name to be used. If -MF defined a file name // before, use it. Othwise, returns a filename formed by appending .d to the // output filename deduced in 'doesn't need linking' and 'no // preprocessing-only' mode. std::string GetDependencyFileName( const std::string& compilation_output_file_name); std::string user_specified_dep_file_name_; std::string user_specified_dep_target_label_; dump_mode mode_; }; } #endif // GLSLC_DEPENDENCY_INFO_H shaderc-2025.2/glslc/src/file.cc000066400000000000000000000016351500222170200163320ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "file.h" namespace glslc { shaderc_util::string_piece GetFileExtension( const shaderc_util::string_piece& filename) { size_t dot_pos = filename.find_last_of("."); if (dot_pos == shaderc_util::string_piece::npos) return ""; return filename.substr(dot_pos + 1); } } // namespace glslc shaderc-2025.2/glslc/src/file.h000066400000000000000000000032461500222170200161740ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef GLSLC_FILE_H_ #define GLSLC_FILE_H_ #include "libshaderc_util/string_piece.h" namespace glslc { // Given a file name, returns its extension. If no extension exists, // returns an empty string_piece. shaderc_util::string_piece GetFileExtension( const shaderc_util::string_piece& filename); // Returns true if the given file name ends with a known shader file extension. inline bool IsStageFile(const shaderc_util::string_piece& filename) { const shaderc_util::string_piece extension = glslc::GetFileExtension(filename); return extension == "vert" || extension == "frag" || extension == "tesc" || extension == "tese" || extension == "geom" || extension == "comp"; } // Returns the file extension if is either "glsl" or "hlsl", or an empty // string otherwise. inline std::string GetGlslOrHlslExtension( const shaderc_util::string_piece& filename) { auto extension = glslc::GetFileExtension(filename); if ((extension == "glsl") || (extension == "hlsl")) return extension.str(); return ""; } } // namespace glslc #endif // GLSLC_FILE_H_ shaderc-2025.2/glslc/src/file_compiler.cc000066400000000000000000000402041500222170200202170ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "file_compiler.h" #include #include #include #include #include #if SHADERC_ENABLE_WGSL_OUTPUT == 1 #include "tint/tint.h" #endif // SHADERC_ENABLE_WGSL_OUTPUT==1 #include "file.h" #include "file_includer.h" #include "shader_stage.h" #include "libshaderc_util/io_shaderc.h" #include "libshaderc_util/message.h" namespace { using shaderc_util::string_piece; // A helper function to emit SPIR-V binary code as a list of hex numbers in // text form. Returns true if a non-empty compilation result is emitted // successfully. Return false if nothing should be emitted, either because the // compilation result is empty, or the compilation output is not SPIR-V binary // code. template bool EmitSpirvBinaryAsCommaSeparatedNumbers(const CompilationResultType& result, std::ostream* out) { // Return early if the compilation output is not in SPIR-V binary code form. if (!std::is_same::value) return false; // Return early if the compilation result is empty. if (result.cbegin() == result.cend()) return false; std::ios::fmtflags output_stream_flag_cache(out->flags()); *out << std::hex << std::setfill('0'); auto RI = result.cbegin(); *out << "0x" << std::setw(8) << *RI++; for (size_t counter = 1; RI != result.cend(); RI++, counter++) { *out << ","; // Break line for every four words. if (counter % 4 == 0) { *out << std::endl; } *out << "0x" << std::setw(8) << *RI; } out->flags(output_stream_flag_cache); return true; } } // anonymous namespace namespace glslc { bool FileCompiler::CompileShaderFile(const InputFileSpec& input_file) { std::vector input_data; std::string path = input_file.name; if (!shaderc_util::ReadFile(path, &input_data)) { return false; } std::string output_file_name = GetOutputFileName(input_file.name); string_piece error_file_name = input_file.name; if (error_file_name == "-") { // If the input file was stdin, we want to output errors as . error_file_name = ""; } string_piece source_string = ""; if (!input_data.empty()) { source_string = {&input_data.front(), &input_data.front() + input_data.size()}; } std::unique_ptr includer( new FileIncluder(&include_file_finder_)); // Get a reference to the dependency trace before we pass the ownership to // shaderc::CompileOptions. const auto& used_source_files = includer->file_path_trace(); options_.SetIncluder(std::move(includer)); if (input_file.stage == shaderc_spirv_assembly) { // Only act if the requested target is SPIR-V binary. if (output_type_ == OutputType::SpirvBinary) { const auto result = compiler_.AssembleToSpv(source_string.data(), source_string.size()); return EmitCompiledResult(result, input_file.name, output_file_name, error_file_name, used_source_files); } else { return true; } } // Set the language. Since we only use the options object in this // method, then it's ok to always set it without resetting it after // compilation. A subsequent compilation will set it again anyway. options_.SetSourceLanguage(input_file.language); switch (output_type_) { case OutputType::SpirvBinary: { const auto result = compiler_.CompileGlslToSpv( source_string.data(), source_string.size(), input_file.stage, error_file_name.data(), input_file.entry_point_name.c_str(), options_); return EmitCompiledResult(result, input_file.name, output_file_name, error_file_name, used_source_files); } case OutputType::SpirvAssemblyText: { const auto result = compiler_.CompileGlslToSpvAssembly( source_string.data(), source_string.size(), input_file.stage, error_file_name.data(), input_file.entry_point_name.c_str(), options_); return EmitCompiledResult(result, input_file.name, output_file_name, error_file_name, used_source_files); } case OutputType::PreprocessedText: { const auto result = compiler_.PreprocessGlsl( source_string.data(), source_string.size(), input_file.stage, error_file_name.data(), options_); return EmitCompiledResult(result, input_file.name, output_file_name, error_file_name, used_source_files); } } return false; } template bool FileCompiler::EmitCompiledResult( const CompilationResultType& result, const std::string& input_file, const std::string& output_file_name, string_piece error_file_name, const std::unordered_set& used_source_files) { total_errors_ += result.GetNumErrors(); total_warnings_ += result.GetNumWarnings(); bool compilation_success = result.GetCompilationStatus() == shaderc_compilation_status_success; // Handle the error message for failing to deduce the shader kind. if (result.GetCompilationStatus() == shaderc_compilation_status_invalid_stage) { auto glsl_or_hlsl_extension = GetGlslOrHlslExtension(error_file_name); if (glsl_or_hlsl_extension != "") { std::cerr << "glslc: error: " << "'" << error_file_name << "': " << "." << glsl_or_hlsl_extension << " file encountered but no -fshader-stage specified ahead"; } else if (error_file_name == "") { std::cerr << "glslc: error: '-': -fshader-stage required when input is from " "standard " "input \"-\""; } else { std::cerr << "glslc: error: " << "'" << error_file_name << "': " << "file not recognized: File format not recognized"; } std::cerr << "\n"; return false; } // Get a string_piece which refers to the normal compilation output for now. // This string_piece might be redirected to the dependency info to be dumped // later, if the handler is instantiated to dump as normal compilation output, // and the original compilation output should be blocked. Otherwise it won't // be touched. The main output stream dumps this string_piece later. string_piece compilation_output( reinterpret_cast(result.cbegin()), reinterpret_cast(result.cend())); // If we have dependency info dumping handler instantiated, we should dump // dependency info first. This may redirect the compilation output // string_piece to dependency info. std::string potential_dependency_info_output; if (dependency_info_dumping_handler_) { if (!dependency_info_dumping_handler_->DumpDependencyInfo( GetCandidateOutputFileName(input_file), error_file_name.data(), &potential_dependency_info_output, used_source_files)) { return false; } if (!potential_dependency_info_output.empty()) { // If the potential_dependency_info_output string is not empty, it means // we should dump dependency info as normal compilation output. Redirect // the compilation output string_piece to the dependency info stored in // potential_dependency_info_output to make it happen. compilation_output = potential_dependency_info_output; } } std::ostream* out = nullptr; std::ofstream potential_file_stream; if (compilation_success) { out = shaderc_util::GetOutputStream(output_file_name, &potential_file_stream, &std::cerr); if (!out || out->fail()) { // An error message has already been emitted to the stderr stream. return false; } // Write compilation output to output file. If an output format for SPIR-V // binary code is specified, it is handled here. switch (binary_emission_format_) { case SpirvBinaryEmissionFormat::Unspecified: case SpirvBinaryEmissionFormat::Binary: // The output format is unspecified or specified as binary output. // On Windows, the output stream must be set to binary mode. By // default the standard output stream is set to text mode, which // translates newlines (\n) to carriage-return newline pairs // (\r\n). if (out == &std::cout) shaderc_util::FlushAndSetBinaryModeOnStdout(); out->write(compilation_output.data(), compilation_output.size()); if (out == &std::cout) shaderc_util::FlushAndSetTextModeOnStdout(); break; case SpirvBinaryEmissionFormat::Numbers: // The output format is specified to be a list of hex numbers, the // compilation output must be in SPIR-V binary code form. assert(output_type_ == OutputType::SpirvBinary); if (EmitSpirvBinaryAsCommaSeparatedNumbers(result, out)) { // Only emits the end-of-line character when the emitted compilation // result is not empty. *out << std::endl; } break; case SpirvBinaryEmissionFormat::CInitList: // The output format is specified to be a C-style initializer list, the // compilation output must be in SPIR-V binary code form. assert(output_type_ == OutputType::SpirvBinary); if (result.begin() != result.end()) { // Only emits the '{' when the compilation result is not empty. *out << "{"; } if (EmitSpirvBinaryAsCommaSeparatedNumbers(result, out)) { // Only emits the end-of-line character when the emitted compilation // result is not empty. *out << "}" << std::endl; } break; case SpirvBinaryEmissionFormat::WGSL: { #if SHADERC_ENABLE_WGSL_OUTPUT == 1 tint::Context ctx; tint::reader::spirv::Parser spv_reader( &ctx, std::vector(result.begin(), result.end())); if (!spv_reader.Parse()) { std::cout << "error: failed to convert SPIR-V binary to WGSL: " << spv_reader.error() << std::endl; return false; } tint::writer::wgsl::Generator wgsl_writer(spv_reader.module()); if (!wgsl_writer.Generate()) { std::cout << "error: failed to convert to WGSL: " << wgsl_writer.error() << std::endl; return false; } *out << wgsl_writer.result(); #endif // SHADERC_ENABLE_WGSL_OUTPUT==1 break; } } } // Write error message to std::cerr. std::cerr << result.GetErrorMessage(); if (out && out->fail()) { // Something wrong happened on output. if (out == &std::cout) { std::cerr << "glslc: error: error writing to standard output" << std::endl; } else { std::cerr << "glslc: error: error writing to output file: '" << output_file_name_ << "'" << std::endl; } return false; } return compilation_success; } void FileCompiler::AddIncludeDirectory(const std::string& path) { include_file_finder_.search_path().push_back(path); } void FileCompiler::SetIndividualCompilationFlag() { if (output_type_ != OutputType::SpirvAssemblyText) { needs_linking_ = false; file_extension_ = ".spv"; } } void FileCompiler::SetDisassemblyFlag() { if (!PreprocessingOnly()) { output_type_ = OutputType::SpirvAssemblyText; needs_linking_ = false; file_extension_ = ".spvasm"; } } void FileCompiler::SetPreprocessingOnlyFlag() { output_type_ = OutputType::PreprocessedText; needs_linking_ = false; if (output_file_name_.empty()) { output_file_name_ = "-"; } } bool FileCompiler::ValidateOptions(size_t num_files) { if (num_files == 0) { std::cerr << "glslc: error: no input files" << std::endl; return false; } if (num_files > 1 && needs_linking_) { std::cerr << "glslc: error: linking multiple files is not supported yet. " "Use -c to compile files individually." << std::endl; return false; } // If we are outputting many object files, we cannot specify -o. Also // if we are preprocessing multiple files they must be to stdout. if (num_files > 1 && ((!PreprocessingOnly() && !needs_linking_ && !output_file_name_.empty()) || (PreprocessingOnly() && output_file_name_ != "-"))) { std::cerr << "glslc: error: cannot specify -o when generating multiple" " output files" << std::endl; return false; } // If we have dependency info dumping handler instantiated, we should check // its validity. if (dependency_info_dumping_handler_) { std::string dependency_info_dumping_hander_error_msg; if (!dependency_info_dumping_handler_->IsValid( &dependency_info_dumping_hander_error_msg, num_files)) { std::cerr << "glslc: error: " << dependency_info_dumping_hander_error_msg << std::endl; return false; } } // If the output format is specified to be a binary, a list of hex numbers or // a C-style initializer list, the output must be in SPIR-V binary code form. if (binary_emission_format_ != SpirvBinaryEmissionFormat::Unspecified) { if (output_type_ != OutputType::SpirvBinary) { std::cerr << "glslc: error: cannot emit output as a "; switch (binary_emission_format_) { case SpirvBinaryEmissionFormat::Binary: std::cerr << "binary"; break; case SpirvBinaryEmissionFormat::Numbers: std::cerr << "list of hex numbers"; break; case SpirvBinaryEmissionFormat::CInitList: std::cerr << "C-style initializer list"; break; case SpirvBinaryEmissionFormat::WGSL: std::cerr << "WGSL source program"; break; case SpirvBinaryEmissionFormat::Unspecified: // The compiler should never be here at runtime. This case is added to // complete the switch cases. break; } std::cerr << " when only preprocessing the source" << std::endl; return false; } if (dependency_info_dumping_handler_ && dependency_info_dumping_handler_->DumpingAsCompilationOutput()) { std::cerr << "glslc: error: cannot dump dependency info when specifying " "any binary output format" << std::endl; return false; } } if (binary_emission_format_ == SpirvBinaryEmissionFormat::WGSL) { #if SHADERC_ENABLE_WGSL_OUTPUT != 1 std::cerr << "glslc: error: can't output WGSL: glslc was built without " "WGSL output support" << std::endl; return false; #endif } return true; } void FileCompiler::OutputMessages() { shaderc_util::OutputMessages(&std::cerr, total_warnings_, total_errors_); } std::string FileCompiler::GetOutputFileName(std::string input_filename) { if (output_file_name_.empty()) { return needs_linking_ ? std::string("a.spv") : GetCandidateOutputFileName(input_filename); } else { return output_file_name_.str(); } } std::string FileCompiler::GetCandidateOutputFileName( std::string input_filename) { if (!output_file_name_.empty() && !PreprocessingOnly()) { return output_file_name_.str(); } std::string extension = file_extension_; if (PreprocessingOnly() || needs_linking_) { extension = ".spv"; } std::string candidate_output_file_name = IsStageFile(input_filename) ? shaderc_util::GetBaseFileName(input_filename) + extension : shaderc_util::GetBaseFileName( input_filename.substr(0, input_filename.find_last_of('.')) + extension); return candidate_output_file_name; } } // namesapce glslc shaderc-2025.2/glslc/src/file_compiler.h000066400000000000000000000232261500222170200200660ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef GLSLC_FILE_COMPILER_H #define GLSLC_FILE_COMPILER_H #include #include "libshaderc_util/file_finder.h" #include "libshaderc_util/string_piece.h" #include "shaderc/shaderc.hpp" #include "dependency_info.h" namespace glslc { // Describes an input file to be compiled. struct InputFileSpec { std::string name; shaderc_shader_kind stage; shaderc_source_language language; std::string entry_point_name; }; // Context for managing compilation of source GLSL files into destination // SPIR-V files or preprocessed output. class FileCompiler { public: enum class SpirvBinaryEmissionFormat { Unspecified, // No binary output format specified, this is the only valid // option when the compilation output is not in SPIR-V binary // code form. Binary, // Emits SPIR-V binary code directly. Numbers, // Emits SPIR-V binary code as a list of hex numbers. CInitList, // Emits SPIR-V binary code as a C-style initializer list // of hex numbers. WGSL, // Emits SPIR-V module converted to WGSL source text. // Requires a build with Tint support. }; FileCompiler() : output_type_(OutputType::SpirvBinary), binary_emission_format_(SpirvBinaryEmissionFormat::Unspecified), needs_linking_(true), total_warnings_(0), total_errors_(0) {} // Compiles a shader received as specified by input_file, returning true // on success and false otherwise. If force_shader_stage is not // shaderc_glsl_infer_source or any default shader stage then the given // shader_stage will be used, otherwise it will be determined from the source // or the file type. // // Places the compilation output into a new file whose name is derived from // input_file according to the rules from glslc/README.asciidoc. // // If version/profile has been forced, the shader's version/profile is set to // that value regardless of the #version directive in the source code. // // Any errors/warnings found in the shader source will be output to std::cerr // and increment the counts reported by OutputMessages(). bool CompileShaderFile(const InputFileSpec& input_file); // Adds a directory to be searched when processing #include directives. // // Best practice: if you add an empty string before any other path, that will // correctly resolve both absolute paths and paths relative to the current // working directory. void AddIncludeDirectory(const std::string& path); // Sets the output filename. A name of "-" indicates standard output. void SetOutputFileName(const shaderc_util::string_piece& file) { output_file_name_ = file; } // Sets the format for SPIR-V binary compilation output. void SetSpirvBinaryOutputFormat(SpirvBinaryEmissionFormat format) { binary_emission_format_ = format; } // Returns false if any options are incompatible. The num_files parameter // represents the number of files that will be compiled. bool ValidateOptions(size_t num_files); // Outputs to std::cerr the number of warnings and errors if there are any. void OutputMessages(); // Sets the flag to indicate individual compilation mode. In this mode, all // files are compiled individually and written to separate output files // instead of linked together. This method also disables linking and sets the // output file extension to ".spv". Disassembly mode and preprocessing only // mode override this mode and flags. void SetIndividualCompilationFlag(); // Sets the flag to indicate disassembly mode. In this mode, the compiler // emits disassembled textual output, instead of outputting object files. // This method also sets the output file extension to ".spvasm" and disables // linking. This mode overrides individual compilation mode, and preprocessing // only mode overrides this mode. void SetDisassemblyFlag(); // Sets the flag to indicate preprocessing only mode. In this mode, instead of // outputting object files, the compiler emits the preprocessed source files. // This method disables linking and sets the output file to stdout. This mode // overrides disassembly mode and individual compilation mode. void SetPreprocessingOnlyFlag(); // Gets the reference of the compiler options which reflects the command-line // arguments. shaderc::CompileOptions& options() { return options_; } // Gets a pointer which points to the dependency info dumping hander. Creates // such a handler if such one does not exist. DependencyInfoDumpingHandler* GetDependencyDumpingHandler() { if (!dependency_info_dumping_handler_) { dependency_info_dumping_handler_.reset( new DependencyInfoDumpingHandler()); } return dependency_info_dumping_handler_.get(); } private: enum class OutputType { SpirvBinary, // A binary module, as defined by the SPIR-V specification. SpirvAssemblyText, // Assembly syntax defined by the SPIRV-Tools project. PreprocessedText, // Preprocessed source code. }; // Emits the compilation output from the given result to the given output // file and returns true if the result represents a successful compilation // step. Otherwise returns false, possibly emits messages to the standard // error stream, and does not produce an output file. Accumulates error // and warning counts for use by the OutputMessages() method. template bool EmitCompiledResult( const CompilationResultType& result, const std::string& input_file_name, const std::string& output_file_name, shaderc_util::string_piece error_file_name, const std::unordered_set& used_source_files); // Returns the final file name to be used for the output file. // // If an output file name is specified by the SetOutputFileName(), use that // argument as the final output file name. // // If the user did not specify an output filename: // If linking is not required, and the input filename has a // standard stage extension (e.g. .vert) then returns the input filename // without directory names but with the result extenstion (e.g. .spv or // .spvasm) appended. // // If linking is not required, and the input file name does not have a // standard stage extension, then also returns the directory-stripped input // filename, but replaces its extension with the result extension. (If the // resolved input filename does not have an extension, then appends the // result extension.) // // If linking is required and output filename is not specified, returns // "a.spv". std::string GetOutputFileName(std::string input_filename); // Returns the candidate output file name deduced from input file name and // user specified output file name. It is computed as follows: // // If the user did specify an output filename and the compiler is not in // preprocessing-only mode, then returns that file name. // // If the user did not specify an output filename: // If the input filename has a standard stage extension (e.g. .vert) then // returns the input filename without directory names but with the result // extenstion (e.g. .spv or .spvasm) appended. // // If the input file name does not have a standard stage extension, then also // returns the directory-stripped input filename, but replaces its extension // with the result extension. (If the resolved input filename does not have // an extension, then appends the result extension.) // // When a resolved extension is not available because the compiler is in // preprocessing-only mode or the compilation requires linking, use .spv as // the extension. std::string GetCandidateOutputFileName(std::string input_filename); // Returns true if the compiler's output is preprocessed text. bool PreprocessingOnly() { return output_type_ == OutputType::PreprocessedText; } // Performs actual SPIR-V compilation on the contents of input files. shaderc::Compiler compiler_; // Reflects the command-line arguments and goes into // compiler_.CompileGlslToSpv(). shaderc::CompileOptions options_; // What kind of output will be produced? OutputType output_type_; // The Flag to indicate to which format the output SPIR-V binary code should // be emitted. SpirvBinaryEmissionFormat binary_emission_format_; // A FileFinder used to substitute #include directives in the source code. shaderc_util::FileFinder include_file_finder_; // Indicates whether linking is needed to generate the final output. bool needs_linking_; // The ownership of dependency dumping handler. std::unique_ptr dependency_info_dumping_handler_ = nullptr; // Reflects the type of file being generated. std::string file_extension_; // Name of the file where the compilation output will go. shaderc_util::string_piece output_file_name_; // Counts warnings encountered in all compilations via this object. size_t total_warnings_; // Counts errors encountered in all compilations via this object. size_t total_errors_; }; } // namespace glslc #endif // GLSLC_FILE_COMPILER_H shaderc-2025.2/glslc/src/file_includer.cc000066400000000000000000000044271500222170200202210ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "file_includer.h" #include #include #include "libshaderc_util/io_shaderc.h" namespace glslc { shaderc_include_result* MakeErrorIncludeResult(const char* message) { return new shaderc_include_result{"", 0, message, strlen(message)}; } FileIncluder::~FileIncluder() = default; shaderc_include_result* FileIncluder::GetInclude( const char* requested_source, shaderc_include_type include_type, const char* requesting_source, size_t) { const std::string full_path = (include_type == shaderc_include_type_relative) ? file_finder_.FindRelativeReadableFilepath(requesting_source, requested_source) : file_finder_.FindReadableFilepath(requested_source); if (full_path.empty()) return MakeErrorIncludeResult("Cannot find or open include file."); // In principle, several threads could be resolving includes at the same // time. Protect the included_files. // Read the file and save its full path and contents into stable addresses. FileInfo* new_file_info = new FileInfo{full_path, {}}; if (!shaderc_util::ReadFile(full_path, &(new_file_info->contents))) { return MakeErrorIncludeResult("Cannot read file"); } included_files_.insert(full_path); return new shaderc_include_result{ new_file_info->full_path.data(), new_file_info->full_path.length(), new_file_info->contents.data(), new_file_info->contents.size(), new_file_info}; } void FileIncluder::ReleaseInclude(shaderc_include_result* include_result) { FileInfo* info = static_cast(include_result->user_data); delete info; delete include_result; } } // namespace glslc shaderc-2025.2/glslc/src/file_includer.h000066400000000000000000000052261500222170200200610ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef GLSLC_FILE_INCLUDER_H_ #define GLSLC_FILE_INCLUDER_H_ #include #include #include #include #include #include #include #include "libshaderc_util/file_finder.h" #include "shaderc/shaderc.hpp" namespace glslc { // An includer for files implementing shaderc's includer interface. It responds // to the file including query from the compiler with the full path and content // of the file to be included. In the case that the file is not found or cannot // be opened, the full path field of in the response will point to an empty // string, and error message will be passed to the content field. // This class provides the basic thread-safety guarantee. class FileIncluder : public shaderc::CompileOptions::IncluderInterface { public: explicit FileIncluder(const shaderc_util::FileFinder* file_finder) : file_finder_(*file_finder) {} ~FileIncluder() override; // Resolves a requested source file of a given type from a requesting // source into a shaderc_include_result whose contents will remain valid // until it's released. shaderc_include_result* GetInclude(const char* requested_source, shaderc_include_type type, const char* requesting_source, size_t include_depth) override; // Releases an include result. void ReleaseInclude(shaderc_include_result* include_result) override; // Returns a reference to the member storing the set of included files. const std::unordered_set& file_path_trace() const { return included_files_; } private: // Used by GetInclude() to get the full filepath. const shaderc_util::FileFinder& file_finder_; // The full path and content of a source file. struct FileInfo { const std::string full_path; std::vector contents; }; // The set of full paths of included files. std::unordered_set included_files_; }; } // namespace glslc #endif // GLSLC_FILE_INCLUDER_H_ shaderc-2025.2/glslc/src/file_test.cc000066400000000000000000000071201500222170200173640ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "file.h" #include namespace { using glslc::GetFileExtension; using glslc::IsStageFile; using glslc::GetGlslOrHlslExtension; using shaderc_util::string_piece; using testing::Eq; class FileExtensionTest : public testing::Test { protected: string_piece empty = ""; string_piece dot = "."; string_piece no_ext = "shader"; string_piece trailing_dot = "shader."; string_piece vert_ext = "shader.vert"; string_piece frag_ext = "shader.frag"; string_piece tesc_ext = "shader.tesc"; string_piece tese_ext = "shader.tese"; string_piece geom_ext = "shader.geom"; string_piece comp_ext = "shader.comp"; string_piece glsl_ext = "shader.glsl"; string_piece hlsl_ext = "shader.hlsl"; string_piece multi_dot = "shader.some..ext"; string_piece both_hg_ext = "shader.hlsl.glsl"; string_piece both_gh_ext = "shader.glsl.hlsl"; }; TEST_F(FileExtensionTest, GetFileExtension) { EXPECT_EQ("", GetFileExtension(empty)); EXPECT_EQ("", GetFileExtension(dot)); EXPECT_EQ("", GetFileExtension(no_ext)); EXPECT_EQ("", GetFileExtension(trailing_dot)); EXPECT_EQ("vert", GetFileExtension(vert_ext)); EXPECT_EQ("frag", GetFileExtension(frag_ext)); EXPECT_EQ("tesc", GetFileExtension(tesc_ext)); EXPECT_EQ("tese", GetFileExtension(tese_ext)); EXPECT_EQ("geom", GetFileExtension(geom_ext)); EXPECT_EQ("comp", GetFileExtension(comp_ext)); EXPECT_EQ("glsl", GetFileExtension(glsl_ext)); EXPECT_EQ("ext", GetFileExtension(multi_dot)); EXPECT_EQ("glsl", GetFileExtension(both_hg_ext)); EXPECT_EQ("hlsl", GetFileExtension(both_gh_ext)); } TEST_F(FileExtensionTest, GetGlslOrHlslExtension) { EXPECT_THAT(GetGlslOrHlslExtension(empty), Eq("")); EXPECT_THAT(GetGlslOrHlslExtension(dot), Eq("")); EXPECT_THAT(GetGlslOrHlslExtension(no_ext), Eq("")); EXPECT_THAT(GetGlslOrHlslExtension(trailing_dot), Eq("")); EXPECT_THAT(GetGlslOrHlslExtension(vert_ext), Eq("")); EXPECT_THAT(GetGlslOrHlslExtension(frag_ext), Eq("")); EXPECT_THAT(GetGlslOrHlslExtension(tesc_ext), Eq("")); EXPECT_THAT(GetGlslOrHlslExtension(tese_ext), Eq("")); EXPECT_THAT(GetGlslOrHlslExtension(geom_ext), Eq("")); EXPECT_THAT(GetGlslOrHlslExtension(comp_ext), Eq("")); EXPECT_THAT(GetGlslOrHlslExtension(glsl_ext), Eq("glsl")); EXPECT_THAT(GetGlslOrHlslExtension(hlsl_ext), Eq("hlsl")); EXPECT_THAT(GetGlslOrHlslExtension(multi_dot), Eq("")); EXPECT_THAT(GetGlslOrHlslExtension(both_hg_ext), Eq("glsl")); EXPECT_THAT(GetGlslOrHlslExtension(both_gh_ext), Eq("hlsl")); } TEST_F(FileExtensionTest, IsStageFile) { EXPECT_FALSE(IsStageFile(empty)); EXPECT_FALSE(IsStageFile(dot)); EXPECT_FALSE(IsStageFile(no_ext)); EXPECT_FALSE(IsStageFile(trailing_dot)); EXPECT_TRUE(IsStageFile(vert_ext)); EXPECT_TRUE(IsStageFile(frag_ext)); EXPECT_TRUE(IsStageFile(tesc_ext)); EXPECT_TRUE(IsStageFile(tese_ext)); EXPECT_TRUE(IsStageFile(geom_ext)); EXPECT_TRUE(IsStageFile(comp_ext)); EXPECT_FALSE(IsStageFile(glsl_ext)); EXPECT_FALSE(IsStageFile(multi_dot)); } } // anonymous namespace shaderc-2025.2/glslc/src/main.cc000066400000000000000000000750571500222170200163500ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include #include #include #include #include #include "file.h" #include "file_compiler.h" #include "libshaderc_util/args.h" #include "libshaderc_util/compiler.h" #include "libshaderc_util/io_shaderc.h" #include "libshaderc_util/string_piece.h" #include "resource_parse.h" #include "shader_stage.h" #include "shaderc/env.h" #include "shaderc/shaderc.h" #include "spirv-tools/libspirv.h" using shaderc_util::string_piece; namespace { // Prints the help message. void PrintHelp(std::ostream* out) { *out << R"(glslc - Compile shaders into SPIR-V Usage: glslc [options] file... An input file of - represents standard input. Options: -c Only run preprocess, compile, and assemble steps. -Dmacro[=defn] Add an implicit macro definition. -E Outputs only the results of the preprocessing step. Output defaults to standard output. -fauto-bind-uniforms Automatically assign bindings to uniform variables that don't have an explicit 'binding' layout in the shader source. -fauto-map-locations Automatically assign locations to uniform variables that don't have an explicit 'location' layout in the shader source. -fauto-combined-image-sampler Removes sampler variables and converts existing textures to combined image-samplers. -fentry-point= Specify the entry point name for HLSL compilation, for all subsequent source files. Default is "main". -fhlsl-16bit-types Enable 16-bit type support for HLSL. -fhlsl_functionality1, -fhlsl-functionality1 Enable extension SPV_GOOGLE_hlsl_functionality1 for HLSL compilation. -fhlsl-iomap Use HLSL IO mappings for bindings. -fhlsl-offsets Use HLSL offset rules for packing members of blocks. Affects only GLSL. HLSL rules are always used for HLSL. -finvert-y Invert position.Y output in vertex shader. -flimit= Specify resource limits. Each limit is specified by a limit name followed by an integer value. Tokens should be separated by whitespace. If the same limit is specified several times, only the last setting takes effect. -flimit-file Set limits as specified in the given file. -fnan-clamp Generate code for max and min builtins so that, when given a NaN operand, the other operand is returned. Similarly, the clamp builtin will favour the non-NaN operands, as if clamp were implemented as a composition of max and min. -fpreserve-bindings Preserve all binding declarations, even if those bindings are not used. -fresource-set-binding [stage] [ ...] Explicitly sets the descriptor set and binding for HLSL resources, by register name. Optionally restrict it to a single stage. -fcbuffer-binding-base [stage] Same as -fubo-binding-base. -fimage-binding-base [stage] Sets the lowest automatically assigned binding number for images. Optionally only set it for a single shader stage. For HLSL, the resource register number is added to this base. -fsampler-binding-base [stage] Sets the lowest automatically assigned binding number for samplers Optionally only set it for a single shader stage. For HLSL, the resource register number is added to this base. -fssbo-binding-base [stage] Sets the lowest automatically assigned binding number for shader storage buffer objects (SSBO). Optionally only set it for a single shader stage. Only affects GLSL. -ftexture-binding-base [stage] Sets the lowest automatically assigned binding number for textures. Optionally only set it for a single shader stage. For HLSL, the resource register number is added to this base. -fuav-binding-base [stage] For automatically assigned bindings for unordered access views (UAV), the register number is added to this base to determine the binding number. Optionally only set it for a single shader stage. Only affects HLSL. -fubo-binding-base [stage] Sets the lowest automatically assigned binding number for uniform buffer objects (UBO). Optionally only set it for a single shader stage. For HLSL, the resource register number is added to this base. -fshader-stage= Treat subsequent input files as having stage . Valid stages are vertex, vert, fragment, frag, tesscontrol, tesc, tesseval, tese, geometry, geom, compute, and comp. -g Generate source-level debug information. -h Display available options. --help Display available options. -I Add directory to include search path. -mfmt= Output SPIR-V binary code using the selected format. This option may be specified only when the compilation output is in SPIR-V binary code form. Available options are: bin - SPIR-V binary words. This is the default. c - Binary words as C initializer list of 32-bit ints num - List of comma-separated 32-bit hex integers -M Generate make dependencies. Implies -E and -w. -MM An alias for -M. -MD Generate make dependencies and compile. -MF Write dependency output to the given file. -MT Specify the target of the rule emitted by dependency generation. -O Optimize the generated SPIR-V code for better performance. -Os Optimize the generated SPIR-V code for smaller size. -O0 Disable optimization. -o Write output to . A file name of '-' represents standard output. -std= Version and profile for GLSL input files. Possible values are concatenations of version and profile, e.g. 310es, 450core, etc. Ignored for HLSL files. -S Emit SPIR-V assembly instead of binary. --show-limits Display available limit names and their default values. --target-env= Set the target client environment, and the semantics of warnings and errors. An optional suffix can specify the client version. Values are: vulkan1.0 # The default vulkan1.1 vulkan1.2 vulkan1.3 vulkan1.4 vulkan # Same as vulkan1.0 opengl4.5 opengl # Same as opengl4.5 --target-spv= Set the SPIR-V version to be used for the generated SPIR-V module. The default is the highest version of SPIR-V required to be supported for the target environment. For example, default for vulkan1.0 is spv1.0, and the default for vulkan1.1 is spv1.3, the default for vulkan1.2 is spv1.5, the default for vulkan1.3 is spv1.6, the default for vulkan1.4 is spv1.6. Values are: spv1.0, spv1.1, spv1.2, spv1.3, spv1.4, spv1.5, spv1.6 --version Display compiler version information. -w Suppresses all warning messages. -Werror Treat all warnings as errors. -x Treat subsequent input files as having type . Valid languages are: glsl, hlsl. For files ending in .hlsl the default is hlsl. Otherwise the default is glsl. )"; } // Sets resource limits according to the given string. The string // should be formated as required for ParseResourceSettings. // Returns true on success. Otherwise returns false and sets err // to a descriptive error message. bool SetResourceLimits(const std::string& str, shaderc::CompileOptions* options, std::string* err) { std::vector settings; if (!ParseResourceSettings(str, &settings, err)) { return false; } for (const auto& setting : settings) { options->SetLimit(setting.limit, setting.value); } return true; } const char kBuildVersion[] = #include "build-version.inc" ; // Gets an optional stage name followed by required offset argument. Returns // false and emits a message to *errs if any errors occur. After calling this // function, *index will be the index of the last command line argument // consumed. If no stage name is provided, then *stage contains // shaderc_glsl_infer_from_source. bool GetOptionalStageThenOffsetArgument(const shaderc_util::string_piece option, std::ostream* errs, int argc, char** argv, int* index, shaderc_shader_kind* shader_kind, uint32_t* offset) { int& argi = *index; if (argi + 1 >= argc) { *errs << "glslc: error: Option " << option << " requires at least one argument" << std::endl; return false; } auto stage = glslc::MapStageNameToForcedKind(argv[argi + 1]); if (stage != shaderc_glsl_infer_from_source) { ++argi; if (argi + 1 >= argc) { *errs << "glslc: error: Option " << option << " with stage " << argv[argi - 1] << " requires an offset argument" << std::endl; return false; } } if (!shaderc_util::ParseUint32(argv[argi + 1], offset)) { *errs << "glslc: error: invalid offset value " << argv[argi + 1] << " for " << option << std::endl; return false; } ++argi; *shader_kind = stage; return true; } } // anonymous namespace int main(int argc, char** argv) { std::vector input_files; shaderc_shader_kind current_fshader_stage = shaderc_glsl_infer_from_source; bool source_language_forced = false; shaderc_source_language current_source_language = shaderc_source_language_glsl; std::string current_entry_point_name("main"); glslc::FileCompiler compiler; bool success = true; bool has_stdin_input = false; // Shader stage for a single option. shaderc_shader_kind arg_stage = shaderc_glsl_infer_from_source; // Binding base for a single option. uint32_t arg_base = 0; // What kind of uniform variable are we setting the binding base for? shaderc_uniform_kind u_kind = shaderc_uniform_kind_buffer; // Sets binding base for the given uniform kind. If stage is // shader_glsl_infer_from_source then set it for all shader stages. auto set_binding_base = [&compiler](shaderc_shader_kind stage, shaderc_uniform_kind kind, uint32_t base) { if (stage == shaderc_glsl_infer_from_source) compiler.options().SetBindingBase(kind, base); else compiler.options().SetBindingBaseForStage(stage, kind, base); }; for (int i = 1; i < argc; ++i) { const string_piece arg = argv[i]; if (arg == "--help" || arg == "-h") { ::PrintHelp(&std::cout); return 0; } else if (arg == "--show-limits") { shaderc_util::Compiler default_compiler; // The static cast here depends on us keeping the shaderc_limit enum in // lockstep with the shaderc_util::Compiler::Limit enum. The risk of mismatch // is low since both are generated from the same resources.inc file. #define RESOURCE(NAME, FIELD, ENUM) \ std::cout << #NAME << " " \ << default_compiler.GetLimit( \ static_cast( \ shaderc_limit_##ENUM)) \ << std::endl; #include "libshaderc_util/resources.inc" #undef RESOURCE return 0; } else if (arg == "--version") { std::cout << kBuildVersion << std::endl; std::cout << "Target: " << spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0) << std::endl; return 0; } else if (arg.starts_with("-o")) { string_piece file_name; if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-o", &file_name)) { std::cerr << "glslc: error: argument to '-o' is missing (expected 1 value)" << std::endl; return 1; } compiler.SetOutputFileName(file_name); } else if (arg.starts_with("-fshader-stage=")) { const string_piece stage = arg.substr(std::strlen("-fshader-stage=")); current_fshader_stage = glslc::GetForcedShaderKindFromCmdLine(arg); if (current_fshader_stage == shaderc_glsl_infer_from_source) { std::cerr << "glslc: error: stage not recognized: '" << stage << "'" << std::endl; return 1; } } else if (arg == "-fauto-bind-uniforms") { compiler.options().SetAutoBindUniforms(true); } else if (arg == "-fauto-combined-image-sampler") { compiler.options().SetAutoSampledTextures(true); } else if (arg == "-fauto-map-locations") { compiler.options().SetAutoMapLocations(true); } else if (arg == "-fhlsl-iomap") { compiler.options().SetHlslIoMapping(true); } else if (arg == "-fhlsl-offsets") { compiler.options().SetHlslOffsets(true); } else if (arg == "-fhlsl_functionality1" || arg == "-fhlsl-functionality1") { compiler.options().SetHlslFunctionality1(true); } else if (arg == "-fhlsl-16bit-types") { compiler.options().SetHlsl16BitTypes(true); } else if (arg == "-finvert-y") { compiler.options().SetInvertY(true); } else if (arg == "-fnan-clamp") { compiler.options().SetNanClamp(true); } else if (arg.starts_with("-fpreserve-bindings")) { compiler.options().SetPreserveBindings(true); } else if (((u_kind = shaderc_uniform_kind_image), (arg == "-fimage-binding-base")) || ((u_kind = shaderc_uniform_kind_texture), (arg == "-ftexture-binding-base")) || ((u_kind = shaderc_uniform_kind_sampler), (arg == "-fsampler-binding-base")) || ((u_kind = shaderc_uniform_kind_buffer), (arg == "-fubo-binding-base")) || ((u_kind = shaderc_uniform_kind_buffer), (arg == "-fcbuffer-binding-base")) || ((u_kind = shaderc_uniform_kind_storage_buffer), (arg == "-fssbo-binding-base")) || ((u_kind = shaderc_uniform_kind_unordered_access_view), (arg == "-fuav-binding-base"))) { if (!GetOptionalStageThenOffsetArgument(arg, &std::cerr, argc, argv, &i, &arg_stage, &arg_base)) return 1; set_binding_base(arg_stage, u_kind, arg_base); } else if (arg == "-fresource-set-binding") { auto need_three_args_err = []() { std::cerr << "glsc: error: Option -fresource-set-binding" << " requires at least 3 arguments" << std::endl; return 1; }; if (i + 1 >= argc) return need_three_args_err(); auto stage = glslc::MapStageNameToForcedKind(argv[i + 1]); if (stage != shaderc_glsl_infer_from_source) { ++i; } bool seen_triple = false; while (i + 3 < argc && argv[i + 1][0] != '-' && argv[i + 2][0] != '-' && argv[i + 3][0] != '-') { seen_triple = true; uint32_t set = 0; if (!shaderc_util::ParseUint32(argv[i + 2], &set)) { std::cerr << "glslc: error: Invalid set number: " << argv[i + 2] << std::endl; return 1; } uint32_t binding = 0; if (!shaderc_util::ParseUint32(argv[i + 3], &binding)) { std::cerr << "glslc: error: Invalid binding number: " << argv[i + 3] << std::endl; return 1; } if (stage == shaderc_glsl_infer_from_source) { compiler.options().SetHlslRegisterSetAndBinding( argv[i + 1], argv[i + 2], argv[i + 3]); } else { compiler.options().SetHlslRegisterSetAndBindingForStage( stage, argv[i + 1], argv[i + 2], argv[i + 3]); } i += 3; } if (!seen_triple) return need_three_args_err(); } else if (arg.starts_with("-fentry-point=")) { current_entry_point_name = arg.substr(std::strlen("-fentry-point=")).str(); } else if (arg.starts_with("-flimit=")) { std::string err; if (!SetResourceLimits(arg.substr(std::strlen("-flimit=")).str(), &compiler.options(), &err)) { std::cerr << "glslc: error: -flimit error: " << err << std::endl; return 1; } } else if (arg.starts_with("-flimit-file")) { std::string err; string_piece limits_file; if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-flimit-file", &limits_file)) { std::cerr << "glslc: error: argument to '-flimit-file' is missing" << std::endl; return 1; } std::vector contents; if (!shaderc_util::ReadFile(limits_file.str(), &contents)) { std::cerr << "glslc: cannot read limits file: " << limits_file << std::endl; return 1; } if (!SetResourceLimits( string_piece(contents.data(), contents.data() + contents.size()) .str(), &compiler.options(), &err)) { std::cerr << "glslc: error: -flimit-file error: " << err << std::endl; return 1; } } else if (arg.starts_with("-std=")) { const string_piece standard = arg.substr(std::strlen("-std=")); int version; shaderc_profile profile; if (!shaderc_parse_version_profile(standard.begin(), &version, &profile)) { std::cerr << "glslc: error: invalid value '" << standard << "' in '-std=" << standard << "'" << std::endl; return 1; } compiler.options().SetForcedVersionProfile(version, profile); } else if (arg.starts_with("--target-env=")) { shaderc_target_env target_env = shaderc_target_env_default; const string_piece target_env_str = arg.substr(std::strlen("--target-env=")); uint32_t version = 0; // Will default appropriately. if (target_env_str == "vulkan") { target_env = shaderc_target_env_vulkan; } else if (target_env_str == "vulkan1.0") { target_env = shaderc_target_env_vulkan; version = shaderc_env_version_vulkan_1_0; } else if (target_env_str == "vulkan1.1") { target_env = shaderc_target_env_vulkan; version = shaderc_env_version_vulkan_1_1; } else if (target_env_str == "vulkan1.2") { target_env = shaderc_target_env_vulkan; version = shaderc_env_version_vulkan_1_2; } else if (target_env_str == "vulkan1.3") { target_env = shaderc_target_env_vulkan; version = shaderc_env_version_vulkan_1_3; } else if (target_env_str == "vulkan1.4") { target_env = shaderc_target_env_vulkan; version = shaderc_env_version_vulkan_1_4; } else if (target_env_str == "opengl") { target_env = shaderc_target_env_opengl; } else if (target_env_str == "opengl4.5") { target_env = shaderc_target_env_opengl; version = shaderc_env_version_opengl_4_5; } else if (target_env_str == "opengl_compat") { target_env = shaderc_target_env_opengl_compat; std::cerr << "glslc: error: opengl_compat is no longer supported" << std::endl; return 1; } else { std::cerr << "glslc: error: invalid value '" << target_env_str << "' in '--target-env=" << target_env_str << "'" << std::endl; return 1; } compiler.options().SetTargetEnvironment(target_env, version); } else if (arg.starts_with("--target-spv=")) { shaderc_spirv_version ver = shaderc_spirv_version_1_0; const string_piece ver_str = arg.substr(std::strlen("--target-spv=")); if (ver_str == "spv1.0") { ver = shaderc_spirv_version_1_0; } else if (ver_str == "spv1.1") { ver = shaderc_spirv_version_1_1; } else if (ver_str == "spv1.2") { ver = shaderc_spirv_version_1_2; } else if (ver_str == "spv1.3") { ver = shaderc_spirv_version_1_3; } else if (ver_str == "spv1.4") { ver = shaderc_spirv_version_1_4; } else if (ver_str == "spv1.5") { ver = shaderc_spirv_version_1_5; } else if (ver_str == "spv1.6") { ver = shaderc_spirv_version_1_6; } else { std::cerr << "glslc: error: invalid value '" << ver_str << "' in '--target-spv=" << ver_str << "'" << std::endl; return 1; } compiler.options().SetTargetSpirv(ver); } else if (arg.starts_with("-mfmt=")) { const string_piece binary_output_format = arg.substr(std::strlen("-mfmt=")); if (binary_output_format == "bin") { compiler.SetSpirvBinaryOutputFormat( glslc::FileCompiler::SpirvBinaryEmissionFormat::Binary); } else if (binary_output_format == "num") { compiler.SetSpirvBinaryOutputFormat( glslc::FileCompiler::SpirvBinaryEmissionFormat::Numbers); } else if (binary_output_format == "c") { compiler.SetSpirvBinaryOutputFormat( glslc::FileCompiler::SpirvBinaryEmissionFormat::CInitList); } else if (binary_output_format == "wgsl") { compiler.SetSpirvBinaryOutputFormat( glslc::FileCompiler::SpirvBinaryEmissionFormat::WGSL); } else { std::cerr << "glslc: error: invalid value '" << binary_output_format << "' in '-mfmt=" << binary_output_format << "'" << std::endl; return 1; } } else if (arg.starts_with("-x")) { string_piece option_arg; if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-x", &option_arg)) { std::cerr << "glslc: error: argument to '-x' is missing (expected 1 value)" << std::endl; success = false; } else { if (option_arg == "glsl") { current_source_language = shaderc_source_language_glsl; } else if (option_arg == "hlsl") { current_source_language = shaderc_source_language_hlsl; } else { std::cerr << "glslc: error: language not recognized: '" << option_arg << "'" << std::endl; return 1; } source_language_forced = true; } } else if (arg == "-c") { compiler.SetIndividualCompilationFlag(); } else if (arg == "-E") { compiler.SetPreprocessingOnlyFlag(); } else if (arg == "-M" || arg == "-MM") { // -M implies -E and -w compiler.SetPreprocessingOnlyFlag(); compiler.options().SetSuppressWarnings(); if (compiler.GetDependencyDumpingHandler()->DumpingModeNotSet()) { compiler.GetDependencyDumpingHandler() ->SetDumpAsNormalCompilationOutput(); } else { std::cerr << "glslc: error: both -M (or -MM) and -MD are specified. " "Only one should be used at one time." << std::endl; return 1; } } else if (arg == "-MD") { if (compiler.GetDependencyDumpingHandler()->DumpingModeNotSet()) { compiler.GetDependencyDumpingHandler() ->SetDumpToExtraDependencyInfoFiles(); } else { std::cerr << "glslc: error: both -M (or -MM) and -MD are specified. " "Only one should be used at one time." << std::endl; return 1; } } else if (arg == "-MF") { string_piece dep_file_name; if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-MF", &dep_file_name)) { std::cerr << "glslc: error: missing dependency info filename after '-MF'" << std::endl; return 1; } compiler.GetDependencyDumpingHandler()->SetDependencyFileName( std::string(dep_file_name.data(), dep_file_name.size())); } else if (arg == "-MT") { string_piece dep_file_name; if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-MT", &dep_file_name)) { std::cerr << "glslc: error: missing dependency info target after '-MT'" << std::endl; return 1; } compiler.GetDependencyDumpingHandler()->SetTarget( std::string(dep_file_name.data(), dep_file_name.size())); } else if (arg == "-S") { compiler.SetDisassemblyFlag(); } else if (arg.starts_with("-D")) { const size_t length = arg.size(); if (length <= 2) { std::cerr << "glslc: error: argument to '-D' is missing" << std::endl; } else { const string_piece argument = arg.substr(2); // Get the exact length of the macro string. size_t equal_sign_loc = argument.find_first_of('='); size_t name_length = equal_sign_loc != shaderc_util::string_piece::npos ? equal_sign_loc : argument.size(); const string_piece name_piece = argument.substr(0, name_length); if (name_piece.starts_with("GL_")) { std::cerr << "glslc: error: names beginning with 'GL_' cannot be defined: " << arg << std::endl; return 1; } if (name_piece.find("__") != string_piece::npos) { std::cerr << "glslc: warning: names containing consecutive underscores " "are reserved: " << arg << std::endl; } const string_piece value_piece = (equal_sign_loc == string_piece::npos || equal_sign_loc == argument.size() - 1) ? "" : argument.substr(name_length + 1); // TODO(deki): check arg for newlines. compiler.options().AddMacroDefinition( name_piece.data(), name_piece.size(), value_piece.data(), value_piece.size()); } } else if (arg.starts_with("-I")) { string_piece option_arg; if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-I", &option_arg)) { std::cerr << "glslc: error: argument to '-I' is missing (expected 1 value)" << std::endl; success = false; } else { compiler.AddIncludeDirectory(option_arg.str()); } } else if (arg == "-g") { compiler.options().SetGenerateDebugInfo(); } else if (arg.starts_with("-O")) { if (arg == "-O") { compiler.options().SetOptimizationLevel( shaderc_optimization_level_performance); } else if (arg == "-Os") { compiler.options().SetOptimizationLevel( shaderc_optimization_level_size); } else if (arg == "-O0") { compiler.options().SetOptimizationLevel( shaderc_optimization_level_zero); } else { std::cerr << "glslc: error: invalid value '" << arg.substr(std::strlen("-O")) << "' in '" << arg << "'" << std::endl; return 1; } } else if (arg == "-w") { compiler.options().SetSuppressWarnings(); } else if (arg == "-Werror") { compiler.options().SetWarningsAsErrors(); } else if (!(arg == "-") && arg[0] == '-') { std::cerr << "glslc: error: " << (arg[1] == '-' ? "unsupported option" : "unknown argument") << ": '" << arg << "'" << std::endl; return 1; } else { if (arg == "-") { if (has_stdin_input) { std::cerr << "glslc: error: specifying standard input \"-\" as input " << "more than once is not allowed." << std::endl; return 1; } has_stdin_input = true; } const auto language = source_language_forced ? current_source_language : ((glslc::GetFileExtension(arg) == "hlsl") ? shaderc_source_language_hlsl : shaderc_source_language_glsl); // If current_fshader_stage is shaderc_glsl_infer_from_source, that means // we didn't set forced shader kinds (otherwise an error should have // already been emitted before). So we should deduce the shader kind // from the file name. If current_fshader_stage is specifed to one of // the forced shader kinds, use that for the following compilation. input_files.emplace_back(glslc::InputFileSpec{ arg.str(), (current_fshader_stage == shaderc_glsl_infer_from_source ? glslc::DeduceDefaultShaderKindFromFileName(arg) : current_fshader_stage), language, current_entry_point_name}); } } if (!compiler.ValidateOptions(input_files.size())) return 1; if (!success) return 1; for (const auto& input_file : input_files) { success &= compiler.CompileShaderFile(input_file); } compiler.OutputMessages(); return success ? 0 : 1; } shaderc-2025.2/glslc/src/resource_parse.cc000066400000000000000000000057401500222170200204350ustar00rootroot00000000000000// Copyright 2016 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "resource_parse.h" #include #include #include #include #include namespace { // Converts a limit string to a limit enum. Returns true on successful // conversion. bool StringToLimit(const std::string& str, shaderc_limit* limit) { const char* cstr = str.c_str(); #define RESOURCE(NAME, FIELD, ENUM) \ if (0 == std::strcmp(#NAME, cstr)) { \ *limit = shaderc_limit_##ENUM; \ return true; \ } #include "libshaderc_util/resources.inc" #undef RESOURCE return false; } // Returns true if we should ignore the setting. bool IgnoreSetting(const std::string& str) { const std::string ignore_list[] = { "nonInductiveForLoops", "whileLoops", "doWhileLoops", "generalUniformIndexing", "generalAttributeMatrixVectorIndexing", "generalVaryingIndexing", "generalSamplerIndexing", "generalVariableIndexing", "generalConstantMatrixVectorIndexing", }; return std::find(std::begin(ignore_list), std::end(ignore_list), str) != std::end(ignore_list); } } // anonymous namespace namespace glslc { bool ParseResourceSettings(const std::string& input, std::vector* limits, std::string* err) { auto failure = [err, limits](std::string msg) { *err = msg; limits->clear(); return false; }; std::istringstream input_stream(input); std::istream_iterator pos((input_stream)); limits->clear(); while (pos != std::istream_iterator()) { const std::string limit_name = *pos++; shaderc_limit limit = static_cast(0); bool ignore = IgnoreSetting(limit_name); if (!ignore) { if (!StringToLimit(limit_name, &limit)) return failure(std::string("invalid resource limit: " + limit_name)); } if (pos == std::istream_iterator()) return failure(std::string("missing value after limit: ") + limit_name); const std::string value_str = *pos; int value; std::istringstream value_stream(value_str); value_stream >> value; if (value_stream.bad() || !value_stream.eof() || value_stream.fail()) return failure(std::string("invalid integer: ") + value_str); if (!ignore) limits->push_back({limit, value}); ++pos; } return true; } } // anonymous namespace shaderc-2025.2/glslc/src/resource_parse.h000066400000000000000000000040061500222170200202710ustar00rootroot00000000000000// Copyright 2016 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef GLSLC_RESOURCE_PARSE_H #define GLSLC_RESOURCE_PARSE_H #include #include #include "shaderc/shaderc.h" namespace glslc { // A resource limit setting. struct ResourceSetting { shaderc_limit limit; int value; }; // Returns true when two resource setting structures are equal. inline bool operator==(const ResourceSetting& lhs, const ResourceSetting& rhs) { return (lhs.limit == rhs.limit) && (lhs.value == rhs.value); } // Parses a resource limit setting string. On success, returns true and populates // the limits parameter. On failure returns failure and emits a message to err. // The setting string should be a seqeuence of pairs, where each pair // is a limit name followed by a decimal integer. Tokens should be separated // by whitespace. In particular, this function accepts Glslang's configuration // file syntax. If a limit is mentioned multiple times, then the last setting // takes effect. Ignore settings for: // nonInductiveForLoops // whileLoops // doWhileLoops // generalUniformIndexing // generalAttributeMatrixVectorIndexing // generalVaryingIndexing // generalSamplerIndexing // generalVariableIndexing // generalConstantMatrixVectorIndexing bool ParseResourceSettings(const std::string& input, std::vector* limits, std::string* err); } // namespace glslc #endif // GLSLC_FILE_H_ shaderc-2025.2/glslc/src/resource_parse_test.cc000066400000000000000000000060521500222170200214710ustar00rootroot00000000000000// Copyright 2017 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "resource_parse.h" #include namespace { using glslc::ParseResourceSettings; using glslc::ResourceSetting; using testing::Eq; struct ResourceSettingsCase { std::string input; bool success; std::vector settings; std::string message; }; using ParseResourceSettingsTest = ::testing::TestWithParam; TEST_P(ParseResourceSettingsTest, Sample) { std::vector settings; std::string err; const bool succeeded = ParseResourceSettings(GetParam().input, &settings, &err); EXPECT_THAT(succeeded, Eq(GetParam().success)); EXPECT_THAT(settings, Eq(GetParam().settings)); EXPECT_THAT(err, Eq(GetParam().message)); } INSTANTIATE_TEST_SUITE_P(ParseResources, ParseResourceSettingsTest, ::testing::ValuesIn(std::vector{ {"", true, {}, ""}, {" \t \t \n ", true, {}, ""}, {" blorp blam", false, {}, "invalid resource limit: blorp"}, {"MaxLightsxyz", false, {}, "invalid resource limit: MaxLightsxyz"}, {"MaxLights", false, {}, "missing value after limit: MaxLights"}, {"MaxLights x", false, {}, "invalid integer: x"}, {"MaxLights 99x", false, {}, "invalid integer: 99x"}, {"MaxLights 12 blam", false, {}, "invalid resource limit: blam"}, {"MaxLights 12", true, {{shaderc_limit_max_lights, 12}}, ""}, // Test negative number {"MinProgramTexelOffset -9", true, {{shaderc_limit_min_program_texel_offset, -9}}, ""}, // Test leading, intervening, and trailing whitespace {" \tMaxLights \n 12 \t ", true, {{shaderc_limit_max_lights, 12}}, ""}, // Test more than one limit setting. {"MinProgramTexelOffset -10 MaxLights 4", true, {{shaderc_limit_min_program_texel_offset, -10}, {shaderc_limit_max_lights, 4}}, ""}, // Check ignore cases. {"nonInductiveForLoops", false, {}, "missing value after limit: nonInductiveForLoops"}, {"nonInductiveForLoops 1", true, {}, ""}, {"whileLoops 1", true, {}, ""}, {"doWhileLoops 1", true, {}, ""}, {"generalUniformIndexing 1", true, {}, ""}, {"generalAttributeMatrixVectorIndexing 1", true, {}, ""}, {"generalVaryingIndexing 1", true, {}, ""}, {"generalSamplerIndexing 1", true, {}, ""}, {"generalVariableIndexing 1", true, {}, ""}, {"generalConstantMatrixVectorIndexing 1", true, {}, ""}, // Check an ignore case with a regular case {"whileLoops 1 MaxLights 99", true, {{shaderc_limit_max_lights, 99}}, ""}, })); } // anonymous namespace shaderc-2025.2/glslc/src/shader_stage.cc000066400000000000000000000071611500222170200200440ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "shader_stage.h" #include "file.h" using shaderc_util::string_piece; namespace { // Maps an identifier to a shader stage. struct StageMapping { const char* id; shaderc_shader_kind stage; }; } // anonymous namespace namespace glslc { shaderc_shader_kind MapStageNameToForcedKind(const string_piece& stage_name) { const StageMapping string_to_kind[] = { {"vertex", shaderc_glsl_vertex_shader}, {"vert", shaderc_glsl_vertex_shader}, {"fragment", shaderc_glsl_fragment_shader}, {"frag", shaderc_glsl_fragment_shader}, {"tesscontrol", shaderc_glsl_tess_control_shader}, {"tesc", shaderc_glsl_tess_control_shader}, {"tesseval", shaderc_glsl_tess_evaluation_shader}, {"tese", shaderc_glsl_tess_evaluation_shader}, {"geometry", shaderc_glsl_geometry_shader}, {"geom", shaderc_glsl_geometry_shader}, {"compute", shaderc_glsl_compute_shader}, {"comp", shaderc_glsl_compute_shader}, {"rgen", shaderc_glsl_raygen_shader }, {"rahit", shaderc_glsl_anyhit_shader }, {"rchit", shaderc_glsl_closesthit_shader }, {"rmiss", shaderc_glsl_miss_shader }, {"rint", shaderc_glsl_intersection_shader }, {"rcall", shaderc_glsl_callable_shader }, {"task", shaderc_glsl_task_shader }, {"mesh", shaderc_glsl_mesh_shader }, }; for (const auto& entry : string_to_kind) { if (stage_name == entry.id) return entry.stage; } return shaderc_glsl_infer_from_source; } shaderc_shader_kind GetForcedShaderKindFromCmdLine( const shaderc_util::string_piece& f_shader_stage_str) { size_t equal_pos = f_shader_stage_str.find_first_of("="); if (equal_pos == std::string::npos) return shaderc_glsl_infer_from_source; return MapStageNameToForcedKind(f_shader_stage_str.substr(equal_pos + 1)); } shaderc_shader_kind DeduceDefaultShaderKindFromFileName( const string_piece file_name) { // Add new stage types here. static const StageMapping kStringToStage[] = { {"vert", shaderc_glsl_default_vertex_shader}, {"frag", shaderc_glsl_default_fragment_shader}, {"tesc", shaderc_glsl_default_tess_control_shader}, {"tese", shaderc_glsl_default_tess_evaluation_shader}, {"geom", shaderc_glsl_default_geometry_shader}, {"comp", shaderc_glsl_default_compute_shader}, {"spvasm", shaderc_spirv_assembly}, {"rgen", shaderc_glsl_default_raygen_shader }, {"rahit", shaderc_glsl_default_anyhit_shader }, {"rchit", shaderc_glsl_default_closesthit_shader }, {"rmiss", shaderc_glsl_default_miss_shader }, {"rint", shaderc_glsl_default_intersection_shader }, {"rcall", shaderc_glsl_default_callable_shader }, {"task", shaderc_glsl_default_task_shader }, {"mesh", shaderc_glsl_default_mesh_shader }, }; const string_piece extension = glslc::GetFileExtension(file_name); shaderc_shader_kind stage = shaderc_glsl_infer_from_source; for (const auto& entry : kStringToStage) { if (extension == entry.id) stage = entry.stage; } return stage; } } // namespace glslc shaderc-2025.2/glslc/src/shader_stage.h000066400000000000000000000031211500222170200176760ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef GLSLC_SHADER_STAGE_H_ #define GLSLC_SHADER_STAGE_H_ #include #include "libshaderc_util/string_piece.h" #include "shaderc/shaderc.h" namespace glslc { // Maps a shader stage name to a forced shader stage enum value. Returns // 'shaderc_glsl_infer_from_source' if the stage name is unrecognized. shaderc_shader_kind MapStageNameToForcedKind( const shaderc_util::string_piece& f_shader_stage_str); // Parse the string piece from command line to get the force shader stage. // If the 'f_shader_stage_str' cannot be parsed to a valid force shader stage, // returns 'shaderc_glsl_infer_from_source'. Requires the string to begin with // '='. shaderc_shader_kind GetForcedShaderKindFromCmdLine( const shaderc_util::string_piece& f_shader_stage_str); // Parse the file name extension to get the default shader kind. shaderc_shader_kind DeduceDefaultShaderKindFromFileName( shaderc_util::string_piece file_name); } // namespace glslc #endif // GLSLC_SHADER_STAGE_H_ shaderc-2025.2/glslc/src/stage_test.cc000066400000000000000000000064261500222170200175600ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Some of the tests here check code paths that are not checked by // integration tests. // Generally, these would be conditions not generated by the Glslang // compiler. It's easier to write these unit tests than to inject // a dependency on a fake compiler. #include #include #include "shaderc/shaderc.h" #include "shader_stage.h" using shaderc_util::string_piece; namespace { TEST(DeduceDefaultShaderKindFromFileName, ValidStage) { std::stringstream error_stream; EXPECT_EQ(shaderc_glsl_default_vertex_shader, glslc::DeduceDefaultShaderKindFromFileName("a.vert")); EXPECT_EQ(shaderc_glsl_default_fragment_shader, glslc::DeduceDefaultShaderKindFromFileName("a.frag")); EXPECT_EQ(shaderc_glsl_default_geometry_shader, glslc::DeduceDefaultShaderKindFromFileName("a.geom")); EXPECT_EQ(shaderc_glsl_default_tess_control_shader, glslc::DeduceDefaultShaderKindFromFileName("a.tesc")); EXPECT_EQ(shaderc_glsl_default_tess_evaluation_shader, glslc::DeduceDefaultShaderKindFromFileName("a.tese")); EXPECT_EQ(shaderc_glsl_default_compute_shader, glslc::DeduceDefaultShaderKindFromFileName("a.comp")); EXPECT_EQ(shaderc_glsl_default_raygen_shader, glslc::DeduceDefaultShaderKindFromFileName("a.rgen")); EXPECT_EQ(shaderc_glsl_default_anyhit_shader, glslc::DeduceDefaultShaderKindFromFileName("a.rahit")); EXPECT_EQ(shaderc_glsl_default_closesthit_shader, glslc::DeduceDefaultShaderKindFromFileName("a.rchit")); EXPECT_EQ(shaderc_glsl_default_miss_shader, glslc::DeduceDefaultShaderKindFromFileName("a.rmiss")); EXPECT_EQ(shaderc_glsl_default_intersection_shader, glslc::DeduceDefaultShaderKindFromFileName("a.rint")); EXPECT_EQ(shaderc_glsl_default_callable_shader, glslc::DeduceDefaultShaderKindFromFileName("a.rcall")); EXPECT_EQ(shaderc_glsl_default_task_shader, glslc::DeduceDefaultShaderKindFromFileName("a.task")); EXPECT_EQ(shaderc_glsl_default_mesh_shader, glslc::DeduceDefaultShaderKindFromFileName("a.mesh")); } TEST(DeduceDefaultShaderKindFromFileName, InvalidStage) { std::stringstream error_stream; EXPECT_EQ(shaderc_glsl_infer_from_source, glslc::DeduceDefaultShaderKindFromFileName("a.glsl")); EXPECT_EQ(shaderc_glsl_infer_from_source, glslc::DeduceDefaultShaderKindFromFileName("-")); EXPECT_EQ(shaderc_glsl_infer_from_source, glslc::DeduceDefaultShaderKindFromFileName("a.foo")); EXPECT_EQ(shaderc_glsl_infer_from_source, glslc::DeduceDefaultShaderKindFromFileName("no-file-extension")); } } // anonymous namespace shaderc-2025.2/glslc/test/000077500000000000000000000000001500222170200152675ustar00rootroot00000000000000shaderc-2025.2/glslc/test/CMakeLists.txt000066400000000000000000000022761500222170200200360ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. add_test(NAME shaderc_expect_unittests COMMAND ${Python_EXECUTABLE} -m unittest expect_unittest.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) add_test(NAME shaderc_glslc_test_framework_unittests COMMAND ${Python_EXECUTABLE} -m unittest glslc_test_framework_unittest.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) if(${SHADERC_ENABLE_TESTS}) add_test(NAME glslc_tests COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glslc_test_framework.py $ $ --test-dir ${CMAKE_CURRENT_SOURCE_DIR}) endif() shaderc-2025.2/glslc/test/assembly.py000066400000000000000000000111011500222170200174520ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader def assembly_comments(): return """ ; SPIR-V ; Version: 1.0 ; Generator: Google Shaderc over Glslang; 11 ; Bound: 6 ; Schema: 0""" def empty_main_assembly(): return assembly_comments() + """ OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Vertex %4 "main" OpSource ESSL 310 OpName %4 "main" %2 = OpTypeVoid %3 = OpTypeFunction %2 %4 = OpFunction %2 None %3 %5 = OpLabel OpReturn OpFunctionEnd""" def empty_main(): return '#version 310 es\nvoid main() {}' @inside_glslc_testsuite('SpirvAssembly') class TestAssemblyFileAsOnlyParameter(expect.ValidNamedObjectFile): """Tests that glslc accepts a SPIR-V assembly file as the only parameter.""" shader = FileShader(empty_main_assembly(), '.spvasm') glslc_args = [shader] expected_object_filenames = ('a.spv',) @inside_glslc_testsuite('SpirvAssembly') class TestDashCAssemblyFile(expect.ValidObjectFile): """Tests that -c works with SPIR-V assembly file.""" shader = FileShader(empty_main_assembly(), '.spvasm') glslc_args = ['-c', shader] @inside_glslc_testsuite('SpirvAssembly') class TestAssemblyFileWithOnlyComments(expect.ValidObjectFile): """Tests that glslc accepts an assembly file with only comments inside.""" shader = FileShader(assembly_comments(), '.spvasm') glslc_args = ['-c', shader] @inside_glslc_testsuite('SpirvAssembly') class TestEmptyAssemblyFile(expect.ValidObjectFile): """Tests that glslc accepts an empty assembly file.""" shader = FileShader('', '.spvasm') glslc_args = ['-c', shader] @inside_glslc_testsuite('SpirvAssembly') class TestDashEAssemblyFile(expect.SuccessfulReturn, expect.NoGeneratedFiles): """Tests that -E works with SPIR-V assembly file.""" shader = FileShader(empty_main_assembly(), '.spvasm') glslc_args = ['-E', shader] @inside_glslc_testsuite('SpirvAssembly') class TestDashSAssemblyFile(expect.SuccessfulReturn, expect.NoGeneratedFiles): """Tests that -S works with SPIR-V assembly file.""" shader = FileShader(empty_main_assembly(), '.spvasm') glslc_args = ['-S', shader] @inside_glslc_testsuite('SpirvAssembly') class TestMultipleAssemblyFiles(expect.ValidObjectFile): """Tests that glslc accepts multiple SPIR-V assembly files.""" shader1 = FileShader(empty_main_assembly(), '.spvasm') shader2 = FileShader(empty_main_assembly(), '.spvasm') shader3 = FileShader(empty_main_assembly(), '.spvasm') glslc_args = ['-c', shader1, shader2, shader3] @inside_glslc_testsuite('SpirvAssembly') class TestHybridInputFiles(expect.ValidObjectFile): """Tests that glslc accepts a mix of SPIR-V assembly files and GLSL source files.""" shader1 = FileShader(empty_main_assembly(), '.spvasm') shader2 = FileShader(empty_main(), '.vert') shader3 = FileShader(empty_main(), '.frag') glslc_args = ['-c', shader1, shader2, shader3] @inside_glslc_testsuite('SpirvAssembly') class TestShaderStageWithAssemblyFile(expect.ErrorMessage): """Tests that assembly files don't work with -fshader-stage""" shader = FileShader(empty_main_assembly(), '.spvasm') glslc_args = ['-c', '-fshader-stage=vertex', shader] expected_error = [ shader, ": error: #version: Desktop shaders for Vulkan SPIR-V require " "version 140 or higher\n", shader, ":2: error: 'extraneous semicolon' :", " not supported for this version or the enabled extensions\n", shader, ":2: error: '' : syntax error, unexpected IDENTIFIER\n", '3 errors generated.\n'] @inside_glslc_testsuite('SpirvAssembly') class TestStdWithAssemblyFile(expect.ValidObjectFile): """Tests that --std= doesn't affect the processing of assembly files.""" shader = FileShader(empty_main_assembly(), '.spvasm') glslc_args = ['-c', '-std=310es', shader] shaderc-2025.2/glslc/test/environment.py000066400000000000000000000045151500222170200202120ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Classes for conveniently specifying a test environment. These classes have write() methods that create objects in a test's environment. For instance, File creates a file, and Directory creates a directory with some files or subdirectories in it. Example: test.environment = Directory('.', [ File('a.vert', 'void main(){}'), Directory('subdir', [ File('b', 'b content'), File('c', 'c content') ]) ]) In general, these classes don't clean up the disk content they create. They were written in a test framework that handles clean-up at a higher level. """ import os class Directory: """Specifies a directory or a subdirectory.""" def __init__(self, name, content): """content is a list of File or Directory objects.""" self.name = name self.content = content @staticmethod def create(path): """Creates a directory path if it doesn't already exist.""" try: os.makedirs(path) except OSError: # Handles both pre-existence and a racing creation. if not os.path.isdir(path): raise def write(self, parent): """Creates a self.name directory within parent (which is a string path) and recursively writes the content in it. """ full_path = os.path.join(parent, self.name) Directory.create(full_path) for c in self.content: c.write(full_path) class File: """Specifies a file by name and content.""" def __init__(self, name, content): self.name = name self.content = content def write(self, directory): """Writes content to directory/name.""" with open(os.path.join(directory, self.name), 'w') as f: f.write(self.content) shaderc-2025.2/glslc/test/error_no_object.py000066400000000000000000000044471500222170200210250ustar00rootroot00000000000000# Copyright 2017 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect import os.path from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader @inside_glslc_testsuite('ErrorNoObject') class ErrorGeneratesNoObjectFile(expect.NoObjectFile, expect.NoOutputOnStdout, expect.ErrorMessageSubstr): """Tests that on error, no object file is generated.""" shader = FileShader('#version 150\nBad', '.frag') glslc_args = ['-c', shader] expected_error_substr = ['syntax error'] @inside_glslc_testsuite('ErrorNoObject') class FailureToMakeOutputFileIsErrorWithNoOutputFile( expect.NoNamedOutputFiles, expect.NoOutputOnStdout, expect.ErrorMessageSubstr): """Tests that if we fail to make an output file, no file is generated, and we have certain error messages.""" shader = FileShader('#version 150\nvoid main() {}', '.frag') bad_file = '/file/should/not/exist/today' glslc_args = ['-c', shader, '-o', bad_file] expected_output_filenames = [bad_file] expected_error_substr = ['cannot open output file'] @inside_glslc_testsuite('ErrorNoObject') class FailureToMakeOutputFileAsCurrentDirIsErrorWithNoOutputFile( expect.NoNamedOutputFiles, expect.NoOutputOnStdout, expect.ErrorMessageSubstr): """Tests that if we fail to make an output file because it is the current directory, then no file is generated, and we have certain error messages.""" shader = FileShader('#version 150\nvoid main() {}', '.frag') bad_file = '.' # Current directory glslc_args = ['-c', shader, '-o', bad_file] expected_output_filenames = [bad_file] expected_error_substr = ['cannot open output file'] shaderc-2025.2/glslc/test/expect.py000066400000000000000000000717501500222170200171430ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A number of common glslc result checks coded in mixin classes. A test case can use these checks by declaring their enclosing mixin classes as superclass and providing the expected_* variables required by the check_*() methods in the mixin classes. """ import difflib import functools import os import re import subprocess import sys from glslc_test_framework import GlslCTest from builtins import bytes GLSLANG_GENERATOR_VERSION=11 SHADERC_GENERATOR_NUMBER=13 SHADERC_GENERATOR_WORD=(SHADERC_GENERATOR_NUMBER << 16) + GLSLANG_GENERATOR_VERSION ASSEMBLER_GENERATOR_WORD=(7<<16) def convert_to_string(input): if type(input) is not str: if sys.version_info[0] == 2: return input.decode('utf-8') elif sys.version_info[0] == 3: return str(input, encoding='utf-8', errors='ignore') if input is not None else input else: raise Exception( 'Unable to determine if running Python 2 or 3 from {}'.format( sys.version_info)) else: return input def convert_to_unix_line_endings(source): """Converts all line endings in source to be unix line endings.""" return source.replace('\r\n', '\n').replace('\r', '\n') def substitute_file_extension(filename, extension): """Substitutes file extension, respecting known shader extensions. foo.vert -> foo.vert.[extension] [similarly for .frag, .comp, etc.] foo.glsl -> foo.[extension] foo.unknown -> foo.[extension] foo -> foo.[extension] """ if filename[-5:] not in ['.vert', '.frag', '.tesc', '.tese', '.geom', '.comp', '.spvasm']: return filename.rsplit('.', 1)[0] + '.' + extension else: return filename + '.' + extension def get_object_filename(source_filename): """Gets the object filename for the given source file.""" return substitute_file_extension(source_filename, 'spv') def get_assembly_filename(source_filename): """Gets the assembly filename for the given source file.""" return substitute_file_extension(source_filename, 'spvasm') def verify_file_non_empty(filename): """Checks that a given file exists and is not empty.""" if not os.path.isfile(filename): return False, 'Cannot find file: ' + filename if not os.path.getsize(filename): return False, 'Empty file: ' + filename return True, '' class ReturnCodeIsZero(GlslCTest): """Mixin class for checking that the return code is zero.""" def check_return_code_is_zero(self, status): if status.returncode: return False, 'Non-zero return code: {ret}\n'.format( ret=status.returncode) return True, '' class NoOutputOnStdout(GlslCTest): """Mixin class for checking that there is no output on stdout.""" def check_no_output_on_stdout(self, status): if status.stdout: return False, 'Non empty stdout: {out}\n'.format(out=status.stdout) return True, '' class NoOutputOnStderr(GlslCTest): """Mixin class for checking that there is no output on stderr.""" def check_no_output_on_stderr(self, status): if status.stderr: return False, 'Non empty stderr: {err}\n'.format(err=status.stderr) return True, '' class SuccessfulReturn(ReturnCodeIsZero, NoOutputOnStdout, NoOutputOnStderr): """Mixin class for checking that return code is zero and no output on stdout and stderr.""" pass class NoGeneratedFiles(GlslCTest): """Mixin class for checking that there is no file generated.""" def check_no_generated_files(self, status): all_files = os.listdir(status.directory) input_files = status.input_filenames if all([f.startswith(status.directory) for f in input_files]): all_files = [os.path.join(status.directory, f) for f in all_files] generated_files = set(all_files) - set(input_files) if len(generated_files) == 0: return True, '' else: return False, 'Extra files generated: {}'.format(generated_files) class CorrectBinaryLengthAndPreamble(GlslCTest): """Provides methods for verifying preamble for a SPIR-V binary.""" def verify_binary_length_and_header(self, binary, spv_version = 0x10000): """Checks that the given SPIR-V binary has valid length and header. Returns: False, error string if anything is invalid True, '' otherwise Args: binary: a bytes object containing the SPIR-V binary spv_version: target SPIR-V version number, with same encoding as the version word in a SPIR-V header. """ def read_word(binary, index, little_endian): """Reads the index-th word from the given binary file.""" word = binary[index * 4:(index + 1) * 4] if little_endian: word = reversed(word) return functools.reduce(lambda w, b: (w << 8) | b, word, 0) def check_endianness(binary): """Checks the endianness of the given SPIR-V binary. Returns: True if it's little endian, False if it's big endian. None if magic number is wrong. """ first_word = read_word(binary, 0, True) if first_word == 0x07230203: return True first_word = read_word(binary, 0, False) if first_word == 0x07230203: return False return None num_bytes = len(binary) if num_bytes % 4 != 0: return False, ('Incorrect SPV binary: size should be a multiple' ' of words') if num_bytes < 20: return False, 'Incorrect SPV binary: size less than 5 words' preamble = binary[0:19] little_endian = check_endianness(preamble) # SPIR-V module magic number if little_endian is None: return False, 'Incorrect SPV binary: wrong magic number' # SPIR-V version number version = read_word(preamble, 1, little_endian) # TODO(dneto): Recent Glslang uses version word 0 for opengl_compat # profile if version != spv_version and version != 0: return False, 'Incorrect SPV binary: wrong version number' # Shaderc-over-Glslang (0x000d....) or # SPIRV-Tools (0x0007....) generator number if read_word(preamble, 2, little_endian) != SHADERC_GENERATOR_WORD and \ read_word(preamble, 2, little_endian) != ASSEMBLER_GENERATOR_WORD: return False, ('Incorrect SPV binary: wrong generator magic ' 'number') # reserved for instruction schema if read_word(preamble, 4, little_endian) != 0: return False, 'Incorrect SPV binary: the 5th byte should be 0' return True, '' class CorrectObjectFilePreamble(CorrectBinaryLengthAndPreamble): """Provides methods for verifying preamble for a SPV object file.""" def verify_object_file_preamble(self, filename, spv_version = 0x10000): """Checks that the given SPIR-V binary file has correct preamble.""" success, message = verify_file_non_empty(filename) if not success: return False, message with open(filename, 'rb') as object_file: object_file.seek(0, os.SEEK_END) num_bytes = object_file.tell() object_file.seek(0) binary = bytes(object_file.read()) return self.verify_binary_length_and_header(binary, spv_version) return True, '' class CorrectAssemblyFilePreamble(GlslCTest): """Provides methods for verifying preamble for a SPV assembly file.""" def verify_assembly_file_preamble(self, filename): success, message = verify_file_non_empty(filename) if not success: return False, message with open(filename) as assembly_file: line1 = assembly_file.readline() line2 = assembly_file.readline() line3 = assembly_file.readline() if (line1 != '; SPIR-V\n' or line2 != '; Version: 1.0\n' or (not line3.startswith('; Generator: Google Shaderc over Glslang;'))): return False, 'Incorrect SPV assembly' return True, '' class ValidObjectFile(SuccessfulReturn, CorrectObjectFilePreamble): """Mixin class for checking that every input file generates a valid SPIR-V 1.0 object file following the object file naming rule, and there is no output on stdout/stderr.""" def check_object_file_preamble(self, status): for input_filename in status.input_filenames: object_filename = get_object_filename(input_filename) success, message = self.verify_object_file_preamble( os.path.join(status.directory, object_filename)) if not success: return False, message return True, '' class ValidObjectFile1_3(SuccessfulReturn, CorrectObjectFilePreamble): """Mixin class for checking that every input file generates a valid SPIR-V 1.3 object file following the object file naming rule, and there is no output on stdout/stderr.""" def check_object_file_preamble(self, status): for input_filename in status.input_filenames: object_filename = get_object_filename(input_filename) success, message = self.verify_object_file_preamble( os.path.join(status.directory, object_filename), 0x10300) if not success: return False, message return True, '' class ValidObjectFile1_4(SuccessfulReturn, CorrectObjectFilePreamble): """Mixin class for checking that every input file generates a valid SPIR-V 1.4 object file following the object file naming rule, and there is no output on stdout/stderr.""" def check_object_file_preamble(self, status): for input_filename in status.input_filenames: object_filename = get_object_filename(input_filename) success, message = self.verify_object_file_preamble( os.path.join(status.directory, object_filename), 0x10400) if not success: return False, message return True, '' class ValidObjectFile1_5(SuccessfulReturn, CorrectObjectFilePreamble): """Mixin class for checking that every input file generates a valid SPIR-V 1.5 object file following the object file naming rule, and there is no output on stdout/stderr.""" def check_object_file_preamble(self, status): for input_filename in status.input_filenames: object_filename = get_object_filename(input_filename) success, message = self.verify_object_file_preamble( os.path.join(status.directory, object_filename), 0x10500) if not success: return False, message return True, '' class ValidObjectFile1_6(SuccessfulReturn, CorrectObjectFilePreamble): """Mixin class for checking that every input file generates a valid SPIR-V 1.6 object file following the object file naming rule, and there is no output on stdout/stderr.""" def check_object_file_preamble(self, status): for input_filename in status.input_filenames: object_filename = get_object_filename(input_filename) success, message = self.verify_object_file_preamble( os.path.join(status.directory, object_filename), 0x10600) if not success: return False, message return True, '' class ValidObjectFileWithAssemblySubstr(SuccessfulReturn, CorrectObjectFilePreamble): """Mixin class for checking that every input file generates a valid object file following the object file naming rule, there is no output on stdout/stderr, and the disassmbly contains a specified substring per input.""" def check_object_file_disassembly(self, status): for an_input in status.inputs: object_filename = get_object_filename(an_input.filename) obj_file = str(os.path.join(status.directory, object_filename)) success, message = self.verify_object_file_preamble(obj_file) if not success: return False, message cmd = [status.test_manager.disassembler_path, '--no-color', obj_file] process = subprocess.Popen( args=cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=status.directory) output = process.communicate(None) disassembly = output[0] if not isinstance(an_input.assembly_substr, str): return False, "Missing assembly_substr member" if bytes(an_input.assembly_substr, 'utf-8') not in disassembly: return False, ('Incorrect disassembly output:\n{asm}\n' 'Expected substring not found:\n{exp}'.format( asm=disassembly, exp=an_input.assembly_substr)) return True, '' class ValidNamedObjectFile(SuccessfulReturn, CorrectObjectFilePreamble): """Mixin class for checking that a list of object files with the given names are correctly generated, and there is no output on stdout/stderr. To mix in this class, subclasses need to provide expected_object_filenames as the expected object filenames. """ def check_object_file_preamble(self, status): for object_filename in self.expected_object_filenames: success, message = self.verify_object_file_preamble( os.path.join(status.directory, object_filename)) if not success: return False, message return True, '' class ValidFileContents(GlslCTest): """Mixin class to test that a specific file contains specific text To mix in this class, subclasses need to provide expected_file_contents as the contents of the file and target_filename to determine the location.""" def check_file(self, status): target_filename = os.path.join(status.directory, self.target_filename) if not os.path.isfile(target_filename): return False, 'Cannot find file: ' + target_filename with open(target_filename, 'r') as target_file: file_contents = target_file.read() if isinstance(self.expected_file_contents, str): if file_contents == self.expected_file_contents: return True, '' return False, ('Incorrect file output: \n{act}\n' 'Expected:\n{exp}' 'With diff:\n{diff}'.format( act=file_contents, exp=self.expected_file_contents, diff='\n'.join(list(difflib.unified_diff( self.expected_file_contents.split('\n'), file_contents.split('\n'), fromfile='expected_output', tofile='actual_output'))))) elif isinstance(self.expected_file_contents, type(re.compile(''))): if self.expected_file_contents.search(file_contents): return True, '' return False, ( 'Incorrect file output: \n{act}\n' 'Expected matching regex pattern:\n{exp}'.format( act=file_contents, exp=self.expected_file_contents.pattern)) return False, ('Could not open target file ' + target_filename + ' for reading') class ValidAssemblyFile(SuccessfulReturn, CorrectAssemblyFilePreamble): """Mixin class for checking that every input file generates a valid assembly file following the assembly file naming rule, and there is no output on stdout/stderr.""" def check_assembly_file_preamble(self, status): for input_filename in status.input_filenames: assembly_filename = get_assembly_filename(input_filename) success, message = self.verify_assembly_file_preamble( os.path.join(status.directory, assembly_filename)) if not success: return False, message return True, '' class ValidAssemblyFileWithSubstr(ValidAssemblyFile): """Mixin class for checking that every input file generates a valid assembly file following the assembly file naming rule, there is no output on stdout/stderr, and all assembly files have the given substring specified by expected_assembly_substr. To mix in this class, subclasses need to provde expected_assembly_substr as the expected substring. """ def check_assembly_with_substr(self, status): for input_filename in status.input_filenames: assembly_filename = get_assembly_filename(input_filename) success, message = self.verify_assembly_file_preamble( os.path.join(status.directory, assembly_filename)) if not success: return False, message with open(assembly_filename, 'r') as f: content = f.read() if self.expected_assembly_substr not in convert_to_unix_line_endings(content): return False, ('Incorrect assembly output:\n{asm}\n' 'Expected substring not found:\n{exp}'.format( asm=content, exp=self.expected_assembly_substr)) return True, '' class ValidAssemblyFileWithoutSubstr(ValidAssemblyFile): """Mixin class for checking that every input file generates a valid assembly file following the assembly file naming rule, there is no output on stdout/stderr, and no assembly files have the given substring specified by unexpected_assembly_substr. To mix in this class, subclasses need to provde unexpected_assembly_substr as the substring we expect not to see. """ def check_assembly_for_substr(self, status): for input_filename in status.input_filenames: assembly_filename = get_assembly_filename(input_filename) success, message = self.verify_assembly_file_preamble( os.path.join(status.directory, assembly_filename)) if not success: return False, message with open(assembly_filename, 'r') as f: content = f.read() if self.unexpected_assembly_substr in convert_to_unix_line_endings(content): return False, ('Incorrect assembly output:\n{asm}\n' 'Unexpected substring found:\n{unexp}'.format( asm=content, exp=self.unexpected_assembly_substr)) return True, '' class ValidNamedAssemblyFile(SuccessfulReturn, CorrectAssemblyFilePreamble): """Mixin class for checking that a list of assembly files with the given names are correctly generated, and there is no output on stdout/stderr. To mix in this class, subclasses need to provide expected_assembly_filenames as the expected assembly filenames. """ def check_object_file_preamble(self, status): for assembly_filename in self.expected_assembly_filenames: success, message = self.verify_assembly_file_preamble( os.path.join(status.directory, assembly_filename)) if not success: return False, message return True, '' class ErrorMessage(GlslCTest): """Mixin class for tests that fail with a specific error message. To mix in this class, subclasses need to provide expected_error as the expected error message. The test should fail if the subprocess was terminated by a signal. """ def check_has_error_message(self, status): if not status.returncode: return False, ('Expected error message, but returned success from ' 'glslc') if status.returncode < 0: # On Unix, a negative value -N for Popen.returncode indicates # termination by signal N. # https://docs.python.org/2/library/subprocess.html return False, ('Expected error message, but glslc was terminated by ' 'signal ' + str(status.returncode)) if not status.stderr: return False, 'Expected error message, but no output on stderr' if self.expected_error != convert_to_unix_line_endings(convert_to_string(status.stderr)): return False, ('Incorrect stderr output:\n{act}\n' 'Expected:\n{exp}'.format( act=status.stderr, exp=self.expected_error)) return True, '' class ErrorMessageSubstr(GlslCTest): """Mixin class for tests that fail with a specific substring in the error message. To mix in this class, subclasses need to provide expected_error_substr as the expected error message substring. The test should fail if the subprocess was terminated by a signal. """ def check_has_error_message_as_substring(self, status): if not status.returncode: return False, ('Expected error message, but returned success from ' 'glslc') if status.returncode < 0: # On Unix, a negative value -N for Popen.returncode indicates # termination by signal N. # https://docs.python.org/2/library/subprocess.html return False, ('Expected error message, but glslc was terminated by ' 'signal ' + str(status.returncode)) if not status.stderr: return False, 'Expected error message, but no output on stderr' if self.expected_error_substr not in convert_to_unix_line_endings(convert_to_string(status.stderr)): return False, ('Incorrect stderr output:\n{act}\n' 'Expected substring not found in stderr:\n{exp}'.format( act=status.stderr, exp=self.expected_error_substr)) return True, '' class WarningMessage(GlslCTest): """Mixin class for tests that succeed but have a specific warning message. To mix in this class, subclasses need to provide expected_warning as the expected warning message. """ def check_has_warning_message(self, status): if status.returncode: return False, ('Expected warning message, but returned failure from' ' glslc') if not status.stderr: return False, 'Expected warning message, but no output on stderr' if self.expected_warning != convert_to_unix_line_endings(convert_to_string(status.stderr)): return False, ('Incorrect stderr output:\n{act}\n' 'Expected:\n{exp}'.format( act=status.stderr, exp=self.expected_warning)) return True, '' class ValidObjectFileWithWarning( NoOutputOnStdout, CorrectObjectFilePreamble, WarningMessage): """Mixin class for checking that every input file generates a valid object file following the object file naming rule, with a specific warning message. """ def check_object_file_preamble(self, status): for input_filename in status.input_filenames: object_filename = get_object_filename(input_filename) success, message = self.verify_object_file_preamble( os.path.join(status.directory, object_filename)) if not success: return False, message return True, '' class ValidAssemblyFileWithWarning( NoOutputOnStdout, CorrectAssemblyFilePreamble, WarningMessage): """Mixin class for checking that every input file generates a valid assembly file following the assembly file naming rule, with a specific warning message.""" def check_assembly_file_preamble(self, status): for input_filename in status.input_filenames: assembly_filename = get_assembly_filename(input_filename) success, message = self.verify_assembly_file_preamble( os.path.join(status.directory, assembly_filename)) if not success: return False, message return True, '' class StdoutMatch(GlslCTest): """Mixin class for tests that can expect output on stdout. To mix in this class, subclasses need to provide expected_stdout as the expected stdout output. For expected_stdout, if it's True, then they expect something on stdout but will not check what it is. If it's a string, expect an exact match. If it's anything else, expect expected_stdout.search(stdout) to be true. """ def check_stdout_match(self, status): # "True" in this case means we expect something on stdout, but we do not # care what it is, we want to distinguish this from "blah" which means we # expect exactly the string "blah". if self.expected_stdout is True: if not status.stdout: return False, 'Expected something on stdout' elif type(self.expected_stdout) == str: if self.expected_stdout != convert_to_unix_line_endings( convert_to_string(status.stdout)): return False, ('Incorrect stdout output:\n{ac}\n' 'Expected:\n{ex}'.format( ac=status.stdout, ex=self.expected_stdout)) else: if not self.expected_stdout.search(convert_to_unix_line_endings( convert_to_string(status.stdout))): return False, ('Incorrect stdout output:\n{ac}\n' 'Expected to match regex:\n{ex}'.format( ac=convert_to_string(status.stdout), ex=self.expected_stdout.pattern)) return True, '' class StderrMatch(GlslCTest): """Mixin class for tests that can expect output on stderr. To mix in this class, subclasses need to provide expected_stderr as the expected stderr output. For expected_stderr, if it's True, then they expect something on stderr, but will not check what it is. If it's a string, expect an exact match. """ def check_stderr_match(self, status): # "True" in this case means we expect something on stderr, but we do not # care what it is, we want to distinguish this from "blah" which means we # expect exactly the string "blah". if self.expected_stderr is True: if not status.stderr: return False, 'Expected something on stderr' else: if self.expected_stderr != convert_to_unix_line_endings( convert_to_string(status.stderr)): return False, ('Incorrect stderr output:\n{ac}\n' 'Expected:\n{ex}'.format( ac=status.stderr, ex=self.expected_stderr)) return True, '' class StdoutNoWiderThan80Columns(GlslCTest): """Mixin class for tests that require stdout to 80 characters or narrower. To mix in this class, subclasses need to provide expected_stdout as the expected stdout output. """ def check_stdout_not_too_wide(self, status): if not status.stdout: return True, '' else: for line in status.stdout.splitlines(): if len(line) > 80: return False, ('Stdout line longer than 80 columns: %s' % line) return True, '' class NoObjectFile(GlslCTest): """Mixin class for checking that no input file has a corresponding object file.""" def check_no_object_file(self, status): for input_filename in status.input_filenames: object_filename = get_object_filename(input_filename) full_object_file = os.path.join(status.directory, object_filename) print("checking %s" % full_object_file) if os.path.isfile(full_object_file): return False, ('Expected no object file, but found: %s' % full_object_file) return True, '' class NoNamedOutputFiles(GlslCTest): """Mixin class for checking that no specified output files exist. The expected_output_filenames member should be full pathnames.""" def check_no_named_output_files(self, status): for object_filename in self.expected_output_filenames: if os.path.isfile(object_filename): return False, ('Expected no output file, but found: %s' % object_filename) return True, '' shaderc-2025.2/glslc/test/expect_unittest.py000066400000000000000000000057511500222170200211000ustar00rootroot00000000000000# Copyright 2019 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for the expect module.""" import expect from glslc_test_framework import TestStatus import re import unittest class TestStdoutMatchADotC(expect.StdoutMatch): expected_stdout = re.compile('a.c') class TestExpect(unittest.TestCase): def test_get_object_name(self): """Tests get_object_filename().""" source_and_object_names = [('a.vert', 'a.vert.spv'), ('b.frag', 'b.frag.spv'), ('c.tesc', 'c.tesc.spv'), ('d.tese', 'd.tese.spv'), ('e.geom', 'e.geom.spv'), ('f.comp', 'f.comp.spv'), ('file', 'file.spv'), ('file.', 'file.spv'), ('file.uk', 'file.spv'), ('file.vert.', 'file.vert.spv'), ('file.vert.bla', 'file.vert.spv')] actual_object_names = [ expect.get_object_filename(f[0]) for f in source_and_object_names ] expected_object_names = [f[1] for f in source_and_object_names] self.assertEqual(actual_object_names, expected_object_names) def test_stdout_match_regex_has_match(self): test = TestStdoutMatchADotC() status = TestStatus( test_manager=None, returncode=0, stdout=b'0abc1', stderr=None, directory=None, inputs=None, input_filenames=None) self.assertTrue(test.check_stdout_match(status)[0]) def test_stdout_match_regex_no_match(self): test = TestStdoutMatchADotC() status = TestStatus( test_manager=None, returncode=0, stdout=b'ab', stderr=None, directory=None, inputs=None, input_filenames=None) self.assertFalse(test.check_stdout_match(status)[0]) def test_stdout_match_regex_empty_stdout(self): test = TestStdoutMatchADotC() status = TestStatus( test_manager=None, returncode=0, stdout=b'', stderr=None, directory=None, inputs=None, input_filenames=None) self.assertFalse(test.check_stdout_match(status)[0]) shaderc-2025.2/glslc/test/file_extensions.py000066400000000000000000000055251500222170200210460ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import GlslCTest, inside_glslc_testsuite from placeholder import FileShader def empty_es_310_shader(): return '#version 310 es\n void main() {}\n' @inside_glslc_testsuite('FileExtension') class VerifyVertExtension(expect.ValidObjectFile): """Tests glslc accepts vertex shader extension (.vert).""" shader = FileShader(empty_es_310_shader(), '.vert') glslc_args = ['-c', shader] @inside_glslc_testsuite('FileExtension') class VerifyFragExtension(expect.ValidObjectFile): """Tests glslc accepts fragment shader extension (.frag).""" shader = FileShader(empty_es_310_shader(), '.frag') glslc_args = ['-c', shader] @inside_glslc_testsuite('FileExtension') class VerifyTescExtension(expect.ValidObjectFile): """Tests glslc accepts tessellation control shader extension (.tesc).""" shader = FileShader( '#version 440 core\n layout(vertices = 3) out;\n void main() {}', '.tesc') glslc_args = ['-c', shader] @inside_glslc_testsuite('FileExtension') class VerifyTeseExtension(expect.ValidObjectFile): """Tests glslc accepts tessellation evaluation shader extension (.tese).""" shader = FileShader( '#version 440 core\n layout(triangles) in;\n void main() {}', '.tese') glslc_args = ['-c', shader] @inside_glslc_testsuite('FileExtension') class VerifyGeomExtension(expect.ValidObjectFile): """Tests glslc accepts geomtry shader extension (.geom).""" shader = FileShader( '#version 150 core\n layout (triangles) in;\n' 'layout (line_strip, max_vertices = 4) out;\n void main() {}', '.geom') glslc_args = ['-c', shader] @inside_glslc_testsuite('FileExtension') class VerifyCompExtension(expect.ValidObjectFile): """Tests glslc accepts compute shader extension (.comp).""" shader = FileShader(empty_es_310_shader(), '.comp') glslc_args = ['-c', shader] @inside_glslc_testsuite('FileExtension') class InvalidExtension(expect.ErrorMessage): """Tests the error message if a file extension cannot be determined.""" shader = FileShader('#version 150\n', '.fraga') glslc_args = ['-c', shader] expected_error = [ "glslc: error: '", shader, "': file not recognized: File format not recognized\n"] shaderc-2025.2/glslc/test/glslc_test_framework.py000077500000000000000000000336541500222170200220770ustar00rootroot00000000000000#!/usr/bin/env python # Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Manages and runs tests from the current working directory. This will traverse the current working directory and look for python files that contain subclasses of GlslCTest. If a class has an @inside_glslc_testsuite decorator, an instance of that class will be created and serve as a test case in that testsuite. The test case is then run by the following steps: 1. A temporary directory will be created. 2. The glslc_args member variable will be inspected and all placeholders in it will be expanded by calling instantiate_for_glslc_args() on placeholders. The transformed list elements are then supplied as glslc arguments. 3. If the environment member variable exists, its write() method will be invoked. 4. All expected_* member variables will be inspected and all placeholders in them will be expanded by calling instantiate_for_expectation() on those placeholders. After placeholder expansion, if the expected_* variable is a list, its element will be joined together with '' to form a single string. These expected_* variables are to be used by the check_*() methods. 5. glslc will be run with the arguments supplied in glslc_args. 6. All check_*() member methods will be called by supplying a TestStatus as argument. Each check_*() method is expected to return a (Success, Message) pair where Success is a boolean indicating success and Message is an error message. 7. If any check_*() method fails, the error message is outputted and the current test case fails. If --leave-output was not specified, all temporary files and directories will be deleted. """ import argparse import fnmatch import inspect import os import shutil import subprocess import sys import tempfile from collections import defaultdict from placeholder import PlaceHolder EXPECTED_BEHAVIOR_PREFIX = 'expected_' VALIDATE_METHOD_PREFIX = 'check_' def get_all_variables(instance): """Returns the names of all the variables in instance.""" return [v for v in dir(instance) if not callable(getattr(instance, v))] def get_all_methods(instance): """Returns the names of all methods in instance.""" return [m for m in dir(instance) if callable(getattr(instance, m))] def get_all_superclasses(cls): """Returns all superclasses of a given class. Omits root 'object' superclass. Returns: A list of superclasses of the given class. The order guarantees that * A Base class precedes its derived classes, e.g., for "class B(A)", it will be [..., A, B, ...]. * When there are multiple base classes, base classes declared first precede those declared later, e.g., for "class C(A, B), it will be [..., A, B, C, ...] """ classes = [] for superclass in cls.__bases__: for c in get_all_superclasses(superclass): if c is not object and c not in classes: classes.append(c) for superclass in cls.__bases__: if superclass is not object and superclass not in classes: classes.append(superclass) return classes def get_all_test_methods(test_class): """Gets all validation methods. Returns: A list of validation methods. The order guarantees that * A method defined in superclass precedes one defined in subclass, e.g., for "class A(B)", methods defined in B precedes those defined in A. * If a subclass has more than one superclass, e.g., "class C(A, B)", then methods defined in A precedes those defined in B. """ classes = get_all_superclasses(test_class) classes.append(test_class) all_tests = [m for c in classes for m in get_all_methods(c) if m.startswith(VALIDATE_METHOD_PREFIX)] unique_tests = [] for t in all_tests: if t not in unique_tests: unique_tests.append(t) return unique_tests class GlslCTest: """Base class for glslc test cases. Subclasses define test cases' facts (shader source code, glslc command, result validation), which will be used by the TestCase class for running tests. Subclasses should define glslc_args (specifying glslc command arguments), and at least one check_*() method (for result validation) for a full-fledged test case. All check_*() methods should take a TestStatus parameter and return a (Success, Message) pair, in which Success is a boolean indicating success and Message is an error message. The test passes iff all check_*() methods returns true. Often, a test case class will delegate the check_* behaviors by inheriting from other classes. """ def name(self): return self.__class__.__name__ class TestStatus: """A struct for holding run status of a test case.""" def __init__(self, test_manager, returncode, stdout, stderr, directory, inputs, input_filenames): self.test_manager = test_manager self.returncode = returncode self.stdout = stdout self.stderr = stderr # temporary directory where the test runs self.directory = directory # List of inputs, as PlaceHolder objects. self.inputs = inputs # the names of input shader files (potentially including paths) self.input_filenames = input_filenames class GlslCTestException(Exception): """GlslCTest exception class.""" pass def inside_glslc_testsuite(testsuite_name): """Decorator for subclasses of GlslCTest. This decorator checks that a class meets the requirements (see below) for a test case class, and then puts the class in a certain testsuite. * The class needs to be a subclass of GlslCTest. * The class needs to have glslc_args defined as a list. * The class needs to define at least one check_*() methods. * All expected_* variables required by check_*() methods can only be of bool, str, or list type. * Python runtime will throw an exception if the expected_* member attributes required by check_*() methods are missing. """ def actual_decorator(cls): if not inspect.isclass(cls): raise GlslCTestException('Test case should be a class') if not issubclass(cls, GlslCTest): raise GlslCTestException( 'All test cases should be subclasses of GlslCTest') if 'glslc_args' not in get_all_variables(cls): raise GlslCTestException('No glslc_args found in the test case') if not isinstance(cls.glslc_args, list): raise GlslCTestException('glslc_args needs to be a list') if not any([ m.startswith(VALIDATE_METHOD_PREFIX) for m in get_all_methods(cls)]): raise GlslCTestException( 'No check_*() methods found in the test case') if not all([ isinstance(v, (bool, str, list)) for v in get_all_variables(cls)]): raise GlslCTestException( 'expected_* variables are only allowed to be bool, str, or ' 'list type.') cls.parent_testsuite = testsuite_name return cls return actual_decorator class TestManager: """Manages and runs a set of tests.""" def __init__(self, executable_path, disassembler_path): self.executable_path = executable_path self.disassembler_path = disassembler_path self.num_successes = 0 self.num_failures = 0 self.num_tests = 0 self.leave_output = False self.tests = defaultdict(list) def notify_result(self, test_case, success, message): """Call this to notify the manager of the results of a test run.""" self.num_successes += 1 if success else 0 self.num_failures += 0 if success else 1 counter_string = str( self.num_successes + self.num_failures) + '/' + str(self.num_tests) print('%-10s %-40s ' % (counter_string, test_case.test.name()) + ('Passed' if success else '-Failed-')) if not success: print(' '.join(test_case.command)) print(message) def add_test(self, testsuite, test): """Add this to the current list of test cases.""" self.tests[testsuite].append(TestCase(test, self)) self.num_tests += 1 def run_tests(self): for suite in self.tests: print('Glslc test suite: "{suite}"'.format(suite=suite)) for x in self.tests[suite]: x.runTest() class TestCase: """A single test case that runs in its own directory.""" def __init__(self, test, test_manager): self.test = test self.test_manager = test_manager self.inputs = [] # inputs, as PlaceHolder objects. self.file_shaders = [] # filenames of shader files. self.stdin_shader = None # text to be passed to glslc as stdin def setUp(self): """Creates environment and instantiates placeholders for the test case.""" self.directory = tempfile.mkdtemp(dir=os.getcwd()) glslc_args = self.test.glslc_args # Instantiate placeholders in glslc_args self.test.glslc_args = [ arg.instantiate_for_glslc_args(self) if isinstance(arg, PlaceHolder) else arg for arg in self.test.glslc_args] # Get all shader files' names self.inputs = [arg for arg in glslc_args if isinstance(arg, PlaceHolder)] self.file_shaders = [arg.filename for arg in self.inputs] if 'environment' in get_all_variables(self.test): self.test.environment.write(self.directory) expectations = [v for v in get_all_variables(self.test) if v.startswith(EXPECTED_BEHAVIOR_PREFIX)] # Instantiate placeholders in expectations for expectation_name in expectations: expectation = getattr(self.test, expectation_name) if isinstance(expectation, list): expanded_expections = [ element.instantiate_for_expectation(self) if isinstance(element, PlaceHolder) else element for element in expectation] setattr( self.test, expectation_name, ''.join(expanded_expections)) elif isinstance(expectation, PlaceHolder): setattr(self.test, expectation_name, expectation.instantiate_for_expectation(self)) def tearDown(self): """Removes the directory if we were not instructed to do otherwise.""" if not self.test_manager.leave_output: shutil.rmtree(self.directory) def runTest(self): """Sets up and runs a test, reports any failures and then cleans up.""" self.setUp() success = False message = '' try: self.command = [self.test_manager.executable_path] self.command.extend(self.test.glslc_args) process = subprocess.Popen( args=self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.directory) output = process.communicate(self.stdin_shader) test_status = TestStatus( self.test_manager, process.returncode, output[0], output[1], self.directory, self.inputs, self.file_shaders) run_results = [getattr(self.test, test_method)(test_status) for test_method in get_all_test_methods( self.test.__class__)] success, message = list(zip(*run_results)) success = all(success) message = '\n'.join(message) except Exception as e: success = False message = str(e) self.test_manager.notify_result(self, success, message) self.tearDown() def main(): parser = argparse.ArgumentParser() parser.add_argument('glslc', metavar='path/to/glslc', type=str, nargs=1, help='Path to glslc') parser.add_argument('spirvdis', metavar='path/to/glslc', type=str, nargs=1, help='Path to spirv-dis') parser.add_argument('--leave-output', action='store_const', const=1, help='Do not clean up temporary directories') parser.add_argument('--test-dir', nargs=1, help='Directory to gather the tests from') args = parser.parse_args() default_path = sys.path root_dir = os.getcwd() if args.test_dir: root_dir = args.test_dir[0] manager = TestManager(args.glslc[0], args.spirvdis[0]) if args.leave_output: manager.leave_output = True for root, _, filenames in os.walk(root_dir): for filename in fnmatch.filter(filenames, '*.py'): if filename.endswith('unittest.py'): # Skip unit tests, which are for testing functions of # the test framework. continue sys.path = default_path sys.path.append(root) try: mod = __import__(os.path.splitext(filename)[0]) for _, obj, in inspect.getmembers(mod): if inspect.isclass(obj) and hasattr(obj, 'parent_testsuite'): manager.add_test(obj.parent_testsuite, obj()) except: print("Failed to load " + filename) raise manager.run_tests() if manager.num_failures > 0: sys.exit(-1) if __name__ == '__main__': main() shaderc-2025.2/glslc/test/glslc_test_framework_unittest.py000066400000000000000000000074171500222170200240310ustar00rootroot00000000000000# Copyright 2019 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for the glslc_test_framework module.""" from glslc_test_framework import get_all_test_methods, get_all_superclasses import unittest # Classes to be used in testing get_all_{superclasses|test_methods}() class Root: def check_root(self): pass class A(Root): def check_a(self): pass class B(Root): def check_b(self): pass class C(Root): def check_c(self): pass class D(Root): def check_d(self): pass class E(Root): def check_e(self): pass class H(B, C, D): def check_h(self): pass class I(E): def check_i(self): pass class O(H, I): def check_o(self): pass class U(A, O): def check_u(self): pass class X(U, A): def check_x(self): pass class R1: def check_r1(self): pass class R2: def check_r2(self): pass class Multi(R1, R2): def check_multi(self): pass class TestSpirvTestFramework(unittest.TestCase): def test_get_all_superclasses(self): self.assertEqual(get_all_superclasses(A), [Root]) self.assertEqual(get_all_superclasses(B), [Root]) self.assertEqual(get_all_superclasses(C), [Root]) self.assertEqual(get_all_superclasses(D), [Root]) self.assertEqual(get_all_superclasses(E), [Root]) self.assertEqual(get_all_superclasses(H), [Root, B, C, D]) self.assertEqual(get_all_superclasses(I), [Root, E]) self.assertEqual(get_all_superclasses(O), [Root, B, C, D, E, H, I]) self.assertEqual(get_all_superclasses( U), [Root, B, C, D, E, H, I, A, O]) self.assertEqual(get_all_superclasses( X), [Root, B, C, D, E, H, I, A, O, U]) self.assertEqual(get_all_superclasses(Multi), [R1, R2]) def test_get_all_methods(self): self.assertEqual(get_all_test_methods(A), ['check_root', 'check_a']) self.assertEqual(get_all_test_methods(B), ['check_root', 'check_b']) self.assertEqual(get_all_test_methods(C), ['check_root', 'check_c']) self.assertEqual(get_all_test_methods(D), ['check_root', 'check_d']) self.assertEqual(get_all_test_methods(E), ['check_root', 'check_e']) self.assertEqual( get_all_test_methods(H), ['check_root', 'check_b', 'check_c', 'check_d', 'check_h']) self.assertEqual(get_all_test_methods( I), ['check_root', 'check_e', 'check_i']) self.assertEqual( get_all_test_methods(O), [ 'check_root', 'check_b', 'check_c', 'check_d', 'check_e', 'check_h', 'check_i', 'check_o' ]) self.assertEqual( get_all_test_methods(U), [ 'check_root', 'check_b', 'check_c', 'check_d', 'check_e', 'check_h', 'check_i', 'check_a', 'check_o', 'check_u' ]) self.assertEqual( get_all_test_methods(X), [ 'check_root', 'check_b', 'check_c', 'check_d', 'check_e', 'check_h', 'check_i', 'check_a', 'check_o', 'check_u', 'check_x' ]) self.assertEqual( get_all_test_methods(Multi), ['check_r1', 'check_r2', 'check_multi'])shaderc-2025.2/glslc/test/include.py000066400000000000000000000346101500222170200172700ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import SpecializedString from environment import File, Directory @inside_glslc_testsuite('Include') class VerifyIncludeOneSibling(expect.StdoutMatch): """Tests #including a sibling file.""" environment = Directory('.', [ File('a.vert', '#version 140\ncontent a\n#include "b"\n'), File('b', 'content b\n')]) glslc_args = ['-E', 'a.vert'] expected_stdout = \ """#version 140 #extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" content a #line 0 "b" content b #line 3 "a.vert" """ @inside_glslc_testsuite('Include') class VerifyIncludeNotFound(expect.ErrorMessage): """Tests #including a not existing sibling file.""" environment = Directory('.', [ File('a.vert', '#version 140\ncontent a\n#include "b"\n')]) glslc_args = ['-E', 'a.vert'] expected_error = [ "a.vert:3: error: '#include' : Cannot find or open include file. for header name: b\n", '1 error generated.\n' ] @inside_glslc_testsuite('Include') class VerifyCompileIncludeOneSibling(expect.ValidObjectFile): """Tests #including a sibling file via full compilation.""" environment = Directory('.', [ File('a.vert', '#version 140\nvoid foo(){}\n#include "b"\n'), File('b', 'void main(){foo();}\n')]) glslc_args = ['a.vert'] @inside_glslc_testsuite('Include') class VerifyIncludeWithoutNewline(expect.ErrorMessageSubstr): """Tests a #include without a newline.""" environment = Directory('.', [ File('a.vert', '#version 140\n#include "b"'), File('b', 'content b\n')]) glslc_args = ['-E', 'a.vert'] expected_error_substr = 'expected newline after header name: b' @inside_glslc_testsuite('Include') class VerifyCompileIncludeWithoutNewline(expect.ValidObjectFile): """Tests a #include without a newline via full compilation.""" environment = Directory('.', [ File('a.vert', """#version 140 void main #include "b" """), File('b', """#define PAR () PAR{} """)]) glslc_args = ['a.vert'] @inside_glslc_testsuite('Include') class VerifyIncludeTwoSiblings(expect.StdoutMatch): """Tests #including two sibling files.""" environment = Directory('.', [ File('b.vert', '#version 140\n#include "a"\ncontent b\n#include "c"\n'), File('a', 'content a\n'), File('c', 'content c\n')]) glslc_args = ['-E', 'b.vert'] expected_stdout = \ """#version 140 #extension GL_GOOGLE_include_directive : enable #line 0 "b.vert" #line 0 "a" content a #line 2 "b.vert" content b #line 0 "c" content c #line 4 "b.vert" """ @inside_glslc_testsuite('Include') class VerifyCompileIncludeTwoSiblings(expect.ValidObjectFile): """Tests #including two sibling files via full compilation.""" environment = Directory('.', [ File('b.vert', """#version 140 #include "a" void bfun(){afun();} #include "c" """), File('a', """void afun(){} #define BODY {} """), File('c', 'void main() BODY\n')]) glslc_args = ['b.vert'] @inside_glslc_testsuite('Include') class VerifyNestedIncludeAmongSiblings(expect.StdoutMatch): """Tests #include inside #included sibling files.""" environment = Directory('.', [ File('a.vert', '#version 140\n#include "b"\ncontent a\n'), File('b', 'content b\n#include "c"\n'), File('c', 'content c\n')]) glslc_args = ['-E', 'a.vert'] expected_stdout = \ """#version 140 #extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" #line 0 "b" content b #line 0 "c" content c #line 2 "b" #line 2 "a.vert" content a """ @inside_glslc_testsuite('Include') class VerifyCompileNestedIncludeAmongSiblings(expect.ValidObjectFile): """Tests #include inside #included sibling files via full compilation.""" environment = Directory('.', [ File('a.vert', """#version 140 #define BODY {} #include "b" void main(){cfun();} """), File('b', """void bfun() BODY #include "c" """), File('c', """#define BF bfun() void cfun(){BF;} """)]) glslc_args = ['a.vert'] @inside_glslc_testsuite('Include') class VerifyIncludeSubdir(expect.StdoutMatch): """Tests #including a file from a subdirectory.""" environment = Directory('.', [ File('a.vert', '#version 140\ncontent a1\n#include "subdir/a"\ncontent a2\n'), Directory('subdir', [File('a', 'content suba\n')])]) glslc_args = ['-E', 'a.vert'] expected_stdout = \ """#version 140 #extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" content a1 #line 0 "subdir/a" content suba #line 3 "a.vert" content a2 """ @inside_glslc_testsuite('Include') class VerifyCompileIncludeSubdir(expect.ValidObjectFile): """Tests #including a file from a subdirectory via full compilation.""" environment = Directory('.', [ File('a.vert', """#version 140 #define BODY {} #include "subdir/a" void afun()BODY """), Directory('subdir', [File('a', 'void main() BODY\n')])]) glslc_args = ['a.vert'] @inside_glslc_testsuite('Include') class VerifyIncludeDeepSubdir(expect.StdoutMatch): """Tests #including a file from a subdirectory nested a few levels down.""" environment = Directory('.', [ File('a.vert', '#version 140\ncontent a1\n#include "dir/subdir/subsubdir/a"\ncontent a2\n'), Directory('dir', [ Directory('subdir', [ Directory('subsubdir', [File('a', 'content incl\n')])])])]) glslc_args = ['-E', 'a.vert'] expected_stdout = \ """#version 140 #extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" content a1 #line 0 "dir/subdir/subsubdir/a" content incl #line 3 "a.vert" content a2 """ @inside_glslc_testsuite('Include') class VerifyCompileIncludeDeepSubdir(expect.ValidObjectFile): """Tests #including a file from a subdirectory nested a few levels down via full compilation.""" environment = Directory('.', [ File('a.vert', """#version 140 #define BODY {} #include "dir/subdir/subsubdir/a" void afun()BODY """), Directory('dir', [ Directory('subdir', [ Directory('subsubdir', [File('a', 'void main() BODY\n')])])])]) glslc_args = ['a.vert'] @inside_glslc_testsuite('Include') class TestWrongPoundVersionInIncludingFile(expect.ValidObjectFileWithWarning): """Tests that warning message for #version directive in the including file has the correct filename.""" environment = Directory('.', [ File('a.vert', '#version 100000000\n#include "b.glsl"\n'), File('b.glsl', 'void main() {}\n')]) glslc_args = ['-c', '-std=400', 'a.vert'] expected_warning = [ 'a.vert: warning: (version, profile) forced to be (400, none),' ' while in source code it is (100000000, none)\n' '1 warning generated.\n' ] # TODO(antiagainst): now #version in included files results in an error. # Fix this after #version in included files are supported. # TODO(dneto): I'm not sure what the expected result should be. @inside_glslc_testsuite('Include') class TestWrongPoundVersionInIncludedFile(expect.ErrorMessage): """Tests that warning message for #version directive in the included file has the correct filename.""" environment = Directory('.', [ File('a.vert', '#version 140\n#include "b.glsl"\nvoid main() {}'), File('b.glsl', '#version 10000000\n')]) glslc_args = ['-E', 'a.vert'] expected_error = [ "b.glsl:1: error: '#version' : must occur first in shader\n", '1 error generated.\n' ] @inside_glslc_testsuite('Include') class VerifyRelativeInclude(expect.StdoutMatch): """Tests #including a relative sibling.""" environment = Directory('.', [ File('a.vert', '#version 140\ncontent a\n#include "foo/b.glsl"\n'), Directory('foo', [ File('b.glsl', '#include "c.glsl"\ncontent b\n'), File('c.glsl', 'content c\n') ])]) glslc_args = ['-E', 'a.vert'] expected_stdout = \ """#version 140 #extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" content a #line 0 "foo/b.glsl" #line 0 "foo/c.glsl" content c #line 1 "foo/b.glsl" content b #line 3 "a.vert" """ @inside_glslc_testsuite('Include') class VerifyNestedRelativeInclude(expect.StdoutMatch): """Tests #including a relative child file.""" environment = Directory('.', [ File('a.vert', '#version 140\ncontent a\n#include "foo/b.glsl"\n'), Directory('foo', [ File('b.glsl', '#include "bar/c.glsl"\ncontent b\n'), Directory('bar', [ File('c.glsl', 'content c\n') ]) ]) ]) glslc_args = ['-E', 'a.vert'] expected_stdout = \ """#version 140 #extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" content a #line 0 "foo/b.glsl" #line 0 "foo/bar/c.glsl" content c #line 1 "foo/b.glsl" content b #line 3 "a.vert" """ @inside_glslc_testsuite('Include') class VerifyRelativeIncludeWithDashI(expect.StdoutMatch): """Tests #including a relative file from a -I directory.""" environment = Directory('.', [ File('a.vert', '#version 140\ncontent a\n#include "bar/b.glsl"\n'), Directory('foo', [ Directory('bar', [ File('b.glsl', '#include "c.glsl"\ncontent b\n'), ]), File('c.glsl', 'content c\n') ]) ]) glslc_args = ['-E', 'a.vert', '-Ifoo'] expected_stdout = \ """#version 140 #extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" content a #line 0 "foo/bar/b.glsl" #line 0 "foo/c.glsl" content c #line 1 "foo/bar/b.glsl" content b #line 3 "a.vert" """ @inside_glslc_testsuite('Include') class VerifyRelativeOverridesDashI(expect.StdoutMatch): """Tests that relative includes override -I parameters.""" environment = Directory('.', [ File('a.vert', '#version 140\ncontent a\n#include "b.glsl"\n'), File('b.glsl', 'content base_b\n'), Directory('foo', [ File('b.glsl', '#include "c.glsl"\ncontent b\n'), File('c.glsl', 'content c\n') ]) ]) glslc_args = ['-E', 'a.vert', '-Ifoo'] expected_stdout = \ """#version 140 #extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" content a #line 0 "b.glsl" content base_b #line 3 "a.vert" """ @inside_glslc_testsuite('Include') class VerifyRelativeParent(expect.StdoutMatch): """Tests #including a parent file.""" environment = Directory('.', [ File('a.vert', '#version 140\ncontent a\n#include "b.glsl"\n'), File('c.glsl', 'content c\n'), Directory('foo', [ File('b.glsl', '#include "../c.glsl"\ncontent b\n') ]) ]) glslc_args = ['-E', 'a.vert', '-Ifoo'] expected_stdout = \ """#version 140 #extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" content a #line 0 "foo/b.glsl" #line 0 "foo/../c.glsl" content c #line 1 "foo/b.glsl" content b #line 3 "a.vert" """ @inside_glslc_testsuite('Include') class VerifyRelativeNeighbourDirectory(expect.StdoutMatch): """Tests #including a relative file in a neighbour directory.""" environment = Directory('.', [ File('a.vert', '#version 140\ncontent a\n#include "foo/b.glsl"\n'), Directory('foo', [ File('b.glsl', '#include "../bar/c.glsl"\ncontent b\n') ]), Directory('bar', [ File('c.glsl', 'content c\n') ]) ]) glslc_args = ['-E', 'a.vert'] expected_stdout = \ """#version 140 #extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" content a #line 0 "foo/b.glsl" #line 0 "foo/../bar/c.glsl" content c #line 1 "foo/b.glsl" content b #line 3 "a.vert" """ @inside_glslc_testsuite('Include') class VerifyRelativeOnlyToSelf(expect.ErrorMessage): """Tests that a relative includes are only relative to yourself.""" environment = Directory('.', [ File('a.vert', '#version 140\ncontent a\n#include "foo/b.glsl"\n'), File('c.glsl', 'content c\n'), Directory('foo', [ File('b.glsl', '#include "c.glsl"\ncontent b\n') ]), ]) glslc_args = ['-E', 'a.vert'] expected_error = [ "foo/b.glsl:1: error: '#include' : " 'Cannot find or open include file. for header name: c.glsl\n', '1 error generated.\n' ] @inside_glslc_testsuite('Include') class VerifyRelativeFromAbsolutePath(expect.StdoutMatch): """Tests that absolute files can relatively include.""" environment = Directory('.', [ File('a.vert', '#version 140\ncontent a\n#include "b.glsl"\n'), File('b.glsl', 'content b\n') ]) glslc_args = ['-E', SpecializedString('$directory/a.vert')] expected_stdout = SpecializedString( """#version 140 #extension GL_GOOGLE_include_directive : enable #line 0 "$directory/a.vert" content a #line 0 "$directory/b.glsl" content b #line 3 "$directory/a.vert" """) @inside_glslc_testsuite('Include') class VerifyDashIAbsolutePath(expect.StdoutMatch): """Tests that -I parameters can be absolute paths.""" environment = Directory('.', [ File('a.vert', '#version 140\ncontent a\n#include "b.glsl"\n'), Directory('foo', { File('b.glsl', 'content b\n') }) ]) glslc_args = ['-E', 'a.vert', '-I', SpecializedString('$directory/foo')] expected_stdout = SpecializedString( """#version 140 #extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" content a #line 0 "$directory/foo/b.glsl" content b #line 3 "a.vert" """) shaderc-2025.2/glslc/test/line.py000066400000000000000000000224071500222170200165750ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from environment import Directory, File from glslc_test_framework import inside_glslc_testsuite @inside_glslc_testsuite('#line') class TestPoundVersion310InIncludingFile( expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch): """Tests that #line directives follows the behavior of version 310 (specifying the line number for the next line) when we find a #version 310 directive in the including file.""" environment = Directory('.', [ File('a.vert', '#version 310 es\n#include "b.glsl"\n'), File('b.glsl', 'void main() {}\n')]) glslc_args = ['-E', 'a.vert'] expected_stderr = '' expected_stdout = \ """#version 310 es #extension GL_GOOGLE_include_directive : enable #line 1 "a.vert" #line 1 "b.glsl" void main() { } #line 3 "a.vert" """ @inside_glslc_testsuite('#line') class TestPoundVersion150InIncludingFile( expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch): """Tests that #line directives follows the behavior of version 150 (specifying the line number for itself) when we find a #version 150 directive in the including file.""" environment = Directory('.', [ File('a.vert', '#version 150\n#include "b.glsl"\n'), File('b.glsl', 'void main() {}\n')]) glslc_args = ['-E', 'a.vert'] expected_stderr = '' expected_stdout = \ """#version 150 #extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" #line 0 "b.glsl" void main() { } #line 2 "a.vert" """ @inside_glslc_testsuite('#line') class TestPoundVersionSyntaxErrorInIncludingFile(expect.ErrorMessageSubstr): """Tests that error message for #version directive has the correct filename and line number.""" environment = Directory('.', [ File('a.vert', '#version abc def\n#include "b.glsl"\n'), File('b.glsl', 'void main() {}\n')]) glslc_args = ['-E', 'a.vert'] expected_error_substr = [ "a.vert:1: error: '#version' : must occur first in shader\n", "a.vert:1: error: '#version' : must be followed by version number\n", "a.vert:1: error: '#version' : bad profile name; use es, core, or " "compatibility\n", ] # TODO(antiagainst): now #version in included files results in an error. # Fix this after #version in included files are supported. @inside_glslc_testsuite('#line') class TestPoundVersion310InIncludedFile(expect.ErrorMessageSubstr): """Tests that #line directives follows the behavior of version 310 (specifying the line number for the next line) when we find a #version 310 directive in the included file.""" environment = Directory('.', [ File('a.vert', '#include "b.glsl"\nvoid main() {}'), File('b.glsl', '#version 310 es\n')]) glslc_args = ['-E', 'a.vert'] expected_error_substr = [ "b.glsl:1: error: '#version' : must occur first in shader\n" ] # TODO(antiagainst): now #version in included files results in an error. # Fix this after #version in included files are supported. @inside_glslc_testsuite('#line') class TestPoundVersion150InIncludedFile(expect.ErrorMessageSubstr): """Tests that #line directives follows the behavior of version 150 (specifying the line number for itself) when we find a #version 150 directive in the included file.""" environment = Directory('.', [ File('a.vert', '#include "b.glsl"\nvoid main() {}'), File('b.glsl', '#version 150\n')]) glslc_args = ['-E', 'a.vert'] expected_error_substr = [ "b.glsl:1: error: '#version' : must occur first in shader\n" ] @inside_glslc_testsuite('#line') class TestSpaceAroundPoundVersion310InIncludingFile( expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch): """Tests that spaces around #version & #include directive doesn't matter.""" environment = Directory('.', [ File('a.vert', '\t # \t version 310 \t es\n#\tinclude "b.glsl"\n'), File('b.glsl', 'void main() {}\n')]) glslc_args = ['-E', 'a.vert'] expected_stderr = '' expected_stdout = \ """#version 310 es #extension GL_GOOGLE_include_directive : enable #line 1 "a.vert" #line 1 "b.glsl" void main() { } #line 3 "a.vert" """ @inside_glslc_testsuite('#line') class TestSpaceAroundPoundVersion150InIncludingFile( expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch): """Tests that spaces around #version & #include directive doesn't matter.""" environment = Directory('.', [ File('a.vert', ' \t #\t\tversion\t 150\t \n# include \t "b.glsl"\n'), File('b.glsl', 'void main() {}\n')]) glslc_args = ['-E', 'a.vert'] expected_stderr = '' expected_stdout = \ """#version 150 #extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" #line 0 "b.glsl" void main() { } #line 2 "a.vert" """ @inside_glslc_testsuite('#line') class TestPoundLineWithForcedVersion310( expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch): """Tests that #line directives follows the behavior for the version specified via command-line.""" environment = Directory('.', [ File('a.vert', '#include "b.glsl"\n'), File('b.glsl', 'void main() {}\n')]) glslc_args = ['-E', '-std=310es', 'a.vert'] expected_stderr = '' expected_stdout = \ """#extension GL_GOOGLE_include_directive : enable #line 1 "a.vert" #line 1 "b.glsl" void main() { } #line 2 "a.vert" """ @inside_glslc_testsuite('#line') class TestPoundLineWithForcedVersion150( expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch): """Tests that #line directives follows the behavior for the version specified via command-line.""" environment = Directory('.', [ File('a.vert', '#include "b.glsl"\n'), File('b.glsl', 'void main() {}\n')]) glslc_args = ['-E', '-std=150', 'a.vert'] expected_stderr = '' expected_stdout = \ """#extension GL_GOOGLE_include_directive : enable #line 0 "a.vert" #line 0 "b.glsl" void main() { } #line 1 "a.vert" """ @inside_glslc_testsuite('#line') class TestPoundLineWithForcedDifferentVersion( expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch): """Tests that #line directives follows the behavior for the version specified via command-line, even if there is a version specification in the source code.""" environment = Directory('.', [ File('a.vert', '#version 150\n#include "b.glsl"\n'), File('b.glsl', 'void main() {}\n')]) glslc_args = ['-E', '-std=310es', 'a.vert'] expected_stderr = '' expected_stdout = \ """#version 150 #extension GL_GOOGLE_include_directive : enable #line 1 "a.vert" #line 1 "b.glsl" void main() { } #line 3 "a.vert" """ @inside_glslc_testsuite('#line') class TestErrorsFromMultipleFiles(expect.ErrorMessage): """Tests that errors from different files have the correct error message filename specification.""" including_file = '''#version 310 es #include "error.glsl" int no_return() {} #include "main.glsl" ''' environment = Directory('.', [ File('a.vert', including_file), File('error.glsl', 'int unknown_identifier(int) { return a; }'), File('main.glsl', 'void main() {\n int b = 1.5;\n}')]) glslc_args = ['-c', 'a.vert'] expected_error = [ "error.glsl:1: error: 'a' : undeclared identifier\n", "error.glsl:1: error: 'return' : type does not match, or is not " "convertible to, the function's return type\n", "a.vert:3: error: '' : function does not return a value: no_return\n", "main.glsl:2: error: '=' : cannot convert from ' const float' to " "' temp highp int'\n", "4 errors generated.\n"] @inside_glslc_testsuite('#line') class TestExplicitPoundLineWithPoundInclude( expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch): """Tests that #line works correctly in the presence of #include (which itself will generate some #line directives.""" including_file = '''#version 310 es #line 10000 "injected.glsl" int plus1(int a) { return a + 1; } #include "inc.glsl" int plus2(int a) { return a + 2; } #line 55555 #include "main.glsl" ''' environment = Directory('.', [ File('a.vert', including_file), File('inc.glsl', 'int inc(int a) { return a + 1; }'), File('main.glsl', 'void main() {\n gl_Position = vec4(1.);\n}')]) glslc_args = ['-E', 'a.vert'] expected_stderr = '' expected_stdout = '''#version 310 es #extension GL_GOOGLE_include_directive : enable #line 1 "a.vert" #line 10000 "injected.glsl" int plus1(int a) { return a + 1; } #line 1 "inc.glsl" int inc(int a) { return a + 1; } #line 10002 "injected.glsl" int plus2(int a) { return a + 2; } #line 55555 #line 1 "main.glsl" void main() { gl_Position = vec4(1.); } #line 55556 "injected.glsl" ''' shaderc-2025.2/glslc/test/messages_tests.py000066400000000000000000000217231500222170200206770ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader, StdinShader @inside_glslc_testsuite('ErrorMessages') class MultipleErrors(expect.ErrorMessage): """Test Multiple error messages generated.""" shader = FileShader('#version 140\nint main() {}', '.vert') glslc_args = ['-c', shader] expected_error = [ shader, ":2: error: 'int' : entry point cannot return a value\n", shader, ":2: error: '' : function does not return a value: main\n", '2 errors generated.\n'] @inside_glslc_testsuite('ErrorMessages') class OneError(expect.ErrorMessage): """Tests that only one error message is generated correctly.""" shader = FileShader( """#version 140 int a() { } void main() { int x = a(); } """, '.vert') glslc_args = ['-c', shader] expected_error = [ shader, ":2: error: '' : function does not return a value: a\n", '1 error generated.\n'] @inside_glslc_testsuite('ErrorMessages') class ManyLineError(expect.ErrorMessage): """Tests that only one error message is generated correctly.""" shader = FileShader( """#version 140 int a() { } void main() { int x = a(); } """, '.vert') glslc_args = ['-c', shader] expected_error = [ shader, ":12: error: '' : function does not return a value: a\n", '1 error generated.\n'] @inside_glslc_testsuite('ErrorMessages') class GlobalWarning(expect.WarningMessage): """Tests that a warning message without file/line number is emitted.""" shader = FileShader( """#version 550 void main() { } """, '.vert') glslc_args = ['-c', '-std=400', shader] expected_warning = [ shader, ': warning: (version, profile) forced to be (400, none),' ' while in source code it is (550, none)\n1 warning generated.\n'] @inside_glslc_testsuite('ErrorMessages') class SuppressedGlobalWarning(expect.SuccessfulReturn): """Tests that warning messages without file/line numbers are suppressed with -w.""" shader = FileShader( """#version 550 void main() { } """, '.vert') glslc_args = ['-c', '-std=400', shader, '-w'] @inside_glslc_testsuite('ErrorMessages') class GlobalWarningAsError(expect.ErrorMessage): """Tests that with -Werror an error warning message without file/line number is emitted instead of a warning.""" shader = FileShader( """#version 550 void main() { } """, '.vert') glslc_args = ['-c', '-std=400', shader, '-Werror'] expected_error= [ shader, ': error: (version, profile) forced to be (400, none),' ' while in source code it is (550, none)\n1 error generated.\n'] @inside_glslc_testsuite('ErrorMessages') class WarningOnLine(expect.WarningMessage): """Tests that a warning message with a file/line number is emitted.""" shader = FileShader( """#version 400 layout(location = 0) attribute float x; void main() { } """, '.vert') glslc_args = ['-c', shader] expected_warning = [ shader, ':2: warning: attribute deprecated in version 130; ', 'may be removed in future release\n1 warning generated.\n'] @inside_glslc_testsuite('ErrorMessages') class SuppressedWarningOnLine(expect.SuccessfulReturn): """Tests that a warning message with a file/line number is suppressed in the presence of -w.""" shader = FileShader( """#version 400 layout(location = 0) attribute float x; void main() { } """, '.vert') glslc_args = ['-c', shader, '-w'] @inside_glslc_testsuite('ErrorMessages') class WarningOnLineAsError(expect.ErrorMessage): """Tests that with -Werror an error message with a file/line number is emitted instead of a warning.""" shader = FileShader( """#version 400 layout(location = 0) attribute float x; void main() { } """, '.vert') glslc_args = ['-c', shader, '-Werror'] expected_error = [ shader, ':2: error: attribute deprecated in version 130; ', 'may be removed in future release\n1 error generated.\n'] @inside_glslc_testsuite('ErrorMessages') class WarningAndError(expect.ErrorMessage): """Tests that both warnings and errors are emitted together.""" shader = FileShader( """#version 400 layout(location = 0) attribute float x; int main() { } """, '.vert') glslc_args = ['-c', shader] expected_error = [ shader, ':2: warning: attribute deprecated in version 130; ', 'may be removed in future release\n', shader, ":3: error: 'int' : entry point cannot return a value\n", shader, ":3: error: '' : function does not return a value: main\n", '1 warning and 2 errors generated.\n'] @inside_glslc_testsuite('ErrorMessages') class SuppressedWarningAndError(expect.ErrorMessage): """Tests that only warnings are suppressed in the presence of -w.""" shader = FileShader( """#version 400 layout(location = 0) attribute float x; int main() { } """, '.vert') glslc_args = ['-c', shader, '-w'] expected_error = [ shader, ":3: error: 'int' : entry point cannot return a value\n", shader, ":3: error: '' : function does not return a value: main\n", '2 errors generated.\n'] @inside_glslc_testsuite('ErrorMessages') class WarningAsErrorAndError(expect.ErrorMessage): """Tests that with -Werror an warnings and errors are emitted as errors.""" shader = FileShader( """#version 400 layout(location = 0) attribute float x; int main() { } """, '.vert') glslc_args = ['-c', shader, '-Werror'] expected_error = [ shader, ':2: error: attribute deprecated in version 130; ', 'may be removed in future release\n', shader, ":3: error: 'int' : entry point cannot return a value\n", shader, ":3: error: '' : function does not return a value: main\n", '3 errors generated.\n'] @inside_glslc_testsuite('ErrorMessages') class StdinErrorMessages(expect.StdoutMatch, expect.StderrMatch): """Tests that error messages using input from stdin are correct.""" shader = StdinShader( """#version 140 int a() { } void main() { int x = a(); } """) glslc_args = ['-c', '-fshader-stage=vertex', shader] expected_stdout = '' expected_stderr = [ ":2: error: '' : function does not return a value: a\n", '1 error generated.\n'] @inside_glslc_testsuite('ErrorMessages') class WarningAsErrorMultipleFiles(expect.ErrorMessage): """Tests that with -Werror multiple files emit errors instead of warnings. """ shader = FileShader( """#version 400 layout(location = 0) attribute float x; void main() { } """, '.vert') shader2 = FileShader( """#version 550 void main() { } """, '.vert') glslc_args = ['-c', '-std=400', shader, '-Werror', shader2] expected_error = [ shader, ':2: error: attribute deprecated in version 130; ', 'may be removed in future release\n', shader2, ': error: (version, profile) forced to be (400, none),' ' while in source code it is (550, none)\n', '2 errors generated.\n'] @inside_glslc_testsuite('ErrorMessages') class SuppressedWarningAsError(expect.SuccessfulReturn): """Tests that nothing is returned in the presence of -w -Werror.""" shader = FileShader( """#version 400 layout(location = 0) attribute float x; void main() { } """, '.vert') glslc_args = ['-c', shader, '-w', '-Werror'] @inside_glslc_testsuite('ErrorMessages') class MultipleSuppressed(expect.SuccessfulReturn): """Tests that multiple -w arguments are supported.""" shader = FileShader( """#version 400 layout(location = 0) attribute float x; void main() { } """, '.vert') glslc_args = ['-w', '-c', shader, '-w', '-w', '-w'] @inside_glslc_testsuite('ErrorMessages') class MultipleSuppressedFiles(expect.SuccessfulReturn): """Tests that -w suppresses warnings from all files.""" shader = FileShader( """#version 400 layout(location = 0) attribute float x; void main() { } """, '.vert') shader2 = FileShader( """#version 400 layout(location = 0) attribute float x; void main() { } """, '.vert') glslc_args = ['-w', '-c', shader, shader2] shaderc-2025.2/glslc/test/option_dash_D.py000066400000000000000000000243751500222170200204260ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader @inside_glslc_testsuite('OptionCapD') class TestDashCapDNoArg(expect.ErrorMessage): """Tests -D without macroname.""" glslc_args = ['-D'] expected_error = [ "glslc: error: argument to '-D' is missing\n", 'glslc: error: no input files\n'] @inside_glslc_testsuite('OptionCapD') class TestDashCapDXeqY(expect.ValidObjectFile): """Tests -DX=Y.""" shader = FileShader('#version 150\nvoid main(){X=vec4(1.);}', '.vert') glslc_args = ['-c', '-DX=gl_Position', shader] @inside_glslc_testsuite('OptionCapD') class TestDashCapDXeq(expect.ValidObjectFile): """Tests -DX=.""" shader = FileShader('#version 150\nvoid main(){X}', '.vert') glslc_args = ['-c', '-DX=', shader] @inside_glslc_testsuite('OptionCapD') class TestDashCapDX(expect.ValidObjectFile): """Tests -DX.""" shader = FileShader('#version 150\nvoid main(){X}', '.vert') glslc_args = ['-c', '-DX', shader] @inside_glslc_testsuite('OptionCapD') class TestDashCapDeq(expect.ErrorMessage): """Tests -D=. This is actually allowed by clang, though the resulting #define causes a preprocessing error. """ shader = FileShader('#version 150\nvoid main(){}', '.vert') glslc_args = ['-c', '-D=', shader] # TODO(antiagainst): figure out what should we report as the line number # for errors in predefined macros and fix here. expected_error = [ ":2: error: '#define' : must be followed by macro name\n", '1 error generated.\n'] @inside_glslc_testsuite('OptionCapD') class TestMultipleDashCapD(expect.ValidObjectFile): """Tests multiple -D occurrences.""" shader = FileShader('#version 150\nvoid main(){X Y a=Z;}', '.vert') glslc_args = ['-c', '-DX', '-DY=int', '-DZ=(1+2)', shader] @inside_glslc_testsuite('OptionCapD') class TestMultipleDashCapDOfSameName(expect.ValidObjectFile): """Tests multiple -D occurrences with same macro name.""" shader = FileShader('#version 150\nvoid main(){X Y a=Z;}', '.vert') glslc_args = ['-c', '-DX=main', '-DY=int', '-DZ=(1+2)', '-DX', shader] @inside_glslc_testsuite('OptionCapD') class TestDashCapDGL_(expect.ErrorMessage): """Tests that we cannot -D macros beginning with GL_.""" shader = FileShader('#version 150\nvoid main(){}', '.vert') glslc_args = ['-DGL_ES=1', shader] expected_error = [ "glslc: error: names beginning with 'GL_' cannot be " 'defined: -DGL_ES=1\n'] @inside_glslc_testsuite('OptionCapD') class TestDashCapDReservedMacro(expect.WarningMessage): """Tests that we cannot -D GLSL's predefined macros.""" shader = FileShader('#version 150\nvoid main(){}', '.vert') # Consecutive underscores are banned anywhere in the name. glslc_args = [ '-D__LINE__=1', '-Dmid__dle', '-Dend__', '-D_single_is_valid_', shader] w = 'glslc: warning: names containing consecutive underscores are reserved: ' expected_warning = [w, '-D__LINE__=1\n', w, '-Dmid__dle\n', w, '-Dend__\n'] @inside_glslc_testsuite('OptionCapD') class TestDashCapDWithVersion(expect.ErrorMessage): """Tests -D works well when #version is present.""" shader = FileShader( """#version 310 es void main(){X} void foo(){Y}""", '.vert') glslc_args = ['-DX=', '-DY=return 3;', shader] expected_error = [ shader, ":3: error: 'return' : void function cannot return a value\n", '1 error generated.\n'] @inside_glslc_testsuite('OptionCapD') class TestDashCapDWithCommentBeforeVersion(expect.ErrorMessage): """Tests -D works well with #version preceded by comments.""" shader = FileShader( """// comment 1 /* * comment 2 */ #version 450 core void main(){X} void foo(){Y}""", '.vert') glslc_args = ['-DX=', '-DY=return 3;', shader] expected_error = [ shader, ":7: error: 'return' : void function cannot return a value\n", '1 error generated.\n'] @inside_glslc_testsuite('OptionCapD') class TestDashCapDWithCommentAfterVersion(expect.ErrorMessage): """Tests -D works well with #version followed by comments.""" shader = FileShader( """ #version 150 core /* comment */ void main(){X} void foo(){Y}""", '.vert') glslc_args = ['-DX=', '-DY=return 3;', shader] expected_error = [ shader, ":7: error: 'return' : void function cannot return a value\n", '1 error generated.\n'] @inside_glslc_testsuite('OptionCapD') class TestDashCapDWithDashStd(expect.ErrorMessageSubstr): """Tests -D works well with -std.""" shader = FileShader('void main(){X}\nvoid foo(){Y}', '.vert') glslc_args = ['-DX=', '-DY=return 3;', '-std=310es', shader] expected_error_substr = [ shader, ":2: error: 'return' : void function cannot return a value\n", '1 error generated.\n'] @inside_glslc_testsuite('OptionCapD') class TestDashCapDWithDashStdAndVersion(expect.ErrorMessage): """Tests -D works well with both -std and #version.""" shader = FileShader( """#version 310 es void main(){X} void foo(){Y}""", '.vert') glslc_args = ['-DX=', '-DY=return 3;', '-std=450core', shader] expected_error = [ shader, ': warning: (version, profile) forced to be (450, ', 'core), while in source code it is (310, es)\n', shader, ":3: error: 'return' : void function cannot return a value\n", '1 warning and 1 error generated.\n'] @inside_glslc_testsuite('OptionCapD') class TestDashCapDWithDashStdAndVersionAndComments(expect.ErrorMessage): """Tests -D works well with -std, #version, and comments around it.""" shader = FileShader( """// comment before #version 310 es /* comment after */ void main(){X} void foo(){Y}""", '.vert') glslc_args = ['-DX=', '-DY=return 3;', '-std=450core', shader] expected_error = [ shader, ': warning: (version, profile) forced to be (450, core), while ' 'in source code it is (310, es)\n', shader, ":7: error: 'return' : void function cannot return a value\n", '1 warning and 1 error generated.\n'] @inside_glslc_testsuite('OptionCapD') class TestDashCapDWithDashE(expect.ReturnCodeIsZero, expect.StdoutMatch): """Tests -E outputs expanded -D macros.""" shader = FileShader( """ void main(){Y} """, '.vert') glslc_args = ['-DY=return 3;', '-E', '-std=450core', shader] expected_stdout = [ """ void main() { return 3; } """] @inside_glslc_testsuite('OptionCapD') class TestDashCapDWithDashEIfDef(expect.ReturnCodeIsZero, expect.StdoutMatch): """Tests -E processes -DX #ifdefs correctly.""" shader = FileShader( """ #ifdef X void f() { } #else void f() { int x; } #endif void main(){ return 3; } """, '.vert') glslc_args = ['-DX', '-E', '-std=450core', shader] expected_stdout = [ """ void f() { } void main() { return 3; } """] @inside_glslc_testsuite('OptionCapD') class TestDashCapDWithDashEIfNDef(expect.ReturnCodeIsZero, expect.StdoutMatch): """Tests -E processes -DX #ifndefs correctly.""" shader = FileShader( """ #ifndef X void f() { } #else void f() { int x; } #endif void main(){ return 3; } """, '.vert') glslc_args = ['-DX', '-E', '-std=450core', shader] expected_stdout = [ """ void f() { int x; } void main() { return 3; } """] @inside_glslc_testsuite('OptionCapD') class TestDashCapDWithDashEEqIfDef(expect.ReturnCodeIsZero, expect.StdoutMatch): """Tests -E processes -DX= #ifdefs correctly.""" shader = FileShader( """ #ifdef X void f() { } #else void f() { int x; } #endif void main() { return 3; } """, '.vert') glslc_args = ['-DX=', '-E', '-std=450core', shader] expected_stdout = [ """ void f() { } void main() { return 3; } """] @inside_glslc_testsuite('OptionCapD') class TestDashCapDWithDashEEqIfNDef(expect.ReturnCodeIsZero, expect.StdoutMatch): """Tests -E processes -DX= #ifndefs correctly.""" shader = FileShader( """ #ifndef X void f() { } #else void f() { int x; } #endif void main(){ return 3; } """, '.vert') glslc_args = ['-DX=', '-E', '-std=450core', shader] expected_stdout = [ """ void f() { int x; } void main() { return 3; } """] @inside_glslc_testsuite('OptionCapD') class TestDashCapDWithDashEFunctionMacro(expect.ReturnCodeIsZero, expect.StdoutMatch): """Tests -E processes -D function macros correctly.""" shader = FileShader( """ void main(){ return FOO(3); } """, '.vert') glslc_args = ['-DFOO(x)=(2*x+1)*x*x', '-E', '-std=450core', shader] expected_stdout = [ """ void main() { return(2 * 3 + 1) * 3 * 3; } """] @inside_glslc_testsuite('OptionCapD') class TestDashCapDWithDashENestedMacro(expect.ReturnCodeIsZero, expect.StdoutMatch): """Tests -E processes referencing -D options correctly.""" shader = FileShader( """ void main() { return X; } """, '.vert') glslc_args = ['-DY=4', '-DX=Y', '-E', '-std=450core', shader] expected_stdout = [ """ void main() { return 4; } """] shaderc-2025.2/glslc/test/option_dash_E.py000066400000000000000000000202651500222170200204210ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader, StdinShader @inside_glslc_testsuite('OptionCapE') class TestDashCapENoDefs(expect.StdoutMatch): """Tests -E without any defines.""" shader = FileShader('#version 140\nvoid main(){}', '.vert') expected_stdout = '#version 140\nvoid main() { }\n' glslc_args = ['-E', shader] @inside_glslc_testsuite('OptionCapE') class TestDashCapEGlslFileAccepted(expect.StdoutMatch): """Tests -E if we provide a .glsl file without an explicit stage.""" shader = FileShader('#version 140\nvoid main(){}', '.glsl') expected_stdout = '#version 140\nvoid main() { }\n' glslc_args = ['-E', shader] @inside_glslc_testsuite('OptionCapE') class TestDashCapESingleDefine(expect.StdoutMatch): """Tests -E with command-line define.""" shader = FileShader('#version 140\nvoid main(){ int a = X; }', '.vert') expected_stdout = '#version 140\nvoid main() { int a = 4; }\n' glslc_args = ['-DX=4', '-E', shader] @inside_glslc_testsuite('OptionCapE') class TestDashCapEExpansion(expect.StdoutMatch): """Tests -E with macro expansion.""" shader = FileShader('''#version 140 #define X 4 void main() { int a = X; } ''', '.vert') expected_stdout = '''#version 140 void main() { int a = 4; } ''' glslc_args = ['-E', shader] @inside_glslc_testsuite('OptionCapE') class TestDashCapEFunctionMacro(expect.StdoutMatch): """Tests -E with function-style macro expansion.""" shader = FileShader('''#version 140 #define X(A) 4+A void main() { int a = X(1); } ''', '.vert') expected_stdout = '''#version 140 void main() { int a = 4 + 1; } ''' glslc_args = ['-E', shader] @inside_glslc_testsuite('OptionCapE') class TestDashCapEPragma(expect.StdoutMatch): """Tests -E to make sure pragmas get retained.""" shader = FileShader('''#version 140 #pragma optimize(off) void main() { } ''', '.vert') expected_stdout = '''#version 140 #pragma optimize(off) void main() { } ''' glslc_args = ['-E', shader] @inside_glslc_testsuite('OptionCapE') class TestDashCapEExtension(expect.StdoutMatch): """Tests -E to make sure extensions get retained.""" shader = FileShader('''#version 140 #extension foo: require void main() { } ''', '.vert') expected_stdout = '''#version 140 #extension foo : require void main() { } ''' glslc_args = ['-E', shader] @inside_glslc_testsuite('OptionCapE') class TestDashCapELine(expect.StdoutMatch): """Tests -E to make sure line numbers get retained.""" shader = FileShader('''#version 140 #define X 4 #line X #line 2 3 void main() { } ''', '.vert') expected_stdout = '''#version 140 #line 4 #line 2 3 void main() { } ''' glslc_args = ['-E', shader] @inside_glslc_testsuite('OptionCapE') class TestDashCapEError(expect.ErrorMessage): """Tests -E to make sure #errors get retained.""" shader = FileShader('''#version 140 #if 1 #error This is an error #endif void main() { } ''', '.vert') expected_error = [ shader, ':3: error: \'#error\' : This is an error\n', '1 error generated.\n'] glslc_args = ['-E', shader] @inside_glslc_testsuite('OptionCapE') class TestDashCapEStdin(expect.StdoutMatch): """Tests to make sure -E works with stdin.""" shader = StdinShader('''#version 140 void main() { } ''') expected_stdout = '''#version 140 void main() { } ''' glslc_args = ['-E', '-fshader-stage=vertex', shader] @inside_glslc_testsuite('OptionCapE') class TestDashCapEStdinDoesNotRequireShaderStage(expect.StdoutMatch): """Tests to make sure -E works with stdin even when no shader-stage is specified.""" shader = StdinShader('''#version 140 void main() { } ''') expected_stdout = '''#version 140 void main() { } ''' glslc_args = ['-E', shader] @inside_glslc_testsuite('OptionCapE') class TestDashCapEMultipleFiles(expect.StdoutMatch): """Tests to make sure -E works with multiple files.""" shader = StdinShader('''#version 140 void main() { } ''') shader2 = FileShader('''#version 140 void function() { } ''', '.vert') expected_stdout = '''#version 140 void main() { } #version 140 void function() { } ''' glslc_args = ['-E', '-fshader-stage=vertex', shader, shader2] @inside_glslc_testsuite('OptionCapE') class TestDashCapEMultipleFilesWithoutStage(expect.StdoutMatch): """Tests to make sure -E works with multiple files even if we do not specify a stage.""" shader = StdinShader('''#version 140 void main() { } ''') shader2 = FileShader('''#version 140 void function() { } ''', '.glsl') expected_stdout = '''#version 140 void main() { } #version 140 void function() { } ''' glslc_args = ['-E', shader, shader2] @inside_glslc_testsuite('OptionCapE') class TestDashCapEOutputFile(expect.SuccessfulReturn, expect.ValidFileContents): """Tests to make sure -E works with output files.""" shader = FileShader('''#version 140 void function() { } ''', '.vert') expected_file_contents = '''#version 140 void function() { } ''' target_filename = 'foo' glslc_args = ['-E', shader, '-ofoo'] @inside_glslc_testsuite('OptionCapE') class TestDashCapEWithS(expect.StdoutMatch): """Tests -E in the presence of -S.""" shader = FileShader('#version 140\nvoid main(){}', '.vert') expected_stdout = '#version 140\nvoid main() { }\n' glslc_args = ['-E', '-S', shader] @inside_glslc_testsuite('OptionCapE') class TestMultipileDashCapE(expect.StdoutMatch): """Tests that using -E multiple times works.""" shader = FileShader('#version 140\nvoid main(){}', '.vert') expected_stdout = '#version 140\nvoid main() { }\n' glslc_args = ['-E', '-E', shader, '-E'] @inside_glslc_testsuite('OptionCapE') class TestDashCapEAfterFile(expect.StdoutMatch): """Tests that using -E after the filename also works.""" shader = FileShader('#version 140\nvoid main(){}', '.vert') expected_stdout = '#version 140\nvoid main() { }\n' glslc_args = [shader, '-E'] @inside_glslc_testsuite('OptionCapE') class TestDashCapEWithDashC(expect.StdoutMatch): """Tests to make sure -E works in the presence of -c.""" shader = FileShader('''#version 140 void main() { } ''', '.vert') shader2 = FileShader('''#version 140 void function() { } ''', '.vert') expected_stdout = '''#version 140 void main() { } #version 140 void function() { } ''' glslc_args = ['-E', '-c', shader, shader2] @inside_glslc_testsuite('OptionCapE') class TestDashCapEWithPPErrors(expect.ErrorMessage): """Tests to make sure -E outputs error messages for preprocessing errors.""" shader = FileShader('''#version 310 es #extension s enable // missing : #defin A // Bad define #if X // In glsl X must be defined for X to work. // Lack of endif. void main() { } ''', '.vert') expected_error = [ shader, ':2: error: \'#extension\' : \':\' missing after extension', ' name\n', shader, ':3: error: \'#\' : invalid directive: defin\n', shader, ':4: error: \'preprocessor evaluation\' : undefined macro in', ' expression not allowed in es profile X\n', shader, ':8: error: \'\' : missing #endif\n', '4 errors generated.\n'] glslc_args = ['-E', shader] @inside_glslc_testsuite('OptionCapE') class TestDashCapEStdinErrors(expect.ErrorMessage): """Tests that -E outputs error messages correctly for stdin input.""" shader = StdinShader('''#version 310 es #extension s enable // missing : void main() { } ''') expected_error = [ ':2: error: \'#extension\' : \':\' missing after extension', ' name\n', '1 error generated.\n'] glslc_args = ['-E', shader] shaderc-2025.2/glslc/test/option_dash_M.py000066400000000000000000001004201500222170200204210ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect import os.path import sys from environment import File, Directory from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader from glslc_test_framework import GlslCTest MINIMAL_SHADER = '#version 140\nvoid main() {}' EMPTY_SHADER_IN_CURDIR = Directory('.', [File('shader.vert', MINIMAL_SHADER)]) EMPTY_SHADER_IN_SUBDIR = Directory('subdir', [File('shader.vert', MINIMAL_SHADER)]) def process_test_specified_dependency_info_rules(test_specified_rules): """A helper function to process the expected dependency info rules specified in tests before checking the actual dependency rule output. This is required because the filename and path of temporary files created through FileShader is unknown at the time the expected dependency info rules are declared. Note this function process the given rule list in-place. """ for rule in test_specified_rules: # If the 'target' value is not a hard-coded file name but a # FileShader, we need its full path, append extension to it and # strip the directory component from it to get the complete target # name. if isinstance(rule['target'], FileShader): rule['target'] = rule['target'].filename if 'target_extension' in rule: if rule['target_extension'] is not None: rule['target'] = rule['target'] + rule['target_extension'] rule.pop('target_extension') rule['target'] = os.path.basename(rule['target']) # The dependency set may have FileShader too, we need to replace # them with their absolute paths. dependent_file_name_set = set() for dependent_file in rule['dependency']: if isinstance(dependent_file, FileShader): dependent_file_name_set.add(dependent_file.filename) else: dependent_file_name_set.add(dependent_file) rule['dependency'] = dependent_file_name_set def parse_text_rules(text_lines): """ A helper function to read text lines and construct and returns a list of dependency rules which can be used for comparison. The list is built with the text order. Each rule is described in the following way: {'target': , 'dependency': } """ rules = [] for line in text_lines: if line.strip() == "": continue rule = {'target': line.split(': ')[0].strip(), 'dependency': set(line.split(': ')[-1].strip().split(' '))} rules.append(rule) return rules class DependencyInfoStdoutMatch(GlslCTest): """Mixin class for tests that can expect dependency info in Stdout. To mix in this class, the subclass needs to provide dependency_rules_expected as a list of dictionaries, each dictionary describes one expected make rule for a target file. A expected rule should be specified in the following way: rule = {'target': , 'target_extension': <.spv, .spvasm or None>, 'dependency': } The 'target_extension' field is optional, its value will be appended to 'target' to get complete target name. And the list 'dependency_rules_expected' is a list of such rules and the order of the rules does matter. """ def check_stdout_dependency_info(self, status): if not status.stdout: return False, 'Expect dependency rules on stdout' if sys.version_info[0] == 2: rules = parse_text_rules(status.stdout.decode('utf-8').split('\n')) elif sys.version_info[0] == 3: rules = parse_text_rules(str(status.stdout, encoding='utf-8', errors='ignore').split('\n')) process_test_specified_dependency_info_rules( self.dependency_rules_expected) if self.dependency_rules_expected != rules: return False, ('Incorrect dependency info:\n{ac_rules}\n' 'Expected:\n{ex_rules}\n' 'Stdout output:\n{ac_stdout}\n'.format( ac_rules=rules, ex_rules=self.dependency_rules_expected, ac_stdout=status.stdout)) return True, '' @inside_glslc_testsuite('OptionsCapM') class TestDashCapMSingleInputRelativePathNoInclude(DependencyInfoStdoutMatch): """Tests -M with single input file which doesn't contain #include and is represented in relative path. e.g. glslc -M shader.vert => shader.vert.spv: shader.vert """ environment = EMPTY_SHADER_IN_CURDIR glslc_args = ['-M', 'shader.vert'] dependency_rules_expected = [{'target': "shader.vert.spv", 'dependency': {"shader.vert"}}] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMSingleInputAbsolutePathNoInclude(DependencyInfoStdoutMatch): """Tests -M with single input file which doesn't contain #include and is represented in absolute path. e.g. glslc -M /usr/local/shader.vert => shader.vert.spv: /usr/local/shader.vert """ shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = ['-M', shader] dependency_rules_expected = [{'target': shader, 'target_extension': '.spv', 'dependency': {shader}}] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMSingleInputRelativePathWithInclude( DependencyInfoStdoutMatch): """Tests -M with single input file which does contain #include and is represented in relative path. e.g. glslc -M a.vert => a.vert.spv: a.vert b.vert """ environment = Directory('.', [ File('a.vert', '#version 140\n#include "b.vert"\nvoid main(){}\n'), File('b.vert', 'void foo(){}\n'), ]) glslc_args = ['-M', 'a.vert'] dependency_rules_expected = [{'target': 'a.vert.spv', 'dependency': {'a.vert', 'b.vert'}}] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMSingleInputRelativePathWithIncludeSubdir( DependencyInfoStdoutMatch): """Tests -M with single input file which does #include another file in a subdirectory of current directory and is represented in relative path. e.g. glslc -M a.vert => a.vert.spv: a.vert include/b.vert """ environment = Directory('.', [ File('a.vert', ('#version 140\n#include "include/b.vert"' '\nvoid main(){}\n')), Directory('include', [File('b.vert', 'void foo(){}\n')]), ]) glslc_args = ['-M', 'a.vert'] dependency_rules_expected = [{'target': 'a.vert.spv', 'dependency': {'a.vert', 'include/b.vert'}}] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMSingleInputRelativePathWithDashI(DependencyInfoStdoutMatch): """Tests -M with single input file works with -I option. The #include directive does not specify 'include/' for the file to be include. e.g. glslc -M a.vert -I include => a.vert.spv: a.vert include/b.vert """ environment = Directory('.', [ File('a.vert', ('#version 140\n#include "b.vert"' '\nvoid main(){}\n')), Directory('include', [File('b.vert', 'void foo(){}\n')]), ]) glslc_args = ['-M', 'a.vert', '-I', 'include'] dependency_rules_expected = [{'target': 'a.vert.spv', 'dependency': {'a.vert', 'include/b.vert'}}] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMSingleInputRelativePathWithNestedInclude( DependencyInfoStdoutMatch): """Tests -M with single input file under nested #include case. The input file is represented in relative path. e.g. glslc -M a.vert => a.vert.spv: a.vert b.vert c.vert """ environment = Directory('.', [ File('a.vert', '#version 140\n#include "b.vert"\nvoid main(){}\n'), File('b.vert', 'void foo(){}\n#include "c.vert"\n'), File('c.vert', 'void bar(){}\n'), ]) glslc_args = ['-M', 'a.vert'] dependency_rules_expected = [{'target': 'a.vert.spv', 'dependency': {'a.vert', 'b.vert', 'c.vert'}}] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMMultipleInputRelativePathNoInclude( DependencyInfoStdoutMatch): """Tests -M with multiple input file which don't contain #include and are represented in relative paths. e.g. glslc -M a.vert b.vert => a.vert.spv: a.vert b.vert.spv: b.vert """ environment = Directory('.', [ File('a.vert', MINIMAL_SHADER), File('b.vert', MINIMAL_SHADER), ]) glslc_args = ['-M', 'a.vert', 'b.vert'] dependency_rules_expected = [{'target': 'a.vert.spv', 'dependency': {'a.vert'}}, {'target': 'b.vert.spv', 'dependency': {'b.vert'}}, ] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMMultipleInputAbsolutePathNoInclude( DependencyInfoStdoutMatch): """Tests -M with single input file which doesn't contain #include and is represented in absolute path. e.g. glslc -M /usr/local/a.vert /usr/local/b.vert => a.vert.spv: /usr/local/a.vert b.vert.spv: /usr/local/b.vert """ shader_a = FileShader(MINIMAL_SHADER, '.vert') shader_b = FileShader(MINIMAL_SHADER, '.vert') glslc_args = ['-M', shader_a, shader_b] dependency_rules_expected = [{'target': shader_a, 'target_extension': '.spv', 'dependency': {shader_a}}, {'target': shader_b, 'target_extension': '.spv', 'dependency': {shader_b}}, ] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMDashCapMT(DependencyInfoStdoutMatch): """Tests -MT works with -M. User can specify the target object name in the generated dependency info. e.g. glslc -M shader.vert -MT target => target: shader.vert """ environment = EMPTY_SHADER_IN_CURDIR glslc_args = ['-M', 'shader.vert', '-MT', 'target'] dependency_rules_expected = [{'target': 'target', 'dependency': {'shader.vert'}}] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMInputAbsolutePathWithInclude(DependencyInfoStdoutMatch): """Tests -M have included files represented in absolute paths when the input file is represented in absolute path. E.g. Assume a.vert has '#include "b.vert"' glslc -M /usr/local/a.vert => a.vert.spv: /usr/local/a.vert /usr/local/b.vert """ environment = Directory('.', [File('b.vert', 'void foo(){}\n')]) shader_main = FileShader( '#version 140\n#include "b.vert"\nvoid main(){}\n', '.vert') glslc_args = ['-M', shader_main] dependency_rules_expected = [{ 'target': shader_main, 'target_extension': '.spv', 'dependency': {shader_main} # The dependency here is not complete. we can not get the absolute path # of b.vert here. It will be added in check_stdout_dependency_info() }] def check_stdout_dependency_info(self, status): # Add the absolute path of b.vert to the dependency set self.dependency_rules_expected[0]['dependency'].add(os.path.dirname( self.shader_main.filename) + '/b.vert') return DependencyInfoStdoutMatch.check_stdout_dependency_info(self, status) @inside_glslc_testsuite('OptionsCapM') class TestDashCapMSingleInputAbsolutePathWithIncludeSubdir( DependencyInfoStdoutMatch): """Tests -M with single input file which does #include another file in a subdirectory of current directory and is represented in absolute path. e.g. glslc -M /usr/local/a.vert => a.vert.spv: /usr/local/a.vert /usr/local/include/b.vert """ environment = Directory('.', [ Directory('include', [File('b.vert', 'void foo(){}\n')]), ]) shader_main = FileShader('#version 140\n#include "include/b.vert"\n', '.vert') glslc_args = ['-M', shader_main] dependency_rules_expected = [{ 'target': shader_main, 'target_extension': '.spv', 'dependency': {shader_main} # The dependency here is not complete. we can not get the absolute # path of include/b.vert here. It will be added in # check_stdout_dependency_info() }] def check_stdout_dependency_info(self, status): # Add the absolute path of include/b.vert to the dependency set self.dependency_rules_expected[0]['dependency'].add(os.path.dirname( self.shader_main.filename) + '/include/b.vert') return DependencyInfoStdoutMatch.check_stdout_dependency_info(self, status) @inside_glslc_testsuite('OptionsCapM') class TestDashCapMOverridesOtherModes(DependencyInfoStdoutMatch): """Tests -M overrides other compiler mode options, includeing -E, -c and -S. """ environment = Directory('.', [ File('a.vert', MINIMAL_SHADER), File('b.vert', MINIMAL_SHADER), ]) glslc_args = ['-M', '-E', '-c', '-S', 'a.vert', 'b.vert'] dependency_rules_expected = [{'target': 'a.vert.spv', 'dependency': {'a.vert'}}, {'target': 'b.vert.spv', 'dependency': {'b.vert'}}] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMMEquivalentToCapM(DependencyInfoStdoutMatch): """Tests that -MM behaves as -M. e.g. glslc -MM shader.vert => shader.vert.spv: shader.vert """ environment = EMPTY_SHADER_IN_CURDIR glslc_args = ['-MM', 'shader.vert'] dependency_rules_expected = [{'target': 'shader.vert.spv', 'dependency': {'shader.vert'}}] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMImpliesDashCapE(DependencyInfoStdoutMatch, expect.NoOutputOnStderr): """Tests that -M implies -E, a .glsl file without an explict stage should not generate an error. e.g. glslc -M shader.glsl => shader.spv: shader.glsl """ environment = Directory('.', [File('shader.glsl', MINIMAL_SHADER)]) glslc_args = ['-M', 'shader.glsl'] dependency_rules_expected = [{'target': 'shader.spv', 'dependency': {'shader.glsl'}}] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMImpliesDashW(DependencyInfoStdoutMatch, expect.NoOutputOnStderr): """Tests that -M implies -w, a deprecated attribute should not generate warning message. e.g. glslc -M shader.vert => shader.vert.spv: shader.vert """ environment = Directory('.', [File( 'shader.vert', """#version 400 layout(location=0) attribute float x; void main() {}""")]) glslc_args = ['-M', 'shader.vert'] dependency_rules_expected = [{'target': 'shader.vert.spv', 'dependency': {'shader.vert'}}] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMMImpliesDashCapE(DependencyInfoStdoutMatch, expect.NoOutputOnStderr): """Tests that -M implies -E, a .glsl file without an explict stage should not generate an error. e.g. glslc -MM shader.glsl => shader.spv: shader.glsl """ environment = Directory('.', [File('shader.glsl', MINIMAL_SHADER)]) glslc_args = ['-MM', 'shader.glsl'] dependency_rules_expected = [{'target': 'shader.spv', 'dependency': {'shader.glsl'}}] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMMImpliesDashW(DependencyInfoStdoutMatch, expect.NoOutputOnStderr): """Tests that -MM implies -w, a deprecated attribute should not generate warning message. e.g. glslc -MM shader.vert => shader.vert.spv: shader.vert """ environment = Directory('.', [File( 'shader.vert', """ #version 400 layout(location = 0) attribute float x; void main() {}""")]) glslc_args = ['-MM', 'shader.vert'] dependency_rules_expected = [{'target': 'shader.vert.spv', 'dependency': {'shader.vert'}}] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMD(expect.ValidFileContents, expect.ValidNamedObjectFile): """Tests that -MD generates dependency info file and compilation output. e.g. glslc -MD shader.vert => => """ environment = EMPTY_SHADER_IN_CURDIR glslc_args = ['-MD', 'shader.vert'] expected_object_filenames = ('a.spv', ) target_filename = 'shader.vert.spv.d' expected_file_contents = ['shader.vert.spv: shader.vert\n'] class DependencyInfoFileMatch(GlslCTest): """Mixin class for tests that can expect dependency info files. To mix in this class, subclasses need to provide dependency_info_filenames and dependency_info_files_expected_contents which are two lists. list dependency_info_filenames contains the dependency info file names and list dependency_info_files_expected_contents contains the expected matching dependency rules. The item order of the two lists should match, which means: dependency_info_files_expected_contents[i] should describe the dependency rules saved in dependency_info_filenames[i] The content of each dependency info file is described in same 'list of dict' structure explained in class DependencyInfoStdoutMatch's doc string. """ def check_dependency_info_files(self, status): dep_info_files = \ [os.path.join(status.directory, f) for f in self.dependency_info_filenames] for i, df in enumerate(dep_info_files): if not os.path.isfile(df): return False, 'Cannot find file: ' + df try: with open(df, 'r') as dff: content = dff.read() rules = parse_text_rules(content.split('\n')) process_test_specified_dependency_info_rules( self.dependency_info_files_expected_contents[i]) if self.dependency_info_files_expected_contents[ i] != rules: return False, ( 'Incorrect dependency info:\n{ac_rules}\n' 'Expected:\n{ex_rules}\n' 'Incorrect file output:\n{ac_out}\n' 'Incorrect dependency info file:\n{ac_file}\n'.format( ac_rules=rules, ex_rules=self.dependency_rules_expected, ac_stdout=content, ac_file=df)) except IOError: return False, ('Could not open dependency info file ' + df + ' for reading') return True, '' @inside_glslc_testsuite('OptionsCapM') class TestDashCapMWorksWithDashO(DependencyInfoFileMatch): """Tests -M works with -o option. When user specifies an output file name with -o, the dependency info should be dumped to the user specified output file. """ environment = EMPTY_SHADER_IN_CURDIR glslc_args = ['-M', 'shader.vert', '-o', 'dep_info'] dependency_info_filenames = ('dep_info', ) dependency_info_files_expected_contents = [] dependency_info_files_expected_contents.append( [{'target': 'shader.vert.spv', 'dependency': {'shader.vert'}}]) @inside_glslc_testsuite('OptionsCapM') class TestDashCapMDMultipleFile(expect.ValidNamedObjectFile, DependencyInfoFileMatch): """Tests that -MD generates dependency info file for multiple files. e.g. glslc -MD a.vert b.vert -c => => => => """ environment = Directory('.', [File('a.vert', MINIMAL_SHADER), File('b.vert', MINIMAL_SHADER)]) glslc_args = ['-MD', 'a.vert', 'b.vert', '-c'] expected_object_filenames = ('a.vert.spv', 'b.vert.spv', ) dependency_info_filenames = ['a.vert.spv.d', 'b.vert.spv.d'] dependency_info_files_expected_contents = [] dependency_info_files_expected_contents.append([{'target': 'a.vert.spv', 'dependency': {'a.vert'}} ]) dependency_info_files_expected_contents.append([{'target': 'b.vert.spv', 'dependency': {'b.vert'}} ]) @inside_glslc_testsuite('OptionsCapM') class TestDashCapMDMultipleFilePreprocessingOnlyMode(expect.StdoutMatch, DependencyInfoFileMatch): """Tests that -MD generates dependency info file for multiple files in preprocessing only mode. e.g. glslc -MD a.vert b.vert -E => stdout: preprocess result of a.vert and b.vert => => """ environment = Directory('.', [File('a.vert', MINIMAL_SHADER), File('b.vert', MINIMAL_SHADER)]) glslc_args = ['-MD', 'a.vert', 'b.vert', '-E'] dependency_info_filenames = ['a.vert.spv.d', 'b.vert.spv.d'] dependency_info_files_expected_contents = [] dependency_info_files_expected_contents.append([{'target': 'a.vert.spv', 'dependency': {'a.vert'}} ]) dependency_info_files_expected_contents.append([{'target': 'b.vert.spv', 'dependency': {'b.vert'}} ]) expected_stdout = ("#version 140\nvoid main() { }\n" "#version 140\nvoid main() { }\n") @inside_glslc_testsuite('OptionsCapM') class TestDashCapMDMultipleFileDisassemblyMode(expect.ValidNamedAssemblyFile, DependencyInfoFileMatch): """Tests that -MD generates dependency info file for multiple files in disassembly mode. e.g. glslc -MD a.vert b.vert -S => => => => """ environment = Directory('.', [File('a.vert', MINIMAL_SHADER), File('b.vert', MINIMAL_SHADER)]) glslc_args = ['-MD', 'a.vert', 'b.vert', '-S'] expected_assembly_filenames = ('a.vert.spvasm', 'b.vert.spvasm', ) dependency_info_filenames = ['a.vert.spvasm.d', 'b.vert.spvasm.d'] dependency_info_files_expected_contents = [] dependency_info_files_expected_contents.append([{'target': 'a.vert.spvasm', 'dependency': {'a.vert'}} ]) dependency_info_files_expected_contents.append([{'target': 'b.vert.spvasm', 'dependency': {'b.vert'}} ]) @inside_glslc_testsuite('OptionsCapM') class TestDashCapMT(expect.ValidFileContents, expect.ValidNamedObjectFile): """Tests that -MT generates dependency info file with specified target label. e.g. glslc -MD shader.vert -MT target_label => => """ environment = EMPTY_SHADER_IN_CURDIR glslc_args = ['-MD', 'shader.vert', '-MT', 'target_label'] expected_object_filenames = ('a.spv', ) target_filename = 'shader.vert.spv.d' expected_file_contents = ['target_label: shader.vert\n'] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMF(expect.ValidFileContents, expect.ValidNamedObjectFile): """Tests that -MF dumps dependency info into specified file. e.g. glslc -MD shader.vert -MF dep_file => => """ environment = EMPTY_SHADER_IN_CURDIR glslc_args = ['-MD', 'shader.vert', '-MF', 'dep_file'] expected_object_filenames = ('a.spv', ) target_filename = 'dep_file' expected_file_contents = ['shader.vert.spv: shader.vert\n'] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMDSpecifyOutputFileName(expect.ValidFileContents, expect.ValidNamedObjectFile): """Tests that -MD has the default dependency info file name and target label correct when -o appears in the command line. The default dependency info file name and target label should be deduced from the linking-disabled compilation output. e.g. glslc -MD subdir/shader.vert -c -o output => <./output: valid SPIR-V object file> => <./output.d: dependency info: "output: shader.vert"> """ environment = EMPTY_SHADER_IN_SUBDIR glslc_args = ['-MD', 'subdir/shader.vert', '-c', '-o', 'output'] expected_object_filenames = ('output', ) target_filename = 'output.d' expected_file_contents = ['output: subdir/shader.vert\n'] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMDWithDashMFDashMTDashO(expect.ValidFileContents, expect.ValidNamedObjectFile): """Tests that -MD, -MF, -MT and -o gernates dependency info file and compilation output file correctly e.g. glslc -MD subdir/shader.vert -c -o subdir/out -MF dep_info -MT label => => """ environment = EMPTY_SHADER_IN_SUBDIR glslc_args = ['-MD', 'subdir/shader.vert', '-c', '-o', 'subdir/out', '-MF', 'dep_info', '-MT', 'label'] expected_object_filenames = ('subdir/out', ) target_filename = 'dep_info' expected_file_contents = ['label: subdir/shader.vert\n'] @inside_glslc_testsuite('OptionsCapM') class TestDashCapMDWithDashMFDashMTDashODisassemblyMode( expect.ValidFileContents, expect.ValidNamedAssemblyFile): """Tests that -MD, -MF, -MT and -o gernates dependency info file and compilation output file correctly in disassembly mode e.g. glslc -MD subdir/shader.vert -s -o subdir/out -MF dep_info -MT label => => """ environment = EMPTY_SHADER_IN_SUBDIR glslc_args = ['-MD', 'subdir/shader.vert', '-S', '-o', 'subdir/out', '-MF', 'dep_info', '-MT', 'label'] expected_assembly_filenames = ('subdir/out', ) target_filename = 'dep_info' expected_file_contents = ['label: subdir/shader.vert\n'] @inside_glslc_testsuite('OptionsCapM') class TestErrorSetBothDashCapMAndDashCapMD(expect.StderrMatch): """Tests that when both -M (or -MM) and -MD are specified, glslc should exit with an error message complaining the case and neither dependency info output nor compilation output. This test has -MD before -M flag. """ environment = EMPTY_SHADER_IN_CURDIR glslc_args = ['-MD', '-M', 'shader.vert'] expected_stderr = ['glslc: error: both -M (or -MM) and -MD are specified. ' 'Only one should be used at one time.\n'] @inside_glslc_testsuite('OptionsCapM') class TestErrorSetBothDashCapMDAndDashCapM(expect.StderrMatch): """Tests that when both -M (or -MM) and -MD are specified, glslc should exit with an error message complaining the case and neither dependency info output nor compilation output. This test has -M before -MD flag. """ environment = EMPTY_SHADER_IN_CURDIR glslc_args = ['-M', '-MD', 'shader.vert'] expected_stderr = ['glslc: error: both -M (or -MM) and -MD are specified. ' 'Only one should be used at one time.\n'] @inside_glslc_testsuite('OptionsCapM') class TestErrorDashCapMFWithMultipleInputFiles(expect.StderrMatch): """Tests that when -MF option is specified, only one input file should be provided.""" environment = Directory('.', [File('a.vert', MINIMAL_SHADER), File('b.vert', MINIMAL_SHADER)]) glslc_args = ['-MD', 'a.vert', 'b.vert', '-c', '-MF', 'dep_info'] expected_stderr = ['glslc: error: ' 'to specify dependency info file name or dependency ' 'info target, only one input file is allowed.\n'] @inside_glslc_testsuite('OptionsCapM') class TestErrorDashCapMTWithMultipleInputFiles(expect.StderrMatch): """Tests that when -MT option is specified, only one input file should be provided.""" environment = Directory('.', [File('a.vert', MINIMAL_SHADER), File('b.vert', MINIMAL_SHADER)]) glslc_args = ['-M', 'a.vert', 'b.vert', '-c', '-MT', 'target'] expected_stderr = ['glslc: error: ' 'to specify dependency info file name or dependency ' 'info target, only one input file is allowed.\n'] @inside_glslc_testsuite('OptionsCapM') class TestErrorDashCapMFMissingDashMAndDashMD(expect.StderrMatch): """Tests that when only -MF is specified while -M and -MD are not specified, glslc should emit an error complaining that the user must specifiy either -M (-MM) or -MD to generate dependency info. """ environment = EMPTY_SHADER_IN_CURDIR glslc_args = ['-MF', 'dep_info', 'shader.vert', '-c'] expected_stderr = ['glslc: error: ' 'to generate dependencies you must specify either -M ' '(-MM) or -MD\n'] @inside_glslc_testsuite('OptionsCapM') class TestErrorDashCapMTMissingDashMAndMDWith(expect.StderrMatch): """Tests that when only -MF and -MT is specified while -M and -MD are not specified, glslc should emit an error complaining that the user must specifiy either -M (-MM) or -MD to generate dependency info. """ environment = EMPTY_SHADER_IN_CURDIR glslc_args = ['-MF', 'dep_info', '-MT', 'target', 'shader.vert', '-c'] expected_stderr = ['glslc: error: ' 'to generate dependencies you must specify either -M ' '(-MM) or -MD\n'] @inside_glslc_testsuite('OptionsCapM') class TestErrorMissingDependencyInfoFileName(expect.StderrMatch): """Tests that dependency file name is missing when -MF is specified.""" environment = EMPTY_SHADER_IN_CURDIR glslc_args = ['target', 'shader.vert', '-c', '-MF'] expected_stderr = ['glslc: error: ' 'missing dependency info filename after \'-MF\'\n'] @inside_glslc_testsuite('OptionsCapM') class TestErrorMissingDependencyTargetName(expect.StderrMatch): """Tests that dependency target name is missing when -MT is specified.""" environment = EMPTY_SHADER_IN_CURDIR glslc_args = ['target', 'shader.vert', '-c', '-MT'] expected_stderr = ['glslc: error: ' 'missing dependency info target after \'-MT\'\n'] shaderc-2025.2/glslc/test/option_dash_S.py000066400000000000000000000130651500222170200204370ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect import os.path from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader, StdinShader def simple_vertex_shader(): return """#version 310 es void main() { gl_Position = vec4(1., 2., 3., 4.); }""" def simple_fragment_shader(): return """#version 310 es void main() { gl_FragDepth = 10.; }""" def simple_compute_shader(): return """#version 310 es void main() { uvec3 temp = gl_WorkGroupID; }""" @inside_glslc_testsuite('OptionDashCapS') class TestSingleDashCapSSingleFile(expect.ValidAssemblyFile): """Tests that -S works with a single file.""" shader = FileShader(simple_vertex_shader(), '.vert') glslc_args = ['-S', shader] @inside_glslc_testsuite('OptionDashCapS') class TestSingleFileSingleDashCapS(expect.ValidAssemblyFile): """Tests that the position of -S doesn't matter.""" shader = FileShader(simple_vertex_shader(), '.vert') glslc_args = [shader, '-S'] @inside_glslc_testsuite('OptionDashCapS') class TestSingleDashCapSMultipleFiles(expect.ValidAssemblyFile): """Tests that -S works with multiple files.""" shader1 = FileShader(simple_vertex_shader(), '.vert') shader2 = FileShader(simple_vertex_shader(), '.vert') shader3 = FileShader(simple_fragment_shader(), '.frag') glslc_args = ['-S', shader1, shader2, shader3] @inside_glslc_testsuite('OptionDashCapS') class TestMultipleDashCapSSingleFile(expect.ValidAssemblyFile): """Tests that multiple -Ss works as one.""" shader = FileShader(simple_vertex_shader(), '.vert') glslc_args = ['-S', '-S', shader, '-S'] @inside_glslc_testsuite('OptionDashCapS') class TestMultipleDashCapSMultipleFiles(expect.ValidAssemblyFile): """Tests a mix of -Ss and files.""" shader1 = FileShader(simple_fragment_shader(), '.frag') shader2 = FileShader(simple_vertex_shader(), '.vert') shader3 = FileShader(simple_compute_shader(), '.comp') glslc_args = ['-S', shader1, '-S', '-S', shader2, '-S', shader3, '-S'] @inside_glslc_testsuite('OptionDashCapS') class TestDashCapSWithDashC(expect.ValidAssemblyFile): """Tests that -S overwrites -c.""" shader1 = FileShader(simple_fragment_shader(), '.frag') shader2 = FileShader(simple_vertex_shader(), '.vert') glslc_args = ['-c', '-S', shader1, '-c', '-c', shader2] @inside_glslc_testsuite('OptionDashCapS') class TestDashCapSWithDashFShaderStage(expect.ValidAssemblyFile): """Tests that -S works with -fshader-stage=.""" shader1 = FileShader(simple_fragment_shader(), '.glsl') shader2 = FileShader(simple_vertex_shader(), '.glsl') shader3 = FileShader(simple_compute_shader(), '.glsl') glslc_args = ['-S', '-fshader-stage=fragment', shader1, '-fshader-stage=vertex', shader2, '-fshader-stage=compute', shader3] @inside_glslc_testsuite('OptionDashCapS') class TestDashCapSWithDashStd(expect.ValidAssemblyFileWithWarning): """Tests that -S works with -std=.""" shader1 = FileShader(simple_fragment_shader(), '.frag') shader2 = FileShader(simple_vertex_shader(), '.vert') shader3 = FileShader(simple_compute_shader(), '.comp') glslc_args = ['-S', '-std=450', shader1, shader2, shader3] w = (': warning: (version, profile) forced to be (450, none), ' 'while in source code it is (310, es)\n') expected_warning = [ shader1, w, shader2, w, shader3, w, '3 warnings generated.\n'] @inside_glslc_testsuite('OptionDashCapS') class TestDashCapSWithDashOSingleFile(expect.SuccessfulReturn, expect.CorrectAssemblyFilePreamble): """Tests that -S works with -o on a single file.""" shader = FileShader(simple_fragment_shader(), '.frag') glslc_args = ['-S', '-o', 'blabla', shader] def check_output_blabla(self, status): output_name = os.path.join(status.directory, 'blabla') return self.verify_assembly_file_preamble(output_name) @inside_glslc_testsuite('OptionDashCapS') class TestDashCapSWithDashOMultipleFiles(expect.ErrorMessage): """Tests that -S works with -o on a single file.""" shader1 = FileShader(simple_fragment_shader(), '.frag') shader2 = FileShader(simple_vertex_shader(), '.vert') glslc_args = ['-S', '-o', 'blabla', shader1, shader2] expected_error = ['glslc: error: cannot specify -o when ' 'generating multiple output files\n'] @inside_glslc_testsuite('OptionDashCapS') class TestDashCapSWithStdIn(expect.ValidAssemblyFile): """Tests that -S works with stdin.""" shader = StdinShader(simple_fragment_shader()) glslc_args = ['-S', '-fshader-stage=fragment', shader] @inside_glslc_testsuite('OptionDashCapS') class TestDashCapSWithStdOut( expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch): """Tests that -S works with stdout.""" shader = FileShader(simple_fragment_shader(), '.frag') glslc_args = ['-S', '-o', '-', shader] expected_stdout = True expected_stderr = '' shaderc-2025.2/glslc/test/option_dash_c.py000066400000000000000000000035411500222170200204550ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader def empty_es_310_shader(): return '#version 310 es\n void main() {}\n' @inside_glslc_testsuite('OptionC') class TestSingleDashCSingleFile(expect.ValidObjectFile): """Tests that glslc accepts -c [filename].""" shader = FileShader(empty_es_310_shader(), '.vert') glslc_args = ['-c', shader] @inside_glslc_testsuite('OptionC') class TestSingleFileSingleDashC(expect.ValidObjectFile): """Tests that glslc accepts [filename] -c.""" shader = FileShader(empty_es_310_shader(), '.vert') glslc_args = [shader, '-c'] @inside_glslc_testsuite('OptionC') class TestMultipleFiles(expect.ValidObjectFile): """Tests that glslc accepts -c and multiple source files.""" shader1 = FileShader(empty_es_310_shader(), '.vert') shader2 = FileShader(empty_es_310_shader(), '.frag') glslc_args = ['-c', shader1, shader2] @inside_glslc_testsuite('OptionC') class TestMultipleDashC(expect.ValidObjectFile): """Tests that glslc accepts multiple -c and treated them as one.""" shader1 = FileShader(empty_es_310_shader(), '.vert') shader2 = FileShader(empty_es_310_shader(), '.vert') glslc_args = ['-c', shader1, '-c', '-c', shader2] shaderc-2025.2/glslc/test/option_dash_cap_O.py000066400000000000000000000132221500222170200212510ustar00rootroot00000000000000# Copyright 2016 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from environment import File, Directory from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader MINIMAL_SHADER = '#version 310 es\nvoid main() {}' EMPTY_SHADER_IN_CWD = Directory('.', [File('shader.vert', MINIMAL_SHADER)]) ASSEMBLY_WITH_DEBUG_SOURCE = [ """; SPIR-V ; Version: 1.0 ; Generator: Google Shaderc over Glslang; 11 ; Bound: 7 ; Schema: 0 OpCapability Shader %2 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Vertex %main "main" %1 = OpString "shader.vert" OpSource ESSL 310 %1 "// OpModuleProcessed entry-point main // OpModuleProcessed client vulkan100 // OpModuleProcessed target-env vulkan1.0 // OpModuleProcessed entry-point main #line 1 #version 310 es void main() {}" OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" OpSourceExtension "GL_GOOGLE_include_directive" OpName %main "main" %void = OpTypeVoid %4 = OpTypeFunction %void OpLine %1 2 11 %main = OpFunction %void None %4 %6 = OpLabel OpLine %1 2 0 OpReturn OpFunctionEnd """ ] ASSEMBLY_O0 = [ """; SPIR-V ; Version: 1.0 ; Generator: Google Shaderc over Glslang; 11 ; Bound: 6 ; Schema: 0 OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Vertex %main "main" OpSource ESSL 310 OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" OpSourceExtension "GL_GOOGLE_include_directive" OpName %main "main" %void = OpTypeVoid %3 = OpTypeFunction %void %main = OpFunction %void None %3 %5 = OpLabel OpReturn OpFunctionEnd """] ASSEMBLY_O = [ """; SPIR-V ; Version: 1.0 ; Generator: Google Shaderc over Glslang; 11 ; Bound: 6 ; Schema: 0 OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Vertex %4 "main" %void = OpTypeVoid %3 = OpTypeFunction %void %4 = OpFunction %void None %3 %5 = OpLabel OpReturn OpFunctionEnd """] ASSEMBLY_Os = [ """; SPIR-V ; Version: 1.0 ; Generator: Google Shaderc over Glslang; 11 ; Bound: 6 ; Schema: 0 OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Vertex %4 "main" %void = OpTypeVoid %3 = OpTypeFunction %void %4 = OpFunction %void None %3 %5 = OpLabel OpReturn OpFunctionEnd """] @inside_glslc_testsuite('OptionDashCapO') class TestDashCapO0(expect.ValidFileContents): """Tests that -O0 works.""" environment = EMPTY_SHADER_IN_CWD glslc_args = ['-S', '-O0', 'shader.vert'] target_filename = 'shader.vert.spvasm' expected_file_contents = ASSEMBLY_O0 @inside_glslc_testsuite('OptionDashCapO') class TestDashCapOPerformance(expect.ValidFileContents): """Tests -O works.""" environment = EMPTY_SHADER_IN_CWD glslc_args = ['-S', '-O', 'shader.vert'] target_filename = 'shader.vert.spvasm' expected_file_contents = ASSEMBLY_O @inside_glslc_testsuite('OptionDashCapO') class TestDashCapOs(expect.ValidFileContents): """Tests that -Os works.""" environment = EMPTY_SHADER_IN_CWD glslc_args = ['-S', '-Os', 'shader.vert'] target_filename = 'shader.vert.spvasm' expected_file_contents = ASSEMBLY_Os @inside_glslc_testsuite('OptionDashCapO') class TestDashCapOOverriding(expect.ValidFileContents): """Tests that if there are multiple -O's, only the last one takes effect.""" environment = EMPTY_SHADER_IN_CWD glslc_args = ['-S', '-Os', '-O0', '-Os', '-O0', 'shader.vert'] target_filename = 'shader.vert.spvasm' expected_file_contents = ASSEMBLY_O0 @inside_glslc_testsuite('OptionDashCapO') class TestDashCapOWithDashG(expect.ValidFileContents): """Tests that -g restrains -O from turning on strip debug info.""" environment = EMPTY_SHADER_IN_CWD glslc_args = ['-S', '-Os', '-g', 'shader.vert'] target_filename = 'shader.vert.spvasm' expected_file_contents = ASSEMBLY_WITH_DEBUG_SOURCE @inside_glslc_testsuite('OptionDashCapO') class TestDashGWithDashCapO(expect.ValidFileContents): """Tests that -g restrains -O from turning on strip debug info.""" environment = EMPTY_SHADER_IN_CWD glslc_args = ['-S', '-g', '-Os', 'shader.vert'] target_filename = 'shader.vert.spvasm' expected_file_contents = ASSEMBLY_WITH_DEBUG_SOURCE @inside_glslc_testsuite('OptionDashCapO') class TestWrongOptLevel(expect.NoGeneratedFiles, expect.ErrorMessage): """Tests erroring out with wrong optimization level.""" shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = ['-c', '-O2', shader] expected_error = "glslc: error: invalid value '2' in '-O2'\n" shaderc-2025.2/glslc/test/option_dash_fhlsl_offsets.py000066400000000000000000000030471500222170200230750ustar00rootroot00000000000000# Copyright 2017 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader # A GLSL shader with uniforms without explicit bindings. GLSL_SHADER = """#version 450 layout(set=0, binding=0) buffer B { float x; vec3 y; } my_ssbo; void main() { my_ssbo.x = 1.0; }""" @inside_glslc_testsuite('OptionFHlslOffsets') class StandardOffsetsByDefault(expect.ValidAssemblyFileWithSubstr): """Tests that standard GLSL packign is used by default.""" shader = FileShader(GLSL_SHADER, '.vert') glslc_args = ['-S', shader] expected_assembly_substr = "OpMemberDecorate %B 1 Offset 16" @inside_glslc_testsuite('OptionFHlslOffsets') class HlslOffsetsWhenRequested(expect.ValidAssemblyFileWithSubstr): """Tests that standard GLSL packign is used by default.""" shader = FileShader(GLSL_SHADER, '.vert') glslc_args = ['-S', '-fhlsl-offsets', shader] expected_assembly_substr = "OpMemberDecorate %B 1 Offset 4" shaderc-2025.2/glslc/test/option_dash_fnan_clamp.py000066400000000000000000000051411500222170200223270ustar00rootroot00000000000000# Copyright 2019 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader # A GLSL shader using the clamp, max, and min builtin functions. GLSL_FRAG_SHADER_WITH_CLAMP = """#version 450 layout(location=0) in vec4 i; layout(location=0) out vec4 o; void main() { o = clamp(i, vec4(0.5), vec4(1.0)) + max(i, vec4(0.5)) + min(i, vec4(0.5)); } """ @inside_glslc_testsuite('OptionFNanClamp') class TestClampMapsToFClampByDefault(expect.ValidAssemblyFileWithSubstr): shader = FileShader(GLSL_FRAG_SHADER_WITH_CLAMP, '.frag') glslc_args = ['-S', shader] expected_assembly_substr = 'OpExtInst %v4float %1 FClamp' @inside_glslc_testsuite('OptionFNanClamp') class TestMaxMapsToFMaxByDefault(expect.ValidAssemblyFileWithSubstr): shader = FileShader(GLSL_FRAG_SHADER_WITH_CLAMP, '.frag') glslc_args = ['-S', shader] expected_assembly_substr = 'OpExtInst %v4float %1 FMax' @inside_glslc_testsuite('OptionFNanClamp') class TestMinMapsToFMinByDefault(expect.ValidAssemblyFileWithSubstr): shader = FileShader(GLSL_FRAG_SHADER_WITH_CLAMP, '.frag') glslc_args = ['-S', shader] expected_assembly_substr = 'OpExtInst %v4float %1 FMin' @inside_glslc_testsuite('OptionFNanClamp') class TestClampMapsToNClampWithFlag(expect.ValidAssemblyFileWithSubstr): shader = FileShader(GLSL_FRAG_SHADER_WITH_CLAMP, '.frag') glslc_args = ['-S', '-fnan-clamp', shader] expected_assembly_substr = 'OpExtInst %v4float %1 NClamp' @inside_glslc_testsuite('OptionFNanClamp') class TestMaxMapsToNMaxWithFlag(expect.ValidAssemblyFileWithSubstr): shader = FileShader(GLSL_FRAG_SHADER_WITH_CLAMP, '.frag') glslc_args = ['-S', '-fnan-clamp', shader] expected_assembly_substr = 'OpExtInst %v4float %1 NMax' @inside_glslc_testsuite('OptionFNanClamp') class TestMinMapsToNMinWithFlag(expect.ValidAssemblyFileWithSubstr): shader = FileShader(GLSL_FRAG_SHADER_WITH_CLAMP, '.frag') glslc_args = ['-S', '-fnan-clamp', shader] expected_assembly_substr = 'OpExtInst %v4float %1 NMin' shaderc-2025.2/glslc/test/option_dash_g.py000066400000000000000000000036221500222170200204610ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader def empty_es_310_shader(): return '#version 310 es\n void main() {}\n' @inside_glslc_testsuite('OptionG') class TestSingleDashGSingleFile(expect.ValidObjectFile): """Tests that glslc accepts -g [filename]. Need -c for now too.""" shader = FileShader(empty_es_310_shader(), '.vert') glslc_args = ['-c', '-g', shader] @inside_glslc_testsuite('OptionG') class TestSingleFileSingleDashG(expect.ValidObjectFile): """Tests that glslc accepts [filename] -g -c.""" shader = FileShader(empty_es_310_shader(), '.vert') glslc_args = [shader, '-g', '-c'] @inside_glslc_testsuite('OptionG') class TestMultipleFiles(expect.ValidObjectFile): """Tests that glslc accepts -g and multiple source files.""" shader1 = FileShader(empty_es_310_shader(), '.vert') shader2 = FileShader(empty_es_310_shader(), '.frag') glslc_args = ['-c', shader1, '-g', shader2] @inside_glslc_testsuite('OptionG') class TestMultipleDashG(expect.ValidObjectFile): """Tests that glslc accepts multiple -g and treated them as one.""" shader1 = FileShader(empty_es_310_shader(), '.vert') shader2 = FileShader(empty_es_310_shader(), '.vert') glslc_args = ['-c', '-g', shader1, '-g', '-g', shader2] shaderc-2025.2/glslc/test/option_dash_o.py000066400000000000000000000075351500222170200205000ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect import os.path from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader, TempFileName from builtins import bytes @inside_glslc_testsuite('OptionDashO') class TestOptionDashOConcatenatedArg(expect.SuccessfulReturn, expect.CorrectObjectFilePreamble): """Tests that we can concatenate -o and the output filename.""" shader = FileShader('#version 140\nvoid main() {}', '.vert') glslc_args = ['-ofoo', shader] def check_output_foo(self, status): output_name = os.path.join(status.directory, 'foo') return self.verify_object_file_preamble(output_name) @inside_glslc_testsuite('OptionDashO') class ManyOutputFilesWithDashO(expect.ErrorMessage): """Tests -o and -c with several files generates an error.""" shader1 = FileShader('', '.vert') shader2 = FileShader('', '.frag') glslc_args = ['-o', 'foo', '-c', shader1, shader2] expected_error = [ 'glslc: error: cannot specify -o when ' 'generating multiple output files\n'] @inside_glslc_testsuite('OptionDashO') class OutputFileLocation(expect.SuccessfulReturn, expect.CorrectObjectFilePreamble): """Tests that the -o flag puts a file in a new location.""" shader = FileShader('#version 310 es\nvoid main() {}', '.frag') glslc_args = [shader, '-o', TempFileName('a.out')] def check_output_a_out(self, status): output_name = os.path.join(status.directory, 'a.out') return self.verify_object_file_preamble(output_name) @inside_glslc_testsuite('OptionDashO') class DashOMissingArgumentIsAnError(expect.ErrorMessage): """Tests that -o without an argument is an error.""" glslc_args = ['-o'] expected_error = ['glslc: error: argument to \'-o\' is missing ' + '(expected 1 value)\n'] @inside_glslc_testsuite('OptionDashO') class OutputFileBinaryAvoidsCRLFTranslation(expect.ReturnCodeIsZero, expect.NoOutputOnStderr, expect.NoGeneratedFiles, expect.CorrectBinaryLengthAndPreamble): """Tests that the -o flag emits a binary file without CR/LF translation. """ # A shader whose compiled output has three bytes that are newlines. # If the output stream converts the newlines to CR/LF, then we end up # with a file that is 4k + 3 bytes long. That will be caught by the # object file checks. SHADER_WITH_THREE_NEWLINES_IN_BINARY = """#version 450 layout(location = 0) out uint ovar; void main() { ovar = 9; } """ shader = FileShader(SHADER_WITH_THREE_NEWLINES_IN_BINARY, '.vert') glslc_args = [shader, '-o', '-'] def check_stdout_binary(self, status): binary = bytes(status.stdout) newlines = [x for x in binary if x == ord('\n')] num_newlines = len(newlines) if num_newlines % 4 == 0: return False, "Bad test. Need nontrivial number of newlines" if num_newlines != 2: return False, ("Update this test. Expected 3 newlines in the " "binary, but found {}").format(num_newlines) return self.verify_binary_length_and_header(bytes(status.stdout)) shaderc-2025.2/glslc/test/option_dash_x.py000066400000000000000000000123311500222170200204770ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader MINIMAL_SHADER = "#version 140\nvoid main(){}" # This one is valid GLSL but not valid HLSL. GLSL_VERTEX_SHADER = "#version 140\nvoid main(){ gl_Position = vec4(1.0);}" # This one is GLSL but without leading #version. Should result in # a parser error when compiled as HLSL. GLSL_VERTEX_SHADER_WITHOUT_VERSION = "void main(){ gl_Position = vec4(1.0);}" # This one is valid HLSL but not valid GLSL. # Use entry point "main" so we don't have to specify -fentry-point HLSL_VERTEX_SHADER = "float4 main() : SV_POSITION { return float4(1.0); }" @inside_glslc_testsuite('OptionDashX') class TestDashXNoArg(expect.ErrorMessage): """Tests -x with nothing.""" glslc_args = ['-x'] expected_error = [ "glslc: error: argument to '-x' is missing (expected 1 value)\n", 'glslc: error: no input files\n'] @inside_glslc_testsuite('OptionDashX') class TestDashXGlslOnGlslShader(expect.ValidObjectFile): """Tests -x glsl on a GLSL shader.""" shader = FileShader(GLSL_VERTEX_SHADER, '.vert') glslc_args = ['-x', 'glsl', '-c', shader] @inside_glslc_testsuite('OptionDashX') class TestDashXGlslOnHlslShader(expect.ErrorMessageSubstr): """Tests -x glsl on an HLSL shader.""" shader = FileShader(HLSL_VERTEX_SHADER, '.vert') glslc_args = ['-x', 'glsl', '-c', shader] expected_error_substr = ["error: #version: Desktop shaders for Vulkan SPIR-V" " require version 140 or higher\n"] @inside_glslc_testsuite('OptionDashX') class TestDashXHlslOnGlslShader(expect.ErrorMessageSubstr): """Tests -x hlsl on a GLSL shader.""" shader = FileShader(GLSL_VERTEX_SHADER, '.vert') glslc_args = ['-x', 'hlsl', '-c', shader] expected_error_substr = ["error: '#version' : invalid preprocessor command\n"] @inside_glslc_testsuite('OptionDashX') class TestDashXHlslOnGlslShaderWithoutVertex(expect.ErrorMessageSubstr): """Tests -x hlsl on a GLSL shader without leading #version.""" shader = FileShader(GLSL_VERTEX_SHADER_WITHOUT_VERSION, '.vert') glslc_args = ['-x', 'hlsl', '-c', shader] expected_error_substr = ["error: 'vec4' : no matching overloaded function found\n"] @inside_glslc_testsuite('OptionDashX') class TestDashXWrongParam(expect.ErrorMessage): """Tests -x with wrong parameter.""" shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = ['-x', 'gl', shader] expected_error = ["glslc: error: language not recognized: 'gl'\n"] @inside_glslc_testsuite('OptionDashX') class TestMultipleDashX(expect.ValidObjectFile): """Tests that multiple -x works with a single language.""" shader = FileShader(GLSL_VERTEX_SHADER, '.vert') glslc_args = ['-c', '-x', 'glsl', '-x', 'glsl', shader, '-x', 'glsl'] @inside_glslc_testsuite('OptionDashX') class TestMultipleDashXMixedLanguages(expect.ValidObjectFile): """Tests that multiple -x works with different languages.""" glsl_shader = FileShader(GLSL_VERTEX_SHADER, '.vert') hlsl_shader = FileShader(HLSL_VERTEX_SHADER, '.vert') glslc_args = ['-c', '-x', 'hlsl', hlsl_shader, '-x', 'glsl', glsl_shader, '-x', 'hlsl', hlsl_shader, '-x', 'glsl', glsl_shader] @inside_glslc_testsuite('OptionDashX') class TestMultipleDashXCorrectWrong(expect.ErrorMessage): """Tests -x glsl -x [wrong-language].""" shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = ['-x', 'glsl', '-x', 'foo', shader] expected_error = ["glslc: error: language not recognized: 'foo'\n"] @inside_glslc_testsuite('OptionDashX') class TestMultipleDashXWrongCorrect(expect.ErrorMessage): """Tests -x [wrong-language] -x glsl.""" shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = ['-xbar', '-x', 'glsl', shader] expected_error = ["glslc: error: language not recognized: 'bar'\n"] @inside_glslc_testsuite('OptionDashX') class TestDashXGlslConcatenated(expect.ValidObjectFile): """Tests -xglsl.""" shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = ['-xglsl', shader, '-c'] @inside_glslc_testsuite('OptionDashX') class TestDashXWrongParamConcatenated(expect.ErrorMessage): """Tests -x concatenated with a wrong language.""" shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = ['-xsl', shader] expected_error = ["glslc: error: language not recognized: 'sl'\n"] @inside_glslc_testsuite('OptionDashX') class TestDashXEmpty(expect.ErrorMessage): """Tests -x ''.""" shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = ['-x', '', shader] expected_error = ["glslc: error: language not recognized: ''\n"] shaderc-2025.2/glslc/test/option_dashdash_version.py000066400000000000000000000033261500222170200225610ustar00rootroot00000000000000# Copyright 2016 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite import re @inside_glslc_testsuite('OptionDashDashVersion') class TestVersionContainsShaderc(expect.StdoutMatch, expect.ReturnCodeIsZero): """Tests --version output contains 'shaderc'.""" glslc_args = ['--version'] expected_stdout = re.compile('^shaderc') @inside_glslc_testsuite('OptionDashDashVersion') class TestVersionContainsSpirvTools(expect.StdoutMatch, expect.ReturnCodeIsZero): """Tests --version output contains 'spirv-tools'.""" glslc_args = ['--version'] expected_stdout = re.compile('\nspirv-tools') @inside_glslc_testsuite('OptionDashDashVersion') class TestVersionContainsGlslang(expect.StdoutMatch, expect.ReturnCodeIsZero): """Tests --version output contains 'glslang'.""" glslc_args = ['--version'] expected_stdout = re.compile('\nglslang') @inside_glslc_testsuite('OptionDashDashVersion') class TestVersionContainsTarget(expect.StdoutMatch, expect.ReturnCodeIsZero): """Tests --version output contains 'Target:'.""" glslc_args = ['--version'] expected_stdout = re.compile('\nTarget: SPIR-V \d+\.\d+') shaderc-2025.2/glslc/test/option_fauto_bind_uniforms.py000066400000000000000000000453141500222170200232740ustar00rootroot00000000000000# Copyright 2017 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader # A GLSL shader with uniforms without explicit bindings. GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS = """#version 450 #extension GL_ARB_sparse_texture2 : enable uniform texture2D my_tex; uniform sampler my_sam; layout(rgba32f) uniform image2D my_img; layout(rgba32f) uniform imageBuffer my_imbuf; uniform block { float x; float y; } my_ubo; buffer B { float z; } my_ssbo; void main() { texture(sampler2D(my_tex,my_sam),vec2(1.0)); vec4 t; sparseImageLoadARB(my_img,ivec2(0),t); imageLoad(my_imbuf,42); float x = my_ubo.x; my_ssbo.z = 1.1; }""" # An HLSL shader with uniforms without explicit bindings. # The counter buffer has an associated counter that needs a # binding. Compile this shader with --auto-bind-uniforms to # give it a binding, since Glslang does not support attribute # [[vk::counter_binding(N))]]. # See https://github.com/KhronosGroup/glslang/issues/1616 HLSL_SHADER_WITHOUT_BINDINGS = """ SamplerState s1 : register(s1); SamplerComparisonState s2 : register(s2); Texture1D t1 : register(t11); Texture2D t2 : register(t12); Texture3D t3 : register(t13); StructuredBuffer t4 : register(t14); ByteAddressBuffer t5 : register(t15); Buffer t6 : register(t16); RWTexture1D u1 : register(u21); RWTexture1D u2 : register(u22); RWTexture1D u3 : register(u23); RWBuffer u4 : register(u24); RWByteAddressBuffer u5 : register(u25); RWStructuredBuffer u6 : register(u26); AppendStructuredBuffer u7 : register(u27); ConsumeStructuredBuffer u8 : register(u28); float4 main() : SV_Target0 { s1; s2; t1; t2; t3; t4[2]; t5.Load(8); t6; u1; u2; u3; u4[1]; u5.Load(15); u6[2]; u7; u8; // SampleCmp disabled due to https://github.com/KhronosGroup/glslang/issues/2444. //return float4(u8.Consume() + t2.SampleCmp(s2, 1.0, 2.0)) + t1.Sample(s1, 1.0) // + t6.Load(1); return float4(u8.Consume()) + t1.Sample(s1, 1.0) + t6.Load(1); } """ @inside_glslc_testsuite('OptionFAutoBindUniforms') class UniformBindingsNotCreatedByDefault(expect.ErrorMessageSubstr): """Tests that compilation fails when uniforms have no binding.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader] expected_error_substr = "sampler/texture/image requires layout(binding=X)" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FAutoBindingUniformsGeneratesBindings(expect.ValidAssemblyFileWithSubstr): """Tests that the compiler generates bindings for uniforms upon request .""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fauto-bind-uniforms'] # Sufficient to just check one of the uniforms. expected_assembly_substr = "OpDecorate %my_sam Binding 1" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FImageBindingBaseOptionRespectedOnImage(expect.ValidAssemblyFileWithSubstr): """Tests that -fimage-binding-base value is respected on images.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fauto-bind-uniforms', '-fimage-binding-base', '44'] expected_assembly_substr = "OpDecorate %my_img Binding 44" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FImageBindingBaseOptionRespectedOnImageBuffer(expect.ValidAssemblyFileWithSubstr): """Tests that -fimage-binding-base value is respected on image buffers.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fauto-bind-uniforms', '-fimage-binding-base', '44'] expected_assembly_substr = "OpDecorate %my_imbuf Binding 45" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FTextureBindingBaseOptionRespected(expect.ValidAssemblyFileWithSubstr): """Tests that -ftexture-binding-base value is respected.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fauto-bind-uniforms', '-ftexture-binding-base', '44'] expected_assembly_substr = "OpDecorate %my_tex Binding 44" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FSamplerBindingBaseOptionRespected(expect.ValidAssemblyFileWithSubstr): """Tests that -fsampler-binding-base value is respected.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fauto-bind-uniforms', '-fsampler-binding-base', '44'] expected_assembly_substr = "OpDecorate %my_sam Binding 44" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FUboBindingBaseOptionRespectedOnBuffer(expect.ValidAssemblyFileWithSubstr): """Tests that -fubo-binding-base value is respected.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fauto-bind-uniforms', '-fubo-binding-base', '44'] expected_assembly_substr = "OpDecorate %my_ubo Binding 44" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FCbufferBindingBaseOptionRespectedOnBuffer(expect.ValidAssemblyFileWithSubstr): """Tests that -fcbuffer-binding-base value is respected.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fauto-bind-uniforms', '-fcbuffer-binding-base', '44'] expected_assembly_substr = "OpDecorate %my_ubo Binding 44" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FImageBindingBaseNeedsValue(expect.ErrorMessageSubstr): """Tests that -fimage-binding-base requires a value.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fimage-binding-base'] expected_error_substr = "error: Option -fimage-binding-base requires at least one argument" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FTextureBindingBaseNeedsValue(expect.ErrorMessageSubstr): """Tests that -ftexture-binding-base requires a value.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-ftexture-binding-base'] expected_error_substr = "error: Option -ftexture-binding-base requires at least one argument" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FSamplerBindingBaseNeedsValue(expect.ErrorMessageSubstr): """Tests that -fsampler-binding-base requires a value.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fsampler-binding-base'] expected_error_substr = "error: Option -fsampler-binding-base requires at least one argument" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FUboBindingBaseNeedsValue(expect.ErrorMessageSubstr): """Tests that -fubo-binding-base requires a value.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fubo-binding-base'] expected_error_substr = "error: Option -fubo-binding-base requires at least one argument" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FImageBindingBaseNeedsNumberValueIfNotStage(expect.ErrorMessageSubstr): """Tests that -fimage-binding-base requires a number value.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fimage-binding-base', '9x'] expected_error_substr = "error: invalid offset value 9x for -fimage-binding-base" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FTextureBindingBaseNeedsNumberValue(expect.ErrorMessageSubstr): """Tests that -ftexture-binding-base requires a number value.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-ftexture-binding-base', '9x'] expected_error_substr = "error: invalid offset value 9x for -ftexture-binding-base" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FSamplerBindingBaseNeedsNumberValue(expect.ErrorMessageSubstr): """Tests that -fsampler-binding-base requires a number value.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fsampler-binding-base', '9x'] expected_error_substr = "error: invalid offset value 9x for -fsampler-binding-base" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FUboBindingBaseNeedsNumberValue(expect.ErrorMessageSubstr): """Tests that -fubo-binding-base requires a number value.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fubo-binding-base', '9x'] expected_error_substr = "error: invalid offset value 9x for -fubo-binding-base" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FImageBindingBaseNeedsUnsignedNumberValue(expect.ErrorMessageSubstr): """Tests that -fimage-binding-base requires an unsigned number value.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fimage-binding-base', '-6'] expected_error_substr = "error: invalid offset value -6 for -fimage-binding-base" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FTextureBindingBaseNeedsUnsignedNumberValue(expect.ErrorMessageSubstr): """Tests that -ftexture-binding-base requires an unsigned number value.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-ftexture-binding-base', '-6'] expected_error_substr = "error: invalid offset value -6 for -ftexture-binding-base" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FSamplerBindingBaseNeedsUnsignedNumberValue(expect.ErrorMessageSubstr): """Tests that -fsampler-binding-base requires an unsigned value.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fsampler-binding-base', '-6'] expected_error_substr = "error: invalid offset value -6 for -fsampler-binding-base" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FUboBindingBaseNeedsUnsignedNumberValue(expect.ErrorMessageSubstr): """Tests that -fubo-binding-base requires an unsigned value.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fubo-binding-base', '-6'] expected_error_substr = "error: invalid offset value -6 for -fubo-binding-base" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FImageBindingBaseForVertOptionRespectedOnImageCompileAsVert(expect.ValidAssemblyFileWithSubstr): """Tests that -fimage-binding-base with vert stage value is respected on images.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fauto-bind-uniforms', '-fimage-binding-base', 'vert', '44'] expected_assembly_substr = "OpDecorate %my_img Binding 44" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FImageBindingBaseForVertOptionIgnoredOnImageCompileAsFrag(expect.ValidAssemblyFileWithSubstr): """Tests that -fimage-binding-base with vert stage value is ignored when cmopiled as fragment.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', shader, '-fauto-bind-uniforms', '-fimage-binding-base', 'vert', '44'] expected_assembly_substr = "OpDecorate %my_img Binding 2" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FImageBindingBaseForFragOptionRespectedOnImageCompileAsFrag(expect.ValidAssemblyFileWithSubstr): """Tests that -fimage-binding-base with frag stage value is respected on images.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', shader, '-fauto-bind-uniforms', '-fimage-binding-base', 'frag', '44'] expected_assembly_substr = "OpDecorate %my_img Binding 44" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FSsboBindingBaseRespectedOnSsboCompileAsFrag(expect.ValidAssemblyFileWithSubstr): """Tests that -fssbo-binding-base with frag stage value is respected on SSBOs.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', shader, '-fauto-bind-uniforms', '-fssbo-binding-base', '100'] expected_assembly_substr = "OpDecorate %my_ssbo Binding 100" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FSsboBindingBaseForFragOptionRespectedOnSsboCompileAsFrag(expect.ValidAssemblyFileWithSubstr): """Tests that -fssbo-binding-base with frag stage value is respected on SSBOs.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', shader, '-fauto-bind-uniforms', '-fssbo-binding-base', 'frag', '100'] expected_assembly_substr = "OpDecorate %my_ssbo Binding 100" @inside_glslc_testsuite('OptionFAutoBindUniforms') class FSsboBindingBaseForFragOptionIgnoredOnSsboCompileAsVert(expect.ValidAssemblyFileWithSubstr): """Tests that -fssbo-binding-base with frag stage value is ignored on SSBOs when compiling as a vertex shader.""" shader = FileShader(GLSL_SHADER_WITH_UNIFORMS_WITHOUT_BINDINGS, '.vert') glslc_args = ['-S', shader, '-fauto-bind-uniforms', '-fssbo-binding-base', 'frag', '100'] expected_assembly_substr = "OpDecorate %my_ssbo Binding 5" @inside_glslc_testsuite('OptionFAutoBindUniforms') class AutomaticHlslIoMapping(expect.ValidAssemblyFileWithSubstr): """Tests that HLSL IO Mapping uses the register values in the source code.""" shader = FileShader(HLSL_SHADER_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-iomap', '-fauto-bind-uniforms', shader] expected_assembly_substr = "OpDecorate %u8 Binding 28" @inside_glslc_testsuite('OptionFAutoBindUniforms') class HlslFSamplerBindingBaseOptionRespected(expect.ValidAssemblyFileWithSubstr): """Tests that -fsampler-binding-base sets binding base for samplers in HLSL compilation.""" shader = FileShader(HLSL_SHADER_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-iomap', shader, '-fauto-bind-uniforms', '-fsampler-binding-base', '100'] expected_assembly_substr = "OpDecorate %s1 Binding 101" @inside_glslc_testsuite('OptionFAutoBindUniforms') class HlslFSamplerBindingBaseForFragOptionRespected(expect.ValidAssemblyFileWithSubstr): """Tests that -fsampler-binding-base for frag sets binding base for samplers in HLSL compilation.""" shader = FileShader(HLSL_SHADER_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-iomap', shader, '-fauto-bind-uniforms', '-fsampler-binding-base', 'frag', '100'] expected_assembly_substr = "OpDecorate %s1 Binding 101" @inside_glslc_testsuite('OptionFAutoBindUniforms') class HlslFSamplerBindingBaseForComputeOptionIgnoredWhenCompilingAsFrag(expect.ValidAssemblyFileWithSubstr): """Tests that -fsampler-binding-base for compute is ignored when compiling as a fragment shader.""" shader = FileShader(HLSL_SHADER_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-iomap', shader, '-fauto-bind-uniforms', '-fsampler-binding-base', 'compute', '100'] expected_assembly_substr = "OpDecorate %s1 Binding 1" @inside_glslc_testsuite('OptionFAutoBindUniforms') class HlslFTextureBindingBaseOptionRespected(expect.ValidAssemblyFileWithSubstr): """Tests that -ftexture-binding-base sets binding base for textures in HLSL compilation.""" shader = FileShader(HLSL_SHADER_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-iomap', shader, '-fauto-bind-uniforms', '-ftexture-binding-base', '100'] expected_assembly_substr = "OpDecorate %t6 Binding 116" @inside_glslc_testsuite('OptionFAutoBindUniforms') class HlslFTextureBindingBaseForFragOptionRespected(expect.ValidAssemblyFileWithSubstr): """Tests that -ftexture-binding-base for frag sets binding base for textures in HLSL compilation.""" shader = FileShader(HLSL_SHADER_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-iomap', shader, '-fauto-bind-uniforms', '-ftexture-binding-base', 'frag', '100'] expected_assembly_substr = "OpDecorate %t6 Binding 116" @inside_glslc_testsuite('OptionFAutoBindUniforms') class HlslFTextureBindingBaseForComputeOptionIgnoredWhenCompilingAsFrag(expect.ValidAssemblyFileWithSubstr): """Tests that -ftexture-binding-base for compute is ignored when compiling as a fragment shader.""" shader = FileShader(HLSL_SHADER_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-iomap', shader, '-fauto-bind-uniforms', '-ftexture-binding-base', 'compute', '100'] expected_assembly_substr = "OpDecorate %t6 Binding 16" @inside_glslc_testsuite('OptionFAutoBindUniforms') class HlslFUavBindingBaseOptionRespected(expect.ValidAssemblyFileWithSubstr): """Tests that -fuav-binding-base sets binding base for UAVs in HLSL compilation.""" shader = FileShader(HLSL_SHADER_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-iomap', shader, '-fauto-bind-uniforms', '-fuav-binding-base', '100'] expected_assembly_substr = "OpDecorate %u8 Binding 128" @inside_glslc_testsuite('OptionFAutoBindUniforms') class HlslFUavBindingBaseForFragOptionRespected(expect.ValidAssemblyFileWithSubstr): """Tests that -fuav-binding-base for frag sets binding base for UAVs in HLSL compilation.""" shader = FileShader(HLSL_SHADER_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-iomap', shader, '-fauto-bind-uniforms', '-fuav-binding-base', 'frag', '100'] expected_assembly_substr = "OpDecorate %u8 Binding 128" @inside_glslc_testsuite('OptionFAutoBindUniforms') class HlslFUavBindingBaseForComputeOptionIgnoredWhenCompilingAsFrag(expect.ValidAssemblyFileWithSubstr): """Tests that -fuav-binding-base for compute is ignored when compiling as a fragment shader.""" shader = FileShader(HLSL_SHADER_WITHOUT_BINDINGS, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-iomap', shader, '-fauto-bind-uniforms', '-fuav-binding-base', 'compute', '100'] expected_assembly_substr = "OpDecorate %u8 Binding 28" shaderc-2025.2/glslc/test/option_fauto_combined_image_sampler.py000066400000000000000000000050711500222170200250770ustar00rootroot00000000000000# Copyright 2018 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader # A GLSL shader with a separate sampler and texture2D object GLSL_SHADER_SEPARATE_IMAGE_SAMPLER = """#version 460 layout (location=0) in vec2 in_UV; layout (location=0) out vec4 out_Color; layout (set=0,binding=0) uniform sampler u_Sampler; layout (set=0,binding=0) uniform texture2D u_Tex; void main() { out_Color = texture(sampler2D(u_Tex, u_Sampler), in_UV); }""" # An HLSL fragment shader with the usual Texture2D and SamplerState pair HLSL_SHADER_SEPARATE_IMAGE_SAMPLER = """ Texture2D u_Tex; SamplerState u_Sampler; float4 Frag(float2 uv) : COLOR0 { return u_Tex.Sample(u_Sampler, uv); }""" @inside_glslc_testsuite('OptionFAutoCombinedImageSampler') class FAutoCombinedImageSamplerCheckGLSL(expect.ValidAssemblyFileWithSubstr): """Tests that the compiler combines GLSL sampler and texture2D objects.""" shader = FileShader(GLSL_SHADER_SEPARATE_IMAGE_SAMPLER, '.frag') glslc_args = ['-S', '-fauto-combined-image-sampler', shader] expected_assembly_substr = """%10 = OpTypeImage %float 2D 0 0 0 1 Unknown %11 = OpTypeSampledImage %10 %_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11 %u_Tex = OpVariable %_ptr_UniformConstant_11 UniformConstant""" @inside_glslc_testsuite('OptionFAutoCombinedImageSampler') class FAutoCombinedImageSamplerCheckHLSL(expect.ValidAssemblyFileWithSubstr): """Tests that the HLSL compiler combines HLSL Texture2D and SamplerState objects into SPIRV SampledImage.""" shader = FileShader(HLSL_SHADER_SEPARATE_IMAGE_SAMPLER, '.hlsl') glslc_args = ['-S', '-fshader-stage=frag', '-fentry-point=Frag', '-fauto-combined-image-sampler', shader] expected_assembly_substr = """%14 = OpTypeImage %float 2D 0 0 0 1 Unknown %15 = OpTypeSampledImage %14 %_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15 %u_Tex = OpVariable %_ptr_UniformConstant_15 UniformConstant""" shaderc-2025.2/glslc/test/option_fauto_map_locations.py000066400000000000000000000066021500222170200232630ustar00rootroot00000000000000# Copyright 2018 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader # A GLSL shader with inputs and outputs explicit locations. GLSL_SHADER_IO_WITHOUT_LOCATIONS = """#version 310 es in vec4 m_in; in vec4 m_in1; out vec4 m_out; out vec4 m_out1; void main() { m_out = m_in; m_out1 = m_in1; }""" # An HLSL fragment shader with inputs and outputs explicit locations. HLSL_SHADER_IO_WITHOUT_LOCATIONS = """ float4 Foo(float4 a, float4 b) : COLOR0 { return a + b; }""" @inside_glslc_testsuite('OptionFAutoMapLocations') class MissingLocationsResultsInError(expect.ErrorMessageSubstr): """Tests that compilation fails when inputs or outputs have no location.""" shader = FileShader(GLSL_SHADER_IO_WITHOUT_LOCATIONS, '.vert') glslc_args = ['-S', shader] expected_error_substr = "SPIR-V requires location for user input/output" @inside_glslc_testsuite('OptionFAutoMapLocations') class FAutoMapLocationsGeneratesLocationsCheckInput(expect.ValidAssemblyFileWithSubstr): """Tests that the compiler generates locations upon request: Input 0""" shader = FileShader(GLSL_SHADER_IO_WITHOUT_LOCATIONS, '.vert') glslc_args = ['-S', shader, '-fauto-map-locations'] expected_assembly_substr = "OpDecorate %m_in Location 0" @inside_glslc_testsuite('OptionFAutoMapLocations') class FAutoMapLocationsGeneratesLocationsCheckOutput0(expect.ValidAssemblyFileWithSubstr): """Tests that the compiler generates locations upon request: Output 0""" shader = FileShader(GLSL_SHADER_IO_WITHOUT_LOCATIONS, '.vert') glslc_args = ['-S', shader, '-fauto-map-locations'] expected_assembly_substr = "OpDecorate %m_out Location 0" # Currently Glslang only generates Location 0. # See https://github.com/KhronosGroup/glslang/issues/1261 # TODO(dneto): Write tests that check Location 1 is generated for inputs and # outputs. # Glslang's HLSL compiler automatically assigns locations inptus and outputs. @inside_glslc_testsuite('OptionFAutoMapLocations') class HLSLCompilerGeneratesLocationsCheckInput0(expect.ValidAssemblyFileWithSubstr): """Tests that the HLSL compiler generates locations automatically: Input 0.""" shader = FileShader(HLSL_SHADER_IO_WITHOUT_LOCATIONS, '.hlsl') glslc_args = ['-S', '-fshader-stage=frag', '-fentry-point=Foo', shader] expected_assembly_substr = "OpDecorate %a Location 0" @inside_glslc_testsuite('OptionFAutoMapLocations') class HLSLCompilerGeneratesLocationsCheckOutput(expect.ValidAssemblyFileWithSubstr): """Tests that the HLSL compiler generates locations automatically: Output.""" shader = FileShader(HLSL_SHADER_IO_WITHOUT_LOCATIONS, '.hlsl') glslc_args = ['-S', '-fshader-stage=frag', '-fentry-point=Foo', shader] expected_assembly_substr = "OpDecorate %_entryPointOutput Location 0" shaderc-2025.2/glslc/test/option_fentry_point.py000066400000000000000000000120261500222170200217520ustar00rootroot00000000000000# Copyright 2016 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader MINIMAL_SHADER = "#version 140\nvoid main(){}" # This one is valid GLSL but not valid HLSL. GLSL_VERTEX_SHADER = "#version 140\nvoid main(){ gl_Position = vec4(1.0);}" # This one is valid HLSL but not valid GLSL. HLSL_VERTEX_SHADER = "float4 EntryPoint() : SV_POSITION { return float4(1.0); }" HLSL_VERTEX_SHADER_WITH_MAIN = "float4 main() : SV_POSITION { return float4(1.0); }" HLSL_VERTEX_SHADER_WITH_FOOBAR = "float4 Foobar() : SV_POSITION { return float4(1.0); }" # Expected assembly code within certain shaders. ASSEMBLY_ENTRY_POINT = "OpEntryPoint Vertex %EntryPoint \"EntryPoint\"" ASSEMBLY_MAIN = "OpEntryPoint Vertex %main \"main\"" ASSEMBLY_FOOBAR = "OpEntryPoint Vertex %Foobar \"Foobar\"" @inside_glslc_testsuite('OptionFEntryPoint') class TestEntryPointDefaultsToMainForGlsl(expect.ValidAssemblyFileWithSubstr): """Tests that entry point name defaults to "main" in a GLSL shader.""" shader = FileShader(GLSL_VERTEX_SHADER, '.vert') glslc_args = ['-S', shader] expected_assembly_substr = ASSEMBLY_MAIN @inside_glslc_testsuite('OptionFEntryPoint') class TestEntryPointDefaultsToMainForHlsl(expect.ValidAssemblyFileWithSubstr): """Tests that entry point name defaults to "main" in an HLSL shader.""" shader = FileShader(HLSL_VERTEX_SHADER_WITH_MAIN, '.vert') glslc_args = ['-x', 'hlsl', '-S', shader] expected_assembly_substr = ASSEMBLY_MAIN @inside_glslc_testsuite('OptionFEntryPoint') class TestFEntryPointMainOnGlslShader(expect.ValidAssemblyFileWithSubstr): """Tests -fentry-point=main with a GLSL shader.""" shader = FileShader(GLSL_VERTEX_SHADER, '.vert') glslc_args = ['-fentry-point=main', '-S', shader] expected_assembly_substr = ASSEMBLY_MAIN @inside_glslc_testsuite('OptionFEntryPoint') class TestFEntryPointMainOnHlslShaderNotMatchingSource(expect.ValidObjectFileWithWarning): """Tests -x hlsl on an HLSL shader with -fentry-point=main not matching the source.""" shader = FileShader(HLSL_VERTEX_SHADER, '.vert') glslc_args = ['-x', 'hlsl', '-fentry-point=main', '-c', shader] expected_warning = [shader, ': warning: Linking vertex stage: Entry point not found\n' '1 warning generated.\n'] @inside_glslc_testsuite('OptionFEntryPoint') class TestFEntryPointSpecifiedOnHlslShaderInDisassembly(expect.ValidObjectFileWithAssemblySubstr): """Tests -x hlsl on an HLSL shader with -fentry-point=EntryPoint matching source.""" shader = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT) glslc_args = ['-x', 'hlsl', '-fentry-point=EntryPoint', '-c', shader] @inside_glslc_testsuite('OptionFEntryPoint') class TestFEntryPointAffectsSubsequentShaderFiles(expect.ValidObjectFileWithAssemblySubstr): """Tests -x hlsl affects several subsequent shader source files.""" shader1 = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT) shader2 = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT) glslc_args = ['-x', 'hlsl', '-fentry-point=EntryPoint', '-c', shader1, shader2] @inside_glslc_testsuite('OptionFEntryPoint') class TestFEntryPointOverridesItself(expect.ValidObjectFileWithAssemblySubstr): """Tests that a later -fentry-point option overrides an earlier use.""" shader = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT) glslc_args = ['-x', 'hlsl', '-fentry-point=foobar', '-fentry-point=EntryPoint', '-c', shader] @inside_glslc_testsuite('OptionFEntryPoint') class TestFEntryPointDefaultAndTwoOthers(expect.ValidObjectFileWithAssemblySubstr): """Tests three shaders with different entry point names. The first uses "main" with default entry point processing, and the remaining shaders get their own -fentry-point argument.""" shaderMain = FileShader(HLSL_VERTEX_SHADER_WITH_MAIN, '.vert', assembly_substr=ASSEMBLY_MAIN) shaderEntryPoint = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT) shaderFoobar = FileShader(HLSL_VERTEX_SHADER_WITH_FOOBAR, '.vert', assembly_substr=ASSEMBLY_FOOBAR) glslc_args = ['-x', 'hlsl', '-c', shaderMain, '-fentry-point=EntryPoint', shaderEntryPoint, '-fentry-point=Foobar', shaderFoobar] shaderc-2025.2/glslc/test/option_fhlsl_16bit_types.py000066400000000000000000000033641500222170200226000ustar00rootroot00000000000000# Copyright 2018 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader HLSL_SHADER_WITH_HALF_TYPE = """ float4 main() : SV_Target0 { half h0 = (half)0.0; half h1 = (half)1.0; half h2 = (half)2.0; half h3 = (half)3.0; half4 v = (half4)(h0,h1,h2,h3) * (half)2.0; return (float4)(v); } """ @inside_glslc_testsuite('OptionFHlsl16BitTypes') class TestHlsl16BitTypes_EnablesCapability(expect.ValidAssemblyFileWithSubstr): """Tests that -fhlsl_16bit_types enables the 16bit floating point capability.""" shader = FileShader(HLSL_SHADER_WITH_HALF_TYPE, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-16bit-types', '-fauto-bind-uniforms', shader] expected_assembly_substr = 'OpCapability Float16'; @inside_glslc_testsuite('OptionFHlsl16BitTypes') class TestHlsl16BitTypes_CreatesType(expect.ValidAssemblyFileWithSubstr): """Tests that -fhlsl_16bit_types creates the 16bit floating point capability.""" shader = FileShader(HLSL_SHADER_WITH_HALF_TYPE, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-16bit-types', '-fauto-bind-uniforms', shader] expected_assembly_substr = '= OpTypeFloat 16'; shaderc-2025.2/glslc/test/option_fhlsl_functionality1.py000066400000000000000000000060401500222170200233720ustar00rootroot00000000000000# Copyright 2018 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader # An HLSL shader with a counter buffer with a counter increment. # Glslang doesn't automatically assign a binding to the counter, and # it doesn't understand [[vk::counter_binding(n)]], so compile this # with --auto-bind-uniforms. # See https://github.com/KhronosGroup/glslang/issues/1616 HLSL_VERTEX_SHADER_WITH_COUNTER_BUFFER = """ RWStructuredBuffer Ainc; float4 main() : SV_Target0 { return float4(Ainc.IncrementCounter(), 0, 1, 2); } """ @inside_glslc_testsuite('OptionFHlslFunctionality1') class TestHlslFunctionality1MentionsExtension(expect.ValidAssemblyFileWithSubstr): """Tests that -fhlsl_functionality1 enabled SPV_GOOGLE_hlsl_functionality1.""" shader = FileShader(HLSL_VERTEX_SHADER_WITH_COUNTER_BUFFER, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl_functionality1', '-fauto-bind-uniforms', shader] expected_assembly_substr = 'OpExtension "SPV_GOOGLE_hlsl_functionality1"' @inside_glslc_testsuite('OptionFHlslFunctionality1') class TestHlslFunctionality1DecoratesCounter(expect.ValidAssemblyFileWithSubstr): """Tests that -fhlsl_functionality1 decorates the output target""" shader = FileShader(HLSL_VERTEX_SHADER_WITH_COUNTER_BUFFER, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl_functionality1', '-fauto-bind-uniforms', shader] expected_assembly_substr = 'OpDecorateString' ## Next tests use the option with the hypen instead of underscore. @inside_glslc_testsuite('OptionFHlslFunctionality1') class TestHlslHyphenFunctionality1MentionsExtension(expect.ValidAssemblyFileWithSubstr): """Tests that -fhlsl-functionality1 enabled SPV_GOOGLE_hlsl_functionality1.""" shader = FileShader(HLSL_VERTEX_SHADER_WITH_COUNTER_BUFFER, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl_functionality1', '-fauto-bind-uniforms', shader] expected_assembly_substr = 'OpExtension "SPV_GOOGLE_hlsl_functionality1"' @inside_glslc_testsuite('OptionFHlslFunctionality1') class TestHlslHyphenFunctionality1DecoratesCounter(expect.ValidAssemblyFileWithSubstr): """Tests that -fhlsl-functionality1 decorates the output target""" shader = FileShader(HLSL_VERTEX_SHADER_WITH_COUNTER_BUFFER, '.frag') glslc_args = ['-S', '-x', 'hlsl', '-fhlsl_functionality1', '-fauto-bind-uniforms', shader] expected_assembly_substr = 'OpDecorateString' shaderc-2025.2/glslc/test/option_flimit.py000066400000000000000000000375061500222170200205300ustar00rootroot00000000000000# Copyright 2016 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from environment import File, Directory from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader def shader_source_with_tex_offset(offset): """Returns a vertex shader using a texture access with the given offset.""" return """#version 450 layout (binding=0) uniform sampler1D tex; void main() { vec4 x = textureOffset(tex, 1.0, """ + str(offset) + "); }" def shader_with_tex_offset(offset): """Returns a vertex FileShader using a texture access with the given offset.""" return FileShader(shader_source_with_tex_offset(offset), ".vert") @inside_glslc_testsuite('OptionFLimit') class TestFLimitNoEqual(expect.ErrorMessage): """Tests -flimit without equal.""" glslc_args = ['-flimit'] expected_error = ["glslc: error: unknown argument: '-flimit'\n"] @inside_glslc_testsuite('OptionFLimit') class TestFLimitJustEqual(expect.ValidObjectFile): """Tests -flimit= with no argument.""" shader = shader_with_tex_offset(0); glslc_args = ['-c', shader, '-flimit='] @inside_glslc_testsuite('OptionFLimit') class TestFLimitJustEqualMaxOffset(expect.ValidObjectFile): """Tests -flimit= with no argument. The shader uses max offset.""" shader = shader_with_tex_offset(7); glslc_args = ['-c', shader, '-flimit='] @inside_glslc_testsuite('OptionFLimit') class TestFLimitJustEqualMinOffset(expect.ValidObjectFile): """Tests -flimit= with no argument. The shader uses min offset.""" shader = shader_with_tex_offset(-8); glslc_args = ['-c', shader, '-flimit='] @inside_glslc_testsuite('OptionFLimit') class TestFLimitJustEqualBelowMinOffset(expect.ErrorMessageSubstr): """Tests -flimit= with no argument. The shader uses below min default offset.""" shader = shader_with_tex_offset(-9); glslc_args = ['-c', shader, '-flimit='] expected_error_substr = ["'texel offset' : value is out of range"] @inside_glslc_testsuite('OptionFLimit') class TestFLimitLowerThanDefaultMinOffset(expect.ValidObjectFile): """Tests -flimit= with lower than default argument. The shader uses below min offset.""" shader = shader_with_tex_offset(-9); glslc_args = ['-c', shader, '-flimit= MinProgramTexelOffset -9 '] @inside_glslc_testsuite('OptionFLimit') class TestFLimitIgnoredLangFeatureSettingSample(expect.ValidObjectFile): """Tests -flimit= an ignored option.""" shader = FileShader("#version 150\nvoid main() { while(true); }", '.vert') glslc_args = ['-c', shader, '-flimit=whileLoops 0'] @inside_glslc_testsuite('OptionFLimit') class TestFLimitLowerThanDefaultMinOffset(expect.ValidObjectFile): """Tests -flimit= with lower than default argument. The shader uses that offset.""" shader = shader_with_tex_offset(-9); glslc_args = ['-c', shader, '-flimit= MinProgramTexelOffset -9 '] @inside_glslc_testsuite('OptionFLimitFile') class TestFLimitFileNoArg(expect.ErrorMessage): """Tests -flimit-file without an argument""" shader = shader_with_tex_offset(-9); glslc_args = ['-c', shader, '-flimit-file'] expected_error = "glslc: error: argument to '-flimit-file' is missing\n" @inside_glslc_testsuite('OptionFLimitFile') class TestFLimitFileMissingFile(expect.ErrorMessageSubstr): """Tests -flimit-file without an argument""" shader = shader_with_tex_offset(-9); glslc_args = ['-c', shader, '-flimit-file', 'i do not exist'] expected_error_substr = "glslc: error: cannot open input file: 'i do not exist'"; @inside_glslc_testsuite('OptionFLimitFile') class TestFLimitFileSetsLowerMinTexelOffset(expect.ValidObjectFile): """Tests -flimit-file with lower than default argument. The shader uses that offset.""" limits_file = File('limits.txt', 'MinProgramTexelOffset -9') shader = File('shader.vert', shader_source_with_tex_offset(-9)); environment = Directory('.', [limits_file, shader]) glslc_args = ['-c', shader.name, '-flimit-file', limits_file.name] @inside_glslc_testsuite('OptionFLimitFile') class TestFLimitFileInvalidContents(expect.ErrorMessage): """Tests -flimit-file bad file contents.""" limits_file = File('limits.txt', 'thisIsBad') shader = File('shader.vert', shader_source_with_tex_offset(-9)); environment = Directory('.', [limits_file, shader]) glslc_args = ['-c', shader.name, '-flimit-file', limits_file.name] expected_error = 'glslc: error: -flimit-file error: invalid resource limit: thisIsBad\n' ## Mesh shading def mesh_shader_with_params(kwargs): """Returns a mesh shader as a FileShader, with given parameters""" import sys source = """#version 450 #extension {} : enable layout(local_size_x={}) in; layout(local_size_y={}) in; layout(local_size_z={}) in; layout(triangles) out; layout(max_vertices={}) out; layout(max_primitives={}) out; layout(triangles) out; void main() {{ }} """.format(kwargs['extension'],kwargs['x'],kwargs['y'],kwargs['z'],kwargs['max_vert'],kwargs['max_prim']) return FileShader(source,".mesh") def task_shader_with_params(kwargs): """Returns a task shader as a FileShader, with given parameters""" import sys source = """#version 450 #extension {} : enable layout(local_size_x={}) in; layout(local_size_y={}) in; layout(local_size_z={}) in; void main() {{ }} """.format(kwargs['extension'],kwargs['x'],kwargs['y'],kwargs['z']) return FileShader(source,".task") def meshDefaults(nv_or_ext,show=False): result = dict({ # See Glslang's glslang/ResourceLimits/ResourceLimits.cpp 'nv': { 'extension': 'GL_NV_mesh_shader', 'x': 32, 'y': 1, 'z': 1, 'max_vert': 256, 'max_prim': 512 }, 'ext': { 'extension': 'GL_EXT_mesh_shader', 'x': 128, 'y': 128, 'z': 128, 'max_vert': 256, 'max_prim': 256 } })[nv_or_ext] if show: import sys print(result,file=sys.stderr) return result ## GL_NV_mesh_shader @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_NV_X_ok(expect.ValidObjectFile): shader = mesh_shader_with_params(meshDefaults('nv')) glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeX_NV 32'] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_NV_X_bad(expect.ErrorMessageSubstr): shader = mesh_shader_with_params(meshDefaults('nv')) expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeNV" glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeX_NV 31'] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_NV_Y_ok(expect.ValidObjectFile): shader = mesh_shader_with_params(meshDefaults('nv')) glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeY_NV 1'] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_NV_Y_bad(expect.ErrorMessageSubstr): d = meshDefaults('nv') d['y'] = 3 shader = mesh_shader_with_params(d) expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeNV" glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeY_NV 2'] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_NV_Z_ok(expect.ValidObjectFile): shader = mesh_shader_with_params(meshDefaults('nv')) glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeZ_NV 1'] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_NV_Z_bad(expect.ErrorMessageSubstr): d = meshDefaults('nv') d['z'] = 3 shader = mesh_shader_with_params(d) expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeNV" glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeZ_NV 2'] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_NV_MaxVert_ok(expect.ValidObjectFile): shader = mesh_shader_with_params(meshDefaults('nv')) glslc_args = ['-c', shader, '-flimit= MaxMeshOutputVerticesNV 256'] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_NV_MaxVert_bad(expect.ErrorMessageSubstr): shader = mesh_shader_with_params(meshDefaults('nv')) expected_error_substr = "'max_vertices' : too large, must be less than gl_MaxMeshOutputVerticesNV" glslc_args = ['-c', shader, '-flimit= MaxMeshOutputVerticesNV 255'] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_NV_MaxPrim_ok(expect.ValidObjectFile): shader = mesh_shader_with_params(meshDefaults('nv')) glslc_args = ['-c', shader, '-flimit= MaxMeshOutputPrimitivesNV 512'] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_NV_MaxPrim_bad(expect.ErrorMessageSubstr): shader = mesh_shader_with_params(meshDefaults('nv')) expected_error_substr = "'max_primitives' : too large, must be less than gl_MaxMeshOutputPrimitivesNV" glslc_args = ['-c', shader, '-flimit= MaxMeshOutputPrimitivesNV 511'] @inside_glslc_testsuite('OptionFLimit_Task') class TestFLimitTaskShader_NV_X_ok(expect.ValidObjectFile): shader = task_shader_with_params(meshDefaults('nv')) glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeX_NV 32'] @inside_glslc_testsuite('OptionFLimit_Task') class TestFLimitTaskShader_NV_X_bad(expect.ErrorMessageSubstr): shader = task_shader_with_params(meshDefaults('nv')) expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeNV" glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeX_NV 31'] @inside_glslc_testsuite('OptionFLimit_Task') class TestFLimitTaskShader_NV_Y_ok(expect.ValidObjectFile): shader = task_shader_with_params(meshDefaults('nv')) glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeY_NV 1'] @inside_glslc_testsuite('OptionFLimit_Task') class TestFLimitTaskShader_NV_Y_bad(expect.ErrorMessageSubstr): d = meshDefaults('nv') d['y'] = 3 shader = task_shader_with_params(d) expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeNV" glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeY_NV 2'] @inside_glslc_testsuite('OptionFLimit_Task') class TestFLimitTaskShader_NV_Z_ok(expect.ValidObjectFile): shader = task_shader_with_params(meshDefaults('nv')) glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeZ_NV 1'] @inside_glslc_testsuite('OptionFLimit_Task') class TestFLimitTaskShader_NV_Z_bad(expect.ErrorMessageSubstr): d = meshDefaults('nv') d['z'] = 3 shader = task_shader_with_params(d) expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeNV" glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeZ_NV 2'] # TODO: Test MaxMeshViewCountNV ## GL_EXT_mesh_shader ## It requires SPIR-V 1.4 s14 = '--target-spv=spv1.4' @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_EXT_X_ok(expect.ValidObjectFile1_4): shader = mesh_shader_with_params(meshDefaults('ext')) glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeX_EXT 128', s14] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_EXT_X_bad(expect.ErrorMessageSubstr): shader = mesh_shader_with_params(meshDefaults('ext')) expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeEXT" glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeX_EXT 127', s14] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_EXT_Y_ok(expect.ValidObjectFile1_4): shader = mesh_shader_with_params(meshDefaults('ext')) glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeY_EXT 128', s14] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_EXT_Y_bad(expect.ErrorMessageSubstr): shader = mesh_shader_with_params(meshDefaults('ext')) expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeEXT" glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeY_EXT 127', s14] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_EXT_Z_ok(expect.ValidObjectFile1_4): shader = mesh_shader_with_params(meshDefaults('ext')) glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeZ_EXT 128', s14] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_EXT_Z_bad(expect.ErrorMessageSubstr): shader = mesh_shader_with_params(meshDefaults('ext')) expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeEXT" glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeZ_EXT 127', s14] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_EXT_MaxVert_ok(expect.ValidObjectFile1_4): shader = mesh_shader_with_params(meshDefaults('ext')) glslc_args = ['-c', shader, '-flimit= MaxMeshOutputVerticesEXT 256', s14] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_EXT_MaxVert_bad(expect.ErrorMessageSubstr): shader = mesh_shader_with_params(meshDefaults('ext')) expected_error_substr = "'max_vertices' : too large, must be less than gl_MaxMeshOutputVerticesEXT" glslc_args = ['-c', shader, '-flimit= MaxMeshOutputVerticesEXT 255', s14] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_EXT_MaxPrim_ok(expect.ValidObjectFile1_4): shader = mesh_shader_with_params(meshDefaults('ext')) glslc_args = ['-c', shader, '-flimit= MaxMeshOutputPrimitivesEXT 256', s14] @inside_glslc_testsuite('OptionFLimit_Mesh') class TestFLimitMeshShader_EXT_MaxPrim_bad(expect.ErrorMessageSubstr): shader = mesh_shader_with_params(meshDefaults('ext')) expected_error_substr = "'max_primitives' : too large, must be less than gl_MaxMeshOutputPrimitivesEXT" glslc_args = ['-c', shader, '-flimit= MaxMeshOutputPrimitivesEXT 255', s14] @inside_glslc_testsuite('OptionFLimit_Task') class TestFLimitTaskShader_EXT_X_ok(expect.ValidObjectFile1_4): shader = task_shader_with_params(meshDefaults('ext')) glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeX_EXT 128', s14] @inside_glslc_testsuite('OptionFLimit_Task') class TestFLimitTaskShader_EXT_X_bad(expect.ErrorMessageSubstr): shader = task_shader_with_params(meshDefaults('ext')) expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeEXT" glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeX_EXT 127', s14] @inside_glslc_testsuite('OptionFLimit_Task') class TestFLimitTaskShader_EXT_Y_ok(expect.ValidObjectFile1_4): shader = task_shader_with_params(meshDefaults('ext')) glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeY_EXT 128', s14] @inside_glslc_testsuite('OptionFLimit_Task') class TestFLimitTaskShader_EXT_Y_bad(expect.ErrorMessageSubstr): import sys d = meshDefaults('ext',True) print("TaskShader_EXT_Y_bad {}".format(str(d)),file=sys.stderr) shader = task_shader_with_params(meshDefaults('ext',True)) expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeEXT" glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeY_EXT 127', s14] @inside_glslc_testsuite('OptionFLimit_Task') class TestFLimitTaskShader_EXT_Z_ok(expect.ValidObjectFile1_4): shader = task_shader_with_params(meshDefaults('ext')) glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeZ_EXT 128', s14] @inside_glslc_testsuite('OptionFLimit_Task') class TestFLimitTaskShader_EXT_Z_bad(expect.ErrorMessageSubstr): shader = task_shader_with_params(meshDefaults('ext')) expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeEXT" glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeZ_EXT 127', s14] # TODO: Test MaxMeshViewCountEXT shaderc-2025.2/glslc/test/option_fpreserve_bindings.py000066400000000000000000000051421500222170200231110ustar00rootroot00000000000000# Copyright 2023 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader # A GLSL shader with unused bindings. GLSL_SHADER_WITH_UNUSED_BINDINGS = """#version 450 layout(binding=0) buffer InputA { vec4 x[]; } inputA; layout(binding=1) buffer InputB { vec4 x[]; } inputB; layout(binding=2) buffer Output { vec4 x[]; } outputO; void main() {} """ @inside_glslc_testsuite('OptionFPreserveBindings') class TestFPreserveBindingsInputA(expect.ValidAssemblyFileWithSubstr): """Tests that the compiler preserves bindings when optimizations are enabled.""" shader = FileShader(GLSL_SHADER_WITH_UNUSED_BINDINGS, '.comp') glslc_args = ['-S', '-O', shader, '-fpreserve-bindings'] # Check the first buffer. expected_assembly_substr = "Binding 0" @inside_glslc_testsuite('OptionFPreserveBindings') class TestFPreserveBindingsInputB(expect.ValidAssemblyFileWithSubstr): """Tests that the compiler preserves bindings when optimizations are enabled.""" shader = FileShader(GLSL_SHADER_WITH_UNUSED_BINDINGS, '.comp') glslc_args = ['-S', '-O', shader, '-fpreserve-bindings'] # Check the first buffer. expected_assembly_substr = "Binding 1" @inside_glslc_testsuite('OptionFPreserveBindings') class TestFPreserveBindingsOutputO(expect.ValidAssemblyFileWithSubstr): """Tests that the compiler preserves bindings when optimizations are enabled.""" shader = FileShader(GLSL_SHADER_WITH_UNUSED_BINDINGS, '.comp') glslc_args = ['-S', '-O', shader, '-fpreserve-bindings'] # Check the first buffer. expected_assembly_substr = "Binding 2" @inside_glslc_testsuite('OptionFPreserveBindings') class TestFNoPreserveBindings(expect.ValidAssemblyFileWithoutSubstr): """Tests that the compiler removes bindings when -fpreserve-bindings is not set.""" shader = FileShader(GLSL_SHADER_WITH_UNUSED_BINDINGS, '.comp') glslc_args = ['-S', '-O', shader] # Check that all binding decorations are gone. unexpected_assembly_substr = "OpDecorate" shaderc-2025.2/glslc/test/option_fresource_set_binding.py000066400000000000000000000111461500222170200235760ustar00rootroot00000000000000# Copyright 2017 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader # An HLSL shader with uniforms without explicit bindings. HLSL_SHADER = """ Buffer t4 : register(t4); Buffer t5 : register(t5); float4 main() : SV_Target0 { return float4(t4.Load(0) + t5.Load(1)); } """ NEED_THREE_ARGS_ERR = "error: Option -fresource-set-binding requires at least 3 arguments" @inside_glslc_testsuite('OptionFRegisterSetBinding') class FRegisterSetBindingForFragRespected(expect.ValidAssemblyFileWithSubstr): """Tests -fresource-set-binding on specific shader two textures""" shader = FileShader(HLSL_SHADER, '.frag') glslc_args = ['-S', '-x', 'hlsl', shader, '-fresource-set-binding', 'frag', 't4', '9', '16', 't5', '17', '18'] expected_assembly_substr = """OpDecorate %t4 Binding 16 OpDecorate %t4 DescriptorSet 9 OpDecorate %t5 Binding 18 OpDecorate %t5 DescriptorSet 17""" @inside_glslc_testsuite('OptionFRegisterSetBinding') class FRegisterSetBindingForFragRespectedJustOneTriple(expect.ValidAssemblyFileWithSubstr): """Tests -fresource-set-binding on specific shader just one texture specified.""" shader = FileShader(HLSL_SHADER, '.frag') glslc_args = ['-S', '-x', 'hlsl', shader, '-fresource-set-binding', 'frag', 't4', '9', '16'] expected_assembly_substr = """OpDecorate %t4 Binding 16 OpDecorate %t4 DescriptorSet 9 OpDecorate %t5 Binding 5 OpDecorate %t5 DescriptorSet 0""" @inside_glslc_testsuite('OptionFRegisterSetBinding') class FRegisterSetBindingForWrongStageIgnored(expect.ValidAssemblyFileWithSubstr): """Tests -fresource-set-binding on wrong shader ignored""" shader = FileShader(HLSL_SHADER, '.frag') glslc_args = ['-S', '-x', 'hlsl', shader, '-fresource-set-binding', 'vert', 't4', '9', '16', 't5', '17', '18'] expected_assembly_substr = """OpDecorate %t4 Binding 4 OpDecorate %t4 DescriptorSet 0 OpDecorate %t5 Binding 5 OpDecorate %t5 DescriptorSet 0""" @inside_glslc_testsuite('OptionFRegisterSetBinding') class FRegisterSetBindingForAllRespected(expect.ValidAssemblyFileWithSubstr): """Tests -fresource-set-binding on all stages respected""" shader = FileShader(HLSL_SHADER, '.frag') glslc_args = ['-S', '-x', 'hlsl', shader, '-fresource-set-binding', 't4', '9', '16', 't5', '17', '18'] expected_assembly_substr = """OpDecorate %t4 Binding 16 OpDecorate %t4 DescriptorSet 9 OpDecorate %t5 Binding 18 OpDecorate %t5 DescriptorSet 17""" @inside_glslc_testsuite('OptionFRegisterSetBinding') class FRegisterSetBindingTooFewArgs(expect.ErrorMessageSubstr): """Tests -fresource-set-binding with too few arguments""" shader = FileShader(HLSL_SHADER, '.frag') glslc_args = ['-S', '-x', 'hlsl', shader, '-fresource-set-binding', 'frag', 't4', '9'] expected_error_substr = NEED_THREE_ARGS_ERR @inside_glslc_testsuite('OptionFRegisterSetBinding') class FRegisterSetBindingInvalidSetNumber(expect.ErrorMessageSubstr): """Tests -fresource-set-binding with inavlid set number""" shader = FileShader(HLSL_SHADER, '.frag') glslc_args = ['-S', '-x', 'hlsl', shader, '-fresource-set-binding', 'frag', 't4', '-9', '16'] expected_error_substr = NEED_THREE_ARGS_ERR @inside_glslc_testsuite('OptionFRegisterSetBinding') class FRegisterSetBindingInvalidBindingNumber(expect.ErrorMessageSubstr): """Tests -fresource-set-binding with inavlid binding number""" shader = FileShader(HLSL_SHADER, '.frag') glslc_args = ['-S', '-x', 'hlsl', shader, '-fresource-set-binding', 'frag', 't4', '9', '-16'] expected_error_substr = NEED_THREE_ARGS_ERR shaderc-2025.2/glslc/test/option_mfmt.py000066400000000000000000000176571500222170200202140ustar00rootroot00000000000000# Copyright 2016 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect import re from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader MINIMAL_SHADER = '#version 140\nvoid main() {}' # Regular expression patterns for the minimal shader. The magic number should # match exactly, and there should not be a trailing comma at the end of the # list. When -mfmt=c is specified, curly brackets should be presented. MINIMAL_SHADER_NUM_FORMAT_PATTERN = "^0x07230203.*[0-9a-f]$" MINIMAL_SHADER_C_FORMAT_PATTERN = "^\\{0x07230203.*[0-9a-f]\\}" ERROR_SHADER = '#version 140\n#error\nvoid main() {}' @inside_glslc_testsuite('OptionMfmt') class TestFmtCWorksWithDashC(expect.ValidFileContents): """Tests that -mfmt=c works with -c for single input file. SPIR-V binary code output should be emitted as a C-style initializer list in the output file. """ shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = [shader, '-c', '-mfmt=c', '-o', 'output_file'] target_filename = 'output_file' expected_file_contents = re.compile(MINIMAL_SHADER_C_FORMAT_PATTERN, re.S) @inside_glslc_testsuite('OptionMfmt') class TestFmtNumWorksWithDashC(expect.ValidFileContents): """Tests that -mfmt=num works with -c for single input file. SPIR-V binary code output should be emitted as a list of hex numbers in the output file. """ shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = [shader, '-c', '-mfmt=num', '-o', 'output_file'] target_filename = 'output_file' expected_file_contents = re.compile(MINIMAL_SHADER_NUM_FORMAT_PATTERN, re.S) @inside_glslc_testsuite('OptionMfmt') class TestFmtBinWorksWithDashC(expect.ValidObjectFile): """Tests that -mfmt=bin works with -c for single input file. This test should simply have the SPIR-V binary generated. """ shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = [shader, '-c', '-mfmt=bin'] @inside_glslc_testsuite('OptionMfmt') class TestFmtCWithLinking(expect.ValidFileContents): """Tests that -mfmt=c works when linkding is enabled (no -c specified). SPIR-V binary code should be emitted as a C-style initializer list in the output file. """ shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = [shader, '-mfmt=c'] target_filename = 'a.spv' expected_file_contents = re.compile(MINIMAL_SHADER_C_FORMAT_PATTERN, re.S) @inside_glslc_testsuite('OptionMfmt') class TestFmtNumWithLinking(expect.ValidFileContents): """Tests that -mfmt=num works when linkding is enabled (no -c specified). SPIR-V binary code should be emitted as a C-style initializer list in the output file. """ shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = [shader, '-mfmt=num'] target_filename = 'a.spv' expected_file_contents = re.compile(MINIMAL_SHADER_NUM_FORMAT_PATTERN, re.S) @inside_glslc_testsuite('OptionMfmt') class TestFmtCErrorWhenOutputDisasembly(expect.ErrorMessage): """Tests that specifying '-mfmt=c' when the compiler is set to disassembly mode should trigger an error. """ shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = [shader, '-mfmt=c', '-S', '-o', 'output_file'] expected_error = ("glslc: error: cannot emit output as a C-style " "initializer list when only preprocessing the source\n") @inside_glslc_testsuite('OptionMfmt') class TestFmtNumErrorWhenOutputDisasembly(expect.ErrorMessage): """Tests that specifying '-mfmt=num' when the compiler is set to disassembly mode should trigger an error. """ shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = [shader, '-mfmt=num', '-S', '-o', 'output_file'] expected_error = ( "glslc: error: cannot emit output as a list of hex numbers " "when only preprocessing the source\n") @inside_glslc_testsuite('OptionMfmt') class TestFmtBinErrorWhenOutputDisasembly(expect.ErrorMessage): """Tests that specifying '-mfmt=bin' when the compiler is set to disassembly mode should trigger an error. """ shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = [shader, '-mfmt=bin', '-S', '-o', 'output_file'] expected_error = ("glslc: error: cannot emit output as a binary " "when only preprocessing the source\n") @inside_glslc_testsuite('OptionMfmt') class TestFmtNumErrorWhenOutputPreprocess(expect.ErrorMessage): """Tests that specifying '-mfmt=num' when the compiler is set to preprocessing only mode should trigger an error. """ shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = [shader, '-mfmt=num', '-E', '-o', 'output_file'] expected_error = ( "glslc: error: cannot emit output as a list of hex numbers " "when only preprocessing the source\n") @inside_glslc_testsuite('OptionMfmt') class TestFmtCErrorWithDashCapM(expect.ErrorMessage): """Tests that specifying '-mfmt=c' should trigger an error when the compiler is set to dump dependency info as the output (-M or -MM is specified). """ shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = [shader, '-mfmt=c', '-M', '-o', 'output_file'] expected_error = ("glslc: error: cannot emit output as a C-style " "initializer list when only preprocessing the source\n") @inside_glslc_testsuite('OptionMfmt') class TestFmtCWorksWithDashCapMD(expect.ValidFileContents): """Tests that -mfmt=c works with '-c -MD'. SPIR-V binary code should be emitted as a C-style initializer list in the output file. """ shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = [shader, '-mfmt=c', '-c', '-MD', '-o', 'output_file'] target_filename = 'output_file' expected_file_contents = re.compile(MINIMAL_SHADER_C_FORMAT_PATTERN, re.S) @inside_glslc_testsuite('OptionMfmt') class TestFmtNumWorksWithDashCapMD(expect.ValidFileContents): """Tests that -mfmt=num works with '-c -MD'. SPIR-V binary code should be emitted as a C-style initializer list in the output file. """ shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = [shader, '-mfmt=num', '-c', '-MD', '-o', 'output_file'] target_filename = 'output_file' expected_file_contents = re.compile(MINIMAL_SHADER_NUM_FORMAT_PATTERN, re.S) @inside_glslc_testsuite('OptionMfmt') class TestFmtCExitsElegantlyWithErrorInShader(expect.ErrorMessage): """Tests that the compiler fails elegantly with -mfmt=c when there are errors in the input shader. """ shader = FileShader(ERROR_SHADER, '.vert') glslc_args = [shader, '-mfmt=c'] expected_error = [shader, ':3: error: \'#error\' :\n', '1 error generated.\n'] @inside_glslc_testsuite('OptionMfmt') class TestFmtNumExitsElegantlyWithErrorInShader(expect.ErrorMessage): """Tests that the compiler fails elegantly with -mfmt=num when there are errors in the input shader. """ shader = FileShader(ERROR_SHADER, '.vert') glslc_args = [shader, '-mfmt=num'] expected_error = [shader, ':3: error: \'#error\' :\n', '1 error generated.\n'] @inside_glslc_testsuite('OptionMfmt') class TestFmtBinExitsElegantlyWithErrorInShader(expect.ErrorMessage): """Tests that the compiler fails elegantly with -mfmt=binary when there are errors in the input shader. """ shader = FileShader(ERROR_SHADER, '.vert') glslc_args = [shader, '-mfmt=bin'] expected_error = [shader, ':3: error: \'#error\' :\n', '1 error generated.\n'] shaderc-2025.2/glslc/test/option_shader_stage.py000066400000000000000000000172571500222170200216760ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader def simple_vertex_shader(): return """#version 310 es void main() { gl_Position = vec4(1., 2., 3., 4.); }""" def simple_hlsl_vertex_shader(): # Use "main" so we don't have to specify -fentry-point return """float4 main() : SV_POSITION { return float4(1.0); } """ def simple_fragment_shader(): return """#version 310 es void main() { gl_FragDepth = 10.; }""" def simple_tessellation_control_shader(): return """#version 440 core layout(vertices = 3) out; void main() { }""" def simple_tessellation_evaluation_shader(): return """#version 440 core layout(triangles) in; void main() { }""" def simple_geometry_shader(): return """#version 150 core layout (triangles) in; layout (line_strip, max_vertices = 4) out; void main() { }""" def simple_compute_shader(): return """#version 310 es void main() { uvec3 temp = gl_WorkGroupID; }""" @inside_glslc_testsuite('OptionShaderStage') class TestShaderStageWithGlslExtension(expect.ValidObjectFile): """Tests -fshader-stage with .glsl extension.""" shader = FileShader(simple_vertex_shader(), '.glsl') glslc_args = ['-c', '-fshader-stage=vertex', shader] @inside_glslc_testsuite('OptionShaderStage') class TestShaderStageWithHlslExtension(expect.ValidObjectFile): """Tests -fshader-stage with .hlsl extension.""" shader = FileShader(simple_hlsl_vertex_shader(), '.hlsl') glslc_args = ['-c', '-fshader-stage=vertex', shader] @inside_glslc_testsuite('OptionShaderStage') class TestShaderStageWithKnownExtension(expect.ValidObjectFile): """Tests -fshader-stage with known extension.""" shader = FileShader(simple_fragment_shader(), '.frag') glslc_args = ['-c', '-fshader-stage=fragment', shader] @inside_glslc_testsuite('OptionShaderStage') class TestShaderStageWithUnknownExtension(expect.ValidObjectFile): """Tests -fshader-stage with unknown extension.""" shader = FileShader(simple_vertex_shader(), '.unknown') glslc_args = ['-c', '-fshader-stage=vertex', shader] @inside_glslc_testsuite('OptionShaderStage') class TestShaderStageWithNoExtension(expect.ValidObjectFile): """Tests -fshader-stage with no extension.""" shader = FileShader(simple_vertex_shader(), '') glslc_args = ['-c', '-fshader-stage=vertex', shader] @inside_glslc_testsuite('OptionShaderStage') class TestAllShaderStages(expect.ValidObjectFile): """Tests all possible -fshader-stage values.""" shader1 = FileShader(simple_vertex_shader(), '.glsl') shader2 = FileShader(simple_fragment_shader(), '.glsl') shader3 = FileShader(simple_tessellation_control_shader(), '.glsl') shader4 = FileShader(simple_tessellation_evaluation_shader(), '.glsl') shader5 = FileShader(simple_geometry_shader(), '.glsl') shader6 = FileShader(simple_compute_shader(), '.glsl') glslc_args = [ '-c', '-fshader-stage=vertex', shader1, '-fshader-stage=fragment', shader2, '-fshader-stage=tesscontrol', shader3, '-fshader-stage=tesseval', shader4, '-fshader-stage=geometry', shader5, '-fshader-stage=compute', shader6] @inside_glslc_testsuite('OptionShaderStage') class TestShaderStageOverwriteFileExtension(expect.ValidObjectFile): """Tests -fshader-stage has precedence over file extension.""" # a vertex shader camouflaged with .frag extension shader = FileShader(simple_vertex_shader(), '.frag') # Command line says it's vertex shader. Should compile successfully # as a vertex shader. glslc_args = ['-c', '-fshader-stage=vertex', shader] @inside_glslc_testsuite('OptionShaderStage') class TestShaderStageLatterOverwriteFormer(expect.ValidObjectFile): """Tests a latter -fshader-stage overwrite a former one.""" shader = FileShader(simple_vertex_shader(), '.glsl') glslc_args = [ '-c', '-fshader-stage=fragment', '-fshader-stage=vertex', shader] @inside_glslc_testsuite('OptionShaderStage') class TestShaderStageWithMultipleFiles(expect.ValidObjectFile): """Tests -fshader-stage covers all subsequent files.""" shader1 = FileShader(simple_vertex_shader(), '.glsl') # a vertex shader with .frag extension shader2 = FileShader(simple_vertex_shader(), '.frag') shader3 = FileShader(simple_vertex_shader(), '.a_vert_shader') glslc_args = ['-c', '-fshader-stage=vertex', shader1, shader2, shader3] @inside_glslc_testsuite('OptionShaderStage') class TestShaderStageMultipleShaderStage(expect.ValidObjectFile): """Tests multiple -fshader-stage.""" shader1 = FileShader(simple_vertex_shader(), '.glsl') shader2 = FileShader(simple_fragment_shader(), '.frag') shader3 = FileShader(simple_vertex_shader(), '.a_vert_shader') glslc_args = [ '-c', '-fshader-stage=vertex', shader1, '-fshader-stage=fragment', shader2, '-fshader-stage=vertex', shader3] @inside_glslc_testsuite('OptionShaderStage') class TestFileExtensionBeforeShaderStage(expect.ValidObjectFile): """Tests that file extensions before -fshader-stage are not affected.""" # before -fshader-stage shader1 = FileShader(simple_vertex_shader(), '.vert') # after -fshader-stage shader2 = FileShader(simple_fragment_shader(), '.frag') shader3 = FileShader(simple_fragment_shader(), '.vert') glslc_args = ['-c', shader1, '-fshader-stage=fragment', shader2, shader3] @inside_glslc_testsuite('OptionShaderStage') class TestShaderStageWrongShaderStageValue(expect.ErrorMessage): """Tests that wrong shader stage value results in an error.""" shader = FileShader(simple_vertex_shader(), '.glsl') glslc_args = ['-c', '-fshader-stage=unknown', shader] expected_error = ["glslc: error: stage not recognized: 'unknown'\n"] @inside_glslc_testsuite('OptionShaderStage') class TestShaderStageGlslExtensionMissingShaderStage(expect.ErrorMessage): """Tests that missing -fshader-stage for .glsl extension results in an error.""" shader = FileShader(simple_vertex_shader(), '.glsl') glslc_args = ['-c', shader] expected_error = [ "glslc: error: '", shader, "': .glsl file encountered but no -fshader-stage specified ahead\n"] @inside_glslc_testsuite('OptionShaderStage') class TestShaderStageHlslExtensionMissingShaderStage(expect.ErrorMessage): """Tests that missing -fshader-stage for .hlsl extension results in an error.""" shader = FileShader(simple_hlsl_vertex_shader(), '.hlsl') glslc_args = ['-c', '-x', 'hlsl', shader] expected_error = [ "glslc: error: '", shader, "': .hlsl file encountered but no -fshader-stage specified ahead\n"] @inside_glslc_testsuite('OptionShaderStage') class TestShaderStageUnknownExtensionMissingShaderStage(expect.ErrorMessage): """Tests that missing -fshader-stage for unknown extension results in an error.""" shader = FileShader(simple_vertex_shader(), '.a_vert_shader') glslc_args = ['-c', shader] expected_error = [ "glslc: error: '", shader, "': file not recognized: File format not recognized\n"] shaderc-2025.2/glslc/test/option_std.py000066400000000000000000000266731500222170200200410ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader def core_vert_shader_without_version(): # gl_ClipDistance doesn't exist in es profile (at least until 3.10). return 'void main() { gl_ClipDistance[0] = 5.; }' def core_frag_shader_without_version(): # gl_SampleID appears in core profile from 4.00. # gl_sampleID doesn't exsit in es profile (at least until 3.10). return 'void main() { int temp = gl_SampleID; }' def hlsl_compute_shader_with_barriers(): # Use "main" to avoid the need for -fentry-point return 'void main() { AllMemoryBarrierWithGroupSync(); }' @inside_glslc_testsuite('OptionStd') class TestStdNoArg(expect.ErrorMessage): """Tests -std alone.""" glslc_args = ['-std'] expected_error = ["glslc: error: unknown argument: '-std'\n"] @inside_glslc_testsuite('OptionStd') class TestStdEqNoArg(expect.ErrorMessage): """Tests -std= with no argument.""" glslc_args = ['-std='] expected_error = ["glslc: error: invalid value '' in '-std='\n"] @inside_glslc_testsuite('OptionStd') class TestStdEqSpaceArg(expect.ErrorMessage): """Tests -std= .""" shader = FileShader(core_frag_shader_without_version(), '.frag') glslc_args = ['-c', '-std=', '450core', shader] expected_error = ["glslc: error: invalid value '' in '-std='\n"] # TODO(dneto): The error message changes with different versions of glslang. @inside_glslc_testsuite('OptionStd') class TestMissingVersionAndStd(expect.ErrorMessageSubstr): """Tests that missing both #version and -std results in errors.""" shader = FileShader(core_frag_shader_without_version(), '.frag') glslc_args = ['-c', shader] expected_error_substr = ['error:'] @inside_glslc_testsuite('OptionStd') class TestMissingVersionButHavingStd(expect.ValidObjectFile): """Tests that correct -std fixes missing #version.""" shader = FileShader(core_frag_shader_without_version(), '.frag') glslc_args = ['-c', '-std=450core', shader] @inside_glslc_testsuite('OptionStd') class TestGLSL460(expect.ValidObjectFile): """Tests that GLSL version 4.6 is supported.""" shader = FileShader(core_frag_shader_without_version(), '.frag') glslc_args = ['-c', '-std=460', shader] @inside_glslc_testsuite('OptionStd') class TestGLSL460Core(expect.ValidObjectFile): """Tests that GLSL version 4.6 core profile is supported.""" shader = FileShader(core_frag_shader_without_version(), '.frag') glslc_args = ['-c', '-std=460core', shader] @inside_glslc_testsuite('OptionStd') class TestESSL320(expect.ValidObjectFile): """Tests that ESSL version 3.2 is supported.""" shader = FileShader(core_frag_shader_without_version(), '.frag') glslc_args = ['-c', '-std=320es', shader] @inside_glslc_testsuite('OptionStd') class TestStdIgnoredInHlsl(expect.ValidObjectFile): """Tests HLSL compilation ignores -std.""" # Compute shaders are not available in OpenGL 150 shader = FileShader(hlsl_compute_shader_with_barriers(), '.comp') glslc_args = ['-c', '-x', 'hlsl', '-std=150', shader] @inside_glslc_testsuite('OptionStd') class TestMissingVersionAndWrongStd(expect.ErrorMessage): """Tests missing #version and wrong -std results in errors.""" shader = FileShader(core_frag_shader_without_version(), '.frag') glslc_args = ['-c', '-std=310es', shader] expected_error = [ shader, ":1: error: 'gl_SampleID' : required extension not requested: " 'GL_OES_sample_variables\n1 error generated.\n'] @inside_glslc_testsuite('OptionStd') class TestConflictingVersionAndStd(expect.ValidObjectFileWithWarning): """Tests that with both #version and -std, -std takes precedence.""" # Wrong #version here on purpose. shader = FileShader( '#version 310 es\n' + core_frag_shader_without_version(), '.frag') # -std overwrites the wrong #version. glslc_args = ['-c', '-std=450core', shader] expected_warning = [ shader, ': warning: (version, profile) forced to be (450, core), while ' 'in source code it is (310, es)\n1 warning generated.\n'] @inside_glslc_testsuite('OptionStd') class TestMultipleStd(expect.ValidObjectFile): """Tests that for multiple -std, the last one takes effect.""" shader = FileShader(core_frag_shader_without_version(), '.frag') glslc_args = ['-c', '-std=100', '-std=310es', shader, '-std=450core'] @inside_glslc_testsuite('OptionStd') class TestMultipleFiles(expect.ValidObjectFileWithWarning): """Tests that -std covers all files.""" shader1 = FileShader(core_frag_shader_without_version(), '.frag') shader2 = FileShader(core_vert_shader_without_version(), '.vert') shader3 = FileShader( '#version 310 es\n' + core_frag_shader_without_version(), '.frag') glslc_args = ['-c', '-std=450core', shader1, shader2, shader3] expected_warning = [ shader3, ': warning: (version, profile) forced to be (450, ' 'core), while in source code it is (310, es)\n' '1 warning generated.\n'] @inside_glslc_testsuite('OptionStd') class TestUnkownProfile(expect.ErrorMessage): """Tests that -std rejects unknown profile.""" shader = FileShader(core_frag_shader_without_version(), '.frag') glslc_args = ['-c', '-std=450google', shader] expected_error = [ "glslc: error: invalid value '450google' in '-std=450google'\n"] @inside_glslc_testsuite('OptionStd') class TestUnkownVersion(expect.ErrorMessage): """Tests that -std rejects unknown version.""" shader = FileShader(core_frag_shader_without_version(), '.frag') glslc_args = ['-c', '-std=42core', shader] expected_error = [ "glslc: error: invalid value '42core' in '-std=42core'\n"] @inside_glslc_testsuite('OptionStd') class TestTotallyWrongStdValue(expect.ErrorMessage): """Tests that -std rejects totally wrong -std value.""" shader = FileShader(core_vert_shader_without_version(), '.vert') glslc_args = ['-c', '-std=wrong42', shader] expected_error = [ "glslc: error: invalid value 'wrong42' in '-std=wrong42'\n"] @inside_glslc_testsuite('OptionStd') class TestVersionInsideSlashSlashComment(expect.ValidObjectFileWithWarning): """Tests that -std substitutes the correct #version string.""" # The second #version string should be substituted and this shader # should compile successfully with -std=450core. shader = FileShader( '// #version 310 es\n#version 310 es\n' + core_vert_shader_without_version(), '.vert') glslc_args = ['-c', '-std=450core', shader] expected_warning = [ shader, ': warning: (version, profile) forced to be (450, core), while ' 'in source code it is (310, es)\n1 warning generated.\n'] @inside_glslc_testsuite('OptionStd') class TestVersionInsideSlashStarComment(expect.ValidObjectFileWithWarning): """Tests that -std substitutes the correct #version string.""" # The second #version string should be substituted and this shader # should compile successfully with -std=450core. shader = FileShader( '/* #version 310 es */\n#version 310 es\n' + core_vert_shader_without_version(), '.vert') glslc_args = ['-c', '-std=450core', shader] expected_warning = [ shader, ': warning: (version, profile) forced to be (450, core), while ' 'in source code it is (310, es)\n1 warning generated.\n'] @inside_glslc_testsuite('OptionStd') class TestCommentBeforeVersion(expect.ValidObjectFileWithWarning): """Tests that comments before #version (same line) is correctly handled.""" shader = FileShader( '/* some comment */ #version 150\n' + core_vert_shader_without_version(), '.vert') glslc_args = ['-c', '-std=450', shader] expected_warning = [ shader, ': warning: (version, profile) forced to be (450, none), while ' 'in source code it is (150, none)\n1 warning generated.\n'] @inside_glslc_testsuite('OptionStd') class TestCommentAfterVersion(expect.ValidObjectFileWithWarning): """Tests that multiple-line comments after #version is correctly handled.""" shader = FileShader( '#version 150 compatibility ' + '/* start \n second line \n end */\n' + core_vert_shader_without_version(), '.vert') glslc_args = ['-c', '-std=450core', shader] expected_warning = [ shader, ': warning: (version, profile) forced to be (450, core), while ' 'in source code it is (150, compatibility)\n1 warning generated.\n'] # The following test case is disabled because of a bug in glslang. # When checking non-newline whitespaces, glslang only recognizes # ' ' and '\t', leaving '\v' and '\f' unhandled. The following test # case exposes this problem. It should be turned on once a fix for # glslang is landed. #@inside_glslc_testsuite('OptionStd') class TestSpaceAroundVersion(expect.ValidObjectFileWithWarning): """Tests that space around #version is correctly handled.""" shader = FileShader( '\t \t # \t \f\f version \v \t\t 310 \v\v \t es \n' + core_vert_shader_without_version(), '.vert') glslc_args = ['-c', '-std=450core', shader] expected_warning = [ shader, ': warning: (version, profile) forced to be (450, core), while ' 'in source code it is (310, es)\n1 warning generated.\n'] @inside_glslc_testsuite('OptionStd') class TestVersionInsideCrazyComment(expect.ValidObjectFileWithWarning): """Tests that -std substitutes the correct #version string.""" # The fourth #version string should be substituted and this shader # should compile successfully with -std=450core. shader = FileShader( '/* */ /* // /* #version 310 es */\n' + # /*-style comment '// /* */ /* /* // #version 310 es\n' + # //-style comment '///*////*//*/*/ #version 310 es*/\n' + # //-style comment '#version 310 es\n' + core_vert_shader_without_version(), '.vert') glslc_args = ['-c', '-std=450core', shader] expected_warning = [ shader, ': warning: (version, profile) forced to be (450, core), while ' 'in source code it is (310, es)\n1 warning generated.\n'] @inside_glslc_testsuite('OptionStd') class TestVersionMissingProfile(expect.ErrorMessage): """Tests that missing required profile in -std results in an error.""" shader = FileShader('#version 140\nvoid main() {}', '.vert') glslc_args = ['-c', '-std=310', shader] expected_error = [ shader, ': error: #version: versions 300, 310, and 320 require ', "specifying the 'es' profile\n1 error generated.\n"] @inside_glslc_testsuite('OptionStd') class TestVersionRedundantProfile(expect.ErrorMessageSubstr): """Tests that adding non-required profile in -std results in an error.""" shader = FileShader('#version 140\nvoid main() {}', '.vert') glslc_args = ['-c', '-std=100core', shader] expected_error_substr = [ shader, ': error: #version: versions before 150 do not allow ' 'a profile token\n'] shaderc-2025.2/glslc/test/option_target_env.py000066400000000000000000000210021500222170200213620ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader def opengl_compat_fragment_shader(): return """#version 330 uniform highp sampler2D tex; void main() { gl_FragColor = texture2D(tex, vec2(0.0, 0.0)); }""" def opengl_vertex_shader(): return """#version 330 void main() { int t = gl_VertexID; }""" def vulkan_vertex_shader(): return """#version 310 es void main() { int t = gl_VertexIndex; }""" def vulkan_compute_subgroup_shader(): """Returns a compute shader that requires Vulkan 1.1""" return """#version 450 #extension GL_KHR_shader_subgroup_basic : enable void main() { subgroupBarrier(); }""" @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqOpenglCompatWithOpenGlCompatShader(expect.ErrorMessageSubstr): """Tests that compiling OpenGL Compatibility Fragment shader with --target-env=opengl_compat works correctly""" shader = FileShader(opengl_compat_fragment_shader(), '.frag') glslc_args = ['--target-env=opengl_compat', '-c', shader] expected_error_substr = "error: opengl_compat is no longer supported" @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqOpenglWithOpenGlCompatShader(expect.ErrorMessageSubstr): """Tests the error message of compiling OpenGL Compatibility Fragment shader with --target-env=opengl""" shader = FileShader(opengl_compat_fragment_shader(), '.frag') glslc_args = ['--target-env=opengl', shader] # Glslang does not give a pretty message. Make sure we get an error. expected_error_substr = "errors generated" @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqOpenglCompatWithOpenGlVertexShader(expect.ErrorMessageSubstr): """Tests that compiling OpenGL vertex shader with --target-env=opengl_compat generates valid SPIR-V code""" shader = FileShader(opengl_vertex_shader(), '.vert') glslc_args = ['--target-env=opengl_compat', '-c', shader] expected_error_substr = "error: opengl_compat is no longer supported" @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqOpenglWithOpenGlVertexShader(expect.ValidObjectFile): """Tests that compiling OpenGL vertex shader with --target-env=opengl generates valid SPIR-V code""" shader = FileShader(opengl_vertex_shader(), '.vert') glslc_args = ['--target-env=opengl', '-c', shader] @inside_glslc_testsuite('OptionTargetEnv') class TestDefaultTargetEnvWithVulkanShader(expect.ValidObjectFile): """Tests that compiling a Vulkan-specific shader with a default target environment succeeds""" shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['-c', shader] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqVulkanWithVulkan1_0ShaderSucceeds(expect.ValidObjectFile): """Tests that compiling a Vulkan-specific Vulkan 1.0 shader succeeds with --target-env=vulkan""" shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['--target-env=vulkan', '-c', shader] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqVulkan1_0WithVulkan1_0ShaderSucceeds(expect.ValidObjectFile): """Tests that compiling a Vulkan-specific Vulkan 1.0 shader succeeds with --target-env=vulkan1.0""" shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['--target-env=vulkan1.0', '-c', shader] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqVulkan1_0WithVulkan1_1ShaderFails(expect.ErrorMessageSubstr): shader = FileShader(vulkan_compute_subgroup_shader(), '.comp') glslc_args = ['--target-env=vulkan1.0', '-c', shader] expected_error_substr = "error: 'subgroup op' : requires SPIR-V 1.3" @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqVulkan1_1WithVulkan1_0ShaderSucceeds(expect.ValidObjectFile1_3): shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['--target-env=vulkan1.1', '-c', shader] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqVulkan1_1WithVulkan1_1ShaderSucceeds(expect.ValidObjectFile1_3): shader = FileShader(vulkan_compute_subgroup_shader(), '.comp') glslc_args = ['--target-env=vulkan1.1', '-c', shader] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqVulkan1_2WithVulkan1_0ShaderSucceeds(expect.ValidObjectFile1_5): shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['--target-env=vulkan1.2', '-c', shader] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqVulkan1_2WithVulkan1_1ShaderSucceeds(expect.ValidObjectFile1_5): shader = FileShader(vulkan_compute_subgroup_shader(), '.comp') glslc_args = ['--target-env=vulkan1.2', '-c', shader] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqVulkan1_3WithVulkan1_0ShaderSucceeds(expect.ValidObjectFile1_6): shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['--target-env=vulkan1.3', '-c', shader] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqVulkan1_3WithVulkan1_1ShaderSucceeds(expect.ValidObjectFile1_6): shader = FileShader(vulkan_compute_subgroup_shader(), '.comp') glslc_args = ['--target-env=vulkan1.3', '-c', shader] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqVulkan1_4WithVulkan1_0ShaderSucceeds(expect.ValidObjectFile1_6): shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['--target-env=vulkan1.4', '-c', shader] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqVulkan1_4WithVulkan1_1ShaderSucceeds(expect.ValidObjectFile1_6): shader = FileShader(vulkan_compute_subgroup_shader(), '.comp') glslc_args = ['--target-env=vulkan1.4', '-c', shader] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqOpenGL4_5WithOpenGLShaderSucceeds(expect.ValidObjectFile): shader = FileShader(opengl_vertex_shader(), '.vert') glslc_args = ['--target-env=opengl4.5', '-c', shader] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqOpenGL4_6WithOpenGLShaderFailsUnsupported(expect.ErrorMessageSubstr): shader = FileShader(opengl_vertex_shader(), '.vert') glslc_args = ['--target-env=opengl4.6', '-c', shader] expected_error_substr = "invalid value 'opengl4.6' in '--target-env=opengl4.6'" # Note: Negative tests are covered in the libshaderc_util unit tests. # For example, that an OpenGL-specific shader should fail to compile # for Vulkan, or a Vulkan-specific shader should fail to compile for # OpenGL. @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqNoArg(expect.ErrorMessage): """Tests the error message of assigning empty string to --target-env""" shader = FileShader(opengl_vertex_shader(), '.vert') glslc_args = ['--target-env=', shader] expected_error = ["glslc: error: invalid value ", "'' in '--target-env='\n"] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvNoEqNoArg(expect.ErrorMessage): """Tests the error message of using --target-env without equal sign and arguments""" shader = FileShader(opengl_vertex_shader(), '.vert') glslc_args = ['--target-env', shader] expected_error = ["glslc: error: unsupported option: ", "'--target-env'\n"] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvNoEqWithArg(expect.ErrorMessage): """Tests the error message of using --target-env without equal sign but arguments""" shader = FileShader(opengl_vertex_shader(), '.vert') glslc_args = ['--target-env', 'opengl', shader] expected_error = ["glslc: error: unsupported option: ", "'--target-env'\n"] @inside_glslc_testsuite('OptionTargetEnv') class TestTargetEnvEqWrongArg(expect.ErrorMessage): """Tests the error message of using --target-env with wrong argument""" shader = FileShader(opengl_vertex_shader(), '.vert') glslc_args = ['--target-env=wrong_arg', shader] expected_error = ["glslc: error: invalid value ", "'wrong_arg' in '--target-env=wrong_arg'\n"] shaderc-2025.2/glslc/test/option_target_spv.py000066400000000000000000000115761500222170200214210ustar00rootroot00000000000000# Copyright 2019 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader def vulkan_vertex_shader(): return """#version 310 es void main() { int t = gl_VertexIndex; }""" def vulkan_compute_subgroup_shader(): """Returns a compute shader that requires Vulkan 1.1 and SPIR-V 1.3""" return """#version 450 #extension GL_KHR_shader_subgroup_basic : enable void main() { subgroupBarrier(); }""" @inside_glslc_testsuite('OptionTargetSpv') class TestDefaultTargetSpvWithVulkanShader(expect.ValidObjectFile): """Tests that compiling a Vulkan-specific shader with a default target environment succeeds""" shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['-c', shader] @inside_glslc_testsuite('OptionTargetSpv') class TestDefaultTargetSpvWithShaderRequiringSpv1p3Fails(expect.ErrorMessageSubstr): """Tests that compiling a shader requiring SPIR-V 1.3 with default SPIR-V target should fail. """ shader = FileShader(vulkan_compute_subgroup_shader(), '.comp') glslc_args = ['-c', shader] expected_error_substr = ["error: 'subgroup op' : requires SPIR-V 1.3\n"] @inside_glslc_testsuite('OptionTargetSpv') class TestTargetSpv1p2WithShaderRequiringSpv1p3Fails(expect.ErrorMessageSubstr): """Tests that compiling a shader requiring SPIR-V 1.3 but targeting 1.2 should fail. """ shader = FileShader(vulkan_compute_subgroup_shader(), '.comp') glslc_args = ['--target-spv=spv1.2', '-c', shader] expected_error_substr = ["error: 'subgroup op' : requires SPIR-V 1.3\n"] @inside_glslc_testsuite('OptionTargetSpv') class TestTargetSpv1p3(expect.ValidObjectFile1_3): """Tests that compiling to spv1.3 succeeds and generates SPIR-V 1.3 binary.""" shader = FileShader(vulkan_compute_subgroup_shader(), '.comp') glslc_args = ['--target-spv=spv1.3', '-c', shader] @inside_glslc_testsuite('OptionTargetSpv') class TestTargetSpv1p4(expect.ValidObjectFile1_4): """Tests that compiling to spv1.4 succeeds and generates SPIR-V 1.4 binary.""" shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['--target-spv=spv1.4', '-c', shader] @inside_glslc_testsuite('OptionTargetSpv') class TestTargetSpv1p5(expect.ValidObjectFile1_5): """Tests that compiling to spv1.5 succeeds and generates SPIR-V 1.5 binary.""" shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['--target-spv=spv1.5', '-c', shader] @inside_glslc_testsuite('OptionTargetSpv') class TestTargetSpv1p5(expect.ValidObjectFile1_6): """Tests that compiling to spv1.6 succeeds and generates SPIR-V 1.6 binary.""" shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['--target-spv=spv1.6', '-c', shader] ### Option parsing error cases @inside_glslc_testsuite('OptionTargetSpv') class TestTargetSpvNoArg(expect.ErrorMessage): """Tests the error message of assigning empty string to --target-spv""" shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['--target-spv=', shader] expected_error = ["glslc: error: invalid value ", "'' in '--target-spv='\n"] @inside_glslc_testsuite('OptionTargetSpv') class TestTargetSpvNoEqNoArg(expect.ErrorMessage): """Tests the error message of using --target-spv without equal sign and arguments""" shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['--target-spv', shader] expected_error = ["glslc: error: unsupported option: ", "'--target-spv'\n"] @inside_glslc_testsuite('OptionTargetSpv') class TestTargetSpvNoEqWithArg(expect.ErrorMessage): """Tests the error message of using --target-spv without equal sign but arguments""" shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['--target-spv', 'spv1.3', shader] expected_error = ["glslc: error: unsupported option: ", "'--target-spv'\n"] @inside_glslc_testsuite('OptionTargetSpv') class TestTargetSpvEqWrongArg(expect.ErrorMessage): """Tests the error message of using --target-spv with wrong argument""" shader = FileShader(vulkan_vertex_shader(), '.vert') glslc_args = ['--target-spv=wrong_arg', shader] expected_error = ["glslc: error: invalid value ", "'wrong_arg' in '--target-spv=wrong_arg'\n"] shaderc-2025.2/glslc/test/parameter_tests.py000066400000000000000000000367701500222170200210600ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect import os.path from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader, StdinShader, TempFileName @inside_glslc_testsuite('File') class SimpleFileCompiled(expect.ValidObjectFile): """Tests whether or not a simple glsl file compiles.""" shader = FileShader('#version 310 es\nvoid main() {}', '.frag') glslc_args = ['-c', shader] @inside_glslc_testsuite('File') class NotSpecifyingOutputName(expect.SuccessfulReturn, expect.CorrectObjectFilePreamble): """Tests that when there is no -o and -E/-S/-c specified, output as a.spv.""" shader = FileShader('#version 140\nvoid main() {}', '.frag') glslc_args = [shader] def check_output_a_spv(self, status): output_name = os.path.join(status.directory, 'a.spv') return self.verify_object_file_preamble(output_name) @inside_glslc_testsuite('Parameters') class HelpParameters( expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch): """Tests the --help flag outputs correctly and does not produce and error.""" glslc_args = ['--help'] expected_stdout = '''glslc - Compile shaders into SPIR-V Usage: glslc [options] file... An input file of - represents standard input. Options: -c Only run preprocess, compile, and assemble steps. -Dmacro[=defn] Add an implicit macro definition. -E Outputs only the results of the preprocessing step. Output defaults to standard output. -fauto-bind-uniforms Automatically assign bindings to uniform variables that don't have an explicit 'binding' layout in the shader source. -fauto-map-locations Automatically assign locations to uniform variables that don't have an explicit 'location' layout in the shader source. -fauto-combined-image-sampler Removes sampler variables and converts existing textures to combined image-samplers. -fentry-point= Specify the entry point name for HLSL compilation, for all subsequent source files. Default is "main". -fhlsl-16bit-types Enable 16-bit type support for HLSL. -fhlsl_functionality1, -fhlsl-functionality1 Enable extension SPV_GOOGLE_hlsl_functionality1 for HLSL compilation. -fhlsl-iomap Use HLSL IO mappings for bindings. -fhlsl-offsets Use HLSL offset rules for packing members of blocks. Affects only GLSL. HLSL rules are always used for HLSL. -finvert-y Invert position.Y output in vertex shader. -flimit= Specify resource limits. Each limit is specified by a limit name followed by an integer value. Tokens should be separated by whitespace. If the same limit is specified several times, only the last setting takes effect. -flimit-file Set limits as specified in the given file. -fnan-clamp Generate code for max and min builtins so that, when given a NaN operand, the other operand is returned. Similarly, the clamp builtin will favour the non-NaN operands, as if clamp were implemented as a composition of max and min. -fpreserve-bindings Preserve all binding declarations, even if those bindings are not used. -fresource-set-binding [stage] [ ...] Explicitly sets the descriptor set and binding for HLSL resources, by register name. Optionally restrict it to a single stage. -fcbuffer-binding-base [stage] Same as -fubo-binding-base. -fimage-binding-base [stage] Sets the lowest automatically assigned binding number for images. Optionally only set it for a single shader stage. For HLSL, the resource register number is added to this base. -fsampler-binding-base [stage] Sets the lowest automatically assigned binding number for samplers Optionally only set it for a single shader stage. For HLSL, the resource register number is added to this base. -fssbo-binding-base [stage] Sets the lowest automatically assigned binding number for shader storage buffer objects (SSBO). Optionally only set it for a single shader stage. Only affects GLSL. -ftexture-binding-base [stage] Sets the lowest automatically assigned binding number for textures. Optionally only set it for a single shader stage. For HLSL, the resource register number is added to this base. -fuav-binding-base [stage] For automatically assigned bindings for unordered access views (UAV), the register number is added to this base to determine the binding number. Optionally only set it for a single shader stage. Only affects HLSL. -fubo-binding-base [stage] Sets the lowest automatically assigned binding number for uniform buffer objects (UBO). Optionally only set it for a single shader stage. For HLSL, the resource register number is added to this base. -fshader-stage= Treat subsequent input files as having stage . Valid stages are vertex, vert, fragment, frag, tesscontrol, tesc, tesseval, tese, geometry, geom, compute, and comp. -g Generate source-level debug information. -h Display available options. --help Display available options. -I Add directory to include search path. -mfmt= Output SPIR-V binary code using the selected format. This option may be specified only when the compilation output is in SPIR-V binary code form. Available options are: bin - SPIR-V binary words. This is the default. c - Binary words as C initializer list of 32-bit ints num - List of comma-separated 32-bit hex integers -M Generate make dependencies. Implies -E and -w. -MM An alias for -M. -MD Generate make dependencies and compile. -MF Write dependency output to the given file. -MT Specify the target of the rule emitted by dependency generation. -O Optimize the generated SPIR-V code for better performance. -Os Optimize the generated SPIR-V code for smaller size. -O0 Disable optimization. -o Write output to . A file name of '-' represents standard output. -std= Version and profile for GLSL input files. Possible values are concatenations of version and profile, e.g. 310es, 450core, etc. Ignored for HLSL files. -S Emit SPIR-V assembly instead of binary. --show-limits Display available limit names and their default values. --target-env= Set the target client environment, and the semantics of warnings and errors. An optional suffix can specify the client version. Values are: vulkan1.0 # The default vulkan1.1 vulkan1.2 vulkan1.3 vulkan1.4 vulkan # Same as vulkan1.0 opengl4.5 opengl # Same as opengl4.5 --target-spv= Set the SPIR-V version to be used for the generated SPIR-V module. The default is the highest version of SPIR-V required to be supported for the target environment. For example, default for vulkan1.0 is spv1.0, and the default for vulkan1.1 is spv1.3, the default for vulkan1.2 is spv1.5, the default for vulkan1.3 is spv1.6, the default for vulkan1.4 is spv1.6. Values are: spv1.0, spv1.1, spv1.2, spv1.3, spv1.4, spv1.5, spv1.6 --version Display compiler version information. -w Suppresses all warning messages. -Werror Treat all warnings as errors. -x Treat subsequent input files as having type . Valid languages are: glsl, hlsl. For files ending in .hlsl the default is hlsl. Otherwise the default is glsl. ''' expected_stderr = '' @inside_glslc_testsuite('Parameters') class HelpIsNotTooWide(expect.StdoutNoWiderThan80Columns): """Tests that --help output is not too wide.""" glslc_args = ['--help'] @inside_glslc_testsuite('Parameters') class UnknownSingleLetterArgument(expect.ErrorMessage): """Tests that an unknown argument triggers an error message.""" glslc_args = ['-a'] expected_error = ["glslc: error: unknown argument: '-a'\n"] @inside_glslc_testsuite('Parameters') class UnknownMultiLetterArgument(expect.ErrorMessage): """Tests that an unknown argument triggers an error message.""" glslc_args = ['-zzz'] expected_error = ["glslc: error: unknown argument: '-zzz'\n"] @inside_glslc_testsuite('Parameters') class UnsupportedOption(expect.ErrorMessage): """Tests that an unsupported option triggers an error message.""" glslc_args = ['--unsupported-option'] expected_error = [ "glslc: error: unsupported option: '--unsupported-option'\n"] @inside_glslc_testsuite('File') class FileNotFound(expect.ErrorMessage): """Tests the error message if a file cannot be found.""" blabla_file = TempFileName('blabla.frag') glslc_args = [blabla_file] expected_error = [ "glslc: error: cannot open input file: '", blabla_file, "': No such file or directory\n"] @inside_glslc_testsuite('Unsupported') class LinkingNotSupported(expect.ErrorMessage): """Tests the error message generated by linking not supported yet.""" shader1 = FileShader('#version 140\nvoid main() {}', '.vert') shader2 = FileShader('#version 140\nvoid main() {}', '.frag') glslc_args = [shader1, shader2] expected_error = [ 'glslc: error: linking multiple files is not supported yet. ', 'Use -c to compile files individually.\n'] @inside_glslc_testsuite('Unsupported') class MultipleStdinUnsupported(expect.ErrorMessage): """Tests the error message generated by having more than one - input.""" glslc_args = ['-c', '-fshader-stage=vertex', '-', '-'] expected_error = [ 'glslc: error: specifying standard input "-" as input more' ' than once is not allowed.\n'] @inside_glslc_testsuite('Parameters') class StdinWithoutShaderStage(expect.StdoutMatch, expect.StderrMatch): """Tests that you must use -fshader-stage when specifying - as input.""" shader = StdinShader( """#version 140 int a() { } void main() { int x = a(); } """) glslc_args = [shader] expected_stdout = '' expected_stderr = [ "glslc: error: '-': -fshader-stage required when input is from " 'standard input "-"\n'] @inside_glslc_testsuite('Parameters') class LimitsHelp(expect.StdoutMatch, expect.StderrMatch): """Tests --show-limits shows correct output.""" glslc_args = ['--show-limits'] expected_stderr = '' expected_stdout = """MaxLights 8 MaxClipPlanes 6 MaxTextureUnits 2 MaxTextureCoords 8 MaxVertexAttribs 16 MaxVertexUniformComponents 4096 MaxVaryingFloats 60 MaxVertexTextureImageUnits 16 MaxCombinedTextureImageUnits 80 MaxTextureImageUnits 16 MaxFragmentUniformComponents 1024 MaxDrawBuffers 8 MaxVertexUniformVectors 256 MaxVaryingVectors 15 MaxFragmentUniformVectors 256 MaxVertexOutputVectors 16 MaxFragmentInputVectors 15 MinProgramTexelOffset -8 MaxProgramTexelOffset 7 MaxClipDistances 8 MaxComputeWorkGroupCountX 65535 MaxComputeWorkGroupCountY 65535 MaxComputeWorkGroupCountZ 65535 MaxComputeWorkGroupSizeX 1024 MaxComputeWorkGroupSizeY 1024 MaxComputeWorkGroupSizeZ 64 MaxComputeUniformComponents 512 MaxComputeTextureImageUnits 16 MaxComputeImageUniforms 8 MaxComputeAtomicCounters 8 MaxComputeAtomicCounterBuffers 1 MaxVaryingComponents 60 MaxVertexOutputComponents 64 MaxGeometryInputComponents 64 MaxGeometryOutputComponents 128 MaxFragmentInputComponents 128 MaxImageUnits 8 MaxCombinedImageUnitsAndFragmentOutputs 8 MaxCombinedShaderOutputResources 8 MaxImageSamples 0 MaxVertexImageUniforms 0 MaxTessControlImageUniforms 0 MaxTessEvaluationImageUniforms 0 MaxGeometryImageUniforms 0 MaxFragmentImageUniforms 8 MaxCombinedImageUniforms 8 MaxGeometryTextureImageUnits 16 MaxGeometryOutputVertices 256 MaxGeometryTotalOutputComponents 1024 MaxGeometryUniformComponents 512 MaxGeometryVaryingComponents 60 MaxTessControlInputComponents 128 MaxTessControlOutputComponents 128 MaxTessControlTextureImageUnits 16 MaxTessControlUniformComponents 1024 MaxTessControlTotalOutputComponents 4096 MaxTessEvaluationInputComponents 128 MaxTessEvaluationOutputComponents 128 MaxTessEvaluationTextureImageUnits 16 MaxTessEvaluationUniformComponents 1024 MaxTessPatchComponents 120 MaxPatchVertices 32 MaxTessGenLevel 64 MaxViewports 16 MaxVertexAtomicCounters 0 MaxTessControlAtomicCounters 0 MaxTessEvaluationAtomicCounters 0 MaxGeometryAtomicCounters 0 MaxFragmentAtomicCounters 8 MaxCombinedAtomicCounters 8 MaxAtomicCounterBindings 1 MaxVertexAtomicCounterBuffers 0 MaxTessControlAtomicCounterBuffers 0 MaxTessEvaluationAtomicCounterBuffers 0 MaxGeometryAtomicCounterBuffers 0 MaxFragmentAtomicCounterBuffers 0 MaxCombinedAtomicCounterBuffers 1 MaxAtomicCounterBufferSize 32 MaxTransformFeedbackBuffers 4 MaxTransformFeedbackInterleavedComponents 64 MaxCullDistances 8 MaxCombinedClipAndCullDistances 8 MaxSamples 4 MaxMeshOutputVerticesNV 256 MaxMeshOutputPrimitivesNV 512 MaxMeshWorkGroupSizeX_NV 32 MaxMeshWorkGroupSizeY_NV 1 MaxMeshWorkGroupSizeZ_NV 1 MaxTaskWorkGroupSizeX_NV 32 MaxTaskWorkGroupSizeY_NV 1 MaxTaskWorkGroupSizeZ_NV 1 MaxMeshViewCountNV 4 MaxMeshOutputVerticesEXT 256 MaxMeshOutputPrimitivesEXT 256 MaxMeshWorkGroupSizeX_EXT 128 MaxMeshWorkGroupSizeY_EXT 128 MaxMeshWorkGroupSizeZ_EXT 128 MaxTaskWorkGroupSizeX_EXT 128 MaxTaskWorkGroupSizeY_EXT 128 MaxTaskWorkGroupSizeZ_EXT 128 MaxMeshViewCountEXT 4 MaxDualSourceDrawBuffersEXT 1 """ shaderc-2025.2/glslc/test/placeholder.py000066400000000000000000000113201500222170200201200ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A number of placeholders and their rules for expansion when used in tests. These placeholders, when used in glslc_args or expected_* variables of GlslCTest, have special meanings. In glslc_args, they will be substituted by the result of instantiate_for_glslc_args(), while in expected_*, by instantiate_for_expectation(). A TestCase instance will be passed in as argument to the instantiate_*() methods. """ import os import tempfile from string import Template from builtins import bytes class PlaceHolderException(Exception): """Exception class for PlaceHolder.""" pass class PlaceHolder(object): """Base class for placeholders.""" def instantiate_for_glslc_args(self, testcase): """Instantiation rules for glslc_args. This method will be called when the current placeholder appears in glslc_args. Returns: A string to replace the current placeholder in glslc_args. """ raise PlaceHolderException('Subclass should implement this function.') def instantiate_for_expectation(self, testcase): """Instantiation rules for expected_*. This method will be called when the current placeholder appears in expected_*. Returns: A string to replace the current placeholder in expected_*. """ raise PlaceHolderException('Subclass should implement this function.') class FileShader(PlaceHolder): """Stands for a shader whose source code is in a file.""" def __init__(self, source, suffix, assembly_substr=None): assert isinstance(source, str) assert isinstance(suffix, str) self.source = source self.suffix = suffix self.filename = None # If provided, this is a substring which is expected to be in # the disassembly of the module generated from this input file. self.assembly_substr = assembly_substr def instantiate_for_glslc_args(self, testcase): """Creates a temporary file and writes the source into it. Returns: The name of the temporary file. """ shader, self.filename = tempfile.mkstemp( dir=testcase.directory, suffix=self.suffix) shader_object = os.fdopen(shader, 'w') shader_object.write(self.source) shader_object.close() return self.filename def instantiate_for_expectation(self, testcase): assert self.filename is not None return self.filename class StdinShader(PlaceHolder): """Stands for a shader whose source code is from stdin.""" def __init__(self, source): assert isinstance(source, str) self.source = source self.filename = None def instantiate_for_glslc_args(self, testcase): """Writes the source code back to the TestCase instance.""" testcase.stdin_shader = bytes(self.source, 'utf-8') self.filename = '-' return self.filename def instantiate_for_expectation(self, testcase): assert self.filename is not None return self.filename class TempFileName(PlaceHolder): """Stands for a temporary file's name.""" def __init__(self, filename): assert isinstance(filename, str) assert filename != '' self.filename = filename def instantiate_for_glslc_args(self, testcase): return os.path.join(testcase.directory, self.filename) def instantiate_for_expectation(self, testcase): return os.path.join(testcase.directory, self.filename) class SpecializedString(PlaceHolder): """Returns a string that has been specialized based on TestCase. The string is specialized by expanding it as a string.Template with all of the specialization being done with each $param replaced by the associated member on TestCase. """ def __init__(self, filename): assert isinstance(filename, str) assert filename != '' self.filename = filename def instantiate_for_glslc_args(self, testcase): return Template(self.filename).substitute(vars(testcase)) def instantiate_for_expectation(self, testcase): return Template(self.filename).substitute(vars(testcase)) shaderc-2025.2/glslc/test/pragma_shader_stage.py000066400000000000000000000351741500222170200216330ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from environment import Directory, File from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader, StdinShader VERTEX_ONLY_SHADER_WITH_PRAGMA = \ """#version 310 es #pragma shader_stage(vertex) void main() { gl_Position = vec4(1.); }""" FRAGMENT_ONLY_SHADER_WITH_PRAGMA = \ """#version 310 es #pragma shader_stage(fragment) void main() { gl_FragDepth = 10.; }""" TESS_CONTROL_ONLY_SHADER_WITH_PRAGMA = \ """#version 440 core #pragma shader_stage(tesscontrol) layout(vertices = 3) out; void main() { }""" TESS_EVAL_ONLY_SHADER_WITH_PRAGMA = \ """#version 440 core #pragma shader_stage(tesseval) layout(triangles) in; void main() { }""" GEOMETRY_ONLY_SHDER_WITH_PRAGMA = \ """#version 150 core #pragma shader_stage(geometry) layout (triangles) in; layout (line_strip, max_vertices = 4) out; void main() { }""" COMPUTE_ONLY_SHADER_WITH_PRAGMA = \ """#version 310 es #pragma shader_stage(compute) void main() { uvec3 temp = gl_WorkGroupID; }""" # In the following tests, # PSS stands for PragmaShaderStage, and OSS stands for OptionShaderStage. @inside_glslc_testsuite('PragmaShaderStage') class TestPSSWithGlslExtension(expect.ValidObjectFile): """Tests #pragma shader_stage() with .glsl extension.""" shader = FileShader(VERTEX_ONLY_SHADER_WITH_PRAGMA, '.glsl') glslc_args = ['-c', shader] @inside_glslc_testsuite('PragmaShaderStage') class TestPSSWithUnkownExtension(expect.ValidObjectFile): """Tests #pragma shader_stage() with unknown extension.""" shader = FileShader(VERTEX_ONLY_SHADER_WITH_PRAGMA, '.unkown') glslc_args = ['-c', shader] @inside_glslc_testsuite('PragmaShaderStage') class TestPSSWithStdin(expect.ValidObjectFile): """Tests #pragma shader_stage() with stdin.""" shader = StdinShader(VERTEX_ONLY_SHADER_WITH_PRAGMA) glslc_args = ['-c', shader] @inside_glslc_testsuite('PragmaShaderStage') class TestPSSWithSameShaderExtension(expect.ValidObjectFile): """Tests that #pragma shader_stage() specifies the same stage as file extesion.""" shader = FileShader(VERTEX_ONLY_SHADER_WITH_PRAGMA, '.vert') glslc_args = ['-c', shader] @inside_glslc_testsuite('PragmaShaderStage') class TestPSSOverrideShaderExtension(expect.ValidObjectFile): """Tests that #pragma shader_stage() overrides file extension.""" shader = FileShader(VERTEX_ONLY_SHADER_WITH_PRAGMA, '.frag') glslc_args = ['-c', shader] @inside_glslc_testsuite('PragmaShaderStage') class TestOSSOverridePSS(expect.ValidObjectFile): """Tests that -fshader-stage overrides #pragma shader_stage().""" # wrong pragma and wrong file extension shader = FileShader( """#version 310 es #pragma shader_stage(fragment) void main() { gl_Position = vec4(1.); }""", '.frag') # -fshader-stage to the rescue! ^.^ glslc_args = ['-c', '-fshader-stage=vertex', shader] @inside_glslc_testsuite('PragmaShaderStage') class TestMultipleSamePSS(expect.ValidObjectFile): """Tests that multiple identical #pragma shader_stage() works.""" shader = FileShader( """#version 310 es #pragma shader_stage(vertex) #pragma shader_stage(vertex) void main() { #pragma shader_stage(vertex) gl_Position = vec4(1.); #pragma shader_stage(vertex) } #pragma shader_stage(vertex) #pragma shader_stage(vertex) """, '.glsl') glslc_args = ['-c', shader] @inside_glslc_testsuite('PragmaShaderStage') class TestConflictingPSS(expect.ErrorMessage): """Conflicting #pragma shader_stage() directives result in an error.""" shader = FileShader( """#version 310 es #pragma shader_stage(vertex) void main() { gl_Position = vec4(1.); } #pragma shader_stage(fragment) """, '.glsl') glslc_args = ['-c', shader] expected_error = [ shader, ":6: error: '#pragma': conflicting stages for 'shader_stage' " "#pragma: 'fragment' (was 'vertex' at ", shader, ':2)\n'] @inside_glslc_testsuite('PragmaShaderStage') class TestAllPSSValues(expect.ValidObjectFile): """Tests all possible #pragma shader_stage() values.""" shader1 = FileShader(VERTEX_ONLY_SHADER_WITH_PRAGMA, '.glsl') shader2 = FileShader(FRAGMENT_ONLY_SHADER_WITH_PRAGMA, '.glsl') shader3 = FileShader(TESS_CONTROL_ONLY_SHADER_WITH_PRAGMA, '.glsl') shader4 = FileShader(TESS_EVAL_ONLY_SHADER_WITH_PRAGMA, '.glsl') shader5 = FileShader(GEOMETRY_ONLY_SHDER_WITH_PRAGMA, '.glsl') shader6 = FileShader(COMPUTE_ONLY_SHADER_WITH_PRAGMA, '.glsl') glslc_args = ['-c', shader1, shader2, shader3, shader4, shader5, shader6] @inside_glslc_testsuite('PragmaShaderStage') class TestWrongPSSValue(expect.ErrorMessage): """Tests that #pragma shader_stage([wrong-stage]) results in an error.""" shader = FileShader( """#version 310 es #pragma shader_stage(superstage) void main() { gl_Position = vec4(1.); } """, '.glsl') glslc_args = ['-c', shader] expected_error = [ shader, ":2: error: '#pragma': invalid stage for 'shader_stage' " "#pragma: 'superstage'\n"] @inside_glslc_testsuite('PragmaShaderStage') class TestEmptyPSSValue(expect.ErrorMessage): """Tests that #pragma shader_stage([empty]) results in an error.""" shader = FileShader( """#version 310 es #pragma shader_stage() void main() { gl_Position = vec4(1.); } """, '.glsl') glslc_args = ['-c', shader] expected_error = [ shader, ":2: error: '#pragma': invalid stage for 'shader_stage' " "#pragma: ''\n"] @inside_glslc_testsuite('PragmaShaderStage') class TestFirstPSSBeforeNonPPCode(expect.ErrorMessage): """Tests that the first #pragma shader_stage() should appear before any non-preprocessing code.""" shader = FileShader( """#version 310 es #ifndef REMOVE_UNUSED_FUNCTION int inc(int i) { return i + 1; } #endif #pragma shader_stage(vertex) void main() { gl_Position = vec4(1.); } """, '.glsl') glslc_args = ['-c', shader] expected_error = [ shader, ":5: error: '#pragma': the first 'shader_stage' #pragma " 'must appear before any non-preprocessing code\n'] @inside_glslc_testsuite('PragmaShaderStage') class TestPSSMultipleErrors(expect.ErrorMessage): """Tests that if there are multiple errors, they are all reported.""" shader = FileShader( """#version 310 es #pragma shader_stage(idontknow) #pragma shader_stage(vertex) void main() { gl_Position = vec4(1.); } #pragma shader_stage(fragment) """, '.glsl') glslc_args = ['-c', shader] expected_error = [ shader, ":2: error: '#pragma': invalid stage for 'shader_stage' " "#pragma: 'idontknow'\n", shader, ":3: error: '#pragma': conflicting stages for 'shader_stage' " "#pragma: 'vertex' (was 'idontknow' at ", shader, ':2)\n', shader, ":7: error: '#pragma': conflicting stages for 'shader_stage' " "#pragma: 'fragment' (was 'idontknow' at ", shader, ':2)\n'] @inside_glslc_testsuite('PragmaShaderStage') class TestSpacesAroundPSS(expect.ValidObjectFile): """Tests that spaces around #pragma shader_stage() works.""" shader = FileShader( """#version 310 es # pragma shader_stage ( vertex ) void main() { gl_Position = vec4(1.); } """, '.glsl') glslc_args = ['-c', shader] @inside_glslc_testsuite('PragmaShaderStage') class TestTabsAroundPSS(expect.ValidObjectFile): """Tests that tabs around #pragma shader_stage() works.""" shader = FileShader( """#version 310 es \t\t#\tpragma\t\t\tshader_stage\t\t(\t\t\t\tvertex\t\t)\t\t\t\t void main() { gl_Position = vec4(1.); } """, '.glsl') glslc_args = ['-c', shader] @inside_glslc_testsuite('PragmaShaderStage') class TestPSSWithMacro(expect.ValidObjectFile): """Tests that #pragma shader_stage() works with macros.""" shader = FileShader( """#version 310 es #if 0 some random stuff here which can cause a problem #else # pragma shader_stage(vertex) #endif void main() { gl_Position = vec4(1.); } """, '.glsl') glslc_args = ['-c', shader] @inside_glslc_testsuite('PragmaShaderStage') class TestPSSWithCmdLineMacroDef(expect.ValidObjectFile): """Tests that macro definitions passed in from command line work.""" shader = FileShader( """#version 310 es #ifdef IS_A_VERTEX_SHADER # pragma shader_stage(vertex) #else # pragma shader_stage(fragment) #endif void main() { gl_Position = vec4(1.); } """, '.glsl') glslc_args = ['-c', '-DIS_A_VERTEX_SHADER', shader] @inside_glslc_testsuite('PragmaShaderStage') class TestNoMacroExpansionInsidePSS(expect.ErrorMessage): """Tests that there is no macro expansion inside #pragma shader_stage().""" shader = FileShader( """#version 310 es #pragma shader_stage(STAGE_FROM_CMDLINE) void main() { gl_Position = vec4(1.); } """, '.glsl') glslc_args = ['-c', '-DSTAGE_FROM_CMDLINE=vertex', shader] expected_error = [ shader, ":2: error: '#pragma': invalid stage for 'shader_stage' " "#pragma: 'STAGE_FROM_CMDLINE'\n"] @inside_glslc_testsuite('PragmaShaderStage') class TestPSSWithPoundLine310(expect.ErrorMessage): """Tests that #pragma shader_stage() works with #line.""" shader = FileShader( """#version 310 es #pragma shader_stage(unknown) #line 42 #pragma shader_stage(google) #line 100 #pragma shader_stage(elgoog) void main() { gl_Position = vec4(1.); } """, '.glsl') glslc_args = ['-c', shader] expected_error = [ shader, ":2: error: '#pragma': invalid stage for 'shader_stage' " "#pragma: 'unknown'\n", shader, ":42: error: '#pragma': conflicting stages for 'shader_stage' " "#pragma: 'google' (was 'unknown' at ", shader, ':2)\n', shader, ":100: error: '#pragma': conflicting stages for 'shader_stage' " "#pragma: 'elgoog' (was 'unknown' at ", shader, ':2)\n'] @inside_glslc_testsuite('PragmaShaderStage') class TestPSSWithPoundLine150(expect.ErrorMessage): """Tests that #pragma shader_stage() works with #line. For older desktop versions, a #line directive specify the line number of the #line directive, not the next line. """ shader = FileShader( """#version 150 #pragma shader_stage(unknown) #line 42 #pragma shader_stage(google) #line 100 #pragma shader_stage(elgoog) void main() { gl_Position = vec4(1.); } """, '.glsl') glslc_args = ['-c', shader] expected_error = [ shader, ":2: error: '#pragma': invalid stage for 'shader_stage' " "#pragma: 'unknown'\n", shader, ":43: error: '#pragma': conflicting stages for 'shader_stage' " "#pragma: 'google' (was 'unknown' at ", shader, ':2)\n', shader, ":101: error: '#pragma': conflicting stages for 'shader_stage' " "#pragma: 'elgoog' (was 'unknown' at ", shader, ':2)\n'] @inside_glslc_testsuite('PragmaShaderStage') class ErrorBeforePragma(expect.ErrorMessage): """Tests that errors before pragmas are emitted.""" shader = FileShader( """#version 310 es #something #pragma shader_stage(vertex) void main() { gl_Position = vec4(1.); } """, '.glsl') glslc_args = ['-c', shader] expected_error = [shader, ':2: error: \'#\' : invalid directive:', ' something\n' '1 error generated.\n'] @inside_glslc_testsuite('PragmaShaderStage') class TestPSSfromIncludedFile(expect.ValidObjectFile): """Tests that #pragma shader_stage() from included files works.""" environment = Directory('.', [ File('a.glsl', '#version 140\n#include "b.glsl"\n' 'void main() { gl_Position = vec4(1.); }\n'), File('b.glsl', '#pragma shader_stage(vertex)')]) glslc_args = ['-c', 'a.glsl'] @inside_glslc_testsuite('PragmaShaderStage') class TestConflictingPSSfromIncludingAndIncludedFile(expect.ErrorMessage): """Tests that conflicting #pragma shader_stage() from including and included files results in an error with the correct location spec.""" environment = Directory('.', [ File('a.vert', '#version 140\n' '#pragma shader_stage(fragment)\n' 'void main() { gl_Position = vec4(1.); }\n' '#include "b.glsl"\n'), File('b.glsl', '#pragma shader_stage(vertex)')]) glslc_args = ['-c', 'a.vert'] expected_error = [ "b.glsl:1: error: '#pragma': conflicting stages for 'shader_stage' " "#pragma: 'vertex' (was 'fragment' at a.vert:2)\n"] @inside_glslc_testsuite('PragmaShaderStage') class TestPSSWithFileNameBasedPoundLine(expect.ErrorMessage): """Tests that #pragma shader_stage() works with filename-based #line.""" shader = FileShader( """#version 310 es #pragma shader_stage(unknown) #line 42 "abc" #pragma shader_stage(google) #line 100 "def" #pragma shader_stage(elgoog) void main() { gl_Position = vec4(1.); } """, '.glsl') glslc_args = ['-c', shader] expected_error = [ shader, ":2: error: '#pragma': invalid stage for 'shader_stage' " "#pragma: 'unknown'\n", "abc:42: error: '#pragma': conflicting stages for 'shader_stage' " "#pragma: 'google' (was 'unknown' at ", shader, ':2)\n', "def:100: error: '#pragma': conflicting stages for 'shader_stage' " "#pragma: 'elgoog' (was 'unknown' at ", shader, ':2)\n'] shaderc-2025.2/glslc/test/stdin_out.py000066400000000000000000000024651500222170200176600ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import expect from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader, StdinShader @inside_glslc_testsuite('StdInOut') class VerifyStdinWorks(expect.ValidObjectFile): """Tests glslc accepts vertex shader extension (.vert).""" shader = StdinShader('#version 140\nvoid main() { }') glslc_args = ['-c', '-fshader-stage=vertex', shader] @inside_glslc_testsuite('StdInOut') class VerifyStdoutWorks( expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch): shader = FileShader('#version 140\nvoid main() {}', '.vert') glslc_args = [shader, '-o', '-'] # We expect SOME stdout, we just do not care what. expected_stdout = True expected_stderr = '' shaderc-2025.2/glslc/test/working_directory.py000066400000000000000000000200411500222170200214020ustar00rootroot00000000000000# Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os.path import expect from environment import File, Directory from glslc_test_framework import inside_glslc_testsuite from placeholder import FileShader MINIMAL_SHADER = '#version 140\nvoid main() {}' # @inside_glslc_testsuite('WorkDir') class TestWorkDirNoArg(expect.ErrorMessage): """Tests -working-directory. Behavior cribbed from Clang.""" glslc_args = ['-working-directory'] expected_error = [ "glslc: error: argument to '-working-directory' is missing " '(expected 1 value)\n', 'glslc: error: no input files\n'] # @inside_glslc_testsuite('WorkDir') class TestWorkDirEqNoArg(expect.ErrorMessage): """Tests -working-directory=. Behavior cribbed from Clang.""" glslc_args = ['-working-directory='] expected_error = ['glslc: error: no input files\n'] EMPTY_SHADER_IN_SUBDIR = Directory( 'subdir', [File('shader.vert', MINIMAL_SHADER)]) # @inside_glslc_testsuite('WorkDir') class TestWorkDirEqNoArgCompileFile(expect.ValidNamedObjectFile): """Tests -working-directory= when compiling input file.""" environment = Directory('.', [EMPTY_SHADER_IN_SUBDIR]) glslc_args = ['-c', '-working-directory=', 'subdir/shader.vert'] # Output file should be generated into subdir/. expected_object_filenames = ('subdir/shader.vert.spv',) # @inside_glslc_testsuite('WorkDir') class TestMultipleWorkDir(expect.ValidNamedObjectFile): """Tests that if there are multiple -working-directory= specified, only the last one takes effect.""" environment = Directory('.', [EMPTY_SHADER_IN_SUBDIR]) glslc_args = ['-c', '-working-directory=i-dont-exist', '-working-directory', 'i-think/me-neither', '-working-directory=subdir', 'shader.vert'] # Output file should be generated into subdir/. expected_object_filenames = ('subdir/shader.vert.spv',) # @inside_glslc_testsuite('WorkDir') class TestWorkDirPosition(expect.ValidNamedObjectFile): """Tests that -working-directory= affects all files before and after it on the command line.""" environment = Directory('subdir', [ File('shader.vert', MINIMAL_SHADER), File('cool.frag', MINIMAL_SHADER), File('bla.vert', MINIMAL_SHADER) ]) glslc_args = ['-c', 'shader.vert', 'bla.vert', '-working-directory=subdir', 'cool.frag'] # Output file should be generated into subdir/. expected_object_filenames = ( 'subdir/shader.vert.spv', 'subdir/cool.frag.spv', 'subdir/bla.vert.spv') # @inside_glslc_testsuite('WorkDir') class TestWorkDirDeepDir(expect.ValidNamedObjectFile): """Tests that -working-directory= works with directory hierarchies.""" environment = Directory('subdir', [ Directory('subsubdir', [ File('one.vert', MINIMAL_SHADER), File('two.frag', MINIMAL_SHADER) ]), File('zero.vert', MINIMAL_SHADER) ]) glslc_args = ['-c', 'zero.vert', 'subsubdir/one.vert', 'subsubdir/two.frag', '-working-directory=subdir'] # Output file should be generated into subdir/. expected_object_filenames = ( 'subdir/zero.vert.spv', 'subdir/subsubdir/one.vert.spv', 'subdir/subsubdir/two.frag.spv') # @inside_glslc_testsuite('WorkDir') class TestWorkDirCompileFile(expect.ValidNamedObjectFile): """Tests -working-directory= when compiling input file.""" environment = Directory('.', [EMPTY_SHADER_IN_SUBDIR]) glslc_args = ['-c', '-working-directory=subdir', 'shader.vert'] # Output file should be generated into subdir/. expected_object_filenames = ('subdir/shader.vert.spv',) # @inside_glslc_testsuite('WorkDir') class TestWorkDirCompileFileOutput(expect.ValidNamedObjectFile): """Tests -working-directory= when compiling input file and specifying output filename.""" environment = Directory('.', [ Directory('subdir', [ Directory('bin', []), File('shader.vert', MINIMAL_SHADER) ]) ]) glslc_args = ['-c', '-o', 'bin/spv', '-working-directory=subdir', 'shader.vert'] # Output file should be generated into subdir/bin/. expected_object_filenames = ('subdir/bin/spv',) # @inside_glslc_testsuite('WorkDir') class TestWorkDirArgNoEq(expect.ValidNamedObjectFile): """Tests -working-directory .""" environment = Directory('.', [EMPTY_SHADER_IN_SUBDIR]) glslc_args = ['-working-directory', 'subdir', 'shader.vert'] expected_object_filenames = ('a.spv',) # @inside_glslc_testsuite('WorkDir') class TestWorkDirEqInArg(expect.ValidNamedObjectFile): """Tests -working-directory=.""" environment = Directory('.', [ Directory('=subdir', [File('shader.vert', MINIMAL_SHADER)]), ]) glslc_args = ['-working-directory==subdir', 'shader.vert'] expected_object_filenames = ('a.spv',) # @inside_glslc_testsuite('WorkDir') class TestWorkDirCompileFileAbsolutePath(expect.ValidObjectFile): """Tests -working-directory= when compiling input file with absolute path.""" shader = FileShader(MINIMAL_SHADER, '.vert') glslc_args = ['-c', '-working-directory=subdir', shader] # The -working-directory flag should not affect the placement of the link file. # The following tests ensure that. class WorkDirDoesntAffectLinkedFile(expect.ValidNamedObjectFile): """A base class for tests asserting that -working-directory has no impact on the location of the output link file. """ environment = Directory('.', [ Directory('subdir', [ File('shader.vert', MINIMAL_SHADER), # Try to fake glslc into putting the linked file here, though it # shouldn't (because -working-directory doesn't impact -o). Directory('bin', [])]), File('shader.vert', "fake file, doesn't compile."), Directory('bin', [])]) # @inside_glslc_testsuite('WorkDir') class TestWorkDirLinkFileDefaultLocation(WorkDirDoesntAffectLinkedFile): """Tests that -working-directory doesn't impact the default link-file location. """ glslc_args = ['-working-directory=subdir', 'shader.vert'] expected_object_filenames = ('a.spv',) # @inside_glslc_testsuite('WorkDir') class TestWorkDirLinkFileExplicit(WorkDirDoesntAffectLinkedFile): """Tests that -working-directory doesn't impact the named link-file location. """ glslc_args = ['-o', 'b.spv', '-working-directory=subdir', 'shader.vert'] expected_object_filenames = ('b.spv',) # @inside_glslc_testsuite('WorkDir') class TestWorkDirLinkFileInSubdir(WorkDirDoesntAffectLinkedFile): """Tests that -working-directory doesn't impact the link-file sent into an existing subdirectory. """ glslc_args = ['-o', 'bin/spv', '-working-directory=subdir', 'shader.vert'] expected_object_filenames = ('bin/spv',) # @inside_glslc_testsuite('WorkDir') class TestWorkDirLinkFileInvalidPath(expect.ErrorMessage): """Tests that -working-directory doesn't impact the error generated for an invalid -o path. """ environment = Directory('.', [ Directory('subdir', [ File('shader.vert', MINIMAL_SHADER), Directory('missing', [])]), # Present here, but missing in parent. File('shader.vert', "fake file, doesn't compile.")]) glslc_args = [ '-o', 'missing/spv', '-working-directory=subdir', 'shader.vert'] expected_error = ['glslc: error: cannot open output file: ', "'missing/spv': No such file or directory\n"] shaderc-2025.2/kokoro/000077500000000000000000000000001500222170200145105ustar00rootroot00000000000000shaderc-2025.2/kokoro/android-release/000077500000000000000000000000001500222170200175465ustar00rootroot00000000000000shaderc-2025.2/kokoro/android-release/build-docker.sh000077500000000000000000000030331500222170200224500ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017-2022 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Android Build Script. # Fail on any error. set -e . /bin/using.sh # Declare the bash `using` function for configuring toolchains. # Display commands being run. set -x using cmake-3.31.2 using ninja-1.10.0 using ndk-r27c # Sets ANDROID_NDK_HOME, pointing at the NDK's root dir cd $ROOT_DIR ./utils/git-sync-deps mkdir build cd $ROOT_DIR/build # Invoke the build. BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT} echo $(date): Starting build... cmake \ -GNinja \ -DCMAKE_MAKE_PROGRAM=ninja \ -DCMAKE_BUILD_TYPE=Release \ -DANDROID_ABI="$TARGET_ARCH" \ -DSHADERC_SKIP_TESTS=ON \ -DSPIRV_SKIP_TESTS=ON \ -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \ -DANDROID_NDK=$ANDROID_NDK_HOME .. echo $(date): Build glslang library... ninja glslang echo $(date): Build everything... ninja echo $(date): Check Shaderc for copyright notices... ninja check-copyright echo $(date): Build completed. shaderc-2025.2/kokoro/android-release/build.sh000077500000000000000000000025411500222170200212060ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2020-2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Linux Build Script. set -e # Fail on any error. SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd )" ROOT_DIR="$( cd "${SCRIPT_DIR}/../.." >/dev/null 2>&1 && pwd )" TARGET_ARCH="$1" # --privileged is required for some sanitizer builds, as they seem to require # PTRACE privileges docker run --rm -i \ --privileged \ --volume "${ROOT_DIR}:${ROOT_DIR}" \ --volume "${KOKORO_ARTIFACTS_DIR}:${KOKORO_ARTIFACTS_DIR}" \ --workdir "${ROOT_DIR}" \ --env ROOT_DIR="${ROOT_DIR}" \ --env SCRIPT_DIR="${SCRIPT_DIR}" \ --env TARGET_ARCH="${TARGET_ARCH}" \ --env KOKORO_ARTIFACTS_DIR="${KOKORO_ARTIFACTS_DIR}" \ --entrypoint "${SCRIPT_DIR}/build-docker.sh" \ us-east4-docker.pkg.dev/shaderc-build/radial-docker/ubuntu-24.04-amd64/cpp-builder shaderc-2025.2/kokoro/android-release/build_arm.sh000077500000000000000000000014051500222170200220430ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Android Build Script. # Fail on any error. set -e # Display commands being run. set -x SCRIPT_DIR=`dirname "$BASH_SOURCE"` source $SCRIPT_DIR/build.sh "armeabi-v7a with NEON" shaderc-2025.2/kokoro/android-release/build_x86.sh000077500000000000000000000013621500222170200217130ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Android Build Script. # Fail on any error. set -e # Display commands being run. set -x SCRIPT_DIR=`dirname "$BASH_SOURCE"` source $SCRIPT_DIR/build.sh x86 shaderc-2025.2/kokoro/android-release/continuous_arm.cfg000066400000000000000000000012431500222170200232740ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. # build_file: "shaderc/kokoro/android-release/build_arm.sh" shaderc-2025.2/kokoro/android-release/continuous_x86.cfg000066400000000000000000000012431500222170200231420ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. # build_file: "shaderc/kokoro/android-release/build_x86.sh" shaderc-2025.2/kokoro/android-release/presubmit_arm.cfg000066400000000000000000000012401500222170200230750ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/android-release/build_arm.sh" shaderc-2025.2/kokoro/android-release/presubmit_x86.cfg000066400000000000000000000012401500222170200227430ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/android-release/build_x86.sh" shaderc-2025.2/kokoro/img/000077500000000000000000000000001500222170200152645ustar00rootroot00000000000000shaderc-2025.2/kokoro/img/linux.png000066400000000000000000000417311500222170200171370ustar00rootroot00000000000000‰PNG  IHDR((&÷pæ pHYs—O—O±¹iCCPPhotoshop ICC profilexÚc``žàèâäÊ$ÀÀPPTRää¥À~ž™!1¹¸À1 À‡!/?/•020|»ÆÀÈÀÀÀpY×ÑÅÉ•4Àš\PTÂÀÀp€Á(%µ8™á CzyIA c ƒHRvA cƒHvH3c OIjE ƒs~AeQfzF‰‚¡¥¥¥‚cJ~RªBpeqIjn±‚g^r~QA~QbIj Ô^—ü÷ÄÌ<#U*ƒˆÈ( >1H.-*ƒ%ƒƒƒƒCC"C=Æ£ oÅ]KW0Þcc bšÀtY˜9’y!óK––[¬z¬­¬÷Ø,Ù¦±}cgßÍ¡ÄÑÅñ…3‘ó—#×nMî4}2ýüêë‚ïá?~úÓúÏñÿ 4ú–ñ]<®iTXtXML:com.adobe.xmp Adobe Photoshop CC 2015 (Macintosh) 2017-07-04T18:08:25+01:00 2017-07-26T11:13:36+01:00 2017-07-26T11:13:36+01:00 image/png 1 Dot Gain 20% xmp.did:5e07c219-b13c-49e1-89a1-2f470b0e8652 xmp.iid:c6b4a0d2-b4b7-4548-9677-f39048023763 xmp.did:6e0a7f0a-5b0a-4e50-aa20-2ef167f27825 xmp.did:6e0a7f0a-5b0a-4e50-aa20-2ef167f27825 created xmp.iid:6e0a7f0a-5b0a-4e50-aa20-2ef167f27825 2017-07-04T18:08:25+01:00 Adobe Photoshop CC 2015 (Macintosh) saved xmp.iid:5278a0f8-50ec-4bcc-9e99-fdd09ae1297c 2017-07-26T11:05:16+01:00 Adobe Photoshop CC 2015 (Macintosh) / saved xmp.iid:c6b4a0d2-b4b7-4548-9677-f39048023763 2017-07-26T11:13:36+01:00 Adobe Photoshop CC 2015 (Macintosh) / 1 9838690/10000 9838690/10000 2 65535 40 40 5\» cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFIDATxÚœ–_hWeÇ_ ¬H£Ú¼Xd(D­¼0>òXaá¼Ðij6ex!† ².4½è¢…"%ÐÔ FNK–:’©èœF¶d,]\9üváù½çœ÷œß¯x/Îùý8ï÷ù>Ïó}þ8999œ9¼cñÓShã,ƒ ršµé/ü#'çJ€¹g-Jœó<2´¬Ý™&„,‚3™ø!Ïx!ÃúŸ] –…e-f(b•罊ÒÒì–ÞÊšã7nÓý~ˆ¦8Ï+BÒZl1úLt{&Z¸n é6È0•šÃ&û ‡c=½ì·ç8W+NJB¬OÑe/ÒC'8Ìk8sÔݯkÌê¢|RŽð3g ÌôL^0™ø›ª‚J Þ{ˆ·1?ªì® *ÅFÅ0ÑЬ9nDbMR9.G—/™[¶GÖVÕ£ü,«€*îE€—+«”ùQWÐÇÅ=²¥’öõމA“hoÅív„ªò !V†Q ÙDZ½ÜL©F •Š0©5ÏÄ.¯ƒO((="ÚÍ3d•Ø\4SÆrÓDcf:§3Ýì~RTËï"Ä›ä2Œþm]¶¡h¦ÌEˆYä÷ÈûÏ÷=†+в¼ !ö=zŒcà ù€ &–уXž¿Ã°8±Iˆ5aÀÉ´"Zq<ÂâÓ¼†Ýt³.†¼j7—|–£Üa€£+Ó¢“ñÁHà{«ÜÝËv‹IiÙ|‰˜’¸t!ú¨ 8½á¨gsÌáLìK3üˆá”ƒãù![ä;Ÿånr!0ñOú€ÓÕ)È%Èv]Qv!ŽdXÿ|ÀV®RÐAc›Ù«t!ÄæÔ@›Ë=Nú€bOPÆq‘Ô1Ÿå´q*VÞ"ñ<ú‘mLÆð[ÇÙÄžN0Z—Ü ãr›j¥Þ}ÑÁĬéäW†Lô±žêÈ¡ï‰?¹ÆNÒÍuF¢ ‡ãeļTbZEà¶ÓÏ0ݶ+ˆxžÇ¼0Ô0!Z؉ØXéöõíôryAa×ób€ÙÙíëßÄKD½Zvö\IEND®B`‚shaderc-2025.2/kokoro/img/macos.png000066400000000000000000000361501500222170200171010ustar00rootroot00000000000000‰PNG  IHDR((&÷pæ pHYs  šœ8(iTXtXML:com.adobe.xmp Adobe Photoshop CC 2015 (Macintosh) 2017-07-04T18:08:25+01:00 2017-07-26T10:59:30+01:00 2017-07-26T10:59:30+01:00 image/png 1 xmp.iid:3d9436ac-531d-42f7-a30f-bdd335e371c2 xmp.did:3d9436ac-531d-42f7-a30f-bdd335e371c2 xmp.did:3d9436ac-531d-42f7-a30f-bdd335e371c2 created xmp.iid:3d9436ac-531d-42f7-a30f-bdd335e371c2 2017-07-04T18:08:25+01:00 Adobe Photoshop CC 2015 (Macintosh) 1 720000/10000 720000/10000 2 65535 40 40 p^[ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFºIDATxÚ”–[lUÇ_²,@Mצ Æ1ØíZ(„(THà@Ð`"µ!!]+÷¾X„Š5åV $i„å¥mDåRQh*P°È6t‹=>ììì™Û)ü“™É¹ý¿ûwF&“XORÈ$¢Œ&Ÿ@/¿s…øŽ éu…ó „ƒx‹…” \b€ÙÇ'¤•PˆSMFHuj3û&œN=Ïðhøœ4²N6ñxØÊÚ`Âz–ˆ²ìQ‹ý w³ŒÇ†ìUox ײٖ™{ª@"žn®ÑŸ±ö¸–'agµí_RAˆž÷è’Æ Æ’â•Úò šdRzØE${LÁ*ÙÁÓtè÷‚œg¾jtI‘ÿ e5lõ¸ûY~åvùh˜P%[1µÔ¤ â OT¯0F I•»D}Oh¡ÄǃII¬äC_Ã>à=Ât3À1›GqÙâ[’q¶I\Тåľ¥‚ÚÌ"ö1ŽŸrµƒ‘2qWñô w‰ðÏÈdÙ fטNãdâ2vÒö(s[ä÷È¥—YjÈÏj™ðoëæÑµ’Fb4¯rŠrš¬Ic¿L8­^qšìröD$ɆP®B’$l*CÕ,¥)ÒZK›¸™R»‚^¨ Ú¥ô*£Ì¥¯`«µŽMantöAha+ïû75ML§¼t‰B£›3µpŠé}4³v‰‘—nF"üA#CÕk&IÈÈØ*1ß¼gmŒç0Ó2S4„Jl9õ‰Ç™ t’¤Èå|ÊbÃþÕÃ/Ë’Ë?4°ÄcŽM¯•ÙûæE)6žs/[˜Êfðµ&b‡,øá:#¤ªÙ˜,!’„µ;O©ˆÜa=|O$Ø(QDý Adobe Photoshop CC 2015 (Macintosh) 2017-07-04T18:08:25+01:00 2017-07-26T11:12:29+01:00 2017-07-26T11:12:29+01:00 image/png 1 xmp.iid:e81e6346-410e-40a0-82be-cca3dccb8a09 adobe:docid:photoshop:e56f1d8a-b278-117a-846f-8e0976eeb308 xmp.did:6de15b69-3c6e-46d6-a65f-7110ebc9ae57 created xmp.iid:6de15b69-3c6e-46d6-a65f-7110ebc9ae57 2017-07-04T18:08:25+01:00 Adobe Photoshop CC 2015 (Macintosh) saved xmp.iid:6f99ad6c-1395-4c8a-ab40-6aef1302cffc 2017-07-26T11:09:22+01:00 Adobe Photoshop CC 2015 (Macintosh) / saved xmp.iid:e81e6346-410e-40a0-82be-cca3dccb8a09 2017-07-26T11:12:29+01:00 Adobe Photoshop CC 2015 (Macintosh) / 1 720000/10000 720000/10000 2 65535 40 40 v6 cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFÙIDATxÚ”–ÍoTUÆçœ;—N;´´[¬h[ÊÇtZ£1Љ‘ÿIDâB£Ñ¸1aÅŠ„àÆš¸%. pe\LL;#B”O#H„~ÎǹwÎ9.æÌý˜ig1wæÎ™ç>ïó>ïsްÀQê@ ÖQ%D‚aöñßsŸ–9Ày*Sr²(¨ S !v]š©ŠåˆIn(÷-ݘnÛ˜¸! S¬2ËIéíÖèŒJµÍ" Ã>ž”D¹léû+Û¼îîw•‰‚fÕÔ1kÜ'ÃÙÁJÇ0Ü\wÏH¦À"˜§1²Hy4$pYⲞQl³VÑ-OxÏ8@uÞ/D^ M¡sr^dl¨ÇüçÎ3ö£ å^ƒ4¬ýúv³®{¨È#ŒòÚ“yã×¥2áð< fƒe˜y,_ð%ãޱ‰C§Àó|üÄ~ްÀ(Ïñ&Sœä2“,1È'À7nø6ܬ‘EäÚg)Tvƒð¹NÿúÑ©ã‡ìk"‚üf±¢€Žò¦ÐV Á?A/‹¡F•Ï女?´Òæ³G^oI¸ 4P[®žzøAs¿GŽrJ]h Ea¸¬áôÞݰÍÝßê[Ã2<è#_»,’)ÇeãU‘Ãà?ê0vò'p+ÒÌ*áJ^VgFÏd¼hSFÕ™;&3„É0$žšätdÒQVv¥Ycäj·dWX× §vzŽÒ¼dxÒ2SŽé˜\‘‰«,×®ø¢+Ô»K¶Ž§íP}’³ê?ÃÁfèÈ΂»w`ù„Ìik۸ʔÉB[¼”#Û°k«ëºüî§¿‹Ê¶ÅRu¦ZªìŠ&kšxD¡œd‡$‰Dñ0‡±ýsýs¹3+”‘;Ë{VöD³µÒ½ç£áEÊ#•™Ñvi-¾Ù¾zÉ ¦GX­÷ÚÐéW_ ûyáÜÒ”žhÑÄ'Ž9›” e÷É¡mäuBþÂèM·rë_=þzlÛÍ™…¯¸R\×DîÐée˜ÚìÙ¦{ÛiRgXÆÚcsGæò§OpX=ØÚ7ýp¶VÒ»ƒñPäS{ÑSÚ ')Så ÝwcâFîLƒœWÝJ)(Ö§+ÅÊD€Á’´N——uð¯IEND®B`‚shaderc-2025.2/kokoro/linux/000077500000000000000000000000001500222170200156475ustar00rootroot00000000000000shaderc-2025.2/kokoro/linux/build-docker.sh000077500000000000000000000052011500222170200205500ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Linux Build Script run inside docker container. set -e # Fail on any error. . /bin/using.sh # Declare the bash `using` function for configuring toolchains. set -x # Display commands being run. SKIP_TESTS="False" BUILD_TYPE="Debug" using cmake-3.31.2 using ninja-1.10.0 using python-3.12 if [ ! -z "$COMPILER" ]; then using "$COMPILER" fi # Possible configurations are: # ASAN, COVERAGE, RELEASE, DEBUG, DEBUG_EXCEPTION, RELEASE_MINGW if [ $CONFIG = "RELEASE" ] || [ $CONFIG = "RELEASE_MINGW" ] then BUILD_TYPE="RelWithDebInfo" fi ADDITIONAL_CMAKE_FLAGS="" if [ $CONFIG = "ASAN" ] then ADDITIONAL_CMAKE_FLAGS="-DCMAKE_CXX_FLAGS=-fsanitize=address -DCMAKE_C_FLAGS=-fsanitize=address" elif [ $CONFIG = "COVERAGE" ] then ADDITIONAL_CMAKE_FLAGS="-DENABLE_CODE_COVERAGE=ON" SKIP_TESTS="True" elif [ $CONFIG = "DEBUG_EXCEPTION" ] then ADDITIONAL_CMAKE_FLAGS="-DDISABLE_EXCEPTIONS=ON -DDISABLE_RTTI=ON" elif [ $CONFIG = "RELEASE_MINGW" ] then ADDITIONAL_CMAKE_FLAGS="-DCMAKE_TOOLCHAIN_FILE=$ROOT_DIR/cmake/linux-mingw-toolchain.cmake" SKIP_TESTS="True" fi cd $ROOT_DIR ./utils/git-sync-deps mkdir build cd $ROOT_DIR/build # Invoke the build. BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT} echo $(date): Starting build... cmake -GNinja -DCMAKE_INSTALL_PREFIX=$KOKORO_ARTIFACTS_DIR/install -DRE2_BUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=$BUILD_TYPE $ADDITIONAL_CMAKE_FLAGS .. echo $(date): Build glslang... ninja glslang-standalone echo $(date): Build everything... ninja echo $(date): Build completed. echo $(date): Check Shaderc for copyright notices... ninja check-copyright if [ $CONFIG = "COVERAGE" ] then echo $(date): Check coverage... ninja report-coverage echo $(date): Check coverage completed. fi echo $(date): Starting ctest... if [ $SKIP_TESTS = "False" ] then ctest --output-on-failure -j4 fi echo $(date): ctest completed. # libshaderc_util/core is generated by the death test in shaderc_util_file_finder_test rm -f libshaderc_util/core # Package the build. ninja install cd $KOKORO_ARTIFACTS_DIR tar czf install.tgz install shaderc-2025.2/kokoro/linux/build.sh000077500000000000000000000025711500222170200173120ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Linux Build Script. set -e # Fail on any error. SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd )" ROOT_DIR="$( cd "${SCRIPT_DIR}/../.." >/dev/null 2>&1 && pwd )" CONFIG=$1 COMPILER=$2 # --privileged is required for some sanitizer builds, as they seem to require # PTRACE privileges docker run --rm -i \ --privileged \ --volume "${ROOT_DIR}:${ROOT_DIR}" \ --volume "${KOKORO_ARTIFACTS_DIR}:${KOKORO_ARTIFACTS_DIR}" \ --workdir "${ROOT_DIR}" \ --env ROOT_DIR="${ROOT_DIR}" \ --env SCRIPT_DIR="${SCRIPT_DIR}" \ --env CONFIG="${CONFIG}" \ --env COMPILER="${COMPILER}" \ --env KOKORO_ARTIFACTS_DIR="${KOKORO_ARTIFACTS_DIR}" \ --entrypoint "${SCRIPT_DIR}/build-docker.sh" \ us-east4-docker.pkg.dev/shaderc-build/radial-docker/ubuntu-24.04-amd64/cpp-builder shaderc-2025.2/kokoro/linux/build_clang_asan.sh000077500000000000000000000013771500222170200214630ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Linux Build Script. # Fail on any error. set -e # Display commands being run. set -x SCRIPT_DIR=`dirname "$BASH_SOURCE"` source $SCRIPT_DIR/build.sh ASAN "clang-13.0.1" shaderc-2025.2/kokoro/linux/build_clang_debug.sh000077500000000000000000000014001500222170200216120ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Linux Build Script. # Fail on any error. set -e # Display commands being run. set -x SCRIPT_DIR=`dirname "$BASH_SOURCE"` source $SCRIPT_DIR/build.sh DEBUG "clang-13.0.1" shaderc-2025.2/kokoro/linux/build_clang_release.sh000077500000000000000000000014021500222170200221460ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Linux Build Script. # Fail on any error. set -e # Display commands being run. set -x SCRIPT_DIR=`dirname "$BASH_SOURCE"` source $SCRIPT_DIR/build.sh RELEASE "clang-13.0.1" shaderc-2025.2/kokoro/linux/build_gcc_coverage.sh000077500000000000000000000014321500222170200217740ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Linux Build Script. # Fail on any error. set -e # Display commands being run. set -x SCRIPT_DIR=`dirname "$BASH_SOURCE"` source $SCRIPT_DIR/build.sh COVERAGE "gcc-7" # gcc-8+ has issues with lcov shaderc-2025.2/kokoro/linux/build_gcc_debug.sh000077500000000000000000000013721500222170200212720ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Linux Build Script. # Fail on any error. set -e # Display commands being run. set -x SCRIPT_DIR=`dirname "$BASH_SOURCE"` source $SCRIPT_DIR/build.sh DEBUG "gcc-13" shaderc-2025.2/kokoro/linux/build_gcc_debug_exception.sh000077500000000000000000000014041500222170200233440ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Linux Build Script. # Fail on any error. set -e # Display commands being run. set -x SCRIPT_DIR=`dirname "$BASH_SOURCE"` source $SCRIPT_DIR/build.sh DEBUG_EXCEPTION "gcc-13" shaderc-2025.2/kokoro/linux/build_gcc_release.sh000077500000000000000000000013741500222170200216260ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Linux Build Script. # Fail on any error. set -e # Display commands being run. set -x SCRIPT_DIR=`dirname "$BASH_SOURCE"` source $SCRIPT_DIR/build.sh RELEASE "gcc-13" shaderc-2025.2/kokoro/linux/build_mingw_release.sh000077500000000000000000000013711500222170200222100ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Linux Build Script. # Fail on any error. set -e # Display commands being run. set -x SCRIPT_DIR=`dirname "$BASH_SOURCE"` source $SCRIPT_DIR/build.sh RELEASE_MINGW shaderc-2025.2/kokoro/linux/continuous_clang_asan.cfg000066400000000000000000000012361500222170200227060ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. build_file: "shaderc/kokoro/linux/build_clang_asan.sh" shaderc-2025.2/kokoro/linux/continuous_clang_debug.cfg000066400000000000000000000013351500222170200230520ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. build_file: "shaderc/kokoro/linux/build_clang_debug.sh" action { define_artifacts { regex: "install.tgz" } } shaderc-2025.2/kokoro/linux/continuous_clang_release.cfg000066400000000000000000000013371500222170200234060ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. build_file: "shaderc/kokoro/linux/build_clang_release.sh" action { define_artifacts { regex: "install.tgz" } } shaderc-2025.2/kokoro/linux/continuous_gcc_debug.cfg000066400000000000000000000013331500222170200225200ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. build_file: "shaderc/kokoro/linux/build_gcc_debug.sh" action { define_artifacts { regex: "install.tgz" } } shaderc-2025.2/kokoro/linux/continuous_gcc_debug_exception.cfg000066400000000000000000000012471500222170200246020ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. build_file: "shaderc/kokoro/linux/build_gcc_debug_exception.sh" shaderc-2025.2/kokoro/linux/continuous_gcc_release.cfg000066400000000000000000000013351500222170200230540ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. build_file: "shaderc/kokoro/linux/build_gcc_release.sh" action { define_artifacts { regex: "install.tgz" } } shaderc-2025.2/kokoro/linux/continuous_license_check.cfg000066400000000000000000000012331500222170200233740ustar00rootroot00000000000000# Copyright (C) 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. build_file: "shaderc/kokoro/linux/license_check.sh" shaderc-2025.2/kokoro/linux/continuous_mingw_release.cfg000066400000000000000000000012411500222170200234350ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. build_file: "shaderc/kokoro/linux/build_mingw_release.sh" shaderc-2025.2/kokoro/linux/license_check.sh000077500000000000000000000016611500222170200207710ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. set -e # Fail on any error. SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd )" ROOT_DIR="$( cd "${SCRIPT_DIR}/../.." >/dev/null 2>&1 && pwd )" docker run --rm -i \ --volume "${ROOT_DIR}:${ROOT_DIR}:ro" \ --workdir "${ROOT_DIR}" \ us-east4-docker.pkg.dev/shaderc-build/radial-docker/ubuntu-24.04-amd64/license-checker shaderc-2025.2/kokoro/linux/presubmit_clang_asan.cfg000066400000000000000000000012351500222170200225110ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/linux/build_clang_asan.sh" shaderc-2025.2/kokoro/linux/presubmit_clang_debug.cfg000066400000000000000000000012361500222170200226560ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/linux/build_clang_debug.sh" shaderc-2025.2/kokoro/linux/presubmit_clang_release.cfg000066400000000000000000000012401500222170200232030ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/linux/build_clang_release.sh" shaderc-2025.2/kokoro/linux/presubmit_gcc_debug.cfg000066400000000000000000000012351500222170200223250ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/linux/build_gcc_debug.sh" shaderc-2025.2/kokoro/linux/presubmit_gcc_release.cfg000066400000000000000000000012361500222170200226600ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/linux/build_gcc_release.sh" shaderc-2025.2/kokoro/linux/presubmit_license_check.cfg000066400000000000000000000012321500222170200231770ustar00rootroot00000000000000# Copyright (C) 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/linux/license_check.sh" shaderc-2025.2/kokoro/linux/presubmit_mingw_release.cfg000066400000000000000000000012401500222170200232400ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/linux/build_mingw_release.sh" shaderc-2025.2/kokoro/macos/000077500000000000000000000000001500222170200156125ustar00rootroot00000000000000shaderc-2025.2/kokoro/macos/build.sh000066400000000000000000000031571500222170200172530ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # MacOS Build Script. # Fail on any error. set -e # Display commands being run. set -x BUILD_ROOT=$PWD SRC=$PWD/github/shaderc BUILD_TYPE=$1 # Get NINJA. wget -q https://github.com/ninja-build/ninja/releases/download/v1.7.2/ninja-mac.zip unzip -q ninja-mac.zip chmod +x ninja export PATH="$PWD:$PATH" cd $SRC ./utils/git-sync-deps mkdir build cd $SRC/build # Invoke the build. BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT} echo $(date): Starting build... cmake -GNinja -DCMAKE_INSTALL_PREFIX=$KOKORO_ARTIFACTS_DIR/install -DRE2_BUILD_TESTING=OFF -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=$BUILD_TYPE .. echo $(date): Build glslang... ninja glslang-standalone echo $(date): Build everything... ninja echo $(date): Check Shaderc for copyright notices... ninja check-copyright echo $(date): Build completed. echo $(date): Starting ctest... ctest --output-on-failure -j4 echo $(date): ctest completed. # Package the build. ninja install cd $KOKORO_ARTIFACTS_DIR tar czf install.tgz install shaderc-2025.2/kokoro/macos/build_clang_debug.sh000066400000000000000000000013621500222170200215610ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # MacOS Build Script. # Fail on any error. set -e # Display commands being run. set -x SCRIPT_DIR=`dirname "$BASH_SOURCE"` source $SCRIPT_DIR/build.sh Debug shaderc-2025.2/kokoro/macos/build_clang_release.sh000066400000000000000000000013731500222170200221150ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # MacOS Build Script. # Fail on any error. set -e # Display commands being run. set -x SCRIPT_DIR=`dirname "$BASH_SOURCE"` source $SCRIPT_DIR/build.sh RelWithDebInfo shaderc-2025.2/kokoro/macos/continuous_clang_debug.cfg000066400000000000000000000013351500222170200230150ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. build_file: "shaderc/kokoro/macos/build_clang_debug.sh" action { define_artifacts { regex: "install.tgz" } } shaderc-2025.2/kokoro/macos/continuous_clang_release.cfg000066400000000000000000000013371500222170200233510ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. build_file: "shaderc/kokoro/macos/build_clang_release.sh" action { define_artifacts { regex: "install.tgz" } } shaderc-2025.2/kokoro/macos/presubmit_clang_debug.cfg000066400000000000000000000012361500222170200226210ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/macos/build_clang_debug.sh" shaderc-2025.2/kokoro/macos/presubmit_clang_release.cfg000066400000000000000000000012401500222170200231460ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/macos/build_clang_release.sh" shaderc-2025.2/kokoro/ndk-build/000077500000000000000000000000001500222170200163615ustar00rootroot00000000000000shaderc-2025.2/kokoro/ndk-build/build-docker.sh000077500000000000000000000037731500222170200212760ustar00rootroot00000000000000#!/bin/bash # Copyright (c) 2018 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Linux Build Script. # Fail on any error. set -e # Display commands being run. set -x # This is required to run any git command in the docker since owner will # have changed between the clone environment, and the docker container. # Marking the root of the repo as safe for ownership changes. git config --global --add safe.directory $ROOT_DIR . /bin/using.sh # Declare the bash `using` function for configuring toolchains. cd $ROOT_DIR function clean_dir() { dir=$1 if [[ -d "$dir" ]]; then rm -fr "$dir" fi mkdir "$dir" } # Get source for dependencies, as specified in the DEPS file /usr/bin/python3 utils/git-sync-deps --treeless using ndk-r27c clean_dir "$ROOT_DIR/build" cd "$ROOT_DIR/build" function do_ndk_build () { echo $(date): Starting ndk-build $@... $ANDROID_NDK_HOME/ndk-build \ -C $ROOT_DIR/android_test \ NDK_PROJECT_PATH=. \ NDK_LIBS_OUT=./libs \ NDK_APP_OUT=./app \ V=1 \ SPVTOOLS_LOCAL_PATH=$ROOT_DIR/third_party/spirv-tools \ SPVHEADERS_LOCAL_PATH=$ROOT_DIR/third_party/spirv-headers \ -j8 $@ } # Builds all the ABIs (see APP_ABI in jni/Application.mk) do_ndk_build # Check that libshaderc_combined builds # Explicitly set each ABI, otherwise it will only pick x86. # It seems to be the behaviour when specifying an explicit target. for abi in x86 x86_64 armeabi-v7a arm64-v8a; do do_ndk_build APP_ABI=$abi libshaderc_combined done echo $(date): ndk-build completed. shaderc-2025.2/kokoro/ndk-build/build.sh000066400000000000000000000035461500222170200200240ustar00rootroot00000000000000#!/bin/bash # Copyright (c) 2021 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Linux Build Script. # Fail on any error. set -e SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd )" ROOT_DIR="$( cd "${SCRIPT_DIR}/../.." >/dev/null 2>&1 && pwd )" BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT} # chown the given directory to the current user, if it exists. # Docker creates files with the root user - this can upset the Kokoro artifact copier. function chown_dir() { dir=$1 if [[ -d "$dir" ]]; then sudo chown -R "$(id -u):$(id -g)" "$dir" fi } set +e # Allow build failures # "--privileged" is required to run ptrace in the asan builds. docker run --rm -i \ --privileged \ --volume "${ROOT_DIR}:${ROOT_DIR}" \ --volume "${KOKORO_ARTIFACTS_DIR}:${KOKORO_ARTIFACTS_DIR}" \ --workdir "${ROOT_DIR}" \ --env SCRIPT_DIR=${SCRIPT_DIR} \ --env ROOT_DIR=${ROOT_DIR} \ --env KOKORO_ARTIFACTS_DIR="${KOKORO_ARTIFACTS_DIR}" \ --env BUILD_SHA="${BUILD_SHA}" \ --entrypoint "${SCRIPT_DIR}/build-docker.sh" \ us-east4-docker.pkg.dev/shaderc-build/radial-docker/ubuntu-24.04-amd64/cpp-builder RESULT=$? # This is important. If the permissions are not fixed, kokoro will fail # to pull build artifacts, and put the build in tool-failure state, which # blocks the logs. chown_dir "${ROOT_DIR}/build" exit $RESULT shaderc-2025.2/kokoro/ndk-build/build_khronos.sh000066400000000000000000000013531500222170200215610ustar00rootroot00000000000000#!/bin/bash # Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Linux Build Script. # Fail on any error. set -e # Display commands being run. set -x SCRIPT_DIR=`dirname "$BASH_SOURCE"` source $SCRIPT_DIR/build.sh shaderc-2025.2/kokoro/ndk-build/continuous_khronos.cfg000066400000000000000000000012411500222170200230110ustar00rootroot00000000000000# Copyright (C) 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. # build_file: "shaderc/kokoro/ndk-build/build_khronos.sh" shaderc-2025.2/kokoro/ndk-build/presubmit_khronos.cfg000066400000000000000000000012401500222170200226140ustar00rootroot00000000000000# Copyright (C) 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. # build_file: "shaderc/kokoro/ndk-build/build_khronos.sh" shaderc-2025.2/kokoro/windows/000077500000000000000000000000001500222170200162025ustar00rootroot00000000000000shaderc-2025.2/kokoro/windows/build.bat000066400000000000000000000056171500222170200200020ustar00rootroot00000000000000:: Copyright (C) 2017 Google Inc. :: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: :: Windows Build Script. @echo on set BUILD_ROOT=%cd% set SRC=%cd%\github\shaderc set BUILD_TYPE=%1 set VS_VERSION=%2 set ARCH=%3 :: Force usage of python 3.12 set PATH=C:\python312;%PATH% :: Glslang requires cmake 3.27 or later set PATH=C:\cmake-3.31.2\bin;%PATH% cd %SRC% python utils\git-sync-deps cmake --version mkdir build cd %SRC%\build :: ######################################### :: set up msvc build env :: ######################################### if %VS_VERSION% == 2019 ( call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" %ARCH% ) else if %VS_VERSION% == 2022 ( call "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvarsall.bat" %ARCH% ) :: ######################################### :: Start building. :: ######################################### echo "Starting build... %DATE% %TIME%" if "%KOKORO_GITHUB_COMMIT%." == "." ( set BUILD_SHA=%KOKORO_GITHUB_PULL_REQUEST_COMMIT% ) else ( set BUILD_SHA=%KOKORO_GITHUB_COMMIT% ) set CMAKE_FLAGS=-DCMAKE_INSTALL_PREFIX=%KOKORO_ARTIFACTS_DIR%\install -DRE2_BUILD_TESTING=OFF -GNinja -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DCMAKE_C_COMPILER=cl.exe -DCMAKE_CXX_COMPILER=cl.exe cmake %CMAKE_FLAGS% .. if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL% echo "Build glslang... %DATE% %TIME%" ninja glslang-standalone if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL% echo "Build everything... %DATE% %TIME%" ninja if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL% echo "Check Shaderc for copyright notices... %DATE% %TIME%" ninja check-copyright if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL% echo "Build Completed %DATE% %TIME%" :: This lets us use !ERRORLEVEL! inside an IF ... () and get the actual error at that point. setlocal ENABLEDELAYEDEXPANSION :: ################################################ :: Run the tests :: ################################################ echo "Running tests... %DATE% %TIME%" ctest -C %BUILD_TYPE% --output-on-failure -j4 if !ERRORLEVEL! NEQ 0 exit /b !ERRORLEVEL! echo "Tests passed %DATE% %TIME%" :: ################################################ :: Install and package. :: ################################################ ninja install cd %KOKORO_ARTIFACTS_DIR% zip -r install.zip install :: Clean up some directories. rm -rf %SRC%\build rm -rf %SRC%\install rm -rf %SRC%\third_party exit /b 0 shaderc-2025.2/kokoro/windows/build_2019_amd64_release.bat000066400000000000000000000014301500222170200231350ustar00rootroot00000000000000:: Copyright (C) 2023 Google Inc. :: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: :: Windows Build Script. @echo on :: Find out the directory of the common build script. set SCRIPT_DIR=%~dp0 :: Call with correct parameter call %SCRIPT_DIR%\build.bat RelWithDebInfo 2019 amd64 shaderc-2025.2/kokoro/windows/build_2022_amd64_debug.bat000066400000000000000000000014171500222170200226020ustar00rootroot00000000000000:: Copyright (C) 2025 Google Inc. :: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: :: Windows Build Script. @echo on :: Find out the directory of the common build script. set SCRIPT_DIR=%~dp0 :: Call with correct parameter call %SCRIPT_DIR%\build.bat Debug 2022 amd64 shaderc-2025.2/kokoro/windows/build_2022_amd64_release.bat000066400000000000000000000014301500222170200231270ustar00rootroot00000000000000:: Copyright (C) 2025 Google Inc. :: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: :: Windows Build Script. @echo on :: Find out the directory of the common build script. set SCRIPT_DIR=%~dp0 :: Call with correct parameter call %SCRIPT_DIR%\build.bat RelWithDebInfo 2022 amd64 shaderc-2025.2/kokoro/windows/continuous_release_2019.cfg000066400000000000000000000013471500222170200232510ustar00rootroot00000000000000# Copyright (C) 2023 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. build_file: "shaderc/kokoro/windows/build_2019_amd64_release.bat" action { define_artifacts { regex: "install.zip" } } shaderc-2025.2/kokoro/windows/presubmit_release_2019.cfg000066400000000000000000000012501500222170200230460ustar00rootroot00000000000000# Copyright (C) 2023 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/windows/build_2019_amd64_release.bat" shaderc-2025.2/kokoro/windows/vs2022_amd64_debug_continuous.cfg000066400000000000000000000013451500222170200242530ustar00rootroot00000000000000# Copyright (C) 2025 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. build_file: "shaderc/kokoro/windows/build_2022_amd64_debug.bat" action { define_artifacts { regex: "install.zip" } } shaderc-2025.2/kokoro/windows/vs2022_amd64_debug_presubmit.cfg000066400000000000000000000013441500222170200240560ustar00rootroot00000000000000# Copyright (C) 2025 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/windows/build_2022_amd64_debug.bat" action { define_artifacts { regex: "install.zip" } } shaderc-2025.2/kokoro/windows/vs2022_amd64_release_continuous.cfg000066400000000000000000000013471500222170200246070ustar00rootroot00000000000000# Copyright (C) 2025 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Continuous build configuration. build_file: "shaderc/kokoro/windows/build_2022_amd64_release.bat" action { define_artifacts { regex: "install.zip" } } shaderc-2025.2/kokoro/windows/vs2022_amd64_release_presubmit.cfg000066400000000000000000000013461500222170200244120ustar00rootroot00000000000000# Copyright (C) 2025 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Presubmit build configuration. build_file: "shaderc/kokoro/windows/build_2022_amd64_release.bat" action { define_artifacts { regex: "install.zip" } } shaderc-2025.2/libshaderc/000077500000000000000000000000001500222170200153045ustar00rootroot00000000000000shaderc-2025.2/libshaderc/Android.mk000066400000000000000000000023031500222170200172130ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_CPP_EXTENSION := .cc .cpp .cxx LOCAL_MODULE:=shaderc LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/include LOCAL_SRC_FILES:=src/shaderc.cc # The Shaderc third_party/Android.mk deduces SPVHEADERS_LOCAL_PATH, # or delegates that responsibility to SPIRV-Tools' Android.mk. LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include $(SPVHEADERS_LOCAL_PATH)/include LOCAL_STATIC_LIBRARIES:=shaderc_util SPIRV-Tools-opt LOCAL_CXXFLAGS:=-std=c++17 -fno-exceptions -fno-rtti -DENABLE_HLSL=1 LOCAL_EXPORT_CPPFLAGS:=-std=c++17 LOCAL_EXPORT_LDFLAGS:=-latomic include $(BUILD_STATIC_LIBRARY) shaderc-2025.2/libshaderc/CMakeLists.txt000066400000000000000000000074611500222170200200540ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. project(libshaderc) # Even though shaderc.hpp is a headers-only library, adding # a dependency here will force clients of the library to rebuild # when it changes. set(SHADERC_SOURCES include/shaderc/shaderc.h include/shaderc/shaderc.hpp src/shaderc.cc src/shaderc_private.h ) add_library(shaderc STATIC ${SHADERC_SOURCES}) shaderc_default_compile_options(shaderc) target_include_directories(shaderc PUBLIC include PRIVATE ${glslang_SOURCE_DIR} ${SPIRV-Headers_SOURCE_DIR}/include) add_library(shaderc_shared SHARED ${SHADERC_SOURCES}) shaderc_default_compile_options(shaderc_shared) target_include_directories(shaderc_shared PUBLIC include PRIVATE ${glslang_SOURCE_DIR} ${SPIRV-Headers_SOURCE_DIR}/include) target_compile_definitions(shaderc_shared PRIVATE SHADERC_IMPLEMENTATION PUBLIC SHADERC_SHAREDLIB ) set_target_properties(shaderc_shared PROPERTIES SOVERSION 1) if(SHADERC_ENABLE_INSTALL) install( FILES include/shaderc/env.h include/shaderc/status.h include/shaderc/visibility.h include/shaderc/shaderc.h include/shaderc/shaderc.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/shaderc) install(TARGETS shaderc shaderc_shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif(SHADERC_ENABLE_INSTALL) find_package(Threads) set(SHADERC_LIBS glslang ${CMAKE_THREAD_LIBS_INIT} shaderc_util SPIRV # from glslang SPIRV-Tools ) target_link_libraries(shaderc PRIVATE ${SHADERC_LIBS}) target_link_libraries(shaderc_shared PRIVATE ${SHADERC_LIBS}) shaderc_add_tests( TEST_PREFIX shaderc LINK_LIBS shaderc INCLUDE_DIRS include ${shaderc_SOURCE_DIR}/libshaderc_util/include ${glslang_SOURCE_DIR} ${spirv-tools_SOURCE_DIR}/include ${SPIRV-Headers_SOURCE_DIR}/include TEST_NAMES shaderc shaderc_cpp shaderc_private) shaderc_add_tests( TEST_PREFIX shaderc_shared LINK_LIBS shaderc_shared SPIRV-Tools INCLUDE_DIRS include ${shaderc_SOURCE_DIR}/libshaderc_util/include ${glslang_SOURCE_DIR} ${spirv-tools_SOURCE_DIR}/include ${SPIRV-Headers_SOURCE_DIR}/include TEST_NAMES shaderc shaderc_cpp shaderc_private) shaderc_combine_static_lib(shaderc_combined shaderc) if(SHADERC_ENABLE_INSTALL) install(TARGETS shaderc_combined DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif(SHADERC_ENABLE_INSTALL) shaderc_add_tests( TEST_PREFIX shaderc_combined LINK_LIBS shaderc_combined ${CMAKE_THREAD_LIBS_INIT} INCLUDE_DIRS include ${shaderc_SOURCE_DIR}/libshaderc_util/include ${glslang_SOURCE_DIR} ${spirv-tools_SOURCE_DIR}/include ${SPIRV-Headers_SOURCE_DIR}/include TEST_NAMES shaderc shaderc_cpp) if(${SHADERC_ENABLE_TESTS}) add_executable(shaderc_c_smoke_test ./src/shaderc_c_smoke_test.c) shaderc_default_c_compile_options(shaderc_c_smoke_test) target_include_directories(shaderc_c_smoke_test PUBLIC ${shaderc_SOURCE_DIR}/libshaderc_util/include) target_link_libraries(shaderc_c_smoke_test PRIVATE shaderc) add_test(NAME shaderc_c_smoke_test COMMAND shaderc_c_smoke_test) endif() shaderc-2025.2/libshaderc/README.md000066400000000000000000000041051500222170200165630ustar00rootroot00000000000000# libshaderc A library for compiling shader strings into SPIR-V. ## Build Artifacts There are two main shaderc libraries that are created during a CMake compilation. The first is `libshaderc`, which is a static library containing just the functionality exposed by libshaderc. It depends on other compilation targets `glslang`, `shaderc_util`, `SPIRV`, `SPIRV-Tools`, and `SPIRV-Tools-opt`. The other is `libshaderc_combined`, which is a static library containing libshaderc and all of its dependencies. ## Integrating libshaderc There are several ways of integrating libshaderc into external projects. 1. If the external project uses CMake, then `shaderc/CMakeLists.txt` can be included into the external project's CMake configuration and shaderc can be used as a link target. This is the simplest way to use libshaderc in an external project. 2. If the external project uses CMake and is building for Linux or Android, `target_link_libraries(shaderc_combined)` can instead be specified. This is functionally identical to the previous option. 3. If the external project does not use CMake, then the external project can instead directly use the generated libraries. `shaderc/libshaderc/include` should be added to the include path, and `build/libshaderc/libshaderc_combined.a` should be linked. Note that on some platforms `-lpthread` should also be specified. 4. If the external project does not use CMake and cannot use `libshaderc_combined`, the following libraries or their platform-dependent counterparts should be linked in the order specified. * `build/libshaderc/libshaderc.a` * `build/third_party/glslang/glslang/glslang.a` * `build/third_party/glslang/libglslang.a` * `build/shaderc_util/libshaderc_util.a` * `build/third_party/glslang/SPIRV/libSPIRV.a` * `build/third_party/spirv-tools/libSPIRV-Tools-opt.a` * `build/third_party/spirv-tools/libSPIRV-Tools.a` 5. If building for Android using the Android NDK, `shaderc/Android.mk` can be included in the application's `Android.mk` and `LOCAL_STATIC_LIBRARIES:=shaderc` can be specified. See `shaderc/android_test` for an example. shaderc-2025.2/libshaderc/include/000077500000000000000000000000001500222170200167275ustar00rootroot00000000000000shaderc-2025.2/libshaderc/include/shaderc/000077500000000000000000000000001500222170200203405ustar00rootroot00000000000000shaderc-2025.2/libshaderc/include/shaderc/env.h000066400000000000000000000053271500222170200213100ustar00rootroot00000000000000// Copyright 2018 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef SHADERC_ENV_H_ #define SHADERC_ENV_H_ #include #ifdef __cplusplus extern "C" { #endif typedef enum { shaderc_target_env_vulkan, // SPIR-V under Vulkan semantics shaderc_target_env_opengl, // SPIR-V under OpenGL semantics // NOTE: SPIR-V code generation is not supported for shaders under OpenGL // compatibility profile. shaderc_target_env_opengl_compat, // SPIR-V under OpenGL semantics, // including compatibility profile // functions shaderc_target_env_webgpu, // Deprecated, SPIR-V under WebGPU // semantics shaderc_target_env_default = shaderc_target_env_vulkan } shaderc_target_env; typedef enum { // For Vulkan, use Vulkan's mapping of version numbers to integers. // See vulkan.h shaderc_env_version_vulkan_1_0 = ((1u << 22)), shaderc_env_version_vulkan_1_1 = ((1u << 22) | (1 << 12)), shaderc_env_version_vulkan_1_2 = ((1u << 22) | (2 << 12)), shaderc_env_version_vulkan_1_3 = ((1u << 22) | (3 << 12)), shaderc_env_version_vulkan_1_4 = ((1u << 22) | (4 << 12)), // For OpenGL, use the number from #version in shaders. // TODO(dneto): Currently no difference between OpenGL 4.5 and 4.6. // See glslang/Standalone/Standalone.cpp // TODO(dneto): Glslang doesn't accept a OpenGL client version of 460. shaderc_env_version_opengl_4_5 = 450, shaderc_env_version_webgpu, // Deprecated, WebGPU env never defined versions } shaderc_env_version; // The known versions of SPIR-V. typedef enum { // Use the values used for word 1 of a SPIR-V binary: // - bits 24 to 31: zero // - bits 16 to 23: major version number // - bits 8 to 15: minor version number // - bits 0 to 7: zero shaderc_spirv_version_1_0 = 0x010000u, shaderc_spirv_version_1_1 = 0x010100u, shaderc_spirv_version_1_2 = 0x010200u, shaderc_spirv_version_1_3 = 0x010300u, shaderc_spirv_version_1_4 = 0x010400u, shaderc_spirv_version_1_5 = 0x010500u, shaderc_spirv_version_1_6 = 0x010600u } shaderc_spirv_version; #ifdef __cplusplus } #endif // __cplusplus #endif // SHADERC_ENV_H_ shaderc-2025.2/libshaderc/include/shaderc/shaderc.h000066400000000000000000000714721500222170200221350ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef SHADERC_SHADERC_H_ #define SHADERC_SHADERC_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include #include "shaderc/env.h" #include "shaderc/status.h" #include "shaderc/visibility.h" // Source language kind. typedef enum { shaderc_source_language_glsl, shaderc_source_language_hlsl, } shaderc_source_language; typedef enum { // Forced shader kinds. These shader kinds force the compiler to compile the // source code as the specified kind of shader. shaderc_vertex_shader, shaderc_fragment_shader, shaderc_compute_shader, shaderc_geometry_shader, shaderc_tess_control_shader, shaderc_tess_evaluation_shader, shaderc_glsl_vertex_shader = shaderc_vertex_shader, shaderc_glsl_fragment_shader = shaderc_fragment_shader, shaderc_glsl_compute_shader = shaderc_compute_shader, shaderc_glsl_geometry_shader = shaderc_geometry_shader, shaderc_glsl_tess_control_shader = shaderc_tess_control_shader, shaderc_glsl_tess_evaluation_shader = shaderc_tess_evaluation_shader, // Deduce the shader kind from #pragma annotation in the source code. Compiler // will emit error if #pragma annotation is not found. shaderc_glsl_infer_from_source, // Default shader kinds. Compiler will fall back to compile the source code as // the specified kind of shader when #pragma annotation is not found in the // source code. shaderc_glsl_default_vertex_shader, shaderc_glsl_default_fragment_shader, shaderc_glsl_default_compute_shader, shaderc_glsl_default_geometry_shader, shaderc_glsl_default_tess_control_shader, shaderc_glsl_default_tess_evaluation_shader, shaderc_spirv_assembly, shaderc_raygen_shader, shaderc_anyhit_shader, shaderc_closesthit_shader, shaderc_miss_shader, shaderc_intersection_shader, shaderc_callable_shader, shaderc_glsl_raygen_shader = shaderc_raygen_shader, shaderc_glsl_anyhit_shader = shaderc_anyhit_shader, shaderc_glsl_closesthit_shader = shaderc_closesthit_shader, shaderc_glsl_miss_shader = shaderc_miss_shader, shaderc_glsl_intersection_shader = shaderc_intersection_shader, shaderc_glsl_callable_shader = shaderc_callable_shader, shaderc_glsl_default_raygen_shader, shaderc_glsl_default_anyhit_shader, shaderc_glsl_default_closesthit_shader, shaderc_glsl_default_miss_shader, shaderc_glsl_default_intersection_shader, shaderc_glsl_default_callable_shader, shaderc_task_shader, shaderc_mesh_shader, shaderc_glsl_task_shader = shaderc_task_shader, shaderc_glsl_mesh_shader = shaderc_mesh_shader, shaderc_glsl_default_task_shader, shaderc_glsl_default_mesh_shader, } shaderc_shader_kind; typedef enum { shaderc_profile_none, // Used if and only if GLSL version did not specify // profiles. shaderc_profile_core, shaderc_profile_compatibility, // Disabled. This generates an error shaderc_profile_es, } shaderc_profile; // Optimization level. typedef enum { shaderc_optimization_level_zero, // no optimization shaderc_optimization_level_size, // optimize towards reducing code size shaderc_optimization_level_performance, // optimize towards performance } shaderc_optimization_level; // Resource limits. typedef enum { shaderc_limit_max_lights, shaderc_limit_max_clip_planes, shaderc_limit_max_texture_units, shaderc_limit_max_texture_coords, shaderc_limit_max_vertex_attribs, shaderc_limit_max_vertex_uniform_components, shaderc_limit_max_varying_floats, shaderc_limit_max_vertex_texture_image_units, shaderc_limit_max_combined_texture_image_units, shaderc_limit_max_texture_image_units, shaderc_limit_max_fragment_uniform_components, shaderc_limit_max_draw_buffers, shaderc_limit_max_vertex_uniform_vectors, shaderc_limit_max_varying_vectors, shaderc_limit_max_fragment_uniform_vectors, shaderc_limit_max_vertex_output_vectors, shaderc_limit_max_fragment_input_vectors, shaderc_limit_min_program_texel_offset, shaderc_limit_max_program_texel_offset, shaderc_limit_max_clip_distances, shaderc_limit_max_compute_work_group_count_x, shaderc_limit_max_compute_work_group_count_y, shaderc_limit_max_compute_work_group_count_z, shaderc_limit_max_compute_work_group_size_x, shaderc_limit_max_compute_work_group_size_y, shaderc_limit_max_compute_work_group_size_z, shaderc_limit_max_compute_uniform_components, shaderc_limit_max_compute_texture_image_units, shaderc_limit_max_compute_image_uniforms, shaderc_limit_max_compute_atomic_counters, shaderc_limit_max_compute_atomic_counter_buffers, shaderc_limit_max_varying_components, shaderc_limit_max_vertex_output_components, shaderc_limit_max_geometry_input_components, shaderc_limit_max_geometry_output_components, shaderc_limit_max_fragment_input_components, shaderc_limit_max_image_units, shaderc_limit_max_combined_image_units_and_fragment_outputs, shaderc_limit_max_combined_shader_output_resources, shaderc_limit_max_image_samples, shaderc_limit_max_vertex_image_uniforms, shaderc_limit_max_tess_control_image_uniforms, shaderc_limit_max_tess_evaluation_image_uniforms, shaderc_limit_max_geometry_image_uniforms, shaderc_limit_max_fragment_image_uniforms, shaderc_limit_max_combined_image_uniforms, shaderc_limit_max_geometry_texture_image_units, shaderc_limit_max_geometry_output_vertices, shaderc_limit_max_geometry_total_output_components, shaderc_limit_max_geometry_uniform_components, shaderc_limit_max_geometry_varying_components, shaderc_limit_max_tess_control_input_components, shaderc_limit_max_tess_control_output_components, shaderc_limit_max_tess_control_texture_image_units, shaderc_limit_max_tess_control_uniform_components, shaderc_limit_max_tess_control_total_output_components, shaderc_limit_max_tess_evaluation_input_components, shaderc_limit_max_tess_evaluation_output_components, shaderc_limit_max_tess_evaluation_texture_image_units, shaderc_limit_max_tess_evaluation_uniform_components, shaderc_limit_max_tess_patch_components, shaderc_limit_max_patch_vertices, shaderc_limit_max_tess_gen_level, shaderc_limit_max_viewports, shaderc_limit_max_vertex_atomic_counters, shaderc_limit_max_tess_control_atomic_counters, shaderc_limit_max_tess_evaluation_atomic_counters, shaderc_limit_max_geometry_atomic_counters, shaderc_limit_max_fragment_atomic_counters, shaderc_limit_max_combined_atomic_counters, shaderc_limit_max_atomic_counter_bindings, shaderc_limit_max_vertex_atomic_counter_buffers, shaderc_limit_max_tess_control_atomic_counter_buffers, shaderc_limit_max_tess_evaluation_atomic_counter_buffers, shaderc_limit_max_geometry_atomic_counter_buffers, shaderc_limit_max_fragment_atomic_counter_buffers, shaderc_limit_max_combined_atomic_counter_buffers, shaderc_limit_max_atomic_counter_buffer_size, shaderc_limit_max_transform_feedback_buffers, shaderc_limit_max_transform_feedback_interleaved_components, shaderc_limit_max_cull_distances, shaderc_limit_max_combined_clip_and_cull_distances, shaderc_limit_max_samples, shaderc_limit_max_mesh_output_vertices_nv, shaderc_limit_max_mesh_output_primitives_nv, shaderc_limit_max_mesh_work_group_size_x_nv, shaderc_limit_max_mesh_work_group_size_y_nv, shaderc_limit_max_mesh_work_group_size_z_nv, shaderc_limit_max_task_work_group_size_x_nv, shaderc_limit_max_task_work_group_size_y_nv, shaderc_limit_max_task_work_group_size_z_nv, shaderc_limit_max_mesh_view_count_nv, shaderc_limit_max_mesh_output_vertices_ext, shaderc_limit_max_mesh_output_primitives_ext, shaderc_limit_max_mesh_work_group_size_x_ext, shaderc_limit_max_mesh_work_group_size_y_ext, shaderc_limit_max_mesh_work_group_size_z_ext, shaderc_limit_max_task_work_group_size_x_ext, shaderc_limit_max_task_work_group_size_y_ext, shaderc_limit_max_task_work_group_size_z_ext, shaderc_limit_max_mesh_view_count_ext, shaderc_limit_max_dual_source_draw_buffers_ext, } shaderc_limit; // Uniform resource kinds. // In Vulkan, uniform resources are bound to the pipeline via descriptors // with numbered bindings and sets. typedef enum { // Image and image buffer. shaderc_uniform_kind_image, // Pure sampler. shaderc_uniform_kind_sampler, // Sampled texture in GLSL, and Shader Resource View in HLSL. shaderc_uniform_kind_texture, // Uniform Buffer Object (UBO) in GLSL. Cbuffer in HLSL. shaderc_uniform_kind_buffer, // Shader Storage Buffer Object (SSBO) in GLSL. shaderc_uniform_kind_storage_buffer, // Unordered Access View, in HLSL. (Writable storage image or storage // buffer.) shaderc_uniform_kind_unordered_access_view, } shaderc_uniform_kind; // Usage examples: // // Aggressively release compiler resources, but spend time in initialization // for each new use. // shaderc_compiler_t compiler = shaderc_compiler_initialize(); // shaderc_compilation_result_t result = shaderc_compile_into_spv( // compiler, "#version 450\nvoid main() {}", 27, // shaderc_glsl_vertex_shader, "main.vert", "main", nullptr); // // Do stuff with compilation results. // shaderc_result_release(result); // shaderc_compiler_release(compiler); // // Keep the compiler object around for a long time, but pay for extra space // occupied. // shaderc_compiler_t compiler = shaderc_compiler_initialize(); // // On the same, other or multiple simultaneous threads. // shaderc_compilation_result_t result = shaderc_compile_into_spv( // compiler, "#version 450\nvoid main() {}", 27, // shaderc_glsl_vertex_shader, "main.vert", "main", nullptr); // // Do stuff with compilation results. // shaderc_result_release(result); // // Once no more compilations are to happen. // shaderc_compiler_release(compiler); // An opaque handle to an object that manages all compiler state. typedef struct shaderc_compiler* shaderc_compiler_t; // Returns a shaderc_compiler_t that can be used to compile modules. // A return of NULL indicates that there was an error initializing the compiler. // Any function operating on shaderc_compiler_t must offer the basic // thread-safety guarantee. // [http://herbsutter.com/2014/01/13/gotw-95-solution-thread-safety-and-synchronization/] // That is: concurrent invocation of these functions on DIFFERENT objects needs // no synchronization; concurrent invocation of these functions on the SAME // object requires synchronization IF AND ONLY IF some of them take a non-const // argument. SHADERC_EXPORT shaderc_compiler_t shaderc_compiler_initialize(void); // Releases the resources held by the shaderc_compiler_t. // After this call it is invalid to make any future calls to functions // involving this shaderc_compiler_t. SHADERC_EXPORT void shaderc_compiler_release(shaderc_compiler_t); // An opaque handle to an object that manages options to a single compilation // result. typedef struct shaderc_compile_options* shaderc_compile_options_t; // Returns a default-initialized shaderc_compile_options_t that can be used // to modify the functionality of a compiled module. // A return of NULL indicates that there was an error initializing the options. // Any function operating on shaderc_compile_options_t must offer the // basic thread-safety guarantee. SHADERC_EXPORT shaderc_compile_options_t shaderc_compile_options_initialize(void); // Returns a copy of the given shaderc_compile_options_t. // If NULL is passed as the parameter the call is the same as // shaderc_compile_options_init. SHADERC_EXPORT shaderc_compile_options_t shaderc_compile_options_clone( const shaderc_compile_options_t options); // Releases the compilation options. It is invalid to use the given // shaderc_compile_options_t object in any future calls. It is safe to pass // NULL to this function, and doing such will have no effect. SHADERC_EXPORT void shaderc_compile_options_release( shaderc_compile_options_t options); // Adds a predefined macro to the compilation options. This has the same // effect as passing -Dname=value to the command-line compiler. If value // is NULL, it has the same effect as passing -Dname to the command-line // compiler. If a macro definition with the same name has previously been // added, the value is replaced with the new value. The macro name and // value are passed in with char pointers, which point to their data, and // the lengths of their data. The strings that the name and value pointers // point to must remain valid for the duration of the call, but can be // modified or deleted after this function has returned. In case of adding // a valueless macro, the value argument should be a null pointer or the // value_length should be 0u. SHADERC_EXPORT void shaderc_compile_options_add_macro_definition( shaderc_compile_options_t options, const char* name, size_t name_length, const char* value, size_t value_length); // Sets the source language. The default is GLSL. SHADERC_EXPORT void shaderc_compile_options_set_source_language( shaderc_compile_options_t options, shaderc_source_language lang); // Sets the compiler mode to generate debug information in the output. SHADERC_EXPORT void shaderc_compile_options_set_generate_debug_info( shaderc_compile_options_t options); // Sets the compiler optimization level to the given level. Only the last one // takes effect if multiple calls of this function exist. SHADERC_EXPORT void shaderc_compile_options_set_optimization_level( shaderc_compile_options_t options, shaderc_optimization_level level); // Forces the GLSL language version and profile to a given pair. The version // number is the same as would appear in the #version annotation in the source. // Version and profile specified here overrides the #version annotation in the // source. Use profile: 'shaderc_profile_none' for GLSL versions that do not // define profiles, e.g. versions below 150. SHADERC_EXPORT void shaderc_compile_options_set_forced_version_profile( shaderc_compile_options_t options, int version, shaderc_profile profile); // Source text inclusion via #include is supported with a pair of callbacks // to an "includer" on the client side. The first callback processes an // inclusion request, and returns an include result. The includer owns // the contents of the result, and those contents must remain valid until the // second callback is invoked to release the result. Both callbacks take a // user_data argument to specify the client context. // To return an error, set the source_name to an empty string and put your // error message in content. // An include result. typedef struct shaderc_include_result { // The name of the source file. The name should be fully resolved // in the sense that it should be a unique name in the context of the // includer. For example, if the includer maps source names to files in // a filesystem, then this name should be the absolute path of the file. // For a failed inclusion, this string is empty. const char* source_name; size_t source_name_length; // The text contents of the source file in the normal case. // For a failed inclusion, this contains the error message. const char* content; size_t content_length; // User data to be passed along with this request. void* user_data; } shaderc_include_result; // The kinds of include requests. enum shaderc_include_type { shaderc_include_type_relative, // E.g. #include "source" shaderc_include_type_standard // E.g. #include }; // An includer callback type for mapping an #include request to an include // result. The user_data parameter specifies the client context. The // requested_source parameter specifies the name of the source being requested. // The type parameter specifies the kind of inclusion request being made. // The requesting_source parameter specifies the name of the source containing // the #include request. The includer owns the result object and its contents, // and both must remain valid until the release callback is called on the result // object. typedef shaderc_include_result* (*shaderc_include_resolve_fn)( void* user_data, const char* requested_source, int type, const char* requesting_source, size_t include_depth); // An includer callback type for destroying an include result. typedef void (*shaderc_include_result_release_fn)( void* user_data, shaderc_include_result* include_result); // Sets includer callback functions. SHADERC_EXPORT void shaderc_compile_options_set_include_callbacks( shaderc_compile_options_t options, shaderc_include_resolve_fn resolver, shaderc_include_result_release_fn result_releaser, void* user_data); // Sets the compiler mode to suppress warnings, overriding warnings-as-errors // mode. When both suppress-warnings and warnings-as-errors modes are // turned on, warning messages will be inhibited, and will not be emitted // as error messages. SHADERC_EXPORT void shaderc_compile_options_set_suppress_warnings( shaderc_compile_options_t options); // Sets the target shader environment, affecting which warnings or errors will // be issued. The version will be for distinguishing between different versions // of the target environment. The version value should be either 0 or // a value listed in shaderc_env_version. The 0 value maps to Vulkan 1.0 if // |target| is Vulkan, and it maps to OpenGL 4.5 if |target| is OpenGL. SHADERC_EXPORT void shaderc_compile_options_set_target_env( shaderc_compile_options_t options, shaderc_target_env target, uint32_t version); // Sets the target SPIR-V version. The generated module will use this version // of SPIR-V. Each target environment determines what versions of SPIR-V // it can consume. Defaults to the highest version of SPIR-V 1.0 which is // required to be supported by the target environment. E.g. Default to SPIR-V // 1.0 for Vulkan 1.0 and SPIR-V 1.3 for Vulkan 1.1. SHADERC_EXPORT void shaderc_compile_options_set_target_spirv( shaderc_compile_options_t options, shaderc_spirv_version version); // Sets the compiler mode to treat all warnings as errors. Note the // suppress-warnings mode overrides this option, i.e. if both // warning-as-errors and suppress-warnings modes are set, warnings will not // be emitted as error messages. SHADERC_EXPORT void shaderc_compile_options_set_warnings_as_errors( shaderc_compile_options_t options); // Sets a resource limit. SHADERC_EXPORT void shaderc_compile_options_set_limit( shaderc_compile_options_t options, shaderc_limit limit, int value); // Sets whether the compiler should automatically assign bindings to uniforms // that aren't already explicitly bound in the shader source. SHADERC_EXPORT void shaderc_compile_options_set_auto_bind_uniforms( shaderc_compile_options_t options, bool auto_bind); // Sets whether the compiler should automatically remove sampler variables // and convert image variables to combined image-sampler variables. SHADERC_EXPORT void shaderc_compile_options_set_auto_combined_image_sampler( shaderc_compile_options_t options, bool upgrade); // Sets whether the compiler should use HLSL IO mapping rules for bindings. // Defaults to false. SHADERC_EXPORT void shaderc_compile_options_set_hlsl_io_mapping( shaderc_compile_options_t options, bool hlsl_iomap); // Sets whether the compiler should determine block member offsets using HLSL // packing rules instead of standard GLSL rules. Defaults to false. Only // affects GLSL compilation. HLSL rules are always used when compiling HLSL. SHADERC_EXPORT void shaderc_compile_options_set_hlsl_offsets( shaderc_compile_options_t options, bool hlsl_offsets); // Sets the base binding number used for for a uniform resource type when // automatically assigning bindings. For GLSL compilation, sets the lowest // automatically assigned number. For HLSL compilation, the regsiter number // assigned to the resource is added to this specified base. SHADERC_EXPORT void shaderc_compile_options_set_binding_base( shaderc_compile_options_t options, shaderc_uniform_kind kind, uint32_t base); // Like shaderc_compile_options_set_binding_base, but only takes effect when // compiling a given shader stage. The stage is assumed to be one of vertex, // fragment, tessellation evaluation, tesselation control, geometry, or compute. SHADERC_EXPORT void shaderc_compile_options_set_binding_base_for_stage( shaderc_compile_options_t options, shaderc_shader_kind shader_kind, shaderc_uniform_kind kind, uint32_t base); // Sets whether the compiler should preserve all bindings, even when those // bindings are not used. SHADERC_EXPORT void shaderc_compile_options_set_preserve_bindings( shaderc_compile_options_t options, bool preserve_bindings); // Sets whether the compiler should automatically assign locations to // uniform variables that don't have explicit locations in the shader source. SHADERC_EXPORT void shaderc_compile_options_set_auto_map_locations( shaderc_compile_options_t options, bool auto_map); // Sets a descriptor set and binding for an HLSL register in the given stage. // This method keeps a copy of the string data. SHADERC_EXPORT void shaderc_compile_options_set_hlsl_register_set_and_binding_for_stage( shaderc_compile_options_t options, shaderc_shader_kind shader_kind, const char* reg, const char* set, const char* binding); // Like shaderc_compile_options_set_hlsl_register_set_and_binding_for_stage, // but affects all shader stages. SHADERC_EXPORT void shaderc_compile_options_set_hlsl_register_set_and_binding( shaderc_compile_options_t options, const char* reg, const char* set, const char* binding); // Sets whether the compiler should enable extension // SPV_GOOGLE_hlsl_functionality1. SHADERC_EXPORT void shaderc_compile_options_set_hlsl_functionality1( shaderc_compile_options_t options, bool enable); // Sets whether 16-bit types are supported in HLSL or not. SHADERC_EXPORT void shaderc_compile_options_set_hlsl_16bit_types( shaderc_compile_options_t options, bool enable); // Enables or disables relaxed Vulkan rules. // // This allows most OpenGL shaders to compile under Vulkan semantics. SHADERC_EXPORT void shaderc_compile_options_set_vulkan_rules_relaxed( shaderc_compile_options_t options, bool enable); // Sets whether the compiler should invert position.Y output in vertex shader. SHADERC_EXPORT void shaderc_compile_options_set_invert_y( shaderc_compile_options_t options, bool enable); // Sets whether the compiler generates code for max and min builtins which, // if given a NaN operand, will return the other operand. Similarly, the clamp // builtin will favour the non-NaN operands, as if clamp were implemented // as a composition of max and min. SHADERC_EXPORT void shaderc_compile_options_set_nan_clamp( shaderc_compile_options_t options, bool enable); // An opaque handle to the results of a call to any shaderc_compile_into_*() // function. typedef struct shaderc_compilation_result* shaderc_compilation_result_t; // Takes a GLSL source string and the associated shader kind, input file // name, compiles it according to the given additional_options. If the shader // kind is not set to a specified kind, but shaderc_glslc_infer_from_source, // the compiler will try to deduce the shader kind from the source // string and a failure in deducing will generate an error. Currently only // #pragma annotation is supported. If the shader kind is set to one of the // default shader kinds, the compiler will fall back to the default shader // kind in case it failed to deduce the shader kind from source string. // The input_file_name is a null-termintated string. It is used as a tag to // identify the source string in cases like emitting error messages. It // doesn't have to be a 'file name'. // The source string will be compiled into SPIR-V binary and a // shaderc_compilation_result will be returned to hold the results. // The entry_point_name null-terminated string defines the name of the entry // point to associate with this GLSL source. If the additional_options // parameter is not null, then the compilation is modified by any options // present. May be safely called from multiple threads without explicit // synchronization. If there was failure in allocating the compiler object, // null will be returned. SHADERC_EXPORT shaderc_compilation_result_t shaderc_compile_into_spv( const shaderc_compiler_t compiler, const char* source_text, size_t source_text_size, shaderc_shader_kind shader_kind, const char* input_file_name, const char* entry_point_name, const shaderc_compile_options_t additional_options); // Like shaderc_compile_into_spv, but the result contains SPIR-V assembly text // instead of a SPIR-V binary module. The SPIR-V assembly syntax is as defined // by the SPIRV-Tools open source project. SHADERC_EXPORT shaderc_compilation_result_t shaderc_compile_into_spv_assembly( const shaderc_compiler_t compiler, const char* source_text, size_t source_text_size, shaderc_shader_kind shader_kind, const char* input_file_name, const char* entry_point_name, const shaderc_compile_options_t additional_options); // Like shaderc_compile_into_spv, but the result contains preprocessed source // code instead of a SPIR-V binary module SHADERC_EXPORT shaderc_compilation_result_t shaderc_compile_into_preprocessed_text( const shaderc_compiler_t compiler, const char* source_text, size_t source_text_size, shaderc_shader_kind shader_kind, const char* input_file_name, const char* entry_point_name, const shaderc_compile_options_t additional_options); // Takes an assembly string of the format defined in the SPIRV-Tools project // (https://github.com/KhronosGroup/SPIRV-Tools/blob/master/syntax.md), // assembles it into SPIR-V binary and a shaderc_compilation_result will be // returned to hold the results. // The assembling will pick options suitable for assembling specified in the // additional_options parameter. // May be safely called from multiple threads without explicit synchronization. // If there was failure in allocating the compiler object, null will be // returned. SHADERC_EXPORT shaderc_compilation_result_t shaderc_assemble_into_spv( const shaderc_compiler_t compiler, const char* source_assembly, size_t source_assembly_size, const shaderc_compile_options_t additional_options); // The following functions, operating on shaderc_compilation_result_t objects, // offer only the basic thread-safety guarantee. // Releases the resources held by the result object. It is invalid to use the // result object for any further operations. SHADERC_EXPORT void shaderc_result_release(shaderc_compilation_result_t result); // Returns the number of bytes of the compilation output data in a result // object. SHADERC_EXPORT size_t shaderc_result_get_length(const shaderc_compilation_result_t result); // Returns the number of warnings generated during the compilation. SHADERC_EXPORT size_t shaderc_result_get_num_warnings( const shaderc_compilation_result_t result); // Returns the number of errors generated during the compilation. SHADERC_EXPORT size_t shaderc_result_get_num_errors(const shaderc_compilation_result_t result); // Returns the compilation status, indicating whether the compilation succeeded, // or failed due to some reasons, like invalid shader stage or compilation // errors. SHADERC_EXPORT shaderc_compilation_status shaderc_result_get_compilation_status( const shaderc_compilation_result_t); // Returns a pointer to the start of the compilation output data bytes, either // SPIR-V binary or char string. When the source string is compiled into SPIR-V // binary, this is guaranteed to be castable to a uint32_t*. If the result // contains assembly text or preprocessed source text, the pointer will point to // the resulting array of characters. SHADERC_EXPORT const char* shaderc_result_get_bytes(const shaderc_compilation_result_t result); // Returns a null-terminated string that contains any error messages generated // during the compilation. SHADERC_EXPORT const char* shaderc_result_get_error_message( const shaderc_compilation_result_t result); // Provides the version & revision of the SPIR-V which will be produced SHADERC_EXPORT void shaderc_get_spv_version(unsigned int* version, unsigned int* revision); // Parses the version and profile from a given null-terminated string // containing both version and profile, like: '450core'. Returns false if // the string can not be parsed. Returns true when the parsing succeeds. The // parsed version and profile are returned through arguments. SHADERC_EXPORT bool shaderc_parse_version_profile(const char* str, int* version, shaderc_profile* profile); #ifdef __cplusplus } #endif // __cplusplus #endif // SHADERC_SHADERC_H_ shaderc-2025.2/libshaderc/include/shaderc/shaderc.hpp000066400000000000000000000672661500222170200225030ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef SHADERC_SHADERC_HPP_ #define SHADERC_SHADERC_HPP_ #include #include #include #include "shaderc.h" namespace shaderc { // A CompilationResult contains the compiler output, compilation status, // and messages. // // The compiler output is stored as an array of elements and accessed // via random access iterators provided by cbegin() and cend(). The iterators // are contiguous in the sense of "Contiguous Iterators: A Refinement of // Random Access Iterators", Nevin Liber, C++ Library Evolution Working // Group Working Paper N3884. // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3884.pdf // // Methods begin() and end() are also provided to enable range-based for. // They are synonyms to cbegin() and cend(), respectively. template class CompilationResult { public: typedef OutputElementType element_type; // The type used to describe the begin and end iterators on the // compiler output. typedef const OutputElementType* const_iterator; // Upon creation, the CompilationResult takes ownership of the // shaderc_compilation_result instance. During destruction of the // CompilationResult, the shaderc_compilation_result will be released. explicit CompilationResult(shaderc_compilation_result_t compilation_result) : compilation_result_(compilation_result) {} CompilationResult() : compilation_result_(nullptr) {} ~CompilationResult() { shaderc_result_release(compilation_result_); } CompilationResult(CompilationResult&& other) : compilation_result_(nullptr) { *this = std::move(other); } CompilationResult& operator=(CompilationResult&& other) { if (compilation_result_) { shaderc_result_release(compilation_result_); } compilation_result_ = other.compilation_result_; other.compilation_result_ = nullptr; return *this; } // Returns any error message found during compilation. std::string GetErrorMessage() const { if (!compilation_result_) { return ""; } return shaderc_result_get_error_message(compilation_result_); } // Returns the compilation status, indicating whether the compilation // succeeded, or failed due to some reasons, like invalid shader stage or // compilation errors. shaderc_compilation_status GetCompilationStatus() const { if (!compilation_result_) { return shaderc_compilation_status_null_result_object; } return shaderc_result_get_compilation_status(compilation_result_); } // Returns a random access (contiguous) iterator pointing to the start // of the compilation output. It is valid for the lifetime of this object. // If there is no compilation result, then returns nullptr. const_iterator cbegin() const { if (!compilation_result_) return nullptr; return reinterpret_cast( shaderc_result_get_bytes(compilation_result_)); } // Returns a random access (contiguous) iterator pointing to the end of // the compilation output. It is valid for the lifetime of this object. // If there is no compilation result, then returns nullptr. const_iterator cend() const { if (!compilation_result_) return nullptr; return cbegin() + shaderc_result_get_length(compilation_result_) / sizeof(OutputElementType); } // Returns the same iterator as cbegin(). const_iterator begin() const { return cbegin(); } // Returns the same iterator as cend(). const_iterator end() const { return cend(); } // Returns the number of warnings generated during the compilation. size_t GetNumWarnings() const { if (!compilation_result_) { return 0; } return shaderc_result_get_num_warnings(compilation_result_); } // Returns the number of errors generated during the compilation. size_t GetNumErrors() const { if (!compilation_result_) { return 0; } return shaderc_result_get_num_errors(compilation_result_); } private: CompilationResult(const CompilationResult& other) = delete; CompilationResult& operator=(const CompilationResult& other) = delete; shaderc_compilation_result_t compilation_result_; }; // A compilation result for a SPIR-V binary module, which is an array // of uint32_t words. using SpvCompilationResult = CompilationResult; // A compilation result in SPIR-V assembly syntax. using AssemblyCompilationResult = CompilationResult; // Preprocessed source text. using PreprocessedSourceCompilationResult = CompilationResult; // Contains any options that can have default values for a compilation. class CompileOptions { public: CompileOptions() { options_ = shaderc_compile_options_initialize(); } ~CompileOptions() { shaderc_compile_options_release(options_); } CompileOptions(const CompileOptions& other) { options_ = shaderc_compile_options_clone(other.options_); } CompileOptions(CompileOptions&& other) { options_ = other.options_; other.options_ = nullptr; } // Adds a predefined macro to the compilation options. It behaves the same as // shaderc_compile_options_add_macro_definition in shaderc.h. void AddMacroDefinition(const char* name, size_t name_length, const char* value, size_t value_length) { shaderc_compile_options_add_macro_definition(options_, name, name_length, value, value_length); } // Adds a valueless predefined macro to the compilation options. void AddMacroDefinition(const std::string& name) { AddMacroDefinition(name.c_str(), name.size(), nullptr, 0u); } // Adds a predefined macro to the compilation options. void AddMacroDefinition(const std::string& name, const std::string& value) { AddMacroDefinition(name.c_str(), name.size(), value.c_str(), value.size()); } // Sets the compiler mode to generate debug information in the output. void SetGenerateDebugInfo() { shaderc_compile_options_set_generate_debug_info(options_); } // Sets the compiler optimization level to the given level. Only the last one // takes effect if multiple calls of this function exist. void SetOptimizationLevel(shaderc_optimization_level level) { shaderc_compile_options_set_optimization_level(options_, level); } // A C++ version of the libshaderc includer interface. class IncluderInterface { public: // Handles shaderc_include_resolver_fn callbacks. virtual shaderc_include_result* GetInclude(const char* requested_source, shaderc_include_type type, const char* requesting_source, size_t include_depth) = 0; // Handles shaderc_include_result_release_fn callbacks. virtual void ReleaseInclude(shaderc_include_result* data) = 0; virtual ~IncluderInterface() = default; }; // Sets the includer instance for libshaderc to call during compilation, as // described in shaderc_compile_options_set_include_callbacks(). Callbacks // are routed to this includer's methods. void SetIncluder(std::unique_ptr&& includer) { includer_ = std::move(includer); shaderc_compile_options_set_include_callbacks( options_, [](void* user_data, const char* requested_source, int type, const char* requesting_source, size_t include_depth) { auto* sub_includer = static_cast(user_data); return sub_includer->GetInclude( requested_source, static_cast(type), requesting_source, include_depth); }, [](void* user_data, shaderc_include_result* include_result) { auto* sub_includer = static_cast(user_data); return sub_includer->ReleaseInclude(include_result); }, includer_.get()); } // Forces the GLSL language version and profile to a given pair. The version // number is the same as would appear in the #version annotation in the // source. Version and profile specified here overrides the #version // annotation in the source. Use profile: 'shaderc_profile_none' for GLSL // versions that do not define profiles, e.g. versions below 150. void SetForcedVersionProfile(int version, shaderc_profile profile) { shaderc_compile_options_set_forced_version_profile(options_, version, profile); } // Sets the compiler mode to suppress warnings. Note this option overrides // warnings-as-errors mode. When both suppress-warnings and warnings-as-errors // modes are turned on, warning messages will be inhibited, and will not be // emitted as error message. void SetSuppressWarnings() { shaderc_compile_options_set_suppress_warnings(options_); } // Sets the source language. The default is GLSL. void SetSourceLanguage(shaderc_source_language lang) { shaderc_compile_options_set_source_language(options_, lang); } // Sets the target shader environment, affecting which warnings or errors will // be issued. The version will be for distinguishing between different // versions of the target environment. The version value should be either 0 // or a value listed in shaderc_env_version. The 0 value maps to Vulkan 1.0 // if |target| is Vulkan, and it maps to OpenGL 4.5 if |target| is OpenGL. void SetTargetEnvironment(shaderc_target_env target, uint32_t version) { shaderc_compile_options_set_target_env(options_, target, version); } // Sets the target SPIR-V version. The generated module will use this version // of SPIR-V. Each target environment determines what versions of SPIR-V // it can consume. Defaults to the highest version of SPIR-V 1.0 which is // required to be supported by the target environment. E.g. Default to SPIR-V // 1.0 for Vulkan 1.0 and SPIR-V 1.3 for Vulkan 1.1. void SetTargetSpirv(shaderc_spirv_version version) { shaderc_compile_options_set_target_spirv(options_, version); } // Sets the compiler mode to make all warnings into errors. Note the // suppress-warnings mode overrides this option, i.e. if both // warning-as-errors and suppress-warnings modes are set on, warnings will not // be emitted as error message. void SetWarningsAsErrors() { shaderc_compile_options_set_warnings_as_errors(options_); } // Sets a resource limit. void SetLimit(shaderc_limit limit, int value) { shaderc_compile_options_set_limit(options_, limit, value); } // Sets whether the compiler should automatically assign bindings to uniforms // that aren't already explicitly bound in the shader source. void SetAutoBindUniforms(bool auto_bind) { shaderc_compile_options_set_auto_bind_uniforms(options_, auto_bind); } // Sets whether the compiler should automatically remove sampler variables // and convert image variables to combined image sampler variables. void SetAutoSampledTextures(bool auto_sampled) { shaderc_compile_options_set_auto_combined_image_sampler(options_, auto_sampled); } // Sets whether the compiler should use HLSL IO mapping rules for bindings. // Defaults to false. void SetHlslIoMapping(bool hlsl_iomap) { shaderc_compile_options_set_hlsl_io_mapping(options_, hlsl_iomap); } // Sets whether the compiler should determine block member offsets using HLSL // packing rules instead of standard GLSL rules. Defaults to false. Only // affects GLSL compilation. HLSL rules are always used when compiling HLSL. void SetHlslOffsets(bool hlsl_offsets) { shaderc_compile_options_set_hlsl_offsets(options_, hlsl_offsets); } // Sets the base binding number used for for a uniform resource type when // automatically assigning bindings. For GLSL compilation, sets the lowest // automatically assigned number. For HLSL compilation, the regsiter number // assigned to the resource is added to this specified base. void SetBindingBase(shaderc_uniform_kind kind, uint32_t base) { shaderc_compile_options_set_binding_base(options_, kind, base); } // Like SetBindingBase, but only takes effect when compiling a given shader // stage. The stage is assumed to be one of vertex, fragment, tessellation // evaluation, tesselation control, geometry, or compute. void SetBindingBaseForStage(shaderc_shader_kind shader_kind, shaderc_uniform_kind kind, uint32_t base) { shaderc_compile_options_set_binding_base_for_stage(options_, shader_kind, kind, base); } // Sets whether the compiler should preserve all bindings, even when those // bindings are not used. void SetPreserveBindings(bool preserve_bindings) { shaderc_compile_options_set_preserve_bindings(options_, preserve_bindings); } // Sets whether the compiler automatically assigns locations to // uniform variables that don't have explicit locations. void SetAutoMapLocations(bool auto_map) { shaderc_compile_options_set_auto_map_locations(options_, auto_map); } // Sets a descriptor set and binding for an HLSL register in the given stage. // Copies the parameter strings. void SetHlslRegisterSetAndBindingForStage(shaderc_shader_kind shader_kind, const std::string& reg, const std::string& set, const std::string& binding) { shaderc_compile_options_set_hlsl_register_set_and_binding_for_stage( options_, shader_kind, reg.c_str(), set.c_str(), binding.c_str()); } // Sets a descriptor set and binding for an HLSL register in any stage. // Copies the parameter strings. void SetHlslRegisterSetAndBinding(const std::string& reg, const std::string& set, const std::string& binding) { shaderc_compile_options_set_hlsl_register_set_and_binding( options_, reg.c_str(), set.c_str(), binding.c_str()); } // Sets whether the compiler should enable extension // SPV_GOOGLE_hlsl_functionality1. void SetHlslFunctionality1(bool enable) { shaderc_compile_options_set_hlsl_functionality1(options_, enable); } // Sets whether 16-bit types are supported in HLSL or not. void SetHlsl16BitTypes(bool enable) { shaderc_compile_options_set_hlsl_16bit_types(options_, enable); } // Enables or disables relaxed Vulkan rules. // // This allows most OpenGL shaders to compile under Vulkan semantics. void SetVulkanRulesRelaxed(bool enable) { shaderc_compile_options_set_vulkan_rules_relaxed(options_, enable); } // Sets whether the compiler should invert position.Y output in vertex shader. void SetInvertY(bool enable) { shaderc_compile_options_set_invert_y(options_, enable); } // Sets whether the compiler should generate code for max and min which, // if given a NaN operand, will return the other operand. Similarly, the // clamp builtin will favour the non-NaN operands, as if clamp were // implemented as a composition of max and min. void SetNanClamp(bool enable) { shaderc_compile_options_set_nan_clamp(options_, enable); } private: CompileOptions& operator=(const CompileOptions& other) = delete; shaderc_compile_options_t options_; std::unique_ptr includer_; friend class Compiler; }; // The compilation context for compiling source to SPIR-V. class Compiler { public: Compiler() : compiler_(shaderc_compiler_initialize()) {} ~Compiler() { shaderc_compiler_release(compiler_); } Compiler(Compiler&& other) { compiler_ = other.compiler_; other.compiler_ = nullptr; } bool IsValid() const { return compiler_ != nullptr; } // Compiles the given source GLSL and returns a SPIR-V binary module // compilation result. // The source_text parameter must be a valid pointer. // The source_text_size parameter must be the length of the source text. // The shader_kind parameter either forces the compilation to be done with a // specified shader kind, or hint the compiler how to determine the exact // shader kind. If the shader kind is set to shaderc_glslc_infer_from_source, // the compiler will try to deduce the shader kind from the source string and // a failure in this proess will generate an error. Currently only #pragma // annotation is supported. If the shader kind is set to one of the default // shader kinds, the compiler will fall back to the specified default shader // kind in case it failed to deduce the shader kind from the source string. // The input_file_name is a null-termintated string. It is used as a tag to // identify the source string in cases like emitting error messages. It // doesn't have to be a 'file name'. // The entry_point_name parameter is a null-terminated string specifying // the entry point name for HLSL compilation. For GLSL compilation, the // entry point name is assumed to be "main". // The compilation is passed any options specified in the CompileOptions // parameter. // It is valid for the returned CompilationResult object to outlive this // compiler object. // Note when the options_ has disassembly mode or preprocessing only mode set // on, the returned CompilationResult will hold a text string, instead of a // SPIR-V binary generated with default options. SpvCompilationResult CompileGlslToSpv(const char* source_text, size_t source_text_size, shaderc_shader_kind shader_kind, const char* input_file_name, const char* entry_point_name, const CompileOptions& options) const { shaderc_compilation_result_t compilation_result = shaderc_compile_into_spv( compiler_, source_text, source_text_size, shader_kind, input_file_name, entry_point_name, options.options_); return SpvCompilationResult(compilation_result); } // Compiles the given source shader and returns a SPIR-V binary module // compilation result. // Like the first CompileGlslToSpv method but assumes the entry point name // is "main". SpvCompilationResult CompileGlslToSpv(const char* source_text, size_t source_text_size, shaderc_shader_kind shader_kind, const char* input_file_name, const CompileOptions& options) const { return CompileGlslToSpv(source_text, source_text_size, shader_kind, input_file_name, "main", options); } // Compiles the given source GLSL and returns a SPIR-V binary module // compilation result. // Like the previous CompileGlslToSpv method but uses default options. SpvCompilationResult CompileGlslToSpv(const char* source_text, size_t source_text_size, shaderc_shader_kind shader_kind, const char* input_file_name) const { shaderc_compilation_result_t compilation_result = shaderc_compile_into_spv(compiler_, source_text, source_text_size, shader_kind, input_file_name, "main", nullptr); return SpvCompilationResult(compilation_result); } // Compiles the given source shader and returns a SPIR-V binary module // compilation result. // Like the first CompileGlslToSpv method but the source is provided as // a std::string, and we assume the entry point is "main". SpvCompilationResult CompileGlslToSpv(const std::string& source_text, shaderc_shader_kind shader_kind, const char* input_file_name, const CompileOptions& options) const { return CompileGlslToSpv(source_text.data(), source_text.size(), shader_kind, input_file_name, options); } // Compiles the given source shader and returns a SPIR-V binary module // compilation result. // Like the first CompileGlslToSpv method but the source is provided as // a std::string. SpvCompilationResult CompileGlslToSpv(const std::string& source_text, shaderc_shader_kind shader_kind, const char* input_file_name, const char* entry_point_name, const CompileOptions& options) const { return CompileGlslToSpv(source_text.data(), source_text.size(), shader_kind, input_file_name, entry_point_name, options); } // Compiles the given source GLSL and returns a SPIR-V binary module // compilation result. // Like the previous CompileGlslToSpv method but assumes the entry point // name is "main". SpvCompilationResult CompileGlslToSpv(const std::string& source_text, shaderc_shader_kind shader_kind, const char* input_file_name) const { return CompileGlslToSpv(source_text.data(), source_text.size(), shader_kind, input_file_name); } // Assembles the given SPIR-V assembly and returns a SPIR-V binary module // compilation result. // The assembly should follow the syntax defined in the SPIRV-Tools project // (https://github.com/KhronosGroup/SPIRV-Tools/blob/master/syntax.md). // It is valid for the returned CompilationResult object to outlive this // compiler object. // The assembling will pick options suitable for assembling specified in the // CompileOptions parameter. SpvCompilationResult AssembleToSpv(const char* source_assembly, size_t source_assembly_size, const CompileOptions& options) const { return SpvCompilationResult(shaderc_assemble_into_spv( compiler_, source_assembly, source_assembly_size, options.options_)); } // Assembles the given SPIR-V assembly and returns a SPIR-V binary module // compilation result. // Like the first AssembleToSpv method but uses the default compiler options. SpvCompilationResult AssembleToSpv(const char* source_assembly, size_t source_assembly_size) const { return SpvCompilationResult(shaderc_assemble_into_spv( compiler_, source_assembly, source_assembly_size, nullptr)); } // Assembles the given SPIR-V assembly and returns a SPIR-V binary module // compilation result. // Like the first AssembleToSpv method but the source is provided as a // std::string. SpvCompilationResult AssembleToSpv(const std::string& source_assembly, const CompileOptions& options) const { return SpvCompilationResult( shaderc_assemble_into_spv(compiler_, source_assembly.data(), source_assembly.size(), options.options_)); } // Assembles the given SPIR-V assembly and returns a SPIR-V binary module // compilation result. // Like the first AssembleToSpv method but the source is provided as a // std::string and also uses default compiler options. SpvCompilationResult AssembleToSpv(const std::string& source_assembly) const { return SpvCompilationResult(shaderc_assemble_into_spv( compiler_, source_assembly.data(), source_assembly.size(), nullptr)); } // Compiles the given source GLSL and returns the SPIR-V assembly text // compilation result. // Options are similar to the first CompileToSpv method. AssemblyCompilationResult CompileGlslToSpvAssembly( const char* source_text, size_t source_text_size, shaderc_shader_kind shader_kind, const char* input_file_name, const char* entry_point_name, const CompileOptions& options) const { shaderc_compilation_result_t compilation_result = shaderc_compile_into_spv_assembly( compiler_, source_text, source_text_size, shader_kind, input_file_name, entry_point_name, options.options_); return AssemblyCompilationResult(compilation_result); } // Compiles the given source GLSL and returns the SPIR-V assembly text // compilation result. // Similare to the previous method, but assumes entry point name is "main". AssemblyCompilationResult CompileGlslToSpvAssembly( const char* source_text, size_t source_text_size, shaderc_shader_kind shader_kind, const char* input_file_name, const CompileOptions& options) const { return CompileGlslToSpvAssembly(source_text, source_text_size, shader_kind, input_file_name, "main", options); } // Compiles the given source GLSL and returns the SPIR-V assembly text // result. Like the first CompileGlslToSpvAssembly method but the source // is provided as a std::string. Options are otherwise similar to // the first CompileToSpv method. AssemblyCompilationResult CompileGlslToSpvAssembly( const std::string& source_text, shaderc_shader_kind shader_kind, const char* input_file_name, const char* entry_point_name, const CompileOptions& options) const { return CompileGlslToSpvAssembly(source_text.data(), source_text.size(), shader_kind, input_file_name, entry_point_name, options); } // Compiles the given source GLSL and returns the SPIR-V assembly text // result. Like the previous CompileGlslToSpvAssembly method but assumes // the entry point name is "main". AssemblyCompilationResult CompileGlslToSpvAssembly( const std::string& source_text, shaderc_shader_kind shader_kind, const char* input_file_name, const CompileOptions& options) const { return CompileGlslToSpvAssembly(source_text, shader_kind, input_file_name, "main", options); } // Preprocesses the given source GLSL and returns the preprocessed // source text as a compilation result. // Options are similar to the first CompileToSpv method. PreprocessedSourceCompilationResult PreprocessGlsl( const char* source_text, size_t source_text_size, shaderc_shader_kind shader_kind, const char* input_file_name, const CompileOptions& options) const { shaderc_compilation_result_t compilation_result = shaderc_compile_into_preprocessed_text( compiler_, source_text, source_text_size, shader_kind, input_file_name, "main", options.options_); return PreprocessedSourceCompilationResult(compilation_result); } // Preprocesses the given source GLSL and returns text result. Like the first // PreprocessGlsl method but the source is provided as a std::string. // Options are otherwise similar to the first CompileToSpv method. PreprocessedSourceCompilationResult PreprocessGlsl( const std::string& source_text, shaderc_shader_kind shader_kind, const char* input_file_name, const CompileOptions& options) const { return PreprocessGlsl(source_text.data(), source_text.size(), shader_kind, input_file_name, options); } private: Compiler(const Compiler&) = delete; Compiler& operator=(const Compiler& other) = delete; shaderc_compiler_t compiler_; }; } // namespace shaderc #endif // SHADERC_SHADERC_HPP_ shaderc-2025.2/libshaderc/include/shaderc/status.h000066400000000000000000000025411500222170200220360ustar00rootroot00000000000000// Copyright 2018 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef SHADERC_STATUS_H_ #define SHADERC_STATUS_H_ #ifdef __cplusplus extern "C" { #endif // Indicate the status of a compilation. typedef enum { shaderc_compilation_status_success = 0, shaderc_compilation_status_invalid_stage = 1, // error stage deduction shaderc_compilation_status_compilation_error = 2, shaderc_compilation_status_internal_error = 3, // unexpected failure shaderc_compilation_status_null_result_object = 4, shaderc_compilation_status_invalid_assembly = 5, shaderc_compilation_status_validation_error = 6, shaderc_compilation_status_transformation_error = 7, shaderc_compilation_status_configuration_error = 8, } shaderc_compilation_status; #ifdef __cplusplus } #endif // __cplusplus #endif // SHADERC_STATUS_H_ shaderc-2025.2/libshaderc/include/shaderc/visibility.h000066400000000000000000000022131500222170200226760ustar00rootroot00000000000000// Copyright 2018 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef SHADERC_VISIBILITY_H_ #define SHADERC_VISIBILITY_H_ // SHADERC_EXPORT tags symbol that will be exposed by the shared libraries. #if defined(SHADERC_SHAREDLIB) #if defined(_WIN32) #if defined(SHADERC_IMPLEMENTATION) #define SHADERC_EXPORT __declspec(dllexport) #else #define SHADERC_EXPORT __declspec(dllimport) #endif #else #if defined(SHADERC_IMPLEMENTATION) #define SHADERC_EXPORT __attribute__((visibility("default"))) #else #define SHADERC_EXPORT #endif #endif #else #define SHADERC_EXPORT #endif #endif // SHADERC_VISIBILITY_H_ shaderc-2025.2/libshaderc/src/000077500000000000000000000000001500222170200160735ustar00rootroot00000000000000shaderc-2025.2/libshaderc/src/common_shaders_for_test.h000066400000000000000000000305621500222170200231600ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef COMMON_SHADERS_FOR_TESTS_H_ #define COMMON_SHADERS_FOR_TESTS_H_ #ifdef __cplusplus extern "C" { #endif // The minimal shader, without a version directive. const char kMinimalShaderWithoutVersion[] = "void main(){}"; // The minimal shader, with a version directive. const char kMinimalShader[] = "#version 140\n" "void main(){}"; const char kMinimalHlslShader[] = "float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION\n" "{ return float4(1.0, 2.0, 3.0, 4.0); }"; const char kMinimalShaderWithMacro[] = "#version 140\n" "#define E main\n" "void E(){}\n"; // The minimal shader that needs valueless predefinition of 'E' to compile. const char kValuelessPredefinitionShader[] = "#version 140\n" "#ifdef E\n" "void main(){}\n" "#else\n" "#error\n" "#endif"; // By default the compiler will emit a warning on line 2 complaining // that 'float' is a deprecated attribute in version 130. Use verison 140 // because some versions of glslang will error out for a too-low version // when generating SPIR-V. const char kDeprecatedAttributeShader[] = "#version 400\n" "layout(location = 0) attribute float x;\n" "void main() {}\n"; // By default the compiler will emit a warning as version 550 is an unknown // version. const char kMinimalUnknownVersionShader[] = "#version 550\n" "void main() {}\n"; // gl_ClipDistance doesn't exist in es profile (at least until 3.10). const char kCoreVertShaderWithoutVersion[] = "void main() {\n" "gl_ClipDistance[0] = 5.;\n" "}\n"; // Generated debug information should contain the name of the vector: // debug_info_sample. const char kMinimalDebugInfoShader[] = "#version 140\n" "void main(){\n" "vec2 debug_info_sample = vec2(1.0,1.0);\n" "}\n"; // Compiler should generate two errors. const char kTwoErrorsShader[] = "#version 150\n" "#error\n" "#error\n" "void main(){}\n"; // Compiler should generate two warnings. const char kTwoWarningsShader[] = "#version 400\n" "layout(location = 0) attribute float x;\n" "layout(location = 1) attribute float y;\n" "void main(){}\n"; // A shader that compiles under OpenGL compatibility profile rules, // but not OpenGL core profile rules. const char kOpenGLCompatibilityFragmentShader[] = R"(#version 100 uniform highp sampler2D tex; void main() { gl_FragColor = texture2D(tex, vec2(0.0,0.0)); })"; // A shader that compiles under OpenGL core profile rules. const char kOpenGLVertexShader[] = R"(#version 330 void main() { int t = gl_VertexID; })"; // Empty 310 es shader. It is valid for vertex, fragment, compute shader kind. const char kEmpty310ESShader[] = "#version 310 es\n" "void main() {}\n"; // Vertex only shader. const char kVertexOnlyShader[] = "#version 310 es\n" "void main() {\n" " gl_Position = vec4(1.);\n" "}"; // TessControl only shader. const char kTessControlOnlyShader[] = "#version 440 core\n" "layout(vertices = 3) out;\n" "void main() { }"; // TessEvaluation only shader. const char kTessEvaluationOnlyShader[] = "#version 440 core\n" "layout(triangles) in;\n" "void main() { }"; // Geometry only shader. const char kGeometryOnlyShader[] = "#version 150 core\n" "layout (triangles) in;\n" "layout (line_strip, max_vertices = 4) out;\n" "void main() { }"; // Vertex only shader with #pragma annotation. const char kVertexOnlyShaderWithPragma[] = "#version 310 es\n" "#pragma shader_stage(vertex)\n" "void main() {\n" " gl_Position = vec4(1.);\n" "}"; // Fragment only shader with #pragma annotation. const char kFragmentOnlyShaderWithPragma[] = "#version 310 es\n" "#pragma shader_stage(fragment)\n" "void main() {\n" " gl_FragDepth = 10.;\n" "}"; // TessControl only shader with #pragma annotation. const char kTessControlOnlyShaderWithPragma[] = "#version 440 core\n" "#pragma shader_stage(tesscontrol)\n" "layout(vertices = 3) out;\n" "void main() { }"; // TessEvaluation only shader with #pragma annotation. const char kTessEvaluationOnlyShaderWithPragma[] = "#version 440 core\n" "#pragma shader_stage(tesseval)\n" "layout(triangles) in;\n" "void main() { }"; // Geometry only shader with #pragma annotation. const char kGeometryOnlyShaderWithPragma[] = "#version 150 core\n" "#pragma shader_stage(geometry)\n" "layout (triangles) in;\n" "layout (line_strip, max_vertices = 4) out;\n" "void main() { }"; // Compute only shader with #pragma annotation. const char kComputeOnlyShaderWithPragma[] = "#version 310 es\n" "#pragma shader_stage(compute)\n" "void main() {\n" " uvec3 temp = gl_WorkGroupID;\n" "}"; // NV mesh shader without #pragma. const char kNVMeshShader[] = "#version 450\n" "#extension GL_NV_mesh_shader : enable\n" "layout(local_size_x=8) in;\n" "layout(max_vertices=5) out;\n" "layout(max_primitives=10) out;\n" "layout(triangles) out;\n" "void main() {\n" " gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_Position = vec4(0.0);\n" "}\n"; // NV mesh shader with #pragma annotation. const char kNVMeshShaderWithPragma[] = "#version 450\n" "#extension GL_NV_mesh_shader : enable\n" "#pragma shader_stage(mesh)\n" "layout(local_size_x=8) in;\n" "layout(max_vertices=5) out;\n" "layout(max_primitives=10) out;\n" "layout(triangles) out;\n" "void main() {\n" " gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_Position = vec4(0.0);\n" "}\n"; // NV task shader without #pragma annotation. const char kNVTaskShader[] = "#version 450\n" "#extension GL_NV_mesh_shader : enable\n" "layout(local_size_x=8) in;\n" "void main() {\n" " gl_TaskCountNV = 2;\n" "}\n"; // NV task shader with #pragma annotation. const char kNVTaskShaderWithPragma[] = "#version 450\n" "#extension GL_NV_mesh_shader : enable\n" "#pragma shader_stage(task)\n" "layout(local_size_x=8) in;\n" "void main() {\n" " gl_TaskCountNV = 2;\n" "}\n"; // Vertex only shader with invalid #pragma annotation. const char kVertexOnlyShaderWithInvalidPragma[] = "#version 310 es\n" "#pragma shader_stage(fragment)\n" "void main() {\n" " gl_Position = vec4(1.);\n" "}"; // Parts of a valid disassembly of a minimal shader. We only check certain // parts since Glslang code generation changes in incidental ways. const char* kMinimalShaderDisassemblySubstrings[] = { "; SPIR-V\n" "; Version: 1.0\n" "; Generator: Google Shaderc over Glslang; 11\n" "; Bound:", " OpCapability Shader\n", " %1 = OpExtInstImport \"GLSL.std.450\"\n", " OpMemoryModel Logical GLSL450\n", " OpReturn\n", " OpFunctionEnd\n"}; const char* kMinimalShaderDebugInfoDisassemblySubstrings[] = { "; SPIR-V\n" "; Version: 1.0\n" "; Generator: Google Shaderc over Glslang; 11\n" "; Bound:", " OpCapability Shader\n", " %2 = OpExtInstImport \"GLSL.std.450\"\n", " OpMemoryModel Logical GLSL450\n", " OpReturn\n", " OpFunctionEnd\n"}; const char kMinimalShaderAssembly[] = R"( ; SPIR-V ; Version: 1.0 ; Generator: Google Shaderc over Glslang; 11 ; Bound: 6 ; Schema: 0 OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Vertex %4 "main" OpSource ESSL 310 OpName %4 "main" %2 = OpTypeVoid %3 = OpTypeFunction %2 %4 = OpFunction %2 None %3 %5 = OpLabel OpReturn OpFunctionEnd)"; const char kShaderWithUniformsWithoutBindings[] = R"(#version 450 #extension GL_ARB_sparse_texture2 : enable uniform texture2D my_tex; uniform sampler my_sam; layout(rgba32f) uniform image2D my_img; layout(rgba32f) uniform imageBuffer my_imbuf; uniform block { float x; float y; } my_ubo; void main() { texture(sampler2D(my_tex,my_sam),vec2(1.0)); vec4 t; sparseImageLoadARB(my_img,ivec2(0),t); imageLoad(my_imbuf,42); float x = my_ubo.x; })"; // A GLSL vertex shader with a weirdly packed block. const char kGlslShaderWeirdPacking[] = R"(#version 450 layout(set=0, binding=0) buffer B { float x; vec3 foo; } my_ssbo; void main() { my_ssbo.x = 1.0; })"; // A HLSL fragment shader with a weirdly packed block. const char kHlslFragShaderWithRegisters[] = R"(Buffer t4 : register(t4); Buffer t5 : register(t5); float4 main() : SV_Target0 { return float4(t4.Load(0) + t5.Load(1)); })"; // A GLSL compute shader using a regular barrier. const char kGlslShaderComputeBarrier[] = R"(#version 450 void main() { barrier(); })"; // A GLSL compute shader using the Subgroups feature. const char kGlslShaderComputeSubgroupBarrier[] = R"(#version 450 #extension GL_KHR_shader_subgroup_basic : enable void main() { subgroupBarrier(); })"; // A GLSL task shader using a regular barrier. const char kGlslShaderTaskBarrier[] = R"(#version 450 #extension GL_NV_mesh_shader : enable layout(local_size_x = 32) in; void main() { barrier(); })"; // A GLSL task shader using the Subgroups feature. const char kGlslShaderTaskSubgroupBarrier[] = R"(#version 450 #extension GL_NV_mesh_shader : enable #extension GL_KHR_shader_subgroup_basic : enable layout(local_size_x = 32) in; void main() { subgroupBarrier(); })"; // A GLSL mesh shader using a regular barrier. const char kGlslShaderMeshBarrier[] = R"(#version 450 #extension GL_NV_mesh_shader : enable layout(local_size_x = 32) in; layout(max_vertices=81) out; layout(max_primitives=32) out; layout(triangles) out; void main() { barrier(); })"; // A GLSL mesh shader using the Subgroups feature. const char kGlslShaderMeshSubgroupBarrier[] = R"(#version 450 #extension GL_NV_mesh_shader : enable #extension GL_KHR_shader_subgroup_basic : enable layout(local_size_x = 32) in; layout(max_vertices=81) out; layout(max_primitives=32) out; layout(triangles) out; void main() { subgroupBarrier(); })"; const char kGlslMultipleFnShader[] = R"(#version 450 layout(location=0) flat in int inVal; layout(location=0) out int outVal; int foo(int a) { return a; } void main() { outVal = foo(inVal); })"; const char kHlslShaderWithCounterBuffer[] = R"(RWStructuredBuffer Ainc; float4 main() : SV_Target0 { return float4(Ainc.IncrementCounter(), 0, 0, 0); })"; const char kHlslWaveActiveSumeComputeShader[] = R"(struct S { uint val; uint result; }; [[vk::binding(0,0)]] RWStructuredBuffer MyBuffer; [numthreads(32, 1, 1)] void main(uint3 id : SV_DispatchThreadID) { MyBuffer[id.x].result = WaveActiveSum(MyBuffer[id.x].val); })"; const char kHlslMemLayoutResourceSelect[] = R"(cbuffer Foo { float a; float3 b; } [[vk::binding(0,0)]] Texture2D Tex; [[vk::binding(1,0)]] SamplerState Sampler1; [[vk::binding(2,0)]] SamplerState Sampler2; static const int val = 42; float4 main() : SV_Target { SamplerState samp; if (val > 5) samp = Sampler1; else samp = Sampler2; return Tex.Sample(samp, float2(0.5, 0.5)) + float4(a, b); })"; const char kGlslShaderWithClamp[] = R"(#version 450 layout(location=0) in vec4 i; layout(location=0) out vec4 o; void main() { o = clamp(i, vec4(0.5), vec4(1.0)); } )"; #ifdef __cplusplus } #endif // __cplusplus #endif // COMMON_SHADERS_FOR_TESTS_H_ shaderc-2025.2/libshaderc/src/shaderc.cc000066400000000000000000000752421500222170200200250ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "shaderc/shaderc.h" #include #include #include #include #include #include #include "libshaderc_util/compiler.h" #include "libshaderc_util/counting_includer.h" #include "libshaderc_util/resources.h" #include "libshaderc_util/spirv_tools_wrapper.h" #include "libshaderc_util/version_profile.h" #include "shaderc_private.h" #include "spirv/unified1/spirv.hpp" #if (defined(_MSC_VER) && !defined(_CPPUNWIND)) || !defined(__EXCEPTIONS) #define TRY_IF_EXCEPTIONS_ENABLED #define CATCH_IF_EXCEPTIONS_ENABLED(X) if (0) #else #define TRY_IF_EXCEPTIONS_ENABLED try #define CATCH_IF_EXCEPTIONS_ENABLED(X) catch (X) #endif namespace { // Returns shader stage (ie: vertex, fragment, etc.) in response to forced // shader kinds. If the shader kind is not a forced kind, returns EshLangCount // to let #pragma annotation or shader stage deducer determine the stage to // use. EShLanguage GetForcedStage(shaderc_shader_kind kind) { switch (kind) { case shaderc_glsl_vertex_shader: return EShLangVertex; case shaderc_glsl_fragment_shader: return EShLangFragment; case shaderc_glsl_compute_shader: return EShLangCompute; case shaderc_glsl_geometry_shader: return EShLangGeometry; case shaderc_glsl_tess_control_shader: return EShLangTessControl; case shaderc_glsl_tess_evaluation_shader: return EShLangTessEvaluation; case shaderc_glsl_raygen_shader: return EShLangRayGenNV; case shaderc_glsl_anyhit_shader: return EShLangAnyHitNV; case shaderc_glsl_closesthit_shader: return EShLangClosestHitNV; case shaderc_glsl_miss_shader: return EShLangMissNV; case shaderc_glsl_intersection_shader: return EShLangIntersectNV; case shaderc_glsl_callable_shader: return EShLangCallableNV; case shaderc_glsl_task_shader: return EShLangTaskNV; case shaderc_glsl_mesh_shader: return EShLangMeshNV; case shaderc_glsl_infer_from_source: case shaderc_glsl_default_vertex_shader: case shaderc_glsl_default_fragment_shader: case shaderc_glsl_default_compute_shader: case shaderc_glsl_default_geometry_shader: case shaderc_glsl_default_tess_control_shader: case shaderc_glsl_default_tess_evaluation_shader: case shaderc_glsl_default_raygen_shader: case shaderc_glsl_default_anyhit_shader: case shaderc_glsl_default_closesthit_shader: case shaderc_glsl_default_miss_shader: case shaderc_glsl_default_intersection_shader: case shaderc_glsl_default_callable_shader: case shaderc_glsl_default_task_shader: case shaderc_glsl_default_mesh_shader: case shaderc_spirv_assembly: return EShLangCount; } assert(0 && "Unhandled shaderc_shader_kind"); return EShLangCount; } // A wrapper functor class to be used as stage deducer for libshaderc_util // Compile() interface. When the given shader kind is one of the default shader // kinds, this functor will be called if #pragma is not found in the source // code. And it returns the corresponding shader stage. When the shader kind is // a forced shader kind, this functor won't be called and it simply returns // EShLangCount to make the syntax correct. When the shader kind is set to // shaderc_glsl_deduce_from_pragma, this functor also returns EShLangCount, but // the compiler should emit error if #pragma annotation is not found in this // case. class StageDeducer { public: explicit StageDeducer( shaderc_shader_kind kind = shaderc_glsl_infer_from_source) : kind_(kind), error_(false) {} // The method that underlying glslang will call to determine the shader stage // to be used in current compilation. It is called only when there is neither // forced shader kind (or say stage, in the view of glslang), nor #pragma // annotation in the source code. This method transforms an user defined // 'default' shader kind to the corresponding shader stage. As this is the // last trial to determine the shader stage, failing to find the corresponding // shader stage will record an error. // Note that calling this method more than once during one compilation will // have the error recorded for the previous call been overwriten by the next // call. EShLanguage operator()(std::ostream* /*error_stream*/, const shaderc_util::string_piece& /*error_tag*/) { EShLanguage stage = GetDefaultStage(kind_); if (stage == EShLangCount) { error_ = true; } else { error_ = false; } return stage; } // Returns true if there is error during shader stage deduction. bool error() const { return error_; } private: // Gets the corresponding shader stage for a given 'default' shader kind. All // other kinds are mapped to EShLangCount which should not be used. EShLanguage GetDefaultStage(shaderc_shader_kind kind) const { switch (kind) { case shaderc_glsl_vertex_shader: case shaderc_glsl_fragment_shader: case shaderc_glsl_compute_shader: case shaderc_glsl_geometry_shader: case shaderc_glsl_tess_control_shader: case shaderc_glsl_tess_evaluation_shader: case shaderc_glsl_infer_from_source: case shaderc_glsl_raygen_shader: case shaderc_glsl_anyhit_shader: case shaderc_glsl_closesthit_shader: case shaderc_glsl_miss_shader: case shaderc_glsl_intersection_shader: case shaderc_glsl_callable_shader: case shaderc_glsl_task_shader: case shaderc_glsl_mesh_shader: return EShLangCount; case shaderc_glsl_default_vertex_shader: return EShLangVertex; case shaderc_glsl_default_fragment_shader: return EShLangFragment; case shaderc_glsl_default_compute_shader: return EShLangCompute; case shaderc_glsl_default_geometry_shader: return EShLangGeometry; case shaderc_glsl_default_tess_control_shader: return EShLangTessControl; case shaderc_glsl_default_tess_evaluation_shader: return EShLangTessEvaluation; case shaderc_glsl_default_raygen_shader: return EShLangRayGenNV; case shaderc_glsl_default_anyhit_shader: return EShLangAnyHitNV; case shaderc_glsl_default_closesthit_shader: return EShLangClosestHitNV; case shaderc_glsl_default_miss_shader: return EShLangMissNV; case shaderc_glsl_default_intersection_shader: return EShLangIntersectNV; case shaderc_glsl_default_callable_shader: return EShLangCallableNV; case shaderc_glsl_default_task_shader: return EShLangTaskNV; case shaderc_glsl_default_mesh_shader: return EShLangMeshNV; case shaderc_spirv_assembly: return EShLangCount; } assert(0 && "Unhandled shaderc_shader_kind"); return EShLangCount; } shaderc_shader_kind kind_; bool error_; }; // A bridge between the libshaderc includer and libshaderc_util includer. class InternalFileIncluder : public shaderc_util::CountingIncluder { public: InternalFileIncluder(const shaderc_include_resolve_fn resolver, const shaderc_include_result_release_fn result_releaser, void* user_data) : resolver_(resolver), result_releaser_(result_releaser), user_data_(user_data) {} InternalFileIncluder() : resolver_(nullptr), result_releaser_(nullptr), user_data_(nullptr) {} private: // Check the validity of the callbacks. bool AreValidCallbacks() const { return resolver_ != nullptr && result_releaser_ != nullptr; } // Maps CountingIncluder IncludeType value to a shaderc_include_type // value. shaderc_include_type GetIncludeType(IncludeType type) { switch (type) { case IncludeType::Local: return shaderc_include_type_relative; case IncludeType::System: return shaderc_include_type_standard; default: break; } assert(0 && "Unhandled IncludeType"); return shaderc_include_type_relative; } // Resolves an include request for the requested source of the given // type in the context of the specified requesting source. On success, // returns a newly allocated IncludeResponse containing the fully resolved // name of the requested source and the contents of that source. // On failure, returns a newly allocated IncludeResponse where the // resolved name member is an empty string, and the contents members // contains error details. virtual glslang::TShader::Includer::IncludeResult* include_delegate( const char* requested_source, const char* requesting_source, IncludeType type, size_t include_depth) override { if (!AreValidCallbacks()) { static const char kUnexpectedIncludeError[] = "#error unexpected include directive"; return new glslang::TShader::Includer::IncludeResult{ "", kUnexpectedIncludeError, strlen(kUnexpectedIncludeError), nullptr}; } shaderc_include_result* include_result = resolver_(user_data_, requested_source, GetIncludeType(type), requesting_source, include_depth); // Make a glslang IncludeResult from a shaderc_include_result. The // user_data member of the IncludeResult is a pointer to the // shaderc_include_result object, so we can later release the latter. return new glslang::TShader::Includer::IncludeResult{ std::string(include_result->source_name, include_result->source_name_length), include_result->content, include_result->content_length, include_result}; } // Releases the given IncludeResult. virtual void release_delegate( glslang::TShader::Includer::IncludeResult* result) override { if (result && result_releaser_) { result_releaser_(user_data_, static_cast(result->userData)); } delete result; } const shaderc_include_resolve_fn resolver_; const shaderc_include_result_release_fn result_releaser_; void* user_data_; }; // Converts the target env to the corresponding one in shaderc_util::Compiler. shaderc_util::Compiler::TargetEnv GetCompilerTargetEnv(shaderc_target_env env) { switch (env) { case shaderc_target_env_opengl: return shaderc_util::Compiler::TargetEnv::OpenGL; case shaderc_target_env_opengl_compat: return shaderc_util::Compiler::TargetEnv::OpenGLCompat; case shaderc_target_env_webgpu: assert(false); break; case shaderc_target_env_vulkan: default: break; } return shaderc_util::Compiler::TargetEnv::Vulkan; } shaderc_util::Compiler::TargetEnvVersion GetCompilerTargetEnvVersion( uint32_t version_number) { using namespace shaderc_util; if (static_cast(Compiler::TargetEnvVersion::Vulkan_1_0) == version_number) { return Compiler::TargetEnvVersion::Vulkan_1_0; } if (static_cast(Compiler::TargetEnvVersion::Vulkan_1_1) == version_number) { return Compiler::TargetEnvVersion::Vulkan_1_1; } if (static_cast(Compiler::TargetEnvVersion::Vulkan_1_2) == version_number) { return Compiler::TargetEnvVersion::Vulkan_1_2; } if (static_cast(Compiler::TargetEnvVersion::Vulkan_1_3) == version_number) { return Compiler::TargetEnvVersion::Vulkan_1_3; } if (static_cast(Compiler::TargetEnvVersion::Vulkan_1_4) == version_number) { return Compiler::TargetEnvVersion::Vulkan_1_4; } if (static_cast(Compiler::TargetEnvVersion::OpenGL_4_5) == version_number) { return Compiler::TargetEnvVersion::OpenGL_4_5; } return Compiler::TargetEnvVersion::Default; } // Returns the Compiler::Limit enum for the given shaderc_limit enum. shaderc_util::Compiler::Limit CompilerLimit(shaderc_limit limit) { switch (limit) { #define RESOURCE(NAME, FIELD, CNAME) \ case shaderc_limit_##CNAME: \ return shaderc_util::Compiler::Limit::NAME; #include "libshaderc_util/resources.inc" #undef RESOURCE default: break; } assert(0 && "Should not have reached here"); return static_cast(0); } // Returns the Compiler::UniformKind for the given shaderc_uniform_kind. shaderc_util::Compiler::UniformKind GetUniformKind(shaderc_uniform_kind kind) { switch (kind) { case shaderc_uniform_kind_texture: return shaderc_util::Compiler::UniformKind::Texture; case shaderc_uniform_kind_sampler: return shaderc_util::Compiler::UniformKind::Sampler; case shaderc_uniform_kind_image: return shaderc_util::Compiler::UniformKind::Image; case shaderc_uniform_kind_buffer: return shaderc_util::Compiler::UniformKind::Buffer; case shaderc_uniform_kind_storage_buffer: return shaderc_util::Compiler::UniformKind::StorageBuffer; case shaderc_uniform_kind_unordered_access_view: return shaderc_util::Compiler::UniformKind::UnorderedAccessView; } assert(0 && "Should not have reached here"); return static_cast(0); } // Returns the Compiler::Stage for generic stage values in shaderc_shader_kind. shaderc_util::Compiler::Stage GetStage(shaderc_shader_kind kind) { switch (kind) { case shaderc_vertex_shader: return shaderc_util::Compiler::Stage::Vertex; case shaderc_fragment_shader: return shaderc_util::Compiler::Stage::Fragment; case shaderc_compute_shader: return shaderc_util::Compiler::Stage::Compute; case shaderc_tess_control_shader: return shaderc_util::Compiler::Stage::TessControl; case shaderc_tess_evaluation_shader: return shaderc_util::Compiler::Stage::TessEval; case shaderc_geometry_shader: return shaderc_util::Compiler::Stage::Geometry; default: break; } assert(0 && "Should not have reached here"); return static_cast(0); } } // anonymous namespace struct shaderc_compile_options { shaderc_target_env target_env = shaderc_target_env_default; uint32_t target_env_version = 0; shaderc_util::Compiler compiler; shaderc_include_resolve_fn include_resolver = nullptr; shaderc_include_result_release_fn include_result_releaser = nullptr; void* include_user_data = nullptr; }; shaderc_compile_options_t shaderc_compile_options_initialize() { return new (std::nothrow) shaderc_compile_options; } shaderc_compile_options_t shaderc_compile_options_clone( const shaderc_compile_options_t options) { if (!options) { return shaderc_compile_options_initialize(); } return new (std::nothrow) shaderc_compile_options(*options); } void shaderc_compile_options_release(shaderc_compile_options_t options) { delete options; } void shaderc_compile_options_add_macro_definition( shaderc_compile_options_t options, const char* name, size_t name_length, const char* value, size_t value_length) { options->compiler.AddMacroDefinition(name, name_length, value, value_length); } void shaderc_compile_options_set_source_language( shaderc_compile_options_t options, shaderc_source_language set_lang) { auto lang = shaderc_util::Compiler::SourceLanguage::GLSL; if (set_lang == shaderc_source_language_hlsl) lang = shaderc_util::Compiler::SourceLanguage::HLSL; options->compiler.SetSourceLanguage(lang); } void shaderc_compile_options_set_generate_debug_info( shaderc_compile_options_t options) { options->compiler.SetGenerateDebugInfo(); } void shaderc_compile_options_set_optimization_level( shaderc_compile_options_t options, shaderc_optimization_level level) { auto opt_level = shaderc_util::Compiler::OptimizationLevel::Zero; switch (level) { case shaderc_optimization_level_size: opt_level = shaderc_util::Compiler::OptimizationLevel::Size; break; case shaderc_optimization_level_performance: opt_level = shaderc_util::Compiler::OptimizationLevel::Performance; break; default: break; } options->compiler.SetOptimizationLevel(opt_level); } void shaderc_compile_options_set_forced_version_profile( shaderc_compile_options_t options, int version, shaderc_profile profile) { // Transfer the profile parameter from public enum type to glslang internal // enum type. No default case here so that compiler will complain if new enum // member is added later but not handled here. switch (profile) { case shaderc_profile_none: options->compiler.SetForcedVersionProfile(version, ENoProfile); break; case shaderc_profile_core: options->compiler.SetForcedVersionProfile(version, ECoreProfile); break; case shaderc_profile_compatibility: options->compiler.SetForcedVersionProfile(version, ECompatibilityProfile); break; case shaderc_profile_es: options->compiler.SetForcedVersionProfile(version, EEsProfile); break; } } void shaderc_compile_options_set_include_callbacks( shaderc_compile_options_t options, shaderc_include_resolve_fn resolver, shaderc_include_result_release_fn result_releaser, void* user_data) { options->include_resolver = resolver; options->include_result_releaser = result_releaser; options->include_user_data = user_data; } void shaderc_compile_options_set_suppress_warnings( shaderc_compile_options_t options) { options->compiler.SetSuppressWarnings(); } void shaderc_compile_options_set_target_env(shaderc_compile_options_t options, shaderc_target_env target, uint32_t version) { options->target_env = target; options->compiler.SetTargetEnv(GetCompilerTargetEnv(target), GetCompilerTargetEnvVersion(version)); } void shaderc_compile_options_set_target_spirv(shaderc_compile_options_t options, shaderc_spirv_version ver) { // We made the values match, so we can get away with a static cast. options->compiler.SetTargetSpirv( static_cast(ver)); } void shaderc_compile_options_set_warnings_as_errors( shaderc_compile_options_t options) { options->compiler.SetWarningsAsErrors(); } void shaderc_compile_options_set_limit(shaderc_compile_options_t options, shaderc_limit limit, int value) { options->compiler.SetLimit(CompilerLimit(limit), value); } void shaderc_compile_options_set_auto_bind_uniforms( shaderc_compile_options_t options, bool auto_bind) { options->compiler.SetAutoBindUniforms(auto_bind); } void shaderc_compile_options_set_auto_combined_image_sampler( shaderc_compile_options_t options, bool upgrade) { options->compiler.SetAutoCombinedImageSampler(upgrade); } void shaderc_compile_options_set_hlsl_io_mapping( shaderc_compile_options_t options, bool hlsl_iomap) { options->compiler.SetHlslIoMapping(hlsl_iomap); } void shaderc_compile_options_set_hlsl_offsets(shaderc_compile_options_t options, bool hlsl_offsets) { options->compiler.SetHlslOffsets(hlsl_offsets); } void shaderc_compile_options_set_binding_base(shaderc_compile_options_t options, shaderc_uniform_kind kind, uint32_t base) { options->compiler.SetAutoBindingBase(GetUniformKind(kind), base); } void shaderc_compile_options_set_binding_base_for_stage( shaderc_compile_options_t options, shaderc_shader_kind shader_kind, shaderc_uniform_kind kind, uint32_t base) { options->compiler.SetAutoBindingBaseForStage(GetStage(shader_kind), GetUniformKind(kind), base); } void shaderc_compile_options_set_preserve_bindings( shaderc_compile_options_t options, bool preserve_bindings) { options->compiler.SetPreserveBindings(preserve_bindings); } void shaderc_compile_options_set_auto_map_locations( shaderc_compile_options_t options, bool auto_map) { options->compiler.SetAutoMapLocations(auto_map); } void shaderc_compile_options_set_hlsl_register_set_and_binding_for_stage( shaderc_compile_options_t options, shaderc_shader_kind shader_kind, const char* reg, const char* set, const char* binding) { options->compiler.SetHlslRegisterSetAndBindingForStage(GetStage(shader_kind), reg, set, binding); } void shaderc_compile_options_set_hlsl_register_set_and_binding( shaderc_compile_options_t options, const char* reg, const char* set, const char* binding) { options->compiler.SetHlslRegisterSetAndBinding(reg, set, binding); } void shaderc_compile_options_set_hlsl_functionality1( shaderc_compile_options_t options, bool enable) { options->compiler.EnableHlslFunctionality1(enable); } void shaderc_compile_options_set_hlsl_16bit_types( shaderc_compile_options_t options, bool enable) { options->compiler.EnableHlsl16BitTypes(enable); } void shaderc_compile_options_set_vulkan_rules_relaxed( shaderc_compile_options_t options, bool enable) { options->compiler.SetVulkanRulesRelaxed(enable); } void shaderc_compile_options_set_invert_y(shaderc_compile_options_t options, bool enable) { options->compiler.EnableInvertY(enable); } void shaderc_compile_options_set_nan_clamp(shaderc_compile_options_t options, bool enable) { options->compiler.SetNanClamp(enable); } shaderc_compiler_t shaderc_compiler_initialize() { shaderc_compiler_t compiler = new (std::nothrow) shaderc_compiler; if (compiler) { compiler->initializer.reset(new shaderc_util::GlslangInitializer); } return compiler; } void shaderc_compiler_release(shaderc_compiler_t compiler) { delete compiler; } namespace { shaderc_compilation_result_t CompileToSpecifiedOutputType( const shaderc_compiler_t compiler, const char* source_text, size_t source_text_size, shaderc_shader_kind shader_kind, const char* input_file_name, const char* entry_point_name, const shaderc_compile_options_t additional_options, shaderc_util::Compiler::OutputType output_type) { auto* result = new (std::nothrow) shaderc_compilation_result_vector; if (!result) return nullptr; if (!input_file_name) { result->messages = "Input file name string was null."; result->num_errors = 1; result->compilation_status = shaderc_compilation_status_compilation_error; return result; } result->compilation_status = shaderc_compilation_status_invalid_stage; bool compilation_succeeded = false; // In case we exit early. std::vector compilation_output_data; size_t compilation_output_data_size_in_bytes = 0u; if (!compiler->initializer) return result; TRY_IF_EXCEPTIONS_ENABLED { std::stringstream errors; size_t total_warnings = 0; size_t total_errors = 0; std::string input_file_name_str(input_file_name); EShLanguage forced_stage = GetForcedStage(shader_kind); shaderc_util::string_piece source_string = shaderc_util::string_piece(source_text, source_text + source_text_size); StageDeducer stage_deducer(shader_kind); if (additional_options) { InternalFileIncluder includer(additional_options->include_resolver, additional_options->include_result_releaser, additional_options->include_user_data); // Depends on return value optimization to avoid extra copy. std::tie(compilation_succeeded, compilation_output_data, compilation_output_data_size_in_bytes) = additional_options->compiler.Compile( source_string, forced_stage, input_file_name_str, entry_point_name, // stage_deducer has a flag: error_, which we need to check later. // We need to make this a reference wrapper, so that std::function // won't make a copy for this callable object. std::ref(stage_deducer), includer, output_type, &errors, &total_warnings, &total_errors); } else { // Compile with default options. InternalFileIncluder includer; std::tie(compilation_succeeded, compilation_output_data, compilation_output_data_size_in_bytes) = shaderc_util::Compiler().Compile( source_string, forced_stage, input_file_name_str, entry_point_name, std::ref(stage_deducer), includer, output_type, &errors, &total_warnings, &total_errors); } result->messages = errors.str(); result->SetOutputData(std::move(compilation_output_data)); result->output_data_size = compilation_output_data_size_in_bytes; result->num_warnings = total_warnings; result->num_errors = total_errors; if (compilation_succeeded) { result->compilation_status = shaderc_compilation_status_success; } else { // Check whether the error is caused by failing to deduce the shader // stage. If it is the case, set the error type to shader kind error. // Otherwise, set it to compilation error. result->compilation_status = stage_deducer.error() ? shaderc_compilation_status_invalid_stage : shaderc_compilation_status_compilation_error; } } CATCH_IF_EXCEPTIONS_ENABLED(...) { result->compilation_status = shaderc_compilation_status_internal_error; } return result; } } // anonymous namespace shaderc_compilation_result_t shaderc_compile_into_spv( const shaderc_compiler_t compiler, const char* source_text, size_t source_text_size, shaderc_shader_kind shader_kind, const char* input_file_name, const char* entry_point_name, const shaderc_compile_options_t additional_options) { return CompileToSpecifiedOutputType( compiler, source_text, source_text_size, shader_kind, input_file_name, entry_point_name, additional_options, shaderc_util::Compiler::OutputType::SpirvBinary); } shaderc_compilation_result_t shaderc_compile_into_spv_assembly( const shaderc_compiler_t compiler, const char* source_text, size_t source_text_size, shaderc_shader_kind shader_kind, const char* input_file_name, const char* entry_point_name, const shaderc_compile_options_t additional_options) { return CompileToSpecifiedOutputType( compiler, source_text, source_text_size, shader_kind, input_file_name, entry_point_name, additional_options, shaderc_util::Compiler::OutputType::SpirvAssemblyText); } shaderc_compilation_result_t shaderc_compile_into_preprocessed_text( const shaderc_compiler_t compiler, const char* source_text, size_t source_text_size, shaderc_shader_kind shader_kind, const char* input_file_name, const char* entry_point_name, const shaderc_compile_options_t additional_options) { return CompileToSpecifiedOutputType( compiler, source_text, source_text_size, shader_kind, input_file_name, entry_point_name, additional_options, shaderc_util::Compiler::OutputType::PreprocessedText); } shaderc_compilation_result_t shaderc_assemble_into_spv( const shaderc_compiler_t compiler, const char* source_assembly, size_t source_assembly_size, const shaderc_compile_options_t additional_options) { auto* result = new (std::nothrow) shaderc_compilation_result_spv_binary; if (!result) return nullptr; result->compilation_status = shaderc_compilation_status_invalid_assembly; if (!compiler->initializer) return result; if (source_assembly == nullptr) return result; TRY_IF_EXCEPTIONS_ENABLED { spv_binary assembling_output_data = nullptr; std::string errors; const auto target_env = additional_options ? additional_options->target_env : shaderc_target_env_default; const uint32_t target_env_version = additional_options ? additional_options->target_env_version : 0; const bool assembling_succeeded = shaderc_util::SpirvToolsAssemble( GetCompilerTargetEnv(target_env), GetCompilerTargetEnvVersion(target_env_version), {source_assembly, source_assembly + source_assembly_size}, &assembling_output_data, &errors); result->num_errors = !assembling_succeeded; if (assembling_succeeded) { result->SetOutputData(assembling_output_data); result->output_data_size = assembling_output_data->wordCount * sizeof(uint32_t); result->compilation_status = shaderc_compilation_status_success; } else { result->messages = std::move(errors); result->compilation_status = shaderc_compilation_status_invalid_assembly; } } CATCH_IF_EXCEPTIONS_ENABLED(...) { result->compilation_status = shaderc_compilation_status_internal_error; } return result; } size_t shaderc_result_get_length(const shaderc_compilation_result_t result) { return result->output_data_size; } size_t shaderc_result_get_num_warnings( const shaderc_compilation_result_t result) { return result->num_warnings; } size_t shaderc_result_get_num_errors( const shaderc_compilation_result_t result) { return result->num_errors; } const char* shaderc_result_get_bytes( const shaderc_compilation_result_t result) { return result->GetBytes(); } void shaderc_result_release(shaderc_compilation_result_t result) { delete result; } const char* shaderc_result_get_error_message( const shaderc_compilation_result_t result) { return result->messages.c_str(); } shaderc_compilation_status shaderc_result_get_compilation_status( const shaderc_compilation_result_t result) { return result->compilation_status; } void shaderc_get_spv_version(unsigned int* version, unsigned int* revision) { *version = spv::Version; *revision = spv::Revision; } bool shaderc_parse_version_profile(const char* str, int* version, shaderc_profile* profile) { EProfile glslang_profile; bool success = shaderc_util::ParseVersionProfile( std::string(str, strlen(str)), version, &glslang_profile); if (!success) return false; switch (glslang_profile) { case EEsProfile: *profile = shaderc_profile_es; return true; case ECoreProfile: *profile = shaderc_profile_core; return true; case ECompatibilityProfile: *profile = shaderc_profile_compatibility; return true; case ENoProfile: *profile = shaderc_profile_none; return true; case EBadProfile: case EProfileCount: return false; } // Shouldn't reach here, all profile enum should be handled above. // Be strict to return false. return false; } shaderc-2025.2/libshaderc/src/shaderc_c_smoke_test.c000066400000000000000000000033631500222170200224140ustar00rootroot00000000000000// Copyright 2016 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "shaderc/shaderc.h" #include #include // Because we want to test this as a plain old C file, we cannot use // gtest, so just run a simple smoke test. int main() { const char* test_program = "#version 310 es\n" "layout(location = 0) in highp vec4 vtxColor;\n" "layout(location = 0) out highp vec4 outColor;\n" "void main() {\n" " outColor = vtxColor;" "}\n"; shaderc_compiler_t compiler; shaderc_compilation_result_t result; shaderc_compile_options_t options; compiler = shaderc_compiler_initialize(); options = shaderc_compile_options_initialize(); shaderc_compile_options_add_macro_definition(options, "FOO", 3, "1", 1); result = shaderc_compile_into_spv( compiler, test_program, strlen(test_program), shaderc_glsl_fragment_shader, "a.glsl", "main", options); assert(result); if (shaderc_result_get_compilation_status(result) != shaderc_compilation_status_success) { // Early exit on failure. return -1; } shaderc_result_release(result); shaderc_compile_options_release(options); shaderc_compiler_release(compiler); return 0; } shaderc-2025.2/libshaderc/src/shaderc_cpp_test.cc000066400000000000000000002041761500222170200217260ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include "common_shaders_for_test.h" #include "shaderc/shaderc.hpp" #include "spirv-tools/libspirv.hpp" #include "spirv/unified1/spirv.hpp" namespace { using shaderc::AssemblyCompilationResult; using shaderc::CompileOptions; using shaderc::PreprocessedSourceCompilationResult; using shaderc::SpvCompilationResult; using testing::Each; using testing::Eq; using testing::HasSubstr; using testing::Not; // Helper function to check if the compilation result indicates a successful // compilation. template bool CompilationResultIsSuccess(const shaderc::CompilationResult& result) { return result.GetCompilationStatus() == shaderc_compilation_status_success; } // Examines whether a compilation result has valid SPIR-V code, by checking the // magic number in the fixed postion of the byte array in the result object. // Returns true if the magic number is found at the correct postion, otherwise // returns false. bool IsValidSpv(const SpvCompilationResult& result) { if (!CompilationResultIsSuccess(result)) return false; size_t length_in_words = result.cend() - result.cbegin(); if (length_in_words < 5) return false; const uint32_t* bytes = result.cbegin(); return bytes[0] == spv::MagicNumber; } // Compiles a shader and returns true if the result is valid SPIR-V. The // input_file_name is set to "shader". bool CompilesToValidSpv(const shaderc::Compiler& compiler, const std::string& shader, shaderc_shader_kind kind) { return IsValidSpv(compiler.CompileGlslToSpv(shader, kind, "shader")); } // Compiles a shader with options and returns true if the result is valid // SPIR-V. The input_file_name is set to "shader". bool CompilesToValidSpv(const shaderc::Compiler& compiler, const std::string& shader, shaderc_shader_kind kind, const CompileOptions& options) { return IsValidSpv(compiler.CompileGlslToSpv(shader, kind, "shader", options)); } // Returns the compiler's output from a compilation result as a string. template std::string CompilerOutputAsString( const shaderc::CompilationResult& result) { return std::string(reinterpret_cast(result.cbegin()), reinterpret_cast(result.cend())); } class CppInterface : public testing::Test { protected: // Compiles a shader and returns true on success, false on failure. // The input file name is set to "shader" by default. bool CompilationSuccess(const std::string& shader, shaderc_shader_kind kind) const { return compiler_ .CompileGlslToSpv(shader.c_str(), shader.length(), kind, "shader") .GetCompilationStatus() == shaderc_compilation_status_success; } // Compiles a shader with options and returns true on success, false on // failure. // The input file name is set to "shader" by default. bool CompilationSuccess(const std::string& shader, shaderc_shader_kind kind, const CompileOptions& options) const { return compiler_ .CompileGlslToSpv(shader.c_str(), shader.length(), kind, "shader", options) .GetCompilationStatus() == shaderc_compilation_status_success; } // Compiles a shader, asserts compilation success, and returns the warning // messages. // The input file name is set to "shader" by default. std::string CompilationWarnings(const std::string& shader, shaderc_shader_kind kind, // This could default to options_, but that // can be easily confused with a // no-options-provided case: const CompileOptions& options) { const auto compilation_result = compiler_.CompileGlslToSpv(shader, kind, "shader", options); EXPECT_TRUE(CompilationResultIsSuccess(compilation_result)) << kind << '\n' << shader; return compilation_result.GetErrorMessage(); } // Compiles a shader, asserts compilation fail, and returns the error // messages. std::string CompilationErrors(const std::string& shader, shaderc_shader_kind kind, // This could default to options_, but that can // be easily confused with a no-options-provided // case: const CompileOptions& options) { const auto compilation_result = compiler_.CompileGlslToSpv(shader, kind, "shader", options); EXPECT_FALSE(CompilationResultIsSuccess(compilation_result)) << kind << '\n' << shader; return compilation_result.GetErrorMessage(); } // Assembles the given SPIR-V assembly and returns true on success. bool AssemblingSuccess(const std::string& shader, const CompileOptions& options) const { return compiler_.AssembleToSpv(shader, options).GetCompilationStatus() == shaderc_compilation_status_success; } // Assembles the given SPIR-V assembly and returns true if the result contains // a valid SPIR-V module. bool AssemblingValid(const std::string& shader, const CompileOptions& options) const { return IsValidSpv(compiler_.AssembleToSpv(shader, options)); } // Compiles a shader, expects compilation success, and returns the output // bytes. // The input file name is set to "shader" by default. std::string CompilationOutput(const std::string& shader, shaderc_shader_kind kind, const CompileOptions& options) const { const auto compilation_result = compiler_.CompileGlslToSpv(shader, kind, "shader", options); EXPECT_TRUE(CompilationResultIsSuccess(compilation_result)) << kind << '\n'; // Need to make sure you get complete binary data, including embedded nulls. return CompilerOutputAsString(compilation_result); } // Compiles a shader to SPIR-V assembly, expects compilation success, and // returns the output bytes. // The input file name is set to "shader" by default. std::string AssemblyOutput(const std::string& shader, shaderc_shader_kind kind, const CompileOptions& options) const { const auto compilation_result = compiler_.CompileGlslToSpvAssembly(shader, kind, "shader", options); EXPECT_TRUE(CompilationResultIsSuccess(compilation_result)) << kind << '\n'; // Need to make sure you get complete binary data, including embedded nulls. return CompilerOutputAsString(compilation_result); } // For compiling shaders in subclass tests: shaderc::Compiler compiler_; CompileOptions options_; }; TEST_F(CppInterface, CompilerValidUponConstruction) { EXPECT_TRUE(compiler_.IsValid()); } TEST_F(CppInterface, MultipleCalls) { shaderc::Compiler compiler1, compiler2, compiler3; EXPECT_TRUE(compiler1.IsValid()); EXPECT_TRUE(compiler2.IsValid()); EXPECT_TRUE(compiler3.IsValid()); } #ifndef SHADERC_DISABLE_THREADED_TESTS TEST_F(CppInterface, MultipleThreadsInitializing) { std::unique_ptr compiler1; std::unique_ptr compiler2; std::unique_ptr compiler3; std::thread t1([&compiler1]() { compiler1 = std::unique_ptr(new shaderc::Compiler()); }); std::thread t2([&compiler2]() { compiler2 = std::unique_ptr(new shaderc::Compiler()); }); std::thread t3([&compiler3]() { compiler3 = std::unique_ptr(new shaderc::Compiler()); }); t1.join(); t2.join(); t3.join(); EXPECT_TRUE(compiler1->IsValid()); EXPECT_TRUE(compiler2->IsValid()); EXPECT_TRUE(compiler3->IsValid()); } #endif TEST_F(CppInterface, CompilerMoves) { shaderc::Compiler compiler2(std::move(compiler_)); ASSERT_FALSE(compiler_.IsValid()); ASSERT_TRUE(compiler2.IsValid()); } TEST_F(CppInterface, EmptyString) { EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_vertex_shader)); EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_fragment_shader)); } TEST_F(CppInterface, AssembleEmptyString) { EXPECT_TRUE(AssemblingSuccess("", options_)); } TEST_F(CppInterface, ResultObjectMoves) { SpvCompilationResult result = compiler_.CompileGlslToSpv( kMinimalShader, shaderc_glsl_vertex_shader, "shader"); EXPECT_TRUE(CompilationResultIsSuccess(result)); const SpvCompilationResult result2(std::move(result)); EXPECT_FALSE(CompilationResultIsSuccess(result)); EXPECT_TRUE(CompilationResultIsSuccess(result2)); } TEST_F(CppInterface, GarbageString) { EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_vertex_shader)); EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_fragment_shader)); } TEST_F(CppInterface, AssembleGarbageString) { const auto result = compiler_.AssembleToSpv("jfalkds", options_); EXPECT_FALSE(CompilationResultIsSuccess(result)); EXPECT_EQ(0u, result.GetNumWarnings()); EXPECT_EQ(1u, result.GetNumErrors()); } // TODO(antiagainst): right now there is no assembling difference for all the // target environments exposed by shaderc. So the following is just testing the // target environment is accepted. TEST_F(CppInterface, AssembleTargetEnv) { options_.SetTargetEnvironment(shaderc_target_env_opengl, 0); EXPECT_TRUE(AssemblingValid("OpCapability Shader", options_)); } TEST_F(CppInterface, MinimalShader) { EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, shaderc_glsl_vertex_shader)); EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, shaderc_glsl_fragment_shader)); } TEST_F(CppInterface, AssembleMinimalShader) { EXPECT_TRUE(AssemblingValid(kMinimalShaderAssembly, options_)); } TEST_F(CppInterface, BasicOptions) { EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, shaderc_glsl_vertex_shader, options_)); EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, shaderc_glsl_fragment_shader, options_)); } TEST_F(CppInterface, CopiedOptions) { EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, shaderc_glsl_vertex_shader, options_)); CompileOptions copied_options(options_); EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, shaderc_glsl_fragment_shader, copied_options)); } TEST_F(CppInterface, MovedOptions) { EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, shaderc_glsl_vertex_shader, options_)); CompileOptions copied_options(std::move(options_)); EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, shaderc_glsl_fragment_shader, copied_options)); } TEST_F(CppInterface, StdAndCString) { const SpvCompilationResult result1 = compiler_.CompileGlslToSpv(kMinimalShader, strlen(kMinimalShader), shaderc_glsl_fragment_shader, "shader"); const SpvCompilationResult result2 = compiler_.CompileGlslToSpv( std::string(kMinimalShader), shaderc_glsl_fragment_shader, "shader"); EXPECT_TRUE(CompilationResultIsSuccess(result1)); EXPECT_TRUE(CompilationResultIsSuccess(result2)); EXPECT_EQ(std::vector(result1.cbegin(), result1.cend()), std::vector(result2.cbegin(), result2.cend())); } TEST_F(CppInterface, ErrorsReported) { const SpvCompilationResult result = compiler_.CompileGlslToSpv( "int f(){return wrongname;}", shaderc_glsl_vertex_shader, "shader"); ASSERT_FALSE(CompilationResultIsSuccess(result)); EXPECT_THAT(result.GetErrorMessage(), HasSubstr("wrongname")); } #ifndef SHADERC_DISABLE_THREADED_TESTS TEST_F(CppInterface, MultipleThreadsCalling) { bool results[10]; std::vector threads; for (auto& r : results) { threads.emplace_back([this, &r]() { r = CompilationSuccess(kMinimalShader, shaderc_glsl_vertex_shader); }); } for (auto& t : threads) { t.join(); } EXPECT_THAT(results, Each(true)); } #endif TEST_F(CppInterface, AccessorsOnNullResultObject) { const SpvCompilationResult result(nullptr); EXPECT_FALSE(CompilationResultIsSuccess(result)); EXPECT_EQ(std::string(), result.GetErrorMessage()); EXPECT_EQ(result.cend(), result.cbegin()); EXPECT_EQ(nullptr, result.cbegin()); EXPECT_EQ(nullptr, result.cend()); EXPECT_EQ(nullptr, result.begin()); EXPECT_EQ(nullptr, result.end()); } TEST_F(CppInterface, MacroCompileOptions) { options_.AddMacroDefinition("E", "main"); const std::string kMinimalExpandedShader = "#version 150\nvoid E(){}"; const std::string kMinimalDoubleExpandedShader = "#version 150\nF E(){}"; EXPECT_TRUE(CompilationSuccess(kMinimalExpandedShader, shaderc_glsl_vertex_shader, options_)); CompileOptions cloned_options(options_); // The simplest should still compile with the cloned options. EXPECT_TRUE(CompilationSuccess(kMinimalExpandedShader, shaderc_glsl_vertex_shader, cloned_options)); EXPECT_FALSE(CompilationSuccess(kMinimalDoubleExpandedShader, shaderc_glsl_vertex_shader, cloned_options)); cloned_options.AddMacroDefinition("F", "void"); // This should still not work with the original options. EXPECT_FALSE(CompilationSuccess(kMinimalDoubleExpandedShader, shaderc_glsl_vertex_shader, options_)); // This should work with the cloned options that have the additional // parameter. EXPECT_TRUE(CompilationSuccess(kMinimalDoubleExpandedShader, shaderc_glsl_vertex_shader, cloned_options)); } TEST_F(CppInterface, D_DisassemblyOption) { const AssemblyCompilationResult result = compiler_.CompileGlslToSpvAssembly( kMinimalShader, shaderc_glsl_vertex_shader, "shader", options_); EXPECT_TRUE(CompilationResultIsSuccess(result)); // This should work with both the glslang disassembly format and the // SPIR-V Tools assembly format. EXPECT_THAT(CompilerOutputAsString(result), HasSubstr("Capability Shader")); EXPECT_THAT(CompilerOutputAsString(result), HasSubstr("MemoryModel")); CompileOptions cloned_options(options_); auto result_from_cloned_options = compiler_.CompileGlslToSpvAssembly( kMinimalShader, shaderc_glsl_vertex_shader, "shader", cloned_options); EXPECT_TRUE(CompilationResultIsSuccess(result_from_cloned_options)); // The mode should be carried into any clone of the original option object. EXPECT_THAT(CompilerOutputAsString(result_from_cloned_options), HasSubstr("Capability Shader")); EXPECT_THAT(CompilerOutputAsString(result_from_cloned_options), HasSubstr("MemoryModel")); } TEST_F(CppInterface, DisassembleMinimalShader) { const AssemblyCompilationResult result = compiler_.CompileGlslToSpvAssembly( kMinimalShader, shaderc_glsl_vertex_shader, "shader", options_); EXPECT_TRUE(CompilationResultIsSuccess(result)); for (const auto& substring : kMinimalShaderDisassemblySubstrings) { EXPECT_THAT(CompilerOutputAsString(result), HasSubstr(substring)); } } TEST_F(CppInterface, ForcedVersionProfileCorrectStd) { // Forces the version and profile to 450core, which fixes the missing // #version. options_.SetForcedVersionProfile(450, shaderc_profile_core); EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion, shaderc_glsl_vertex_shader, options_)); } TEST_F(CppInterface, ForcedVersionProfileCorrectStdClonedOptions) { // Forces the version and profile to 450core, which fixes the missing // #version. options_.SetForcedVersionProfile(450, shaderc_profile_core); CompileOptions cloned_options(options_); EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion, shaderc_glsl_vertex_shader, cloned_options)); } TEST_F(CppInterface, ForcedVersionProfileInvalidModule) { // Forces the version and profile to 310es, while the source module is invalid // for this version of GLSL. Compilation should fail. options_.SetForcedVersionProfile(310, shaderc_profile_es); EXPECT_THAT(CompilationErrors(kCoreVertShaderWithoutVersion, shaderc_glsl_vertex_shader, options_), HasSubstr("error: 'gl_ClipDistance' : undeclared identifier\n")); } TEST_F(CppInterface, ForcedVersionProfileConflictingStd) { // Forces the version and profile to 450core, which is in conflict with the // #version in shader. const std::string kVertexShader = std::string("#version 310 es\n") + kCoreVertShaderWithoutVersion; options_.SetForcedVersionProfile(450, shaderc_profile_core); EXPECT_THAT( CompilationWarnings(kVertexShader, shaderc_glsl_vertex_shader, options_), HasSubstr("warning: (version, profile) forced to be (450, core), " "while in source code it is (310, es)\n")); } TEST_F(CppInterface, ForcedVersionProfileUnknownVersionStd) { // Forces the version and profile to 4242core, which is an unknown version. options_.SetForcedVersionProfile(4242 /*unknown version*/, shaderc_profile_core); auto const errs = CompilationErrors(kMinimalShader, shaderc_glsl_vertex_shader, options_); EXPECT_THAT(errs, HasSubstr("warning: (version, profile) forced to be (4242, core)," " while in source code it is (140, none)\n")); EXPECT_THAT(errs, HasSubstr("error: version not supported\n")); } TEST_F(CppInterface, ForcedVersionProfileVersionsBefore150) { // Versions before 150 do not allow a profile token, shaderc_profile_none // should be passed down as the profile parameter. options_.SetForcedVersionProfile(140, shaderc_profile_none); EXPECT_TRUE( CompilationSuccess(kMinimalShader, shaderc_glsl_vertex_shader, options_)); } TEST_F(CppInterface, ForcedVersionProfileRedundantProfileStd) { // Forces the version and profile to 100core. But versions before 150 do not // allow a profile token, compilation should fail. options_.SetForcedVersionProfile(100, shaderc_profile_core); EXPECT_THAT( CompilationErrors(kMinimalShader, shaderc_glsl_vertex_shader, options_), HasSubstr("error: #version: versions before 150 do not allow a profile " "token\n")); } TEST_F(CppInterface, GenerateDebugInfoBinary) { options_.SetGenerateDebugInfo(); const std::string binary_output = CompilationOutput( kMinimalDebugInfoShader, shaderc_glsl_vertex_shader, options_); // The binary output should contain the name of the vector (debug_info_sample) // null-terminated, as well as the whole original source. std::string vector_name("debug_info_sample"); vector_name.resize(vector_name.size() + 1); EXPECT_THAT(binary_output, HasSubstr(vector_name)); EXPECT_THAT(binary_output, HasSubstr(kMinimalDebugInfoShader)); } TEST_F(CppInterface, GenerateDebugInfoBinaryClonedOptions) { options_.SetGenerateDebugInfo(); CompileOptions cloned_options(options_); const std::string binary_output = CompilationOutput( kMinimalDebugInfoShader, shaderc_glsl_vertex_shader, cloned_options); // The binary output should contain the name of the vector (debug_info_sample) // null-terminated, as well as the whole original source. std::string vector_name("debug_info_sample"); vector_name.resize(vector_name.size() + 1); EXPECT_THAT(binary_output, HasSubstr(vector_name)); EXPECT_THAT(binary_output, HasSubstr(kMinimalDebugInfoShader)); } TEST_F(CppInterface, GenerateDebugInfoDisassembly) { options_.SetGenerateDebugInfo(); // Debug info should also be emitted in disassembly mode. // The output disassembly should contain the name of the vector: // debug_info_sample. EXPECT_THAT(AssemblyOutput(kMinimalDebugInfoShader, shaderc_glsl_vertex_shader, options_), HasSubstr("debug_info_sample")); } TEST_F(CppInterface, GenerateDebugInfoDisassemblyClonedOptions) { options_.SetGenerateDebugInfo(); // Generate debug info mode should be carried to the cloned options. CompileOptions cloned_options(options_); EXPECT_THAT(CompilationOutput(kMinimalDebugInfoShader, shaderc_glsl_vertex_shader, cloned_options), HasSubstr("debug_info_sample")); } TEST_F(CppInterface, CompileAndOptimizeWithLevelZero) { options_.SetOptimizationLevel(shaderc_optimization_level_zero); const std::string disassembly_text = AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_); for (const auto& substring : kMinimalShaderDisassemblySubstrings) { EXPECT_THAT(disassembly_text, HasSubstr(substring)); } // Check that we still have debug instructions. EXPECT_THAT(disassembly_text, HasSubstr("OpName")); EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); } TEST_F(CppInterface, CompileAndOptimizeWithLevelPerformance) { options_.SetOptimizationLevel(shaderc_optimization_level_performance); const std::string disassembly_text = AssemblyOutput( kGlslMultipleFnShader, shaderc_glsl_fragment_shader, options_); // Check that we do not have function calls anymore. EXPECT_THAT(disassembly_text, Not(HasSubstr("OpFunctionCall"))); } TEST_F(CppInterface, CompileAndOptimizeWithLevelSize) { options_.SetOptimizationLevel(shaderc_optimization_level_size); const std::string disassembly_text = AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_); for (const auto& substring : kMinimalShaderDisassemblySubstrings) { EXPECT_THAT(disassembly_text, HasSubstr(substring)); } // Check that we do not have debug instructions. EXPECT_THAT(disassembly_text, Not(HasSubstr("OpName"))); EXPECT_THAT(disassembly_text, Not(HasSubstr("OpSource"))); } TEST_F(CppInterface, CompileAndOptimizeForVulkan10Failure) { options_.SetSourceLanguage(shaderc_source_language_hlsl); options_.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_0); options_.SetOptimizationLevel(shaderc_optimization_level_performance); EXPECT_THAT(CompilationErrors(kHlslWaveActiveSumeComputeShader, shaderc_compute_shader, options_), // TODO(antiagainst): the error message can be improved to be more // explicit regarding Vulkan 1.1 HasSubstr("compilation succeeded but failed to optimize: " "Capability GroupNonUniform is not allowed by Vulkan " "1.0 specification (or requires extension)")); } TEST_F(CppInterface, CompileAndOptimizeForVulkan11Success) { options_.SetSourceLanguage(shaderc_source_language_hlsl); options_.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1); options_.SetOptimizationLevel(shaderc_optimization_level_performance); const std::string disassembly_text = AssemblyOutput( kHlslWaveActiveSumeComputeShader, shaderc_compute_shader, options_); EXPECT_THAT(disassembly_text, HasSubstr("OpGroupNonUniformIAdd")); } TEST_F(CppInterface, FollowingOptLevelOverridesPreviousOne) { options_.SetOptimizationLevel(shaderc_optimization_level_size); // Optimization level settings overridden by options_.SetOptimizationLevel(shaderc_optimization_level_zero); const std::string disassembly_text = AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_); for (const auto& substring : kMinimalShaderDisassemblySubstrings) { EXPECT_THAT(disassembly_text, HasSubstr(substring)); } // Check that we still have debug instructions. EXPECT_THAT(disassembly_text, HasSubstr("OpName")); EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); } TEST_F(CppInterface, GenerateDebugInfoOverridesOptimizationLevel) { options_.SetOptimizationLevel(shaderc_optimization_level_size); // Optimization level settings overridden by options_.SetGenerateDebugInfo(); const std::string disassembly_text = AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_); for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) { EXPECT_THAT(disassembly_text, HasSubstr(substring)); } // Check that we still have debug instructions. EXPECT_THAT(disassembly_text, HasSubstr("OpName")); EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); } TEST_F(CppInterface, GenerateDebugInfoProhibitsOptimizationLevel) { // Setting generate debug info first also works. options_.SetGenerateDebugInfo(); options_.SetOptimizationLevel(shaderc_optimization_level_size); const std::string disassembly_text = AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_); for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) { EXPECT_THAT(disassembly_text, HasSubstr(substring)); } // Check that we still have debug instructions. EXPECT_THAT(disassembly_text, HasSubstr("OpName")); EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); } TEST_F(CppInterface, GetNumErrors) { std::string shader(kTwoErrorsShader); const SpvCompilationResult compilation_result = compiler_.CompileGlslToSpv(kTwoErrorsShader, strlen(kTwoErrorsShader), shaderc_glsl_vertex_shader, "shader"); EXPECT_FALSE(CompilationResultIsSuccess(compilation_result)); EXPECT_EQ(2u, compilation_result.GetNumErrors()); EXPECT_EQ(0u, compilation_result.GetNumWarnings()); } TEST_F(CppInterface, GetNumWarnings) { const SpvCompilationResult compilation_result = compiler_.CompileGlslToSpv(kTwoWarningsShader, strlen(kTwoWarningsShader), shaderc_glsl_vertex_shader, "shader"); EXPECT_TRUE(CompilationResultIsSuccess(compilation_result)); EXPECT_EQ(2u, compilation_result.GetNumWarnings()); EXPECT_EQ(0u, compilation_result.GetNumErrors()); } TEST_F(CppInterface, ZeroErrorsZeroWarnings) { const SpvCompilationResult compilation_result = compiler_.CompileGlslToSpv(kMinimalShader, strlen(kMinimalShader), shaderc_glsl_vertex_shader, "shader"); EXPECT_TRUE(CompilationResultIsSuccess(compilation_result)); EXPECT_EQ(0u, compilation_result.GetNumErrors()); EXPECT_EQ(0u, compilation_result.GetNumWarnings()); } TEST_F(CppInterface, ErrorTypeUnknownShaderStage) { // The shader kind/stage can not be determined, the error type field should // indicate the error type is shaderc_shader_kind_error. const SpvCompilationResult compilation_result = compiler_.CompileGlslToSpv(kMinimalShader, strlen(kMinimalShader), shaderc_glsl_infer_from_source, "shader"); EXPECT_EQ(shaderc_compilation_status_invalid_stage, compilation_result.GetCompilationStatus()); } TEST_F(CppInterface, ErrorTypeCompilationError) { // The shader kind is valid, the result object's error type field should // indicate this compilaion fails due to compilation errors. const SpvCompilationResult compilation_result = compiler_.CompileGlslToSpv( kTwoErrorsShader, shaderc_glsl_vertex_shader, "shader"); EXPECT_EQ(shaderc_compilation_status_compilation_error, compilation_result.GetCompilationStatus()); } TEST_F(CppInterface, ErrorTagIsInputFileName) { std::string shader(kTwoErrorsShader); const SpvCompilationResult compilation_result = compiler_.CompileGlslToSpv(kTwoErrorsShader, strlen(kTwoErrorsShader), shaderc_glsl_vertex_shader, "SampleInputFile"); // Expects compilation failure errors. The error tag should be // 'SampleInputFile' EXPECT_FALSE(CompilationResultIsSuccess(compilation_result)); EXPECT_THAT(compilation_result.GetErrorMessage(), HasSubstr("SampleInputFile:3: error:")); } TEST_F(CppInterface, PreprocessingOnlyOption) { const PreprocessedSourceCompilationResult result = compiler_.PreprocessGlsl( kMinimalShaderWithMacro, shaderc_glsl_vertex_shader, "shader", options_); EXPECT_TRUE(CompilationResultIsSuccess(result)); EXPECT_THAT(CompilerOutputAsString(result), HasSubstr("void main() { }")); const std::string kMinimalShaderCloneOption = "#version 140\n" "#define E_CLONE_OPTION main\n" "void E_CLONE_OPTION(){}\n"; CompileOptions cloned_options(options_); const PreprocessedSourceCompilationResult result_from_cloned_options = compiler_.PreprocessGlsl(kMinimalShaderCloneOption, shaderc_glsl_vertex_shader, "shader", cloned_options); EXPECT_TRUE(CompilationResultIsSuccess(result_from_cloned_options)); EXPECT_THAT(CompilerOutputAsString(result_from_cloned_options), HasSubstr("void main() { }")); } // A shader kind test case needs: 1) A shader text with or without #pragma // annotation, 2) shader_kind. struct ShaderKindTestCase { const char* shader_; shaderc_shader_kind shader_kind_; }; // Test the shader kind deduction process. If the shader kind is one // of the non-default ones, the compiler will just try to compile the // source code in that specified shader kind. If the shader kind is // shaderc_glsl_deduce_from_pragma, the compiler will determine the shader // kind from #pragma annotation in the source code and emit error if none // such annotation is found. When the shader kind is one of the default // ones, the compiler will fall back to use the specified shader kind if // and only if #pragma annoation is not found. // Valid shader kind settings should generate valid SPIR-V code. using ValidShaderKind = testing::TestWithParam; TEST_P(ValidShaderKind, ValidSpvCode) { const ShaderKindTestCase& test_case = GetParam(); shaderc::Compiler compiler; EXPECT_TRUE( CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_)); } INSTANTIATE_TEST_SUITE_P( CompileStringTest, ValidShaderKind, testing::ValuesIn(std::vector{ // Valid default shader kinds. {kEmpty310ESShader, shaderc_glsl_default_vertex_shader}, {kEmpty310ESShader, shaderc_glsl_default_fragment_shader}, {kEmpty310ESShader, shaderc_glsl_default_compute_shader}, {kGeometryOnlyShader, shaderc_glsl_default_geometry_shader}, {kTessControlOnlyShader, shaderc_glsl_default_tess_control_shader}, {kTessEvaluationOnlyShader, shaderc_glsl_default_tess_evaluation_shader}, // #pragma annotation overrides default shader kinds. {kVertexOnlyShaderWithPragma, shaderc_glsl_default_compute_shader}, {kFragmentOnlyShaderWithPragma, shaderc_glsl_default_vertex_shader}, {kTessControlOnlyShaderWithPragma, shaderc_glsl_default_fragment_shader}, {kTessEvaluationOnlyShaderWithPragma, shaderc_glsl_default_tess_control_shader}, {kGeometryOnlyShaderWithPragma, shaderc_glsl_default_tess_evaluation_shader}, {kComputeOnlyShaderWithPragma, shaderc_glsl_default_geometry_shader}, // Specified non-default shader kind overrides #pragma annotation. {kVertexOnlyShaderWithInvalidPragma, shaderc_glsl_vertex_shader}, })); // Invalid shader kind settings should generate errors. using InvalidShaderKind = testing::TestWithParam; TEST_P(InvalidShaderKind, CompilationShouldFail) { const ShaderKindTestCase& test_case = GetParam(); shaderc::Compiler compiler; EXPECT_FALSE( CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_)); } INSTANTIATE_TEST_SUITE_P( CompileStringTest, InvalidShaderKind, testing::ValuesIn(std::vector{ // Invalid default shader kind. {kVertexOnlyShader, shaderc_glsl_default_fragment_shader}, // Sets to deduce shader kind from #pragma, but #pragma is defined in // the source code. {kVertexOnlyShader, shaderc_glsl_infer_from_source}, // Invalid #pragma cause errors, even though default shader kind is set // to valid shader kind. {kVertexOnlyShaderWithInvalidPragma, shaderc_glsl_default_vertex_shader}, })); // To test file inclusion, use an unordered_map as a fake file system to store // fake files to be included. The unordered_map represents a filesystem by // mapping filename (or path) string to the contents of that file as a string. using FakeFS = std::unordered_map; // An includer test case needs: 1) A fake file system which is actually an // unordered_map, so that we can resolve the content given a string. A valid // fake file system must have one entry with key:'root' to specify the start // shader file for compilation. 2) An string that we expect to see in the // compilation output. class IncluderTestCase { public: IncluderTestCase(FakeFS fake_fs, std::string expected_substring) : fake_fs_(fake_fs), expected_substring_(expected_substring) { assert(fake_fs_.find("root") != fake_fs_.end() && "Valid fake file system needs a 'root' file\n"); } const FakeFS& fake_fs() const { return fake_fs_; } const std::string& expected_substring() const { return expected_substring_; } private: FakeFS fake_fs_; std::string expected_substring_; }; // A mock class that simulates an includer. This class implements // IncluderInterface to provide GetInclude() and ReleaseInclude() methods. class TestIncluder : public shaderc::CompileOptions::IncluderInterface { public: explicit TestIncluder(const FakeFS& fake_fs) : fake_fs_(fake_fs), responses_({}) {} // Get path and content from the fake file system. shaderc_include_result* GetInclude(const char* requested_source, shaderc_include_type type, const char* requesting_source, size_t include_depth) override { responses_.emplace_back(shaderc_include_result{ requested_source, strlen(requested_source), fake_fs_.at(std::string(requested_source)).c_str(), fake_fs_.at(std::string(requested_source)).size()}); return &responses_.back(); } // Response data is owned as private property, no need to release explicitly. void ReleaseInclude(shaderc_include_result*) override {} private: const FakeFS& fake_fs_; std::vector responses_; }; using IncluderTests = testing::TestWithParam; // Parameterized tests for includer. TEST_P(IncluderTests, SetIncluder) { const IncluderTestCase& test_case = GetParam(); const FakeFS& fs = test_case.fake_fs(); const std::string& shader = fs.at("root"); shaderc::Compiler compiler; CompileOptions options; options.SetIncluder(std::unique_ptr(new TestIncluder(fs))); const auto compilation_result = compiler.PreprocessGlsl( shader.c_str(), shaderc_glsl_vertex_shader, "shader", options); // Checks the existence of the expected string. EXPECT_THAT(CompilerOutputAsString(compilation_result), HasSubstr(test_case.expected_substring())); } TEST_P(IncluderTests, SetIncluderClonedOptions) { const IncluderTestCase& test_case = GetParam(); const FakeFS& fs = test_case.fake_fs(); const std::string& shader = fs.at("root"); shaderc::Compiler compiler; CompileOptions options; options.SetIncluder(std::unique_ptr(new TestIncluder(fs))); // Cloned options should have all the settings. CompileOptions cloned_options(options); const auto compilation_result = compiler.PreprocessGlsl( shader.c_str(), shaderc_glsl_vertex_shader, "shader", cloned_options); // Checks the existence of the expected string. EXPECT_THAT(CompilerOutputAsString(compilation_result), HasSubstr(test_case.expected_substring())); } INSTANTIATE_TEST_SUITE_P(CppInterface, IncluderTests, testing::ValuesIn(std::vector{ IncluderTestCase( // Fake file system. { {"root", "#version 150\n" "void foo() {}\n" "#include \"path/to/file_1\"\n"}, {"path/to/file_1", "content of file_1\n"}, }, // Expected output. "#line 0 \"path/to/file_1\"\n" " content of file_1\n" "#line 3"), IncluderTestCase( // Fake file system. {{"root", "#version 150\n" "void foo() {}\n" "#include \"path/to/file_1\"\n"}, {"path/to/file_1", "#include \"path/to/file_2\"\n" "content of file_1\n"}, {"path/to/file_2", "content of file_2\n"}}, // Expected output. "#line 0 \"path/to/file_1\"\n" "#line 0 \"path/to/file_2\"\n" " content of file_2\n" "#line 1 \"path/to/file_1\"\n" " content of file_1\n" "#line 3"), })); TEST_F(CppInterface, WarningsOnLine) { // By default the compiler will emit a warning on line 2 complaining // that 'float' is a deprecated attribute in version 130. EXPECT_THAT( CompilationWarnings(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, CompileOptions()), HasSubstr(":2: warning: attribute deprecated in version 130; may be " "removed in future release\n")); } TEST_F(CppInterface, SuppressWarningsOnLine) { // Sets the compiler to suppress warnings, so that the deprecated attribute // warning won't be emitted. options_.SetSuppressWarnings(); EXPECT_EQ("", CompilationWarnings(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, options_)); } TEST_F(CppInterface, SuppressWarningsOnLineClonedOptions) { // Sets the compiler to suppress warnings, so that the deprecated attribute // warning won't be emitted, and the mode should be carried into any clone of // the original option object. options_.SetSuppressWarnings(); CompileOptions cloned_options(options_); EXPECT_EQ("", CompilationWarnings(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, cloned_options)); } TEST_F(CppInterface, WarningsOnLineAsErrors) { // Sets the compiler to make warnings into errors. So that the deprecated // attribute warning will be emitted as an error and compilation should fail. options_.SetWarningsAsErrors(); EXPECT_THAT( CompilationErrors(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, options_), HasSubstr(":2: error: attribute deprecated in version 130; may be " "removed in future release\n")); } TEST_F(CppInterface, WarningsOnLineAsErrorsClonedOptions) { // Sets the compiler to make warnings into errors. So that the deprecated // attribute warning will be emitted as an error and compilation should fail. options_.SetWarningsAsErrors(); CompileOptions cloned_options(options_); // The error message should show an error instead of a warning. EXPECT_THAT( CompilationErrors(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, cloned_options), HasSubstr(":2: error: attribute deprecated in version 130; may be " "removed in future release\n")); } TEST_F(CppInterface, GlobalWarnings) { // By default the compiler will emit a warning as version 550 is an unknown // version. options_.SetForcedVersionProfile(400, shaderc_profile_core); EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader, shaderc_glsl_vertex_shader, options_), HasSubstr("(version, profile) forced to be (400, core)," " while in source code it is (550, none)\n")); } TEST_F(CppInterface, SuppressGlobalWarnings) { // Sets the compiler to suppress warnings, so that the unknown version warning // won't be emitted. options_.SetSuppressWarnings(); options_.SetForcedVersionProfile(400, shaderc_profile_core); EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader, shaderc_glsl_vertex_shader, options_), Eq("")); } TEST_F(CppInterface, SuppressGlobalWarningsClonedOptions) { // Sets the compiler to suppress warnings, so that the unknown version warning // won't be emitted, and the mode should be carried into any clone of the // original option object. options_.SetSuppressWarnings(); options_.SetForcedVersionProfile(400, shaderc_profile_core); CompileOptions cloned_options(options_); EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader, shaderc_glsl_vertex_shader, cloned_options), Eq("")); } TEST_F(CppInterface, GlobalWarningsAsErrors) { // Sets the compiler to make warnings into errors. So that the unknown // version warning will be emitted as an error and compilation should fail. options_.SetWarningsAsErrors(); options_.SetForcedVersionProfile(400, shaderc_profile_core); EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader, shaderc_glsl_vertex_shader, options_), HasSubstr("(version, profile) forced to be (400, core)," " while in source code it is (550, none)\n")); } TEST_F(CppInterface, GlobalWarningsAsErrorsClonedOptions) { // Sets the compiler to make warnings into errors. This mode should be carried // into any clone of the original option object. options_.SetWarningsAsErrors(); options_.SetForcedVersionProfile(400, shaderc_profile_core); CompileOptions cloned_options(options_); EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader, shaderc_glsl_vertex_shader, cloned_options), HasSubstr("(version, profile) forced to be (400, core)," " while in source code it is (550, none)\n")); } TEST_F(CppInterface, SuppressWarningsModeFirstOverridesWarningsAsErrorsMode) { // Sets suppress-warnings mode first, then sets warnings-as-errors mode. // suppress-warnings mode should override warnings-as-errors mode, no // error message should be output for this case. options_.SetSuppressWarnings(); options_.SetWarningsAsErrors(); // Warnings on line should be inhibited. EXPECT_EQ("", CompilationWarnings(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, options_)); // Global warnings should be inhibited. // However, the unknown version will cause an error. EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader, shaderc_glsl_vertex_shader, options_), Eq("shader: error: version not supported\n")); } TEST_F(CppInterface, SuppressWarningsModeSecondOverridesWarningsAsErrorsMode) { // Sets warnings-as-errors mode first, then sets suppress-warnings mode. // suppress-warnings mode should override warnings-as-errors mode, no // error message should be output for this case. options_.SetWarningsAsErrors(); options_.SetSuppressWarnings(); // Warnings on line should be inhibited. EXPECT_EQ("", CompilationWarnings(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, options_)); // Global warnings should be inhibited. // However, the unknown version will cause an error. EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader, shaderc_glsl_vertex_shader, options_), Eq("shader: error: version not supported\n")); } TEST_F(CppInterface, TargetEnvCompileOptionsOpenGLCompatibilityShadersFail) { // Glslang does not support SPIR-V code generation for OpenGL compatibility // profile. options_.SetTargetEnvironment(shaderc_target_env_opengl_compat, 0); const std::string kGlslShader = R"(#version 150 compatibility uniform highp sampler2D tex; void main() { gl_FragColor = texture2D(tex, vec2(0.0,0.0)); } )"; const auto errors = CompilationErrors(kGlslShader, shaderc_glsl_fragment_shader, options_); EXPECT_EQ(errors, "error: OpenGL compatibility profile is not supported"); } std::string BarrierComputeShader() { return R"(#version 450 void main() { barrier(); })"; } std::string SubgroupBarrierComputeShader() { return R"(#version 450 #extension GL_KHR_shader_subgroup_basic : enable void main() { subgroupBarrier(); })"; } TEST_F(CppInterface, TargetEnvCompileOptionsVulkanEnvVulkan1_0ShaderSucceeds) { options_.SetTargetEnvironment(shaderc_target_env_vulkan, 0); EXPECT_TRUE(CompilationSuccess(BarrierComputeShader(), shaderc_glsl_compute_shader, options_)); } TEST_F(CppInterface, TargetEnvCompileOptionsVulkanEnvVulkan1_0ShaderFails) { options_.SetTargetEnvironment(shaderc_target_env_vulkan, 0); EXPECT_FALSE(CompilationSuccess(SubgroupBarrierComputeShader(), shaderc_glsl_compute_shader, options_)); } TEST_F(CppInterface, TargetEnvCompileOptionsVulkan1_0EnvVulkan1_0ShaderSucceeds) { options_.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_0); EXPECT_TRUE(CompilationSuccess(BarrierComputeShader(), shaderc_glsl_compute_shader, options_)); } TEST_F(CppInterface, TargetEnvCompileOptionsVulkan1_0EnvVulkan1_1ShaderFails) { options_.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_0); EXPECT_FALSE(CompilationSuccess(SubgroupBarrierComputeShader(), shaderc_glsl_compute_shader, options_)); } // Simple Vulkan 1.1 tests TEST_F(CppInterface, TargetEnvCompileOptionsVulkan1_1EnvVulkan1_0ShaderSucceeds) { options_.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1); EXPECT_TRUE(CompilationSuccess(BarrierComputeShader(), shaderc_glsl_compute_shader, options_)); } TEST_F(CppInterface, TargetEnvCompileOptionsVulkan1_1EnvVulkan1_1ShaderSucceeds) { options_.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1); EXPECT_TRUE(CompilationSuccess(SubgroupBarrierComputeShader(), shaderc_glsl_compute_shader, options_)); } // Simple Vulkan 1.2 tests TEST_F(CppInterface, TargetEnvCompileOptionsVulkan1_2EnvVulkan1_0ShaderSucceeds) { options_.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_2); EXPECT_TRUE(CompilationSuccess(BarrierComputeShader(), shaderc_glsl_compute_shader, options_)); } TEST_F(CppInterface, TargetEnvCompileOptionsVulkan1_2EnvVulkan1_1ShaderSucceeds) { options_.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_2); EXPECT_TRUE(CompilationSuccess(SubgroupBarrierComputeShader(), shaderc_glsl_compute_shader, options_)); } // Simple Vulkan 1.3 tests TEST_F(CppInterface, TargetEnvCompileOptionsVulkan1_3EnvVulkan1_0ShaderSucceeds) { options_.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_3); EXPECT_TRUE(CompilationSuccess(BarrierComputeShader(), shaderc_glsl_compute_shader, options_)); } TEST_F(CppInterface, TargetEnvCompileOptionsVulkan1_3EnvVulkan1_1ShaderSucceeds) { options_.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_3); EXPECT_TRUE(CompilationSuccess(SubgroupBarrierComputeShader(), shaderc_glsl_compute_shader, options_)); } // Simple Vulkan 1.4 tests TEST_F(CppInterface, TargetEnvCompileOptionsVulkan1_4EnvVulkan1_0ShaderSucceeds) { options_.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_4); EXPECT_TRUE(CompilationSuccess(BarrierComputeShader(), shaderc_glsl_compute_shader, options_)); } TEST_F(CppInterface, TargetEnvCompileOptionsVulkan1_4EnvVulkan1_1ShaderSucceeds) { options_.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_4); EXPECT_TRUE(CompilationSuccess(SubgroupBarrierComputeShader(), shaderc_glsl_compute_shader, options_)); } // Other tests TEST_F(CppInterface, BeginAndEndOnSpvCompilationResult) { const SpvCompilationResult compilation_result = compiler_.CompileGlslToSpv( kMinimalShader, shaderc_glsl_vertex_shader, "shader"); EXPECT_TRUE(IsValidSpv(compilation_result)); // Use range-based for to exercise begin() and end(). std::vector binary_words; for (const auto& element : compilation_result) { binary_words.push_back(element); } EXPECT_THAT(binary_words, Eq(std::vector(compilation_result.cbegin(), compilation_result.cend()))); } TEST_F(CppInterface, BeginAndEndOnAssemblyCompilationResult) { const AssemblyCompilationResult compilation_result = compiler_.CompileGlslToSpvAssembly( kMinimalShader, shaderc_glsl_vertex_shader, "shader", options_); const std::string forced_to_be_a_string = CompilerOutputAsString(compilation_result); EXPECT_THAT(forced_to_be_a_string, HasSubstr("MemoryModel")); const std::string string_via_begin_end(compilation_result.begin(), compilation_result.end()); EXPECT_THAT(string_via_begin_end, Eq(forced_to_be_a_string)); } TEST_F(CppInterface, BeginAndEndOnPreprocessedResult) { const PreprocessedSourceCompilationResult compilation_result = compiler_.PreprocessGlsl(kMinimalShader, shaderc_glsl_vertex_shader, "shader", options_); const std::string forced_to_be_a_string = CompilerOutputAsString(compilation_result); EXPECT_THAT(forced_to_be_a_string, HasSubstr("void main()")); const std::string string_via_begin_end(compilation_result.begin(), compilation_result.end()); EXPECT_THAT(string_via_begin_end, Eq(forced_to_be_a_string)); } TEST_F(CppInterface, SourceLangGlslMinimalGlslVertexShaderSucceeds) { options_.SetSourceLanguage(shaderc_source_language_glsl); EXPECT_TRUE(CompilationSuccess(kVertexOnlyShader, shaderc_glsl_vertex_shader, options_)); } TEST_F(CppInterface, SourceLangGlslMinimalHlslVertexShaderFails) { options_.SetSourceLanguage(shaderc_source_language_glsl); EXPECT_FALSE(CompilationSuccess(kMinimalHlslShader, shaderc_glsl_vertex_shader, options_)); } TEST_F(CppInterface, SourceLangHlslMinimalGlslVertexShaderFails) { options_.SetSourceLanguage(shaderc_source_language_hlsl); EXPECT_FALSE(CompilationSuccess(kVertexOnlyShader, shaderc_glsl_vertex_shader, options_)); } TEST_F(CppInterface, SourceLangHlslMinimalHlslVertexShaderSucceeds) { options_.SetSourceLanguage(shaderc_source_language_hlsl); EXPECT_TRUE(CompilationSuccess(kMinimalHlslShader, shaderc_glsl_vertex_shader, options_)); } TEST( EntryPointTest, SourceLangHlslMinimalHlslVertexShaderAsConstCharPtrSucceedsWithEntryPointName) { shaderc::Compiler compiler; CompileOptions options; options.SetSourceLanguage(shaderc_source_language_hlsl); auto result = compiler.CompileGlslToSpv( kMinimalHlslShader, strlen(kMinimalHlslShader), shaderc_glsl_vertex_shader, "shader", "EntryPoint", options); std::vector binary(result.begin(), result.end()); std::string assembly; spvtools::SpirvTools(SPV_ENV_UNIVERSAL_1_0).Disassemble(binary, &assembly); EXPECT_THAT(assembly, HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\"")) << assembly; } TEST( EntryPointTest, SourceLangHlslMinimalHlslVertexShaderAsStdStringSucceedsWithEntryPointName) { shaderc::Compiler compiler; CompileOptions options; options.SetSourceLanguage(shaderc_source_language_hlsl); std::string shader(kMinimalHlslShader); auto result = compiler.CompileGlslToSpv(shader, shaderc_glsl_vertex_shader, "shader", "EntryPoint", options); std::vector binary(result.begin(), result.end()); std::string assembly; spvtools::SpirvTools(SPV_ENV_UNIVERSAL_1_0).Disassemble(binary, &assembly); EXPECT_THAT(assembly, HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\"")) << assembly; } TEST( EntryPointTest, SourceLangHlslMinimalHlslVertexShaderAsConstCharPtrSucceedsToAssemblyWithEntryPointName) { shaderc::Compiler compiler; CompileOptions options; options.SetSourceLanguage(shaderc_source_language_hlsl); auto assembly = compiler.CompileGlslToSpvAssembly( kMinimalHlslShader, strlen(kMinimalHlslShader), shaderc_glsl_vertex_shader, "shader", "EntryPoint", options); EXPECT_THAT(std::string(assembly.begin(), assembly.end()), HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\"")); } TEST( EntryPointTest, SourceLangHlslMinimalHlslVertexShaderAsStdStringSucceedsToAssemblyWithEntryPointName) { shaderc::Compiler compiler; CompileOptions options; options.SetSourceLanguage(shaderc_source_language_hlsl); std::string shader(kMinimalHlslShader); auto assembly = compiler.CompileGlslToSpvAssembly( shader, shaderc_glsl_vertex_shader, "shader", "EntryPoint", options); EXPECT_THAT(std::string(assembly.begin(), assembly.end()), HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\"")); } // Returns a fragment shader accessing a texture with the given // offset. std::string ShaderWithTexOffset(int offset) { std::ostringstream oss; oss << "#version 450\n" "layout (binding=0) uniform sampler1D tex;\n" "void main() { vec4 x = textureOffset(tex, 1.0, " << offset << "); }\n"; return oss.str(); } // Ensure compilation is sensitive to limit setting. Sample just // two particular limits. TEST_F(CppInterface, LimitsTexelOffsetDefault) { EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-9).c_str(), shaderc_glsl_fragment_shader, options_)); EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(), shaderc_glsl_fragment_shader, options_)); EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(), shaderc_glsl_fragment_shader, options_)); EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(8).c_str(), shaderc_glsl_fragment_shader, options_)); } TEST_F(CppInterface, LimitsTexelOffsetLowerMinimum) { options_.SetLimit(shaderc_limit_min_program_texel_offset, -99); EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-100).c_str(), shaderc_glsl_fragment_shader, options_)); EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-99).c_str(), shaderc_glsl_fragment_shader, options_)); } TEST_F(CppInterface, LimitsTexelOffsetHigherMaximum) { options_.SetLimit(shaderc_limit_max_program_texel_offset, 10); EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(10).c_str(), shaderc_glsl_fragment_shader, options_)); EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(11).c_str(), shaderc_glsl_fragment_shader, options_)); } TEST_F(CppInterface, UniformsWithoutBindingsFailCompilation) { CompileOptions options; const std::string errors = CompilationErrors( kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options); EXPECT_THAT(errors, HasSubstr("sampler/texture/image requires layout(binding=X)")); } TEST_F(CppInterface, UniformsWithoutBindingsOptionSetAutoBindingsAssignsBindings) { CompileOptions options; options.SetAutoBindUniforms(true); const std::string disassembly_text = AssemblyOutput( kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4")); } TEST_F(CppInterface, SetBindingBaseForTextureAdjustsTextureBindingsOnly) { CompileOptions options; options.SetAutoBindUniforms(true); options.SetBindingBase(shaderc_uniform_kind_texture, 44); const std::string disassembly_text = AssemblyOutput( kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 44")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3")); } TEST_F(CppInterface, SetBindingBaseForSamplerAdjustsSamplerBindingsOnly) { CompileOptions options; options.SetAutoBindUniforms(true); options.SetBindingBase(shaderc_uniform_kind_sampler, 44); const std::string disassembly_text = AssemblyOutput( kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 44")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3")); } TEST_F(CppInterface, SetBindingBaseForImageAdjustsImageBindingsOnly) { CompileOptions options; options.SetAutoBindUniforms(true); options.SetBindingBase(shaderc_uniform_kind_image, 44); const std::string disassembly_text = AssemblyOutput( kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 44")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 45")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 2")); } TEST_F(CppInterface, SetBindingBaseForBufferAdjustsBufferBindingsOnly) { CompileOptions options; options.SetAutoBindUniforms(true); options.SetBindingBase(shaderc_uniform_kind_buffer, 44); const std::string disassembly_text = AssemblyOutput( kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 44")); } TEST_F(CppInterface, SetBindingBaseSurvivesCloning) { CompileOptions options; options.SetAutoBindUniforms(true); options.SetBindingBase(shaderc_uniform_kind_texture, 40); options.SetBindingBase(shaderc_uniform_kind_sampler, 50); options.SetBindingBase(shaderc_uniform_kind_image, 60); options.SetBindingBase(shaderc_uniform_kind_buffer, 70); CompileOptions cloned_options(options); const std::string disassembly_text = AssemblyOutput(kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, cloned_options); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 40")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 50")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 60")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 61")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 70")); } TEST_F(CppInterface, GlslDefaultPackingUsed) { CompileOptions options; const std::string disassembly_text = AssemblyOutput( kGlslShaderWeirdPacking, shaderc_glsl_vertex_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16")); } TEST_F(CppInterface, HlslOffsetsOptionDisableRespected) { CompileOptions options; options.SetHlslOffsets(false); const std::string disassembly_text = AssemblyOutput( kGlslShaderWeirdPacking, shaderc_glsl_vertex_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16")); } TEST_F(CppInterface, HlslOffsetsOptionEnableRespected) { CompileOptions options; options.SetHlslOffsets(true); const std::string disassembly_text = AssemblyOutput( kGlslShaderWeirdPacking, shaderc_glsl_vertex_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 4")); } TEST_F(CppInterface, HlslRegSetBindingForFragmentRespected) { CompileOptions options; options.SetSourceLanguage(shaderc_source_language_hlsl); options.SetHlslRegisterSetAndBindingForStage(shaderc_fragment_shader, "t4", "9", "16"); const std::string disassembly_text = AssemblyOutput( kHlslFragShaderWithRegisters, shaderc_glsl_fragment_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 DescriptorSet 9")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 Binding 16")); } TEST_F(CppInterface, HlslRegSetBindingForDifferentStageIgnored) { CompileOptions options; options.SetSourceLanguage(shaderc_source_language_hlsl); options.SetHlslRegisterSetAndBindingForStage(shaderc_vertex_shader, "t4", "9", "16"); const std::string disassembly_text = AssemblyOutput( kHlslFragShaderWithRegisters, shaderc_glsl_fragment_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 DescriptorSet 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 Binding 4")); } TEST_F(CppInterface, HlslRegSetBindingForAllStagesRespected) { CompileOptions options; options.SetSourceLanguage(shaderc_source_language_hlsl); options.SetHlslRegisterSetAndBinding("t4", "9", "16"); const std::string disassembly_text = AssemblyOutput( kHlslFragShaderWithRegisters, shaderc_glsl_fragment_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 DescriptorSet 9")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 Binding 16")); } TEST_F(CppInterface, HlslFunctionality1OffByDefault) { CompileOptions options; options.SetSourceLanguage(shaderc_source_language_hlsl); // The counter needs a binding, and there is no way to set it in the shader // source. options.SetAutoBindUniforms(true); const std::string disassembly_text = AssemblyOutput( kHlslShaderWithCounterBuffer, shaderc_glsl_fragment_shader, options); EXPECT_THAT(disassembly_text, Not(HasSubstr("OpDecorateString"))); } TEST_F(CppInterface, HlslFunctionality1Respected) { CompileOptions options; options.SetSourceLanguage(shaderc_source_language_hlsl); // The counter needs a binding, and there is no way to set it in the shader // source. https://github.com/KhronosGroup/glslang/issues/1616 options.SetAutoBindUniforms(true); options.SetHlslFunctionality1(true); const std::string disassembly_text = AssemblyOutput( kHlslShaderWithCounterBuffer, shaderc_glsl_fragment_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateString")); } TEST_F(CppInterface, HlslFunctionality1SurvivesCloning) { CompileOptions options; options.SetSourceLanguage(shaderc_source_language_hlsl); options.SetHlslFunctionality1(true); // The counter needs a binding, and there is no way to set it in the shader // source. https://github.com/KhronosGroup/glslang/issues/1616 options.SetAutoBindUniforms(true); CompileOptions cloned_options(options); const std::string disassembly_text = AssemblyOutput(kHlslShaderWithCounterBuffer, shaderc_glsl_fragment_shader, cloned_options); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateString")); } TEST_F(CppInterface, NanClampDefaultsOff) { CompileOptions options; const std::string disassembly_text = AssemblyOutput( kGlslShaderWithClamp, shaderc_glsl_fragment_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 FClamp")); } TEST_F(CppInterface, NanClampMapsClampToNClamp) { CompileOptions options; options.SetNanClamp(true); const std::string disassembly_text = AssemblyOutput( kGlslShaderWithClamp, shaderc_glsl_fragment_shader, options); EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 NClamp")); } TEST_F(CppInterface, NanClampSurvivesCloning) { CompileOptions options; options.SetNanClamp(true); CompileOptions cloned_options(options); const std::string disassembly_text = AssemblyOutput( kGlslShaderWithClamp, shaderc_glsl_fragment_shader, cloned_options); EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 NClamp")); } } // anonymous namespace shaderc-2025.2/libshaderc/src/shaderc_private.h000066400000000000000000000111721500222170200214110ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_SRC_SHADERC_PRIVATE_H_ #define LIBSHADERC_SRC_SHADERC_PRIVATE_H_ #include #include #include #include #include "shaderc/shaderc.h" #include "libshaderc_util/compiler.h" #include "spirv-tools/libspirv.h" // Described in shaderc.h. struct shaderc_compilation_result { virtual ~shaderc_compilation_result() {} // Returns the data from this compilation as a sequence of bytes. virtual const char* GetBytes() const = 0; // The size of the output data in term of bytes. size_t output_data_size = 0; // Compilation messages. std::string messages; // Number of errors. size_t num_errors = 0; // Number of warnings. size_t num_warnings = 0; // Compilation status. shaderc_compilation_status compilation_status = shaderc_compilation_status_null_result_object; }; // Compilation result class using a vector for holding the compilation // output data. class shaderc_compilation_result_vector : public shaderc_compilation_result { public: ~shaderc_compilation_result_vector() = default; void SetOutputData(std::vector&& data) { output_data_ = std::move(data); } const char* GetBytes() const override { return reinterpret_cast(output_data_.data()); } private: // Compilation output data. In normal compilation mode, it contains the // compiled SPIR-V binary code. In disassembly and preprocessing-only mode, it // contains a null-terminated string which is the text output. For text // output, extra bytes with value 0x00 might be appended to complete the last // uint32_t element. std::vector output_data_; }; // Compilation result class using a spv_binary for holding the compilation // output data. class shaderc_compilation_result_spv_binary : public shaderc_compilation_result { public: ~shaderc_compilation_result_spv_binary() { spvBinaryDestroy(output_data_); } void SetOutputData(spv_binary data) { output_data_ = data; } const char* GetBytes() const override { return reinterpret_cast(output_data_->code); } private: spv_binary output_data_ = nullptr; }; namespace shaderc_util { class GlslangInitializer; } struct shaderc_compiler { std::unique_ptr initializer; }; // Converts a shader stage from shaderc_shader_kind into a shaderc_util::Compiler::Stage. // This is only valid for a specifically named shader stage, e.g. vertex through fragment, // or compute. inline shaderc_util::Compiler::Stage shaderc_convert_specific_stage( shaderc_shader_kind kind) { switch (kind) { case shaderc_vertex_shader: return shaderc_util::Compiler::Stage::Vertex; case shaderc_fragment_shader: return shaderc_util::Compiler::Stage::Fragment; case shaderc_tess_control_shader: return shaderc_util::Compiler::Stage::TessControl; case shaderc_tess_evaluation_shader: return shaderc_util::Compiler::Stage::TessEval; case shaderc_geometry_shader: return shaderc_util::Compiler::Stage::Geometry; case shaderc_compute_shader: return shaderc_util::Compiler::Stage::Compute; case shaderc_raygen_shader: return shaderc_util::Compiler::Stage::RayGenNV; case shaderc_intersection_shader: return shaderc_util::Compiler::Stage::IntersectNV; case shaderc_anyhit_shader: return shaderc_util::Compiler::Stage::AnyHitNV; case shaderc_closesthit_shader: return shaderc_util::Compiler::Stage::ClosestHitNV; case shaderc_miss_shader: return shaderc_util::Compiler::Stage::MissNV; case shaderc_callable_shader: return shaderc_util::Compiler::Stage::CallableNV; case shaderc_task_shader: return shaderc_util::Compiler::Stage::TaskNV; case shaderc_mesh_shader: return shaderc_util::Compiler::Stage::MeshNV; default: // We don't care about the other kinds. break; } // This should not occur. assert(false && "Should have specified a specific stage"); return shaderc_util::Compiler::Stage::TessEval; } #endif // LIBSHADERC_SRC_SHADERC_PRIVATE_H_ shaderc-2025.2/libshaderc/src/shaderc_private_test.cc000066400000000000000000000046571500222170200226200ustar00rootroot00000000000000// Copyright 2017 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include "shaderc_private.h" namespace { TEST(ConvertSpecificStage, Exhaustive) { EXPECT_EQ(shaderc_util::Compiler::Stage::Vertex, shaderc_convert_specific_stage(shaderc_vertex_shader)); EXPECT_EQ(shaderc_util::Compiler::Stage::Fragment, shaderc_convert_specific_stage(shaderc_fragment_shader)); EXPECT_EQ(shaderc_util::Compiler::Stage::TessControl, shaderc_convert_specific_stage(shaderc_tess_control_shader)); EXPECT_EQ(shaderc_util::Compiler::Stage::TessEval, shaderc_convert_specific_stage(shaderc_tess_evaluation_shader)); EXPECT_EQ(shaderc_util::Compiler::Stage::Geometry, shaderc_convert_specific_stage(shaderc_geometry_shader)); EXPECT_EQ(shaderc_util::Compiler::Stage::Compute, shaderc_convert_specific_stage(shaderc_compute_shader)); EXPECT_EQ(shaderc_util::Compiler::Stage::RayGenNV, shaderc_convert_specific_stage(shaderc_raygen_shader)); EXPECT_EQ(shaderc_util::Compiler::Stage::AnyHitNV, shaderc_convert_specific_stage(shaderc_anyhit_shader)); EXPECT_EQ(shaderc_util::Compiler::Stage::ClosestHitNV, shaderc_convert_specific_stage(shaderc_closesthit_shader)); EXPECT_EQ(shaderc_util::Compiler::Stage::IntersectNV, shaderc_convert_specific_stage(shaderc_intersection_shader)); EXPECT_EQ(shaderc_util::Compiler::Stage::MissNV, shaderc_convert_specific_stage(shaderc_miss_shader)); EXPECT_EQ(shaderc_util::Compiler::Stage::CallableNV, shaderc_convert_specific_stage(shaderc_callable_shader)); EXPECT_EQ(shaderc_util::Compiler::Stage::TaskNV, shaderc_convert_specific_stage(shaderc_task_shader)); EXPECT_EQ(shaderc_util::Compiler::Stage::MeshNV, shaderc_convert_specific_stage(shaderc_mesh_shader)); } } // anonymous namespace shaderc-2025.2/libshaderc/src/shaderc_test.cc000066400000000000000000002604531500222170200210640ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "shaderc/shaderc.h" #include #include #include #include #include #include "common_shaders_for_test.h" #include "spirv/unified1/spirv.hpp" namespace { using testing::Each; using testing::HasSubstr; using testing::Not; TEST(Init, MultipleCalls) { shaderc_compiler_t compiler1, compiler2, compiler3; EXPECT_NE(nullptr, compiler1 = shaderc_compiler_initialize()); EXPECT_NE(nullptr, compiler2 = shaderc_compiler_initialize()); EXPECT_NE(nullptr, compiler3 = shaderc_compiler_initialize()); shaderc_compiler_release(compiler1); shaderc_compiler_release(compiler2); shaderc_compiler_release(compiler3); } #ifndef SHADERC_DISABLE_THREADED_TESTS TEST(Init, MultipleThreadsCalling) { shaderc_compiler_t compiler1, compiler2, compiler3; std::thread t1([&compiler1]() { compiler1 = shaderc_compiler_initialize(); }); std::thread t2([&compiler2]() { compiler2 = shaderc_compiler_initialize(); }); std::thread t3([&compiler3]() { compiler3 = shaderc_compiler_initialize(); }); t1.join(); t2.join(); t3.join(); EXPECT_NE(nullptr, compiler1); EXPECT_NE(nullptr, compiler2); EXPECT_NE(nullptr, compiler3); shaderc_compiler_release(compiler1); shaderc_compiler_release(compiler2); shaderc_compiler_release(compiler3); } #endif TEST(Init, SPVVersion) { unsigned int version = 0; unsigned int revision = 0; shaderc_get_spv_version(&version, &revision); EXPECT_EQ(spv::Version, version); EXPECT_EQ(spv::Revision, revision); } // Determines the kind of output required from the compiler. enum class OutputType { SpirvBinary, SpirvAssemblyText, PreprocessedText, }; // Generate a compilation result object with the given compile, // shader source, shader kind, input file name, entry point name, options, // and for the specified output type. The entry point name is only significant // for HLSL compilation. shaderc_compilation_result_t MakeCompilationResult( const shaderc_compiler_t compiler, const std::string& shader, shaderc_shader_kind kind, const char* input_file_name, const char* entry_point_name, const shaderc_compile_options_t options, OutputType output_type) { switch (output_type) { case OutputType::SpirvBinary: return shaderc_compile_into_spv(compiler, shader.c_str(), shader.size(), kind, input_file_name, entry_point_name, options); break; case OutputType::SpirvAssemblyText: return shaderc_compile_into_spv_assembly( compiler, shader.c_str(), shader.size(), kind, input_file_name, entry_point_name, options); break; case OutputType::PreprocessedText: return shaderc_compile_into_preprocessed_text( compiler, shader.c_str(), shader.size(), kind, input_file_name, entry_point_name, options); break; } // We shouldn't reach here. But some compilers might not know that. // Be a little defensive and produce something. return shaderc_compile_into_spv(compiler, shader.c_str(), shader.size(), kind, input_file_name, entry_point_name, options); } // RAII class for shaderc_compilation_result. Used for shader compilation. class Compilation { public: // Compiles shader and keeps the result. Compilation(const shaderc_compiler_t compiler, const std::string& shader, shaderc_shader_kind kind, const char* input_file_name, const char* entry_point_name, const shaderc_compile_options_t options = nullptr, OutputType output_type = OutputType::SpirvBinary) : compiled_result_( MakeCompilationResult(compiler, shader, kind, input_file_name, entry_point_name, options, output_type)) {} ~Compilation() { shaderc_result_release(compiled_result_); } shaderc_compilation_result_t result() const { return compiled_result_; } private: shaderc_compilation_result_t compiled_result_; }; // RAII class for shaderc_compilation_result. Used for shader assembling. class Assembling { public: // Assembles shader and keeps the result. Assembling(const shaderc_compiler_t compiler, const std::string& assembly, const shaderc_compile_options_t options = nullptr) : compiled_result_(shaderc_assemble_into_spv(compiler, assembly.data(), assembly.size(), options)) {} ~Assembling() { shaderc_result_release(compiled_result_); } shaderc_compilation_result_t result() const { return compiled_result_; } private: shaderc_compilation_result_t compiled_result_; }; struct CleanupOptions { void operator()(shaderc_compile_options_t options) const { shaderc_compile_options_release(options); } }; typedef std::unique_ptr compile_options_ptr; // RAII class for shaderc_compiler_t class Compiler { public: Compiler() { compiler = shaderc_compiler_initialize(); } ~Compiler() { shaderc_compiler_release(compiler); } shaderc_compiler_t get_compiler_handle() { return compiler; } private: shaderc_compiler_t compiler; }; // RAII class for shader_compiler_options_t class Options { public: Options() : options_(shaderc_compile_options_initialize()) {} ~Options() { shaderc_compile_options_release(options_); } shaderc_compile_options_t get() { return options_; } private: shaderc_compile_options_t options_; }; // Helper function to check if the compilation result indicates a successful // compilation. bool CompilationResultIsSuccess(const shaderc_compilation_result_t result) { return shaderc_result_get_compilation_status(result) == shaderc_compilation_status_success; } // Returns true if the given result contains a SPIR-V module that contains // at least the number of bytes of the header and the correct magic number. bool ResultContainsValidSpv(shaderc_compilation_result_t result) { if (!CompilationResultIsSuccess(result)) return false; size_t length = shaderc_result_get_length(result); if (length < 20) return false; const uint32_t* bytes = static_cast( static_cast(shaderc_result_get_bytes(result))); return bytes[0] == spv::MagicNumber; } // Compiles a shader and returns true if the result is valid SPIR-V. bool CompilesToValidSpv(Compiler& compiler, const std::string& shader, shaderc_shader_kind kind, const shaderc_compile_options_t options = nullptr) { const Compilation comp(compiler.get_compiler_handle(), shader, kind, "shader", "main", options, OutputType::SpirvBinary); return ResultContainsValidSpv(comp.result()); } // A testing class to test the compilation of a string with or without options. // This class wraps the initailization of compiler and compiler options and // groups the result checking methods. Subclass tests can access the compiler // object and compiler option object to set their properties. Input file names // are set to "shader". class CompileStringTest : public testing::Test { protected: // Compiles a shader and returns true on success, false on failure. bool CompilationSuccess(const std::string& shader, shaderc_shader_kind kind, shaderc_compile_options_t options = nullptr, OutputType output_type = OutputType::SpirvBinary) { return CompilationResultIsSuccess( Compilation(compiler_.get_compiler_handle(), shader, kind, "shader", "main", options, output_type) .result()); } // Compiles a shader, expects compilation success, and returns the warning // messages. const std::string CompilationWarnings( const std::string& shader, shaderc_shader_kind kind, const shaderc_compile_options_t options = nullptr, OutputType output_type = OutputType::SpirvBinary) { const Compilation comp(compiler_.get_compiler_handle(), shader, kind, "shader", "main", options, output_type); EXPECT_TRUE(CompilationResultIsSuccess(comp.result())) << kind << '\n' << shader; return shaderc_result_get_error_message(comp.result()); } // Compiles a shader, expects compilation failure, and returns the messages. const std::string CompilationErrors( const std::string& shader, shaderc_shader_kind kind, const shaderc_compile_options_t options = nullptr, OutputType output_type = OutputType::SpirvBinary, const char* source_name = "shader") { const Compilation comp(compiler_.get_compiler_handle(), shader, kind, source_name, "main", options, output_type); EXPECT_FALSE(CompilationResultIsSuccess(comp.result())) << kind << '\n' << shader; EXPECT_EQ(0u, shaderc_result_get_length(comp.result())); return shaderc_result_get_error_message(comp.result()); } // Compiles a shader and returns the messages. const std::string CompilationMessages( const std::string& shader, shaderc_shader_kind kind, const shaderc_compile_options_t options = nullptr, OutputType output_type = OutputType::SpirvBinary) { const Compilation comp(compiler_.get_compiler_handle(), shader, kind, "shader", "main", options, output_type); return shaderc_result_get_error_message(comp.result()); } // Compiles a shader, expects compilation success, and returns the output // bytes. const std::string CompilationOutput( const std::string& shader, shaderc_shader_kind kind, const shaderc_compile_options_t options = nullptr, OutputType output_type = OutputType::SpirvBinary) { const Compilation comp(compiler_.get_compiler_handle(), shader, kind, "shader", "main", options, output_type); EXPECT_TRUE(CompilationResultIsSuccess(comp.result())) << "shader kind: " << kind << "\nerror message: " << shaderc_result_get_error_message(comp.result()) << "\nshader source code: \n" << shader; // Use string(const char* s, size_t n) constructor instead of // string(const char* s) to make sure the string has complete binary data. // string(const char* s) assumes a null-terminated C-string, which will cut // the binary data when it sees a '\0' byte. return std::string(shaderc_result_get_bytes(comp.result()), shaderc_result_get_length(comp.result())); } Compiler compiler_; compile_options_ptr options_; public: CompileStringTest() : options_(shaderc_compile_options_initialize()) {} }; // A testing class to test the assembling of a string. // This class wraps the initailization of compiler and groups the result // checking methods. Subclass tests can access the compiler object to set their // properties. class AssembleStringTest : public testing::Test { public: AssembleStringTest() : options_(shaderc_compile_options_initialize()) {} ~AssembleStringTest() { shaderc_compile_options_release(options_); } protected: // Assembles the given assembly and returns true on success. bool AssemblingSuccess(const std::string& assembly) { return CompilationResultIsSuccess( Assembling(compiler_.get_compiler_handle(), assembly, options_) .result()); } bool AssemblingValid(const std::string& assembly) { const auto assembling = Assembling(compiler_.get_compiler_handle(), assembly); return ResultContainsValidSpv(assembling.result()); } Compiler compiler_; shaderc_compile_options_t options_; }; // Name holders so that we have test cases being grouped with only one real // compilation class. using CompileStringWithOptionsTest = CompileStringTest; using CompileKindsTest = CompileStringTest; TEST_F(CompileStringTest, EmptyString) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_vertex_shader)); EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_fragment_shader)); } TEST_F(AssembleStringTest, EmptyString) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_TRUE(AssemblingSuccess("")); } TEST_F(CompileStringTest, GarbageString) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_vertex_shader)); EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_fragment_shader)); } TEST_F(AssembleStringTest, GarbageString) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); auto assembling = Assembling(compiler_.get_compiler_handle(), "jfalkds"); EXPECT_FALSE(CompilationResultIsSuccess(assembling.result())); EXPECT_EQ(1u, shaderc_result_get_num_errors(assembling.result())); EXPECT_EQ(0u, shaderc_result_get_num_warnings(assembling.result())); } // TODO(antiagainst): right now there is no assembling difference for all the // target environments exposed by shaderc. So the following is just testing the // target environment is accepted. TEST_F(AssembleStringTest, AcceptTargetEnv) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); shaderc_compile_options_set_target_env(options_, shaderc_target_env_opengl, /* version = */ 0); EXPECT_TRUE(AssemblingSuccess("OpCapability Shader")); } TEST_F(CompileStringTest, ReallyLongShader) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); std::string minimal_shader = ""; minimal_shader += "#version 140\n"; minimal_shader += "void foo(){}"; minimal_shader.append(1024 * 1024 * 8, ' '); // 8MB of spaces. minimal_shader += "void main(){}"; EXPECT_TRUE(CompilesToValidSpv(compiler_, minimal_shader, shaderc_glsl_vertex_shader)); EXPECT_TRUE(CompilesToValidSpv(compiler_, minimal_shader, shaderc_glsl_fragment_shader)); } TEST_F(CompileStringTest, MinimalShader) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, shaderc_glsl_vertex_shader)); EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, shaderc_glsl_fragment_shader)); } TEST_F(AssembleStringTest, MinimalShader) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_TRUE(AssemblingValid(kMinimalShaderAssembly)); } TEST_F(CompileStringTest, WorksWithCompileOptions) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, shaderc_glsl_vertex_shader, options_.get())); } TEST_F(CompileStringTest, GetNumErrors) { Compilation comp(compiler_.get_compiler_handle(), kTwoErrorsShader, shaderc_glsl_vertex_shader, "shader", "main"); // Expects compilation failure and two errors. EXPECT_FALSE(CompilationResultIsSuccess(comp.result())); EXPECT_EQ(2u, shaderc_result_get_num_errors(comp.result())); // Expects the number of warnings to be zero. EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp.result())); } TEST_F(CompileStringTest, GetNumWarnings) { Compilation comp(compiler_.get_compiler_handle(), kTwoWarningsShader, shaderc_glsl_vertex_shader, "shader", "main"); // Expects compilation success with two warnings. EXPECT_TRUE(CompilationResultIsSuccess(comp.result())); EXPECT_EQ(2u, shaderc_result_get_num_warnings(comp.result())); // Expects the number of errors to be zero. EXPECT_EQ(0u, shaderc_result_get_num_errors(comp.result())); } TEST_F(CompileStringTest, ZeroErrorsZeroWarnings) { Compilation comp(compiler_.get_compiler_handle(), kMinimalShader, shaderc_glsl_vertex_shader, "shader", "main"); // Expects compilation success with zero warnings. EXPECT_TRUE(CompilationResultIsSuccess(comp.result())); EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp.result())); // Expects the number of errors to be zero. EXPECT_EQ(0u, shaderc_result_get_num_errors(comp.result())); } TEST_F(CompileStringTest, ErrorTypeUnknownShaderStage) { // The shader kind/stage can not be determined, the error type field should // indicate the error type is shaderc_shader_kind_error. Compilation comp(compiler_.get_compiler_handle(), kMinimalShader, shaderc_glsl_infer_from_source, "shader", "main"); EXPECT_EQ(shaderc_compilation_status_invalid_stage, shaderc_result_get_compilation_status(comp.result())); } TEST_F(CompileStringTest, ErrorTypeCompilationError) { // The shader kind is valid, the result object's error type field should // indicate this compilaion fails due to compilation errors. Compilation comp(compiler_.get_compiler_handle(), kTwoErrorsShader, shaderc_glsl_vertex_shader, "shader", "main"); EXPECT_EQ(shaderc_compilation_status_compilation_error, shaderc_result_get_compilation_status(comp.result())); } TEST_F(CompileStringWithOptionsTest, CloneCompilerOptions) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); compile_options_ptr options_(shaderc_compile_options_initialize()); EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, shaderc_glsl_vertex_shader, options_.get())); compile_options_ptr cloned_options( shaderc_compile_options_clone(options_.get())); EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, shaderc_glsl_vertex_shader, cloned_options.get())); } TEST_F(CompileStringWithOptionsTest, MacroCompileOptions) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, "main", 4u); const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}"; const std::string kMinimalDoubleExpandedShader = "#version 140\nF E(){}"; EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader, shaderc_glsl_vertex_shader, options_.get())); compile_options_ptr cloned_options( shaderc_compile_options_clone(options_.get())); // The simplest should still compile with the cloned options. EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader, shaderc_glsl_vertex_shader, cloned_options.get())); EXPECT_FALSE(CompilesToValidSpv(compiler_, kMinimalDoubleExpandedShader, shaderc_glsl_vertex_shader, cloned_options.get())); shaderc_compile_options_add_macro_definition(cloned_options.get(), "F", 1u, "void", 4u); // This should still not work with the original options. EXPECT_FALSE(CompilesToValidSpv(compiler_, kMinimalDoubleExpandedShader, shaderc_glsl_vertex_shader, options_.get())); // This should work with the cloned options that have the additional // parameter. EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalDoubleExpandedShader, shaderc_glsl_vertex_shader, cloned_options.get())); } TEST_F(CompileStringWithOptionsTest, MacroCompileOptionsNotNullTerminated) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); shaderc_compile_options_add_macro_definition(options_.get(), "EFGH", 1u, "mainnnnnn", 4u); const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}"; EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader, shaderc_glsl_vertex_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, ValuelessMacroCompileOptionsZeroLength) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, "somthing", 0u); EXPECT_TRUE(CompilesToValidSpv(compiler_, kValuelessPredefinitionShader, shaderc_glsl_vertex_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, ValuelessMacroCompileOptionsNullPointer) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, nullptr, 100u); EXPECT_TRUE(CompilesToValidSpv(compiler_, kValuelessPredefinitionShader, shaderc_glsl_vertex_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, DisassemblyOption) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); // This should work with both the glslang assembly format and the // SPIR-V tools assembly format. const std::string disassembly_text = CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("Capability Shader")); EXPECT_THAT(disassembly_text, HasSubstr("MemoryModel")); } TEST_F(CompileStringWithOptionsTest, DisassembleMinimalShader) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); const std::string disassembly_text = CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); for (const auto& substring : kMinimalShaderDisassemblySubstrings) { EXPECT_THAT(disassembly_text, HasSubstr(substring)); } } TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileCorrectStd) { // Forces the version and profile to 450core, which fixes the missing // #version. shaderc_compile_options_set_forced_version_profile(options_.get(), 450, shaderc_profile_core); ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion, shaderc_glsl_vertex_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileCorrectStdClonedOptions) { // Forces the version and profile to 450core, which fixes the missing // #version. shaderc_compile_options_set_forced_version_profile(options_.get(), 450, shaderc_profile_core); // This mode should be carried to any clone of the original options object. compile_options_ptr cloned_options( shaderc_compile_options_clone(options_.get())); ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion, shaderc_glsl_vertex_shader, cloned_options.get())); } TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileInvalidModule) { // Forces the version and profile to 310es, while the source module is invalid // for this version of GLSL. Compilation should fail. shaderc_compile_options_set_forced_version_profile(options_.get(), 310, shaderc_profile_es); ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_THAT(CompilationErrors(kCoreVertShaderWithoutVersion, shaderc_glsl_vertex_shader, options_.get()), HasSubstr("error: 'gl_ClipDistance' : undeclared identifier\n")); } TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileConflictingStd) { // Forces the version and profile to 450core, which is in conflict with the // #version in shader. shaderc_compile_options_set_forced_version_profile(options_.get(), 450, shaderc_profile_core); const std::string kVertexShader = std::string("#version 310 es\n") + kCoreVertShaderWithoutVersion; ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_THAT(CompilationWarnings(kVertexShader, shaderc_glsl_vertex_shader, options_.get()), HasSubstr("warning: (version, profile) forced to be (450, core), " "while in source code it is (310, es)\n")); } TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileUnknownVersionStd) { // Forces the version and profile to 4242core, which is an unknown version. shaderc_compile_options_set_forced_version_profile( options_.get(), 4242 /*unknown version*/, shaderc_profile_core); ASSERT_NE(nullptr, compiler_.get_compiler_handle()); // Warning message should complain about the unknown version. // // Also, Glslang errors out on unkown versions, due to commit: // https://github.com/KhronosGroup/glslang/commit/9353f1afab8d1c2b1811c6acd807675128eaabc5 const auto errs = CompilationErrors( kMinimalShader, shaderc_glsl_vertex_shader, options_.get()); EXPECT_THAT( errs, HasSubstr("warning: (version, profile) forced to be (4242, core), " "while in source code it is (140, none)\n")); EXPECT_THAT(errs, HasSubstr("error: version not supported\n")); } TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileVersionsBefore150) { // Versions before 150 do not allow a profile token, shaderc_profile_none // should be passed down as the profile parameter. shaderc_compile_options_set_forced_version_profile(options_.get(), 140, shaderc_profile_none); ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_TRUE(CompilationSuccess(kMinimalShaderWithoutVersion, shaderc_glsl_vertex_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileRedundantProfileStd) { // Forces the version and profile to 100core. But versions before 150 do not // allow a profile token, compilation should fail. shaderc_compile_options_set_forced_version_profile(options_.get(), 100, shaderc_profile_core); ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_THAT(CompilationErrors(kMinimalShader, shaderc_glsl_vertex_shader, options_.get()), HasSubstr("error: #version: versions before 150 do not allow a " "profile token\n")); } TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoBinary) { shaderc_compile_options_set_generate_debug_info(options_.get()); ASSERT_NE(nullptr, compiler_.get_compiler_handle()); const std::string binary_output = CompilationOutput( kMinimalDebugInfoShader, shaderc_glsl_vertex_shader, options_.get()); // The binary output should contain the name of the vector (debug_info_sample) // null-terminated, as well as the whole original source. std::string vector_name("debug_info_sample"); vector_name.resize(vector_name.size() + 1); EXPECT_THAT(binary_output, HasSubstr(vector_name)); EXPECT_THAT(binary_output, HasSubstr(kMinimalDebugInfoShader)); } TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoBinaryClonedOptions) { shaderc_compile_options_set_generate_debug_info(options_.get()); compile_options_ptr cloned_options( shaderc_compile_options_clone(options_.get())); ASSERT_NE(nullptr, compiler_.get_compiler_handle()); const std::string binary_output = CompilationOutput(kMinimalDebugInfoShader, shaderc_glsl_vertex_shader, cloned_options.get()); // The binary output should contain the name of the vector (debug_info_sample) // null-terminated, as well as the whole original source. std::string vector_name("debug_info_sample"); vector_name.resize(vector_name.size() + 1); EXPECT_THAT(binary_output, HasSubstr(vector_name)); EXPECT_THAT(binary_output, HasSubstr(kMinimalDebugInfoShader)); } TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoDisassembly) { shaderc_compile_options_set_generate_debug_info(options_.get()); ASSERT_NE(nullptr, compiler_.get_compiler_handle()); // Generate assembly text we can compare its output as a string. // The disassembly output should contain the name of the vector: // debug_info_sample. EXPECT_THAT( CompilationOutput(kMinimalDebugInfoShader, shaderc_glsl_vertex_shader, options_.get(), OutputType::SpirvAssemblyText), HasSubstr("debug_info_sample")); } TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeWithLevelZero) { shaderc_compile_options_set_optimization_level( options_.get(), shaderc_optimization_level_zero); const std::string disassembly_text = CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); for (const auto& substring : kMinimalShaderDisassemblySubstrings) { EXPECT_THAT(disassembly_text, HasSubstr(substring)); } // Check that we still have debug instructions. EXPECT_THAT(disassembly_text, HasSubstr("OpName")); EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); } TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeWithLevelPerformance) { shaderc_compile_options_set_optimization_level( options_.get(), shaderc_optimization_level_performance); const std::string disassembly_text = CompilationOutput(kGlslMultipleFnShader, shaderc_glsl_fragment_shader, options_.get(), OutputType::SpirvAssemblyText); // Check that we do not have function calls anymore. EXPECT_THAT(disassembly_text, Not(HasSubstr("OpFunctionCall"))); } TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeWithLevelSize) { shaderc_compile_options_set_optimization_level( options_.get(), shaderc_optimization_level_size); const std::string disassembly_text = CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); for (const auto& substring : kMinimalShaderDisassemblySubstrings) { EXPECT_THAT(disassembly_text, HasSubstr(substring)); } // Check that we do not have debug instructions. EXPECT_THAT(disassembly_text, Not(HasSubstr("OpName"))); EXPECT_THAT(disassembly_text, Not(HasSubstr("OpSource"))); } TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeForVulkan10Failure) { shaderc_compile_options_set_source_language(options_.get(), shaderc_source_language_hlsl); shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_0); shaderc_compile_options_set_optimization_level( options_.get(), shaderc_optimization_level_performance); EXPECT_FALSE(CompilesToValidSpv(compiler_, kHlslWaveActiveSumeComputeShader, shaderc_compute_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeForVulkan11Success) { shaderc_compile_options_set_source_language(options_.get(), shaderc_source_language_hlsl); shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1); shaderc_compile_options_set_optimization_level( options_.get(), shaderc_optimization_level_performance); const std::string disassembly_text = CompilationOutput( kHlslWaveActiveSumeComputeShader, shaderc_compute_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpGroupNonUniformIAdd")); } TEST_F(CompileStringWithOptionsTest, FollowingOptLevelOverridesPreviousOne) { shaderc_compile_options_set_optimization_level( options_.get(), shaderc_optimization_level_size); // Optimization level settings overridden by shaderc_compile_options_set_optimization_level( options_.get(), shaderc_optimization_level_zero); const std::string disassembly_text = CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); for (const auto& substring : kMinimalShaderDisassemblySubstrings) { EXPECT_THAT(disassembly_text, HasSubstr(substring)); } // Check that we still have debug instructions. EXPECT_THAT(disassembly_text, HasSubstr("OpName")); EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); } TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoOverridesOptimizationLevel) { shaderc_compile_options_set_optimization_level( options_.get(), shaderc_optimization_level_size); // Optimization level settings overridden by shaderc_compile_options_set_generate_debug_info(options_.get()); const std::string disassembly_text = CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) { EXPECT_THAT(disassembly_text, HasSubstr(substring)); } // Check that we still have debug instructions. EXPECT_THAT(disassembly_text, HasSubstr("OpName")); EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); } TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoProhibitsOptimizationLevel) { // Setting generate debug info first also works. shaderc_compile_options_set_generate_debug_info(options_.get()); shaderc_compile_options_set_optimization_level( options_.get(), shaderc_optimization_level_size); const std::string disassembly_text = CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) { EXPECT_THAT(disassembly_text, HasSubstr(substring)); } // Check that we still have debug instructions. EXPECT_THAT(disassembly_text, HasSubstr("OpName")); EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); } TEST_F(CompileStringWithOptionsTest, PreprocessingOnlyOption) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); const std::string kMinimalShaderWithMacro = "#version 150\n" "#define E main\n" "void E(){}\n"; const std::string preprocessed_text = CompilationOutput(kMinimalShaderWithMacro, shaderc_glsl_vertex_shader, options_.get(), OutputType::PreprocessedText); EXPECT_THAT(preprocessed_text, HasSubstr("void main() { }")); const std::string kMinimalShaderWithMacroCloneOption = "#version 150\n" "#define E_CLONE_OPTION main\n" "void E_CLONE_OPTION(){}\n"; compile_options_ptr cloned_options( shaderc_compile_options_clone(options_.get())); const std::string preprocessed_text_cloned_options = CompilationOutput( kMinimalShaderWithMacroCloneOption, shaderc_glsl_vertex_shader, options_.get(), OutputType::PreprocessedText); EXPECT_THAT(preprocessed_text_cloned_options, HasSubstr("void main() { }")); } // A shader kind test cases needs: 1) A shader text with or without #pragma // annotation, 2) shader_kind. struct ShaderKindTestCase { const char* shader_; shaderc_shader_kind shader_kind_; }; // Test the shader kind deduction process. If the shader kind is one of the // forced ones, the compiler will just try to compile the source code in that // specified shader kind. If the shader kind is shaderc_glsl_deduce_from_pragma, // the compiler will determine the shader kind from #pragma annotation in the // source code and emit error if none such annotation is found. When the shader // kind is one of the default ones, the compiler will fall back to use the // specified shader kind if and only if #pragma annoation is not found. // Valid shader kind settings should generate valid SPIR-V code. using ValidShaderKind = testing::TestWithParam; TEST_P(ValidShaderKind, ValidSpvCode) { const ShaderKindTestCase& test_case = GetParam(); Compiler compiler; EXPECT_TRUE( CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_)); } INSTANTIATE_TEST_SUITE_P( CompileStringTest, ValidShaderKind, testing::ValuesIn(std::vector{ // Valid default shader kinds. {kEmpty310ESShader, shaderc_glsl_default_vertex_shader}, {kEmpty310ESShader, shaderc_glsl_default_fragment_shader}, {kEmpty310ESShader, shaderc_glsl_default_compute_shader}, {kGeometryOnlyShader, shaderc_glsl_default_geometry_shader}, {kTessControlOnlyShader, shaderc_glsl_default_tess_control_shader}, {kTessEvaluationOnlyShader, shaderc_glsl_default_tess_evaluation_shader}, {kNVMeshShader, shaderc_glsl_default_mesh_shader}, {kNVTaskShader, shaderc_glsl_default_task_shader}, // #pragma annotation overrides default shader kinds. {kVertexOnlyShaderWithPragma, shaderc_glsl_default_compute_shader}, {kFragmentOnlyShaderWithPragma, shaderc_glsl_default_vertex_shader}, {kTessControlOnlyShaderWithPragma, shaderc_glsl_default_fragment_shader}, {kTessEvaluationOnlyShaderWithPragma, shaderc_glsl_default_tess_control_shader}, {kGeometryOnlyShaderWithPragma, shaderc_glsl_default_tess_evaluation_shader}, {kComputeOnlyShaderWithPragma, shaderc_glsl_default_geometry_shader}, {kNVMeshShaderWithPragma, shaderc_glsl_default_geometry_shader}, {kNVTaskShaderWithPragma, shaderc_glsl_default_geometry_shader}, // Infer from source {kVertexOnlyShaderWithPragma, shaderc_glsl_infer_from_source}, {kNVMeshShaderWithPragma, shaderc_glsl_infer_from_source}, {kNVTaskShaderWithPragma, shaderc_glsl_infer_from_source}, // Specified non-default shader kind overrides #pragma annotation. {kVertexOnlyShaderWithInvalidPragma, shaderc_glsl_vertex_shader}, })); using InvalidShaderKind = testing::TestWithParam; // Invalid shader kind settings should generate errors. TEST_P(InvalidShaderKind, CompilationShouldFail) { const ShaderKindTestCase& test_case = GetParam(); Compiler compiler; EXPECT_FALSE( CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_)); } INSTANTIATE_TEST_SUITE_P( CompileStringTest, InvalidShaderKind, testing::ValuesIn(std::vector{ // Invalid default shader kind. {kVertexOnlyShader, shaderc_glsl_default_fragment_shader}, // Sets to deduce shader kind from #pragma, but #pragma is defined in // the source code. {kVertexOnlyShader, shaderc_glsl_infer_from_source}, // Invalid #pragma cause errors, even though default shader kind is set // to valid shader kind. {kVertexOnlyShaderWithInvalidPragma, shaderc_glsl_default_vertex_shader}, })); // To test file inclusion, use an unordered_map as a fake file system to store // fake files to be included. The unordered_map represents a filesystem by // mapping filename (or path) string to the contents of that file as a string. using FakeFS = std::unordered_map; // An includer test case needs: 1) A fake file system which is actually an // unordered_map, so that we can resolve the content given a string. A valid // fake file system must have one entry with key:'root' to specify the start // shader file for compilation. 2) An string that we expect to see in the // compilation output. class IncluderTestCase { public: IncluderTestCase(FakeFS fake_fs, std::string expected_substring) : fake_fs_(fake_fs), expected_substring_(expected_substring) { assert(fake_fs_.find("root") != fake_fs_.end() && "Valid fake file system needs a 'root' file\n"); } const FakeFS& fake_fs() const { return fake_fs_; } const std::string& expected_substring() const { return expected_substring_; } private: FakeFS fake_fs_; std::string expected_substring_; }; // A mock class that simulate an includer. C API needs two function pointers // each for get including data and release the data. This class defined two // static functions, which wrap their matching member functions, to be passed to // libshaderc C API. class TestIncluder { public: explicit TestIncluder(const FakeFS& fake_fs) : fake_fs_(fake_fs), responses_({}) {} // Get path and content from the fake file system. shaderc_include_result* GetInclude(const char* filename) { responses_.emplace_back(shaderc_include_result{ filename, strlen(filename), fake_fs_.at(std::string(filename)).c_str(), fake_fs_.at(std::string(filename)).size()}); return &responses_.back(); } // Response data is owned as private property, no need to release explicitly. void ReleaseInclude(shaderc_include_result*) {} // Wrapper for the corresponding member function. static shaderc_include_result* GetIncluderResponseWrapper( void* user_data, const char* filename, int, const char* includer, size_t include_depth) { return static_cast(user_data)->GetInclude(filename); } // Wrapper for the corresponding member function. static void ReleaseIncluderResponseWrapper(void* user_data, shaderc_include_result* data) { return static_cast(user_data)->ReleaseInclude(data); } private: // Includer response data is stored as private property. const FakeFS& fake_fs_; std::vector responses_; }; using IncluderTests = testing::TestWithParam; // Parameterized tests for includer. TEST_P(IncluderTests, SetIncluderCallbacks) { const IncluderTestCase& test_case = GetParam(); const FakeFS& fs = test_case.fake_fs(); const std::string& shader = fs.at("root"); TestIncluder includer(fs); Compiler compiler; compile_options_ptr options(shaderc_compile_options_initialize()); shaderc_compile_options_set_include_callbacks( options.get(), TestIncluder::GetIncluderResponseWrapper, TestIncluder::ReleaseIncluderResponseWrapper, &includer); const Compilation comp(compiler.get_compiler_handle(), shader, shaderc_glsl_vertex_shader, "shader", "main", options.get(), OutputType::PreprocessedText); // Checks the existence of the expected string. EXPECT_THAT(shaderc_result_get_bytes(comp.result()), HasSubstr(test_case.expected_substring())); } TEST_P(IncluderTests, SetIncluderCallbacksClonedOptions) { const IncluderTestCase& test_case = GetParam(); const FakeFS& fs = test_case.fake_fs(); const std::string& shader = fs.at("root"); TestIncluder includer(fs); Compiler compiler; compile_options_ptr options(shaderc_compile_options_initialize()); shaderc_compile_options_set_include_callbacks( options.get(), TestIncluder::GetIncluderResponseWrapper, TestIncluder::ReleaseIncluderResponseWrapper, &includer); // Cloned options should have all the settings. compile_options_ptr cloned_options( shaderc_compile_options_clone(options.get())); const Compilation comp(compiler.get_compiler_handle(), shader, shaderc_glsl_vertex_shader, "shader", "main", cloned_options.get(), OutputType::PreprocessedText); // Checks the existence of the expected string. EXPECT_THAT(shaderc_result_get_bytes(comp.result()), HasSubstr(test_case.expected_substring())); } INSTANTIATE_TEST_SUITE_P(CompileStringTest, IncluderTests, testing::ValuesIn(std::vector{ IncluderTestCase( // Fake file system. { {"root", "#version 150\n" "void foo() {}\n" "#include \"path/to/file_1\"\n"}, {"path/to/file_1", "content of file_1\n"}, }, // Expected output. "#line 0 \"path/to/file_1\"\n" " content of file_1\n" "#line 3"), IncluderTestCase( // Fake file system. {{"root", "#version 150\n" "void foo() {}\n" "#include \"path/to/file_1\"\n"}, {"path/to/file_1", "#include \"path/to/file_2\"\n" "content of file_1\n"}, {"path/to/file_2", "content of file_2\n"}}, // Expected output. "#line 0 \"path/to/file_1\"\n" "#line 0 \"path/to/file_2\"\n" " content of file_2\n" "#line 1 \"path/to/file_1\"\n" " content of file_1\n" "#line 3"), })); TEST_F(CompileStringWithOptionsTest, WarningsOnLine) { // Some versions of Glslang will return an error, some will return just // warnings. EXPECT_THAT( CompilationMessages(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, options_.get()), HasSubstr(":2: warning: attribute deprecated in version 130; may be " "removed in future release\n")); } TEST_F(CompileStringWithOptionsTest, WarningsOnLineAsErrors) { shaderc_compile_options_set_warnings_as_errors(options_.get()); ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_THAT( CompilationErrors(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, options_.get()), HasSubstr(":2: error: attribute deprecated in version 130; may be " "removed in future release\n")); } TEST_F(CompileStringWithOptionsTest, SuppressWarningsOnLine) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); shaderc_compile_options_set_suppress_warnings(options_.get()); EXPECT_THAT( CompilationMessages(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, options_.get()), Not(HasSubstr(":2: warning: attribute deprecated in version 130; may be " "removed in future release\n"))); } TEST_F(CompileStringWithOptionsTest, GlobalWarnings) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); shaderc_compile_options_set_forced_version_profile(options_.get(), 400, shaderc_profile_core); EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader, shaderc_glsl_vertex_shader, options_.get()), HasSubstr("(version, profile) forced to be (400, core)," " while in source code it is (550, none)\n")); } TEST_F(CompileStringWithOptionsTest, GlobalWarningsAsErrors) { shaderc_compile_options_set_warnings_as_errors(options_.get()); ASSERT_NE(nullptr, compiler_.get_compiler_handle()); shaderc_compile_options_set_forced_version_profile(options_.get(), 400, shaderc_profile_core); EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader, shaderc_glsl_vertex_shader, options_.get()), HasSubstr("(version, profile) forced to be (400, core)," " while in source code it is (550, none)\n")); } TEST_F(CompileStringWithOptionsTest, SuppressGlobalWarnings) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); shaderc_compile_options_set_suppress_warnings(options_.get()); shaderc_compile_options_set_forced_version_profile(options_.get(), 400, shaderc_profile_core); EXPECT_EQ("", CompilationWarnings(kMinimalUnknownVersionShader, shaderc_glsl_vertex_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, SuppressWarningsModeFirstOverridesWarningsAsErrorsMode) { // Sets suppress-warnings mode first, then sets warnings-as-errors mode. // suppress-warnings mode should override warnings-as-errors mode. shaderc_compile_options_set_suppress_warnings(options_.get()); shaderc_compile_options_set_warnings_as_errors(options_.get()); ASSERT_NE(nullptr, compiler_.get_compiler_handle()); // Warnings on particular lines should be inhibited. Compilation comp_line(compiler_.get_compiler_handle(), kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, "shader", "main", options_.get()); EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_line.result())); // Global warnings should be inhibited. Compilation comp_global( compiler_.get_compiler_handle(), kMinimalUnknownVersionShader, shaderc_glsl_vertex_shader, "shader", "main", options_.get()); EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_global.result())); } TEST_F(CompileStringWithOptionsTest, SuppressWarningsModeSecondOverridesWarningsAsErrorsMode) { // Sets suppress-warnings mode first, then sets warnings-as-errors mode. // suppress-warnings mode should override warnings-as-errors mode. shaderc_compile_options_set_warnings_as_errors(options_.get()); shaderc_compile_options_set_suppress_warnings(options_.get()); ASSERT_NE(nullptr, compiler_.get_compiler_handle()); // Warnings on particular lines should be inhibited. Compilation comp_line(compiler_.get_compiler_handle(), kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, "shader", "main", options_.get()); EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_line.result())); // Global warnings should be inhibited. Compilation comp_global( compiler_.get_compiler_handle(), kMinimalUnknownVersionShader, shaderc_glsl_vertex_shader, "shader", "main", options_.get()); EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_global.result())); } TEST_F(CompileStringWithOptionsTest, IfDefCompileOption) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, nullptr, 0u); const std::string kMinimalExpandedShader = "#version 140\n" "#ifdef E\n" "void main(){}\n" "#else\n" "#error\n" "#endif"; EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader, shaderc_glsl_vertex_shader, options_.get())); } TEST_F( CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingOpenGLCompatibilityShaderToBinaryAndAlwaysFails) { // Glslang does not support generating SPIR-V for compatibility profile // shaders. EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader, shaderc_glsl_fragment_shader, options_.get())); shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_opengl_compat, 0); EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader, shaderc_glsl_fragment_shader, options_.get())); shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_opengl, 0); EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader, shaderc_glsl_fragment_shader, options_.get())); shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, 0); EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader, shaderc_glsl_fragment_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, CompilingFailsWhenTargetingOpenGLCompat) { // Confirm that kOpenGLVertexShader fails when targeting OpenGL // compatibility profile. shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_opengl_compat, 0); EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLVertexShader, shaderc_glsl_vertex_shader, options_.get())); const std::string errors = CompilationErrors( kOpenGLVertexShader, shaderc_glsl_vertex_shader, options_.get()); EXPECT_EQ(errors, "error: OpenGL compatibility profile is not supported"); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingOpenGLCoreShaderToBinary) { // Confirm that kOpenGLVertexShader compiles when targeting OpenGL core // profile. shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_opengl, 0); EXPECT_TRUE(CompilesToValidSpv(compiler_, kOpenGLVertexShader, shaderc_glsl_vertex_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_0ShaderToVulkan1_0Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_0); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeBarrier, shaderc_glsl_compute_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_0ShaderToVulkan1_1Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeBarrier, shaderc_glsl_compute_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_1ShaderToVulkan1_0Fails) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_0); EXPECT_FALSE(CompilesToValidSpv(compiler_, kGlslShaderComputeSubgroupBarrier, shaderc_glsl_compute_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_1ShaderToVulkan1_1Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeSubgroupBarrier, shaderc_glsl_compute_shader, options_.get())); } // Simple Vulkan 1.2 tests TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_0ShaderToVulkan1_2Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_2); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeBarrier, shaderc_glsl_compute_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_1ShaderToVulkan1_2Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_2); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeSubgroupBarrier, shaderc_glsl_compute_shader, options_.get())); } // Simple Vulkan 1.3 tests TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_0ShaderToVulkan1_3Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_3); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeBarrier, shaderc_glsl_compute_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_1ShaderToVulkan1_3Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_3); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeSubgroupBarrier, shaderc_glsl_compute_shader, options_.get())); } // Simple Vulkan 1.4 tests TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_0ShaderToVulkan1_4Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_4); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeBarrier, shaderc_glsl_compute_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_1ShaderToVulkan1_4Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_4); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeSubgroupBarrier, shaderc_glsl_compute_shader, options_.get())); } // task shader TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_0TaskShaderToVulkan1_0Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_0); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderTaskBarrier, shaderc_glsl_task_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_0TaskShaderToVulkan1_1Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderTaskBarrier, shaderc_glsl_task_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_1TaskShaderToVulkan1_0Fails) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_0); EXPECT_FALSE(CompilesToValidSpv(compiler_, kGlslShaderTaskSubgroupBarrier, shaderc_glsl_task_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_1TaskShaderToVulkan1_1Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderTaskSubgroupBarrier, shaderc_glsl_task_shader, options_.get())); } // mesh shader TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_0MeshShaderToVulkan1_0Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_0); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderMeshBarrier, shaderc_glsl_mesh_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_0MeshShaderToVulkan1_1Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderMeshBarrier, shaderc_glsl_mesh_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_1MeshShaderToVulkan1_0Fails) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_0); EXPECT_FALSE(CompilesToValidSpv(compiler_, kGlslShaderMeshSubgroupBarrier, shaderc_glsl_mesh_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, TargetEnvRespectedWhenCompilingVulkan1_1MeshShaderToVulkan1_1Succeeds) { shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1); EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderMeshSubgroupBarrier, shaderc_glsl_mesh_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, DISABLED_TargetEnvIgnoredWhenPreprocessing) { // This test is disabled since some versions of glslang may refuse to compile // very old shaders to SPIR-V with OpenGL target. Re-enable and rewrite this // test once we have a differential set of environments to test. const auto output_type = OutputType::PreprocessedText; EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader, shaderc_glsl_fragment_shader, options_.get(), output_type)); shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_opengl_compat, 0); EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader, shaderc_glsl_fragment_shader, options_.get(), output_type)); shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_opengl, 0); EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader, shaderc_glsl_fragment_shader, options_.get(), output_type)); shaderc_compile_options_set_target_env(options_.get(), shaderc_target_env_vulkan, 0); EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader, shaderc_glsl_fragment_shader, options_.get(), output_type)); } TEST_F(CompileStringTest, ShaderKindRespected) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); const std::string kVertexShader = "#version 140\nvoid main(){ gl_Position = vec4(0);}"; EXPECT_TRUE(CompilationSuccess(kVertexShader, shaderc_glsl_vertex_shader)); EXPECT_FALSE(CompilationSuccess(kVertexShader, shaderc_glsl_fragment_shader)); } TEST_F(CompileStringTest, ErrorsReported) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); EXPECT_THAT(CompilationErrors("int f(){return wrongname;}", shaderc_glsl_vertex_shader), HasSubstr("wrongname")); } #ifndef SHADERC_DISABLE_THREADED_TESTS TEST_F(CompileStringTest, MultipleThreadsCalling) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); bool results[10]; std::vector threads; for (auto& r : results) { threads.emplace_back([&r, this]() { r = CompilationSuccess("#version 140\nvoid main(){}", shaderc_glsl_vertex_shader); }); } for (auto& t : threads) { t.join(); } EXPECT_THAT(results, Each(true)); } #endif TEST_F(CompileKindsTest, Vertex) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); const std::string kVertexShader = "#version 140\nvoid main(){ gl_Position = vec4(0);}"; EXPECT_TRUE(CompilationSuccess(kVertexShader, shaderc_glsl_vertex_shader)); } TEST_F(CompileKindsTest, Fragment) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); const std::string kFragShader = "#version 140\nvoid main(){ gl_FragColor = vec4(0);}"; EXPECT_TRUE(CompilationSuccess(kFragShader, shaderc_glsl_fragment_shader)); } TEST_F(CompileKindsTest, Compute) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); const std::string kCompShader = R"(#version 310 es void main() {} )"; EXPECT_TRUE(CompilationSuccess(kCompShader, shaderc_glsl_compute_shader)); } TEST_F(CompileKindsTest, Geometry) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); const std::string kGeoShader = R"(#version 310 es #extension GL_OES_geometry_shader : enable layout(points) in; layout(points, max_vertices=1) out; void main() { gl_Position = vec4(1.0); EmitVertex(); EndPrimitive(); } )"; EXPECT_TRUE(CompilationSuccess(kGeoShader, shaderc_glsl_geometry_shader)); } TEST_F(CompileKindsTest, TessControl) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); const std::string kTessControlShader = R"(#version 310 es #extension GL_OES_tessellation_shader : enable layout(vertices=1) out; void main() {} )"; EXPECT_TRUE( CompilationSuccess(kTessControlShader, shaderc_glsl_tess_control_shader)); } TEST_F(CompileKindsTest, TessEvaluation) { ASSERT_NE(nullptr, compiler_.get_compiler_handle()); const std::string kTessEvaluationShader = R"(#version 310 es #extension GL_OES_tessellation_shader : enable layout(triangles, equal_spacing, ccw) in; void main() { gl_Position = vec4(gl_TessCoord, 1.0); } )"; EXPECT_TRUE(CompilationSuccess(kTessEvaluationShader, shaderc_glsl_tess_evaluation_shader)); } // A test case for ParseVersionProfileTest needs: 1) the input string, 2) // expected parsing results, including 'succeed' flag, version value, and // profile enum. struct ParseVersionProfileTestCase { ParseVersionProfileTestCase( const std::string& input_string, bool expected_succeed, int expected_version = 0, shaderc_profile expected_profile = shaderc_profile_none) : input_string_(input_string), expected_succeed_(expected_succeed), expected_version_(expected_version), expected_profile_(expected_profile) {} std::string input_string_; bool expected_succeed_; int expected_version_; shaderc_profile expected_profile_; }; // Test for a helper function to parse version and profile from string. using ParseVersionProfileTest = testing::TestWithParam; TEST_P(ParseVersionProfileTest, FromNullTerminatedString) { const ParseVersionProfileTestCase& test_case = GetParam(); int version; shaderc_profile profile; bool succeed = shaderc_parse_version_profile(test_case.input_string_.c_str(), &version, &profile); EXPECT_EQ(test_case.expected_succeed_, succeed); // check the return version and profile only when the parsing succeeds. if (succeed) { EXPECT_EQ(test_case.expected_version_, version); EXPECT_EQ(test_case.expected_profile_, profile); } } INSTANTIATE_TEST_SUITE_P( HelperMethods, ParseVersionProfileTest, testing::ValuesIn(std::vector{ // Valid version profiles ParseVersionProfileTestCase("450core", true, 450, shaderc_profile_core), ParseVersionProfileTestCase("450compatibility", true, 450, shaderc_profile_compatibility), ParseVersionProfileTestCase("310es", true, 310, shaderc_profile_es), ParseVersionProfileTestCase("100", true, 100, shaderc_profile_none), // Invalid version profiles, the expected_version and expected_profile // doesn't matter as they won't be checked if the tests pass correctly. ParseVersionProfileTestCase("totally_wrong", false), ParseVersionProfileTestCase("111core", false), ParseVersionProfileTestCase("450wrongprofile", false), ParseVersionProfileTestCase("", false), })); TEST_F(CompileStringTest, NullSourceNameFailsCompilingToBinary) { EXPECT_THAT(CompilationErrors(kEmpty310ESShader, shaderc_glsl_vertex_shader, nullptr, OutputType::SpirvBinary, nullptr), HasSubstr("Input file name string was null.")); } TEST_F(CompileStringTest, NullSourceNameFailsCompilingToAssemblyText) { EXPECT_THAT( CompilationErrors(kEmpty310ESShader, shaderc_glsl_vertex_shader, nullptr, OutputType::SpirvAssemblyText, nullptr), HasSubstr("Input file name string was null.")); } TEST_F(CompileStringTest, NullSourceNameFailsCompilingToPreprocessedText) { EXPECT_THAT(CompilationErrors(kEmpty310ESShader, shaderc_glsl_vertex_shader, nullptr, OutputType::PreprocessedText, nullptr), HasSubstr("Input file name string was null.")); } const char kGlslVertexShader[] = "#version 140\nvoid main(){ gl_Position = vec4(0);}"; const char kHlslVertexShader[] = "float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION\n" "{ return float4(1.0, 2.0, 3.0, 4.0); }"; TEST_F(CompileStringTest, LangGlslOnGlslVertexSucceeds) { shaderc_compile_options_set_source_language(options_.get(), shaderc_source_language_glsl); EXPECT_TRUE(CompilationSuccess(kGlslVertexShader, shaderc_glsl_vertex_shader, options_.get())); } TEST_F(CompileStringTest, LangGlslOnHlslVertexFails) { shaderc_compile_options_set_source_language(options_.get(), shaderc_source_language_glsl); EXPECT_FALSE(CompilationSuccess(kHlslVertexShader, shaderc_glsl_vertex_shader, options_.get())); } TEST_F(CompileStringTest, LangHlslOnGlslVertexFails) { shaderc_compile_options_set_source_language(options_.get(), shaderc_source_language_hlsl); EXPECT_FALSE(CompilationSuccess(kGlslVertexShader, shaderc_glsl_vertex_shader, options_.get())); } TEST_F(CompileStringTest, LangHlslOnHlslVertexSucceeds) { shaderc_compile_options_set_source_language(options_.get(), shaderc_source_language_hlsl); EXPECT_TRUE(CompilationSuccess(kHlslVertexShader, shaderc_glsl_vertex_shader, options_.get())); } TEST(EntryPointTest, LangGlslOnHlslVertexSucceedsButAssumesEntryPointNameIsMain) { Compiler compiler; Options options; auto compilation = Compilation(compiler.get_compiler_handle(), kGlslVertexShader, shaderc_glsl_vertex_shader, "shader", "blah blah blah", options.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(shaderc_result_get_bytes(compilation.result()), HasSubstr("OpEntryPoint Vertex %main \"main\"")) << std::string(shaderc_result_get_bytes(compilation.result())); } TEST(EntryPointTest, LangHlslOnHlslVertexSucceedsWithGivenEntryPointName) { Compiler compiler; Options options; shaderc_compile_options_set_source_language(options.get(), shaderc_source_language_hlsl); auto compilation = Compilation(compiler.get_compiler_handle(), kHlslVertexShader, shaderc_glsl_vertex_shader, "shader", "EntryPoint", options.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(shaderc_result_get_bytes(compilation.result()), HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\"")) << std::string(shaderc_result_get_bytes(compilation.result())); } // Returns a fragment shader accessing a texture with the given // offset. std::string ShaderWithTexOffset(int offset) { std::ostringstream oss; oss << "#version 450\n" "layout (binding=0) uniform sampler1D tex;\n" "void main() { vec4 x = textureOffset(tex, 1.0, " << offset << "); }\n"; return oss.str(); } // Ensure compilation is sensitive to limit setting. Sample just // two particular limits. TEST_F(CompileStringTest, LimitsTexelOffsetDefault) { EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-9).c_str(), shaderc_glsl_fragment_shader, options_.get())); EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(), shaderc_glsl_fragment_shader, options_.get())); EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(), shaderc_glsl_fragment_shader, options_.get())); EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(8).c_str(), shaderc_glsl_fragment_shader, options_.get())); } TEST_F(CompileStringTest, LimitsTexelOffsetLowerMinimum) { shaderc_compile_options_set_limit( options_.get(), shaderc_limit_min_program_texel_offset, -99); EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-100).c_str(), shaderc_glsl_fragment_shader, options_.get())); EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-99).c_str(), shaderc_glsl_fragment_shader, options_.get())); } TEST_F(CompileStringTest, LimitsTexelOffsetHigherMaximum) { shaderc_compile_options_set_limit(options_.get(), shaderc_limit_max_program_texel_offset, 10); EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(10).c_str(), shaderc_glsl_fragment_shader, options_.get())); EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(11).c_str(), shaderc_glsl_fragment_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, UniformsWithoutBindingsFailCompilation) { const std::string errors = CompilationErrors(kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options_.get()); EXPECT_THAT(errors, HasSubstr("sampler/texture/image requires layout(binding=X)")); } TEST_F(CompileStringWithOptionsTest, UniformsWithoutBindingsOptionSetAutoBindingsAssignsBindings) { shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); const std::string disassembly_text = CompilationOutput( kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4")); } TEST_F(CompileStringWithOptionsTest, AutoBindUniformsOptionsSurvivesCloning) { shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); compile_options_ptr cloned_options( shaderc_compile_options_clone(options_.get())); const std::string disassembly_text = CompilationOutput( kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, cloned_options.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4")); } TEST_F(CompileStringWithOptionsTest, SetBindingBaseForTextureAdjustsTextureBindingsOnly) { shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); shaderc_compile_options_set_binding_base(options_.get(), shaderc_uniform_kind_texture, 44); const std::string disassembly_text = CompilationOutput( kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 44")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3")); } TEST_F(CompileStringWithOptionsTest, SetBindingBaseForSamplerAdjustsSamplerBindingsOnly) { shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); shaderc_compile_options_set_binding_base(options_.get(), shaderc_uniform_kind_sampler, 44); const std::string disassembly_text = CompilationOutput( kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 44")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3")); } TEST_F(CompileStringWithOptionsTest, SetBindingBaseForImageAdjustsImageBindingsOnly) { shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); shaderc_compile_options_set_binding_base(options_.get(), shaderc_uniform_kind_image, 44); const std::string disassembly_text = CompilationOutput( kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 44")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 45")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 2")); } TEST_F(CompileStringWithOptionsTest, SetBindingBaseForBufferAdjustsBufferBindingsOnly) { shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); shaderc_compile_options_set_binding_base(options_.get(), shaderc_uniform_kind_buffer, 44); const std::string disassembly_text = CompilationOutput( kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 44")); } TEST_F(CompileStringWithOptionsTest, SetBindingBaseSurvivesCloning) { shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); shaderc_compile_options_set_binding_base(options_.get(), shaderc_uniform_kind_texture, 40); shaderc_compile_options_set_binding_base(options_.get(), shaderc_uniform_kind_sampler, 50); shaderc_compile_options_set_binding_base(options_.get(), shaderc_uniform_kind_image, 60); shaderc_compile_options_set_binding_base(options_.get(), shaderc_uniform_kind_buffer, 70); compile_options_ptr cloned_options( shaderc_compile_options_clone(options_.get())); const std::string disassembly_text = CompilationOutput( kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, cloned_options.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 40")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 50")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 60")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 61")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 70")); } TEST(Compiler, IncludeWithoutOptionsReturnsValidError) { auto compiler = shaderc_compiler_initialize(); const char source[] = "#version 450\n#include \"no where\""; auto result = shaderc_compile_into_spv(compiler, source, strlen(source), shaderc_glsl_vertex_shader, "file", "main", nullptr); EXPECT_EQ(shaderc_compilation_status_compilation_error, shaderc_result_get_compilation_status(result)); EXPECT_THAT(shaderc_result_get_error_message(result), HasSubstr("error: '#include' : #error unexpected include " "directive for header name: no where")); shaderc_result_release(result); shaderc_compiler_release(compiler); } TEST_F( CompileStringWithOptionsTest, SetBindingBaseForTextureForVertexAdjustsTextureBindingsOnlyCompilingAsVertex) { shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); shaderc_compile_options_set_binding_base_for_stage( options_.get(), shaderc_vertex_shader, shaderc_uniform_kind_texture, 100); const std::string disassembly_text = CompilationOutput( kShaderWithUniformsWithoutBindings, shaderc_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 100")) << disassembly_text; EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3")); } TEST_F(CompileStringWithOptionsTest, SetBindingBaseForTextureForVertexIgnoredWhenCompilingAsFragment) { shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); // This is ignored since we're compiling as a different stage. shaderc_compile_options_set_binding_base_for_stage( options_.get(), shaderc_vertex_shader, shaderc_uniform_kind_texture, 100); const std::string disassembly_text = CompilationOutput( kShaderWithUniformsWithoutBindings, shaderc_fragment_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3")); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4")); } TEST_F(CompileStringWithOptionsTest, GlslDefaultPackingUsed) { const std::string disassembly_text = CompilationOutput(kGlslShaderWeirdPacking, shaderc_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16")); } TEST_F(CompileStringWithOptionsTest, HlslOffsetsOptionDisableRespected) { shaderc_compile_options_set_hlsl_offsets(options_.get(), false); const std::string disassembly_text = CompilationOutput(kGlslShaderWeirdPacking, shaderc_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16")); } TEST_F(CompileStringWithOptionsTest, HlslOffsetsOptionEnableRespected) { shaderc_compile_options_set_hlsl_offsets(options_.get(), true); const std::string disassembly_text = CompilationOutput(kGlslShaderWeirdPacking, shaderc_vertex_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 4")); } TEST_F(CompileStringWithOptionsTest, HlslFunctionality1OffByDefault) { shaderc_compile_options_set_source_language(options_.get(), shaderc_source_language_hlsl); // The counter should automatically get a binding. shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); const std::string disassembly_text = CompilationOutput(kHlslShaderWithCounterBuffer, shaderc_fragment_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, Not(HasSubstr("OpDecorateString"))) << disassembly_text; } TEST_F(CompileStringWithOptionsTest, HlslFunctionality1Respected) { shaderc_compile_options_set_source_language(options_.get(), shaderc_source_language_hlsl); shaderc_compile_options_set_hlsl_functionality1(options_.get(), true); // The counter should automatically get a binding. shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); const std::string disassembly_text = CompilationOutput(kHlslShaderWithCounterBuffer, shaderc_fragment_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateString")); } TEST_F(CompileStringWithOptionsTest, HlslFunctionality1SurvivesCloning) { shaderc_compile_options_set_source_language(options_.get(), shaderc_source_language_hlsl); shaderc_compile_options_set_hlsl_functionality1(options_.get(), true); // The counter should automatically get a binding. shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); compile_options_ptr cloned_options( shaderc_compile_options_clone(options_.get())); const std::string disassembly_text = CompilationOutput(kHlslShaderWithCounterBuffer, shaderc_fragment_shader, cloned_options.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateString")); } TEST_F(CompileStringWithOptionsTest, HlslFlexibleMemoryLayoutAllowed) { shaderc_compile_options_set_source_language(options_.get(), shaderc_source_language_hlsl); shaderc_compile_options_set_optimization_level( options_.get(), shaderc_optimization_level_performance); // There is no way to set the counter's binding, so set it automatically. // See https://github.com/KhronosGroup/glslang/issues/1616 shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); EXPECT_TRUE(CompilesToValidSpv(compiler_, kHlslMemLayoutResourceSelect, shaderc_fragment_shader, options_.get())); } TEST_F(CompileStringWithOptionsTest, ClampMapsToFClampByDefault) { const std::string disassembly_text = CompilationOutput(kGlslShaderWithClamp, shaderc_fragment_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 FClamp")); } TEST_F(CompileStringWithOptionsTest, ClampMapsToNClampWithNanClamp) { shaderc_compile_options_set_nan_clamp(options_.get(), true); const std::string disassembly_text = CompilationOutput(kGlslShaderWithClamp, shaderc_fragment_shader, options_.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 NClamp")); } TEST_F(CompileStringWithOptionsTest, NanClampSurvivesCloning) { shaderc_compile_options_set_nan_clamp(options_.get(), true); compile_options_ptr cloned_options( shaderc_compile_options_clone(options_.get())); const std::string disassembly_text = CompilationOutput(kGlslShaderWithClamp, shaderc_fragment_shader, cloned_options.get(), OutputType::SpirvAssemblyText); EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 NClamp")); } } // anonymous namespace shaderc-2025.2/libshaderc_util/000077500000000000000000000000001500222170200163415ustar00rootroot00000000000000shaderc-2025.2/libshaderc_util/Android.mk000066400000000000000000000022051500222170200202510ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:=shaderc_util LOCAL_CXXFLAGS:=-std=c++17 -fno-exceptions -fno-rtti -DENABLE_HLSL=1 LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/include LOCAL_SRC_FILES:=src/args.cc \ src/compiler.cc \ src/file_finder.cc \ src/io_shaderc.cc \ src/message.cc \ src/resources.cc \ src/shader_stage.cc \ src/spirv_tools_wrapper.cc \ src/version_profile.cc LOCAL_STATIC_LIBRARIES:=SPIRV SPIRV-Tools-opt glslang LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include include $(BUILD_STATIC_LIBRARY) shaderc-2025.2/libshaderc_util/CMakeLists.txt000066400000000000000000000052171500222170200211060ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. project(libshaderc_util) add_library(shaderc_util STATIC include/libshaderc_util/counting_includer.h include/libshaderc_util/file_finder.h include/libshaderc_util/format.h include/libshaderc_util/io_shaderc.h include/libshaderc_util/mutex.h include/libshaderc_util/message.h include/libshaderc_util/resources.h include/libshaderc_util/spirv_tools_wrapper.h include/libshaderc_util/string_piece.h include/libshaderc_util/universal_unistd.h include/libshaderc_util/version_profile.h src/args.cc src/compiler.cc src/file_finder.cc src/io_shaderc.cc src/message.cc src/resources.cc src/shader_stage.cc src/spirv_tools_wrapper.cc src/version_profile.cc ) shaderc_default_compile_options(shaderc_util) target_include_directories(shaderc_util PUBLIC include PRIVATE ${glslang_SOURCE_DIR}) # We use parts of Glslang's HLSL compilation interface, which # now requires this preprocessor definition. add_definitions(-DENABLE_HLSL) find_package(Threads) target_link_libraries(shaderc_util PRIVATE glslang SPIRV SPIRV-Tools-opt ${CMAKE_THREAD_LIBS_INIT}) shaderc_add_tests( TEST_PREFIX shaderc_util LINK_LIBS shaderc_util TEST_NAMES counting_includer string_piece format file_finder io_shaderc message mutex version_profile) if(${SHADERC_ENABLE_TESTS}) target_include_directories(shaderc_util_counting_includer_test PRIVATE ${glslang_SOURCE_DIR}) target_include_directories(shaderc_util_version_profile_test PRIVATE ${glslang_SOURCE_DIR}) endif() shaderc_add_tests( TEST_PREFIX shaderc_util LINK_LIBS shaderc_util INCLUDE_DIRS ${glslang_SOURCE_DIR} ${spirv-tools_SOURCE_DIR}/include TEST_NAMES compiler) # This target copies content of testdata into the build directory. add_custom_target(testdata COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/testdata/copy-to-build.cmake COMMENT "Copy testdata into build directory") if(${SHADERC_ENABLE_TESTS}) add_dependencies(shaderc_util_file_finder_test testdata) add_dependencies(shaderc_util_io_shaderc_test testdata) endif() shaderc-2025.2/libshaderc_util/include/000077500000000000000000000000001500222170200177645ustar00rootroot00000000000000shaderc-2025.2/libshaderc_util/include/libshaderc_util/000077500000000000000000000000001500222170200231215ustar00rootroot00000000000000shaderc-2025.2/libshaderc_util/include/libshaderc_util/args.h000066400000000000000000000031651500222170200242330ustar00rootroot00000000000000// Copyright 2019 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_INC_ARGS_H #define LIBSHADERC_UTIL_INC_ARGS_H #include #include #include "libshaderc_util/string_piece.h" namespace shaderc_util { // Gets the option argument for the option at *index in argv in a way consistent // with clang/gcc. On success, returns true and writes the parsed argument into // *option_argument. Returns false if any errors occur. After calling this // function, *index will be the index of the last command line argument // consumed. bool GetOptionArgument(int argc, char** argv, int* index, const std::string& option, string_piece* option_argument); // Parses the given string as a number of the specified type. Returns true // if parsing succeeded, and stores the parsed value via |value|. // (I've worked out the general case for this in // SPIRV-Tools source/util/parse_number.h. -- dneto) bool ParseUint32(const std::string& str, uint32_t* value); } // namespace shaderc_util #endif // LIBSHADERC_UTIL_INC_ARGS_H shaderc-2025.2/libshaderc_util/include/libshaderc_util/compiler.h000066400000000000000000000617351500222170200251200ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_INC_COMPILER_H #define LIBSHADERC_UTIL_INC_COMPILER_H #include #include #include #include #include #include #include #include #include "counting_includer.h" #include "file_finder.h" #include "glslang/Public/ShaderLang.h" #include "mutex.h" #include "resources.h" #include "string_piece.h" // Fix a typo in glslang/Public/ShaderLang.h #define EShTargetClientVersion EshTargetClientVersion namespace shaderc_util { // To break recursive including. This header is already included in // spirv_tools_wrapper.h, so cannot include spirv_tools_wrapper.h here. enum class PassId; // Initializes glslang on creation, and destroys it on completion. // Used to tie gslang process operations to object lifetimes. // Additionally initialization/finalization of glslang is not thread safe, so // synchronizes these operations. class GlslangInitializer { public: GlslangInitializer(); ~GlslangInitializer(); private: static unsigned int initialize_count_; // Using a bare pointer here to avoid any global class construction at the // beginning of the execution. static std::mutex* glslang_mutex_; }; // Maps macro names to their definitions. Stores string_pieces, so the // underlying strings must outlive it. using MacroDictionary = std::unordered_map; // Holds all of the state required to compile source GLSL into SPIR-V. class Compiler { public: // Source language enum class SourceLanguage { GLSL, // The default HLSL, }; // Target environment. enum class TargetEnv { Vulkan, // Default to Vulkan 1.0 OpenGL, // Default to OpenGL 4.5 OpenGLCompat, // Support removed. Generates error if used. }; // Target environment versions. These numbers match those used by Glslang. enum class TargetEnvVersion : uint32_t { Default = 0, // Default for the corresponding target environment // For Vulkan, use numbering scheme from vulkan.h Vulkan_1_0 = ((1 << 22)), // Vulkan 1.0 Vulkan_1_1 = ((1 << 22) | (1 << 12)), // Vulkan 1.1 Vulkan_1_2 = ((1 << 22) | (2 << 12)), // Vulkan 1.2 Vulkan_1_3 = ((1 << 22) | (3 << 12)), // Vulkan 1.3 Vulkan_1_4 = ((1 << 22) | (4 << 12)), // Vulkan 1.4 // For OpenGL, use the numbering from #version in shaders. OpenGL_4_5 = 450, }; // SPIR-V version. enum class SpirvVersion : uint32_t { v1_0 = 0x010000u, v1_1 = 0x010100u, v1_2 = 0x010200u, v1_3 = 0x010300u, v1_4 = 0x010400u, v1_5 = 0x010500u, v1_6 = 0x010600u, }; enum class OutputType { SpirvBinary, // A binary module, as defined by the SPIR-V specification. SpirvAssemblyText, // Assembly syntax defined by the SPIRV-Tools project. PreprocessedText, // Preprocessed source code. }; // Supported optimization levels. enum class OptimizationLevel { Zero, // No optimization. Size, // Optimization towards reducing code size. Performance, // Optimization towards better performance. }; // Resource limits. These map to the "max*" fields in // glslang::TBuiltInResource. enum class Limit { #define RESOURCE(NAME, FIELD, CNAME) NAME, #include "resources.inc" #undef RESOURCE }; // Types of uniform variables. enum class UniformKind { // Image, and image buffer. Image = 0, // Pure sampler. Sampler = 1, // Sampled texture in GLSL. // Shader Resource View, for HLSL. (Read-only image or storage buffer.) Texture = 2, // Uniform Buffer Object, or UBO, in GLSL. // Also a Cbuffer in HLSL. Buffer = 3, // Shader Storage Buffer Object, or SSBO StorageBuffer = 4, // Uniform Access View, in HLSL. (Writable storage image or storage // buffer.) UnorderedAccessView = 5, }; enum { kNumUniformKinds = int(UniformKind::UnorderedAccessView) + 1 }; // Shader pipeline stage. // TODO(dneto): Replaces interface uses of EShLanguage with this enum. enum class Stage { Vertex, TessEval, TessControl, Geometry, Fragment, Compute, RayGenNV, IntersectNV, AnyHitNV, ClosestHitNV, MissNV, CallableNV, TaskNV, MeshNV, StageEnd, }; enum { kNumStages = int(Stage::StageEnd) }; // Returns a std::array of all the Stage values. const std::array& stages() const { static std::array values{{ Stage::Vertex, Stage::TessEval, Stage::TessControl, Stage::Geometry, Stage::Fragment, Stage::Compute, Stage::RayGenNV, Stage::IntersectNV, Stage::AnyHitNV, Stage::ClosestHitNV, Stage::MissNV, Stage::CallableNV, Stage::TaskNV, Stage::MeshNV, }}; return values; } // Creates an default compiler instance targeting at Vulkan environment. Uses // version 110 and no profile specification as the default for GLSL. Compiler() // The default version for glsl is 110, or 100 if you are using an es // profile. But we want to default to a non-es profile. : default_version_(110), default_profile_(ENoProfile), force_version_profile_(false), warnings_as_errors_(false), suppress_warnings_(false), generate_debug_info_(false), enabled_opt_passes_(), target_env_(TargetEnv::Vulkan), target_env_version_(TargetEnvVersion::Default), target_spirv_version_(SpirvVersion::v1_0), target_spirv_version_is_forced_(false), source_language_(SourceLanguage::GLSL), limits_(kDefaultTBuiltInResource), auto_bind_uniforms_(false), auto_combined_image_sampler_(false), auto_binding_base_(), auto_map_locations_(false), preserve_bindings_(false), hlsl_iomap_(false), hlsl_offsets_(false), hlsl_legalization_enabled_(true), hlsl_functionality1_enabled_(false), hlsl_16bit_types_enabled_(false), invert_y_enabled_(false), nan_clamp_(false), hlsl_explicit_bindings_() {} // Requests that the compiler place debug information into the object code, // such as identifier names and line numbers. void SetGenerateDebugInfo(); // Sets the optimization level to the given level. Only the last one takes // effect if multiple calls of this method exist. void SetOptimizationLevel(OptimizationLevel level); // Enables or disables HLSL legalization passes. void EnableHlslLegalization(bool hlsl_legalization_enabled); // Enables or disables extension SPV_GOOGLE_hlsl_functionality1 void EnableHlslFunctionality1(bool enable); // Enables or disables HLSL 16-bit types. void EnableHlsl16BitTypes(bool enable); // Enables or disables relaxed Vulkan rules. // // This allows most OpenGL shaders to compile under Vulkan semantics. void SetVulkanRulesRelaxed(bool enable); // Enables or disables invert position.Y output in vertex shader. void EnableInvertY(bool enable); // Sets whether the compiler generates code for max and min builtins which, // if given a NaN operand, will return the other operand. Also, the clamp // builtin will favour the non-NaN operands, as if clamp were implemented // as a composition of max and min. void SetNanClamp(bool enable); // When a warning is encountered it treat it as an error. void SetWarningsAsErrors(); // Any warning message generated is suppressed before it is output. void SetSuppressWarnings(); // Adds an implicit macro definition obeyed by subsequent CompileShader() // calls. The macro and definition should be passed in with their char* // pointer and their lengths. They can be modified or deleted after this // function has returned. void AddMacroDefinition(const char* macro, size_t macro_length, const char* definition, size_t definition_length); // Sets the target environment, including version. The version value should // be 0 or one of the values from TargetEnvVersion. The default value maps // to Vulkan 1.0 if the target environment is Vulkan, and it maps to OpenGL // 4.5 if the target environment is OpenGL. void SetTargetEnv(TargetEnv env, TargetEnvVersion version = TargetEnvVersion::Default); // Sets the target version of SPIR-V. The module will use this version // of SPIR-V. Defaults to the highest version of SPIR-V required to be // supported by the target environment. E.g. default to SPIR-V 1.0 for // Vulkan 1.0, and SPIR-V 1.3 for Vulkan 1.1. void SetTargetSpirv(SpirvVersion version); // Sets the souce language. void SetSourceLanguage(SourceLanguage lang); // Forces (without any verification) the default version and profile for // subsequent CompileShader() calls. void SetForcedVersionProfile(int version, EProfile profile); // Sets a resource limit. void SetLimit(Limit limit, int value); // Returns the current limit. int GetLimit(Limit limit) const; // Set whether the compiler automatically assigns bindings to // uniform variables that don't have explicit bindings. void SetAutoBindUniforms(bool auto_bind) { auto_bind_uniforms_ = auto_bind; } // Sets whether the compiler should automatically remove sampler variables // and convert image variables to combined image-sampler variables. void SetAutoCombinedImageSampler(bool auto_combine) { auto_combined_image_sampler_ = auto_combine; } // Sets the lowest binding number used when automatically assigning bindings // for uniform resources of the given type, for all shader stages. The // default base is zero. void SetAutoBindingBase(UniformKind kind, uint32_t base) { for (auto stage : stages()) { SetAutoBindingBaseForStage(stage, kind, base); } } // Sets the lowest binding number used when automatically assigning bindings // for uniform resources of the given type for a specific shader stage. The // default base is zero. void SetAutoBindingBaseForStage(Stage stage, UniformKind kind, uint32_t base) { auto_binding_base_[static_cast(stage)][static_cast(kind)] = base; } // Sets whether the compiler should preserve all bindings, even when those // bindings are not used. void SetPreserveBindings(bool preserve_bindings) { preserve_bindings_ = preserve_bindings; } // Sets whether the compiler automatically assigns locations to // uniform variables that don't have explicit locations. void SetAutoMapLocations(bool auto_map) { auto_map_locations_ = auto_map; } // Use HLSL IO mapping rules for bindings. Default is false. void SetHlslIoMapping(bool hlsl_iomap) { hlsl_iomap_ = hlsl_iomap; } // Use HLSL rules for offsets in "transparent" memory. These allow for // tighter packing of some combinations of types than standard GLSL packings. void SetHlslOffsets(bool hlsl_offsets) { hlsl_offsets_ = hlsl_offsets; } // Sets an explicit set and binding for the given HLSL register. void SetHlslRegisterSetAndBinding(const std::string& reg, const std::string& set, const std::string& binding) { for (auto stage : stages()) { SetHlslRegisterSetAndBindingForStage(stage, reg, set, binding); } } // Sets an explicit set and binding for the given HLSL register in the given // shader stage. For example, // SetHlslRegisterSetAndBinding(Stage::Fragment, "t1", "4", "5") // means register "t1" in a fragment shader should map to binding 5 in set 4. // (Glslang wants this data as strings, not ints or enums.) The string data // is copied. void SetHlslRegisterSetAndBindingForStage(Stage stage, const std::string& reg, const std::string& set, const std::string& binding) { hlsl_explicit_bindings_[static_cast(stage)].push_back(reg); hlsl_explicit_bindings_[static_cast(stage)].push_back(set); hlsl_explicit_bindings_[static_cast(stage)].push_back(binding); } // Compiles the shader source in the input_source_string parameter. // // If the forced_shader stage parameter is not EShLangCount then // the shader is assumed to be of the given stage. // // For HLSL compilation, entry_point_name is the null-terminated string for // the entry point. For GLSL compilation, entry_point_name is ignored, and // compilation assumes the entry point is named "main". // // The stage_callback function will be called if a shader_stage has // not been forced and the stage can not be determined // from the shader text. Any #include directives are parsed with the given // includer. // // The initializer parameter must be a valid GlslangInitializer object. // Acquire will be called on the initializer and the result will be // destroyed before the function ends. // // The output_type parameter determines what kind of output should be // produced. // // Any error messages are written as if the file name were error_tag. // Any errors are written to the error_stream parameter. // total_warnings and total_errors are incremented once for every // warning or error encountered respectively. // // Returns a tuple consisting of three fields. 1) a boolean which is true when // the compilation succeeded, and false otherwise; 2) a vector of 32-bit words // which contains the compilation output data, either compiled SPIR-V binary // code, or the text string generated in preprocessing-only or disassembly // mode; 3) the size of the output data in bytes. When the output is SPIR-V // binary code, the size is the number of bytes of valid data in the vector. // If the output is a text string, the size equals the length of that string. std::tuple, size_t> Compile( const string_piece& input_source_string, EShLanguage forced_shader_stage, const std::string& error_tag, const char* entry_point_name, const std::function& stage_callback, CountingIncluder& includer, OutputType output_type, std::ostream* error_stream, size_t* total_warnings, size_t* total_errors) const; static EShMessages GetDefaultRules() { return static_cast(EShMsgSpvRules | EShMsgVulkanRules | EShMsgCascadingErrors); } protected: // Preprocesses a shader whose filename is filename and content is // shader_source. If preprocessing is successful, returns true, the // preprocessed shader, and any warning message as a tuple. Otherwise, // returns false, an empty string, and error messages as a tuple. // // The error_tag parameter is the name to use for outputting errors. // The shader_source parameter is the input shader's source text. // The shader_preamble parameter is a context-specific preamble internally // prepended to shader_text without affecting the validity of its #version // position. // // Any #include directives are processed with the given includer. // // If force_version_profile_ is set, the shader's version/profile is forced // to be default_version_/default_profile_ regardless of the #version // directive in the source code. std::tuple PreprocessShader( const std::string& error_tag, const string_piece& shader_source, const string_piece& shader_preamble, CountingIncluder& includer) const; // Cleans up the preamble in a given preprocessed shader. // // The error_tag parameter is the name to be given for the main file. // The pound_extension parameter is the #extension directive we prepended to // the original shader source code via preamble. // The num_include_directives parameter is the number of #include directives // appearing in the original shader source code. // The is_for_next_line means whether the #line sets the line number for the // next line. // // If no #include directive is used in the shader source code, we can safely // delete the #extension directive we injected via preamble. Otherwise, we // need to adjust it if there exists a #version directive in the original // shader source code. std::string CleanupPreamble(const string_piece& preprocessed_shader, const string_piece& error_tag, const string_piece& pound_extension, int num_include_directives, bool is_for_next_line) const; // Determines version and profile from command line, or the source code. // Returns the decoded version and profile pair on success. Otherwise, // returns (0, ENoProfile). std::pair DeduceVersionProfile( const std::string& preprocessed_shader) const; // Determines the shader stage from pragmas embedded in the source text if // possible. In the returned pair, the glslang EShLanguage is the shader // stage deduced. If no #pragma directives for shader stage exist, it's // EShLangCount. If errors occur, the second element in the pair is the // error message. Otherwise, it's an empty string. std::pair GetShaderStageFromSourceCode( string_piece filename, const std::string& preprocessed_shader) const; // Determines version and profile from command line, or the source code. // Returns the decoded version and profile pair on success. Otherwise, // returns (0, ENoProfile). std::pair DeduceVersionProfile( const std::string& preprocessed_shader); // Gets version and profile specification from the given preprocessedshader. // Returns the decoded version and profile pair on success. Otherwise, // returns (0, ENoProfile). std::pair GetVersionProfileFromSourceCode( const std::string& preprocessed_shader) const; // Version to use when force_version_profile_ is true. int default_version_; // Profile to use when force_version_profile_ is true. EProfile default_profile_; // When true, use the default version and profile from eponymous data members. bool force_version_profile_; // Macro definitions that must be available to reference in the shader source. MacroDictionary predefined_macros_; // When true, treat warnings as errors. bool warnings_as_errors_; // Supress warnings when true. bool suppress_warnings_; // When true, compilation will generate debug info with the binary SPIR-V // output. bool generate_debug_info_; // Optimization passes to be applied. std::vector enabled_opt_passes_; // The target environment to compile with. This controls the glslang // EshMessages bitmask, which determines which dialect of GLSL and which // SPIR-V codegen semantics are used. This impacts the warning & error // messages as well as the set of available builtins, as per the // implementation of glslang. TargetEnv target_env_; // The version number of the target environment. The numbering scheme is // particular to each target environment. If this is 0, then use a default // for that particular target environment. See libshaders/shaderc/shaderc.h // for those defaults. TargetEnvVersion target_env_version_; // The SPIR-V version to be used for the generated module. Defaults to 1.0. SpirvVersion target_spirv_version_; // True if the user explicitly set the target SPIR-V version. bool target_spirv_version_is_forced_; // The source language. Defaults to GLSL. SourceLanguage source_language_; // The resource limits to be used. TBuiltInResource limits_; // True if the compiler should automatically bind uniforms that don't // have explicit bindings. bool auto_bind_uniforms_; // True if the compiler should automatically remove sampler variables // and convert image variables to combined image-sampler variables. bool auto_combined_image_sampler_; // The base binding number per uniform type, per stage, used when // automatically binding uniforms that don't hzve explicit bindings in the // shader source. The default is zero. uint32_t auto_binding_base_[kNumStages][kNumUniformKinds]; // True if the compiler should automatically map uniforms that don't // have explicit locations. bool auto_map_locations_; // True if the compiler should preserve all bindings, even when unused. bool preserve_bindings_; // True if the compiler should use HLSL IO mapping rules when compiling HLSL. bool hlsl_iomap_; // True if the compiler should determine block member offsets using HLSL // packing rules instead of standard GLSL rules. bool hlsl_offsets_; // True if the compiler should perform legalization optimization passes if // source language is HLSL. bool hlsl_legalization_enabled_; // True if the compiler should support extension // SPV_GOOGLE_hlsl_functionality1. bool hlsl_functionality1_enabled_; // True if the compiler should support 16-bit HLSL types. bool hlsl_16bit_types_enabled_; // True if the compiler should relax Vulkan rules to allow OGL shaders to // compile. bool vulkan_rules_relaxed_ = false; // True if the compiler should invert position.Y output in vertex shader. bool invert_y_enabled_; // True if the compiler generates code for max and min builtins which, // if given a NaN operand, will return the other operand. Also, the clamp // builtin will favour the non-NaN operands, as if clamp were implemented // as a composition of max and min. bool nan_clamp_; // A sequence of triples, each triple representing a specific HLSL register // name, and the set and binding numbers it should be mapped to, but in // the form of strings. This is how Glslang wants to consume the data. std::vector hlsl_explicit_bindings_[kNumStages]; }; // Converts a string to a vector of uint32_t by copying the content of a given // string to the vector and returns it. Appends '\0' at the end if extra bytes // are required to complete the last element. std::vector ConvertStringToVector(const std::string& str); // Converts a valid Glslang shader stage value to a Compiler::Stage value. inline Compiler::Stage ConvertToStage(EShLanguage stage) { switch (stage) { case EShLangVertex: return Compiler::Stage::Vertex; case EShLangTessControl: return Compiler::Stage::TessEval; case EShLangTessEvaluation: return Compiler::Stage::TessControl; case EShLangGeometry: return Compiler::Stage::Geometry; case EShLangFragment: return Compiler::Stage::Fragment; case EShLangCompute: return Compiler::Stage::Compute; case EShLangRayGenNV: return Compiler::Stage::RayGenNV; case EShLangIntersectNV: return Compiler::Stage::IntersectNV; case EShLangAnyHitNV: return Compiler::Stage::AnyHitNV; case EShLangClosestHitNV: return Compiler::Stage::ClosestHitNV; case EShLangMissNV: return Compiler::Stage::MissNV; case EShLangCallableNV: return Compiler::Stage::CallableNV; case EShLangTaskNV: return Compiler::Stage::TaskNV; case EShLangMeshNV: return Compiler::Stage::MeshNV; default: break; } assert(false && "Invalid case"); return Compiler::Stage::Compute; } // A GlslangClientInfo captures target client version and desired SPIR-V // version. struct GlslangClientInfo { GlslangClientInfo() {} GlslangClientInfo(const std::string& e, glslang::EShClient c, glslang::EShTargetClientVersion cv, glslang::EShTargetLanguage l, glslang::EShTargetLanguageVersion lv) : error(e), client(c), client_version(cv), target_language(l), target_language_version(lv) {} std::string error; // Empty if ok, otherwise contains the error message. glslang::EShClient client = glslang::EShClientNone; glslang::EShTargetClientVersion client_version; glslang::EShTargetLanguage target_language = glslang::EShTargetSpv; glslang::EShTargetLanguageVersion target_language_version = glslang::EShTargetSpv_1_0; }; // Returns the mappings to Glslang client, client version, and SPIR-V version. // Also indicates whether the input values were valid. GlslangClientInfo GetGlslangClientInfo( const std::string& error_tag, // Indicates source location, for errors. shaderc_util::Compiler::TargetEnv env, shaderc_util::Compiler::TargetEnvVersion env_version, shaderc_util::Compiler::SpirvVersion spv_version, bool spv_version_is_forced); } // namespace shaderc_util #endif // LIBSHADERC_UTIL_INC_COMPILER_H shaderc-2025.2/libshaderc_util/include/libshaderc_util/counting_includer.h000066400000000000000000000072301500222170200270070ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_COUNTING_INCLUDER_H #define LIBSHADERC_UTIL_COUNTING_INCLUDER_H #include #include "glslang/Public/ShaderLang.h" #include "libshaderc_util/mutex.h" namespace shaderc_util { // An Includer that counts how many #include directives it saw. // Inclusions are internally serialized, but releasing a previous result // can occur concurrently. class CountingIncluder : public glslang::TShader::Includer { public: // Done as .store(0) instead of in the initializer list for the following // reasons: // Clang > 3.6 will complain about it if it is written as ({0}). // VS2013 fails if it is written as {0}. // G++-4.8 does not correctly support std::atomic_init. CountingIncluder() { num_include_directives_.store(0); } enum class IncludeType { System, // Only do < > include search Local, // Only do " " include search }; // Resolves an include request for a source by name, type, and name of the // requesting source. For the semantics of the result, see the base class. // Also increments num_include_directives and returns the results of // include_delegate(filename). Subclasses should override include_delegate() // instead of this method. Inclusions are serialized. glslang::TShader::Includer::IncludeResult* includeSystem( const char* requested_source, const char* requesting_source, size_t include_depth) final { ++num_include_directives_; include_mutex_.lock(); auto result = include_delegate(requested_source, requesting_source, IncludeType::System, include_depth); include_mutex_.unlock(); return result; } // Like includeSystem, but for "local" include search. glslang::TShader::Includer::IncludeResult* includeLocal( const char* requested_source, const char* requesting_source, size_t include_depth) final { ++num_include_directives_; include_mutex_.lock(); auto result = include_delegate(requested_source, requesting_source, IncludeType::Local, include_depth); include_mutex_.unlock(); return result; } // Releases the given IncludeResult. void releaseInclude(glslang::TShader::Includer::IncludeResult* result) final { release_delegate(result); } int num_include_directives() const { return num_include_directives_.load(); } private: // Invoked by this class to provide results to // glslang::TShader::Includer::include. virtual glslang::TShader::Includer::IncludeResult* include_delegate( const char* requested_source, const char* requesting_source, IncludeType type, size_t include_depth) = 0; // Release the given IncludeResult. virtual void release_delegate( glslang::TShader::Includer::IncludeResult* result) = 0; // The number of #include directive encountered. std::atomic_int num_include_directives_; // A mutex to protect against concurrent inclusions. We can't trust // our delegates to be safe for concurrent inclusions. shaderc_util::mutex include_mutex_; }; } #endif // LIBSHADERC_UTIL_COUNTING_INCLUDER_H shaderc-2025.2/libshaderc_util/include/libshaderc_util/exceptions.h000066400000000000000000000017401500222170200254550ustar00rootroot00000000000000// Copyright 2018 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_EXCEPTIONS_H_ #define LIBSHADERC_UTIL_EXCEPTIONS_H_ #if (defined(_MSC_VER) && !defined(_CPPUNWIND)) || !defined(__EXCEPTIONS) #define TRY_IF_EXCEPTIONS_ENABLED #define CATCH_IF_EXCEPTIONS_ENABLED(X) if (0) #else #define TRY_IF_EXCEPTIONS_ENABLED try #define CATCH_IF_EXCEPTIONS_ENABLED(X) catch (X) #endif #endif // LIBSHADERC_UTIL_EXCEPTIONS_H_ shaderc-2025.2/libshaderc_util/include/libshaderc_util/file_finder.h000066400000000000000000000045721500222170200255500ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_SRC_FILE_FINDER_H_ #define LIBSHADERC_UTIL_SRC_FILE_FINDER_H_ #include #include namespace shaderc_util { // Finds files within a search path. class FileFinder { public: // Searches for a read-openable file based on filename, which must be // non-empty. The search is attempted on filename prefixed by each element of // search_path() in turn. The first hit is returned, or an empty string if // there are no hits. Search attempts treat their argument the way // std::fopen() treats its filename argument, ignoring whether the path is // absolute or relative. // // If a search_path() element is non-empty and not ending in a slash, then a // slash is inserted between it and filename before its search attempt. An // empty string in search_path() means that the filename is tried as-is. std::string FindReadableFilepath(const std::string& filename) const; // Searches for a read-openable file based on filename, which must be // non-empty. The search is first attempted as a path relative to // the requesting_file parameter. If no file is found relative to the // requesting_file then this acts as FindReadableFilepath does. If // requesting_file does not contain a '/' or a '\' character then it is // assumed to be a filename and the request will be relative to the // current directory. std::string FindRelativeReadableFilepath(const std::string& requesting_file, const std::string& filename) const; // Search path for Find(). Users may add/remove elements as desired. std::vector& search_path() { return search_path_; } private: std::vector search_path_; }; } // namespace shaderc_util #endif // LIBSHADERC_UTIL_SRC_FILE_FINDER_H_ shaderc-2025.2/libshaderc_util/include/libshaderc_util/format.h000066400000000000000000000022761500222170200245710ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_FORMAT_H_ #define LIBSHADERC_UTIL_FORMAT_H_ #include namespace shaderc_util { // Returns a string containing for every // key-value entry in map. template std::string format(const Map& map, const std::string& prefix, const std::string& infix, const std::string& postfix) { std::stringstream s; for (const auto& pair : map) { s << prefix << pair.first << infix << pair.second << postfix; } return s.str(); } } // namespace shaderc_util #endif // LIBSHADERC_UTIL_FORMAT_H_ shaderc-2025.2/libshaderc_util/include/libshaderc_util/io_shaderc.h000066400000000000000000000057041500222170200254000ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_IO_H_ #define LIBSHADERC_UTIL_IO_H_ #include #include #include "string_piece.h" namespace shaderc_util { // Returns true if the given path is an absolute path. bool IsAbsolutePath(const std::string& path); // A helper function to return the base file name from either absolute path or // relative path representation of a file. It keeps the component from the last // '/' or '\' to the end of the given string. If the component is '..' or '.', // returns an empty string. If '/' or '\' is the last char of the given string, // also returns an empty string. // e.g.: dir_a/dir_b/file_c.vert => file_c.vert // dir_a/dir_b/.. => // dir_a/dir_b/. => // dir_a/dirb/c/ => // Note that this method doesn't check whether the given path is a valid one or // not. std::string GetBaseFileName(const std::string& file_path); // Reads all of the characters in a given file into input_data. Outputs an // error message to std::cerr if the file could not be read and returns false if // there was an error. If the input_file is "-", then input is read from // std::cin. bool ReadFile(const std::string& input_file_name, std::vector* input_data); // Returns and initializes the file_stream parameter if the output_filename // refers to a file, or returns &std::cout if the output_filename is "-". // Returns nullptr and emits an error message to err if the file could // not be opened for writing. If the output refers to a file, and the open // failed for writing, file_stream is left with its fail_bit set. std::ostream* GetOutputStream(const string_piece& output_filename, std::ofstream* file_stream, std::ostream* err); // Writes output_data to a file, overwriting if it exists. If output_file_name // is "-", writes to std::cout. bool WriteFile(std::ostream* output_stream, const string_piece& output_data); // Flush the standard output stream and set it to binary mode. Subsequent // output will not translate newlines to carriage-return newline pairs. void FlushAndSetBinaryModeOnStdout(); // Flush the standard output stream and set it to text mode. Subsequent // output will translate newlines to carriage-return newline pairs. void FlushAndSetTextModeOnStdout(); } // namespace shaderc_util #endif // LIBSHADERC_UTIL_IO_H_ shaderc-2025.2/libshaderc_util/include/libshaderc_util/message.h000066400000000000000000000067411500222170200247260ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_SRC_MESSAGE_H_ #define LIBSHADERC_UTIL_SRC_MESSAGE_H_ #include "libshaderc_util/string_piece.h" namespace shaderc_util { // TODO(antiagainst): document the differences of the following message types. enum class MessageType { Warning, Error, ErrorSummary, WarningSummary, GlobalWarning, GlobalError, Unknown, Ignored }; // Given a glslang warning/error message, processes it in the following way and // returns its message type. // // * Places the source name into the source_name parameter, if found. // Otherwise, clears the source_name parameter. // * Places the line number into the line_number parameter, if found. // Otherwise, clears the line_number parameter. // * Places the rest of the message (the text past warning/error prefix, source // name, and line number) into the rest parameter. // // If warnings_as_errors is set to true, then all warnings will be treated as // errors. // If suppress_warnings is set to true, then no warnings will be emitted. This // takes precedence over warnings_as_errors. // // Examples: // "ERROR: 0:2: Message" // source_name="0", line_number="2", rest="Message" // "Warning, Message" // source_name="", line_number="", rest="Message" // "ERROR: 2 errors found." // source_name="2", line_number="", rest="errors found". // // Note that filenames can contain colons: // "ERROR: foo:bar.comp.hlsl:2: 'a' : unknown variable" MessageType ParseGlslangOutput(const shaderc_util::string_piece& message, bool warnings_as_errors, bool suppress_warnings, shaderc_util::string_piece* source_name, shaderc_util::string_piece* line_number, shaderc_util::string_piece* rest); // Filters error_messages received from glslang, and outputs, to error_stream, // any that are not ignored in a clang like format. If the warnings_as_errors // boolean is set, then all warnings will be treated as errors. If the // suppress_warnings boolean is set then any warning messages are ignored. This // takes precedence over warnings_as_errors. Increments total_warnings and // total_errors based on the message types. // Returns true if no new errors were found when parsing the messages. // "" will substitute "-1" appearing at the string name/number // segment. bool PrintFilteredErrors(const shaderc_util::string_piece& file_name, std::ostream* error_stream, bool warnings_as_errors, bool suppress_warnings, const char* error_list, size_t* total_warnings, size_t* total_errors); // Outputs, to error_stream, the number of warnings and errors if there are // any. void OutputMessages(std::ostream* error_stream, size_t total_warnings, size_t total_errors); } // namespace glslc #endif // LIBSHADERC_UTIL_SRC_MESSAGE_H_ shaderc-2025.2/libshaderc_util/include/libshaderc_util/mutex.h000066400000000000000000000063671500222170200244500ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_INC_MUTEX_H #define LIBSHADERC_UTIL_INC_MUTEX_H // shaderc_util::mutex will be defined and specialized // depending on the platform that is being compiled. // It is more or less conformant to the C++11 specification of std::mutex. // However it does not implement try_lock. #ifdef _WIN32 // windows.h #defines min and max if we don't define this. // this means things like std::min and std::max break #ifndef NOMINMAX #define NOMINMAX #endif #include namespace shaderc_util { // As the name suggests, this mutex class is for running on windows. // It conforms to the c++11 mutex implementation, and should be a // drop in replacement. class windows_mutex { public: using native_handle_type = HANDLE; windows_mutex() { mutex_ = CreateMutex(nullptr, false, nullptr); } ~windows_mutex() { if (mutex_ != INVALID_HANDLE_VALUE) { CloseHandle(mutex_); } } windows_mutex(const windows_mutex&) = delete; windows_mutex& operator=(const windows_mutex&) = delete; // Locks this mutex, waiting until the mutex is unlocked if it is not already. // It is not valid to lock a mutex that has already been locked. void lock() { WaitForSingleObject(mutex_, INFINITE); } // Unlocks this mutex. It is invalid to unlock a mutex that this thread // has not already locked. void unlock() { ReleaseMutex(mutex_); } // Returns the native handle for this mutex. In this case a HANDLE object. native_handle_type native_handle() { return mutex_; } private: HANDLE mutex_; }; using mutex = windows_mutex; } #else #include #include namespace shaderc_util { // As the name suggests, this mutex class is for running with pthreads. // It conforms to the c++11 mutex implementation, and should be a // drop in replacement. class posix_mutex { public: using native_handle_type = pthread_mutex_t*; posix_mutex() { pthread_mutex_init(&mutex_, nullptr); } ~posix_mutex() { pthread_mutex_destroy(&mutex_); } posix_mutex(const posix_mutex&) = delete; posix_mutex& operator=(const posix_mutex&) = delete; // Locks this mutex, waiting until the mutex is unlocked if it is not already. // It is not valid to lock a mutex that has already been locked. void lock() { pthread_mutex_lock(&mutex_); } // Unlocks this mutex. It is invalid to unlock a mutex that this thread // has not already locked. void unlock() { pthread_mutex_unlock(&mutex_); } // Returns the native handle for this mutex. In this case a pthread_mutex_t*. native_handle_type native_handle() { return &mutex_; } private: pthread_mutex_t mutex_; }; using mutex = posix_mutex; } #endif #endif // LIBSHADERC_UTIL_INC_MUTEX_H shaderc-2025.2/libshaderc_util/include/libshaderc_util/resources.h000066400000000000000000000017451500222170200253130ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_RESOURCES_H_ #define LIBSHADERC_UTIL_RESOURCES_H_ // We want TBuiltInResource #include "glslang/Include/ResourceLimits.h" namespace shaderc_util { using TBuiltInResource = ::TBuiltInResource; // A set of suitable defaults. extern const TBuiltInResource kDefaultTBuiltInResource; } // namespace shaderc_util #endif // LIBSHADERC_UTIL_RESOURCES_H_ shaderc-2025.2/libshaderc_util/include/libshaderc_util/resources.inc000066400000000000000000000247431500222170200256400ustar00rootroot00000000000000// Copyright 2016 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // These are the resource limits in a glslang::TBuiltInResource. // The first field is the string name to be used in a configuration setting. // The second field is the fieldname in TBuiltInResource. // The third field is the enum name fragment for shaderc_limit. // // TODO(dneto): Consider using a single list of names, but use a Python script // to generate *this* file. The original data file would have the first field, // then generate the second field by lowering the case of the first letter, and // generate the third field by taking the second field, and converting a // lower-to-upper case transition into an underscore with lower-case. RESOURCE(MaxLights,maxLights,max_lights) RESOURCE(MaxClipPlanes,maxClipPlanes,max_clip_planes) RESOURCE(MaxTextureUnits,maxTextureUnits,max_texture_units) RESOURCE(MaxTextureCoords,maxTextureCoords,max_texture_coords) RESOURCE(MaxVertexAttribs,maxVertexAttribs,max_vertex_attribs) RESOURCE(MaxVertexUniformComponents,maxVertexUniformComponents,max_vertex_uniform_components) RESOURCE(MaxVaryingFloats,maxVaryingFloats,max_varying_floats) RESOURCE(MaxVertexTextureImageUnits,maxVertexTextureImageUnits,max_vertex_texture_image_units) RESOURCE(MaxCombinedTextureImageUnits,maxCombinedTextureImageUnits,max_combined_texture_image_units) RESOURCE(MaxTextureImageUnits,maxTextureImageUnits,max_texture_image_units) RESOURCE(MaxFragmentUniformComponents,maxFragmentUniformComponents,max_fragment_uniform_components) RESOURCE(MaxDrawBuffers,maxDrawBuffers,max_draw_buffers) RESOURCE(MaxVertexUniformVectors,maxVertexUniformVectors,max_vertex_uniform_vectors) RESOURCE(MaxVaryingVectors,maxVaryingVectors,max_varying_vectors) RESOURCE(MaxFragmentUniformVectors,maxFragmentUniformVectors,max_fragment_uniform_vectors) RESOURCE(MaxVertexOutputVectors,maxVertexOutputVectors,max_vertex_output_vectors) RESOURCE(MaxFragmentInputVectors,maxFragmentInputVectors,max_fragment_input_vectors) RESOURCE(MinProgramTexelOffset,minProgramTexelOffset,min_program_texel_offset) RESOURCE(MaxProgramTexelOffset,maxProgramTexelOffset,max_program_texel_offset) RESOURCE(MaxClipDistances,maxClipDistances,max_clip_distances) RESOURCE(MaxComputeWorkGroupCountX,maxComputeWorkGroupCountX,max_compute_work_group_count_x) RESOURCE(MaxComputeWorkGroupCountY,maxComputeWorkGroupCountY,max_compute_work_group_count_y) RESOURCE(MaxComputeWorkGroupCountZ,maxComputeWorkGroupCountZ,max_compute_work_group_count_z) RESOURCE(MaxComputeWorkGroupSizeX,maxComputeWorkGroupSizeX,max_compute_work_group_size_x) RESOURCE(MaxComputeWorkGroupSizeY,maxComputeWorkGroupSizeY,max_compute_work_group_size_y) RESOURCE(MaxComputeWorkGroupSizeZ,maxComputeWorkGroupSizeZ,max_compute_work_group_size_z) RESOURCE(MaxComputeUniformComponents,maxComputeUniformComponents,max_compute_uniform_components) RESOURCE(MaxComputeTextureImageUnits,maxComputeTextureImageUnits,max_compute_texture_image_units) RESOURCE(MaxComputeImageUniforms,maxComputeImageUniforms,max_compute_image_uniforms) RESOURCE(MaxComputeAtomicCounters,maxComputeAtomicCounters,max_compute_atomic_counters) RESOURCE(MaxComputeAtomicCounterBuffers,maxComputeAtomicCounterBuffers,max_compute_atomic_counter_buffers) RESOURCE(MaxVaryingComponents,maxVaryingComponents,max_varying_components) RESOURCE(MaxVertexOutputComponents,maxVertexOutputComponents,max_vertex_output_components) RESOURCE(MaxGeometryInputComponents,maxGeometryInputComponents,max_geometry_input_components) RESOURCE(MaxGeometryOutputComponents,maxGeometryOutputComponents,max_geometry_output_components) RESOURCE(MaxFragmentInputComponents,maxFragmentInputComponents,max_fragment_input_components) RESOURCE(MaxImageUnits,maxImageUnits,max_image_units) RESOURCE(MaxCombinedImageUnitsAndFragmentOutputs,maxCombinedImageUnitsAndFragmentOutputs,max_combined_image_units_and_fragment_outputs) RESOURCE(MaxCombinedShaderOutputResources,maxCombinedShaderOutputResources,max_combined_shader_output_resources) RESOURCE(MaxImageSamples,maxImageSamples,max_image_samples) RESOURCE(MaxVertexImageUniforms,maxVertexImageUniforms,max_vertex_image_uniforms) RESOURCE(MaxTessControlImageUniforms,maxTessControlImageUniforms,max_tess_control_image_uniforms) RESOURCE(MaxTessEvaluationImageUniforms,maxTessEvaluationImageUniforms,max_tess_evaluation_image_uniforms) RESOURCE(MaxGeometryImageUniforms,maxGeometryImageUniforms,max_geometry_image_uniforms) RESOURCE(MaxFragmentImageUniforms,maxFragmentImageUniforms,max_fragment_image_uniforms) RESOURCE(MaxCombinedImageUniforms,maxCombinedImageUniforms,max_combined_image_uniforms) RESOURCE(MaxGeometryTextureImageUnits,maxGeometryTextureImageUnits,max_geometry_texture_image_units) RESOURCE(MaxGeometryOutputVertices,maxGeometryOutputVertices,max_geometry_output_vertices) RESOURCE(MaxGeometryTotalOutputComponents,maxGeometryTotalOutputComponents,max_geometry_total_output_components) RESOURCE(MaxGeometryUniformComponents,maxGeometryUniformComponents,max_geometry_uniform_components) RESOURCE(MaxGeometryVaryingComponents,maxGeometryVaryingComponents,max_geometry_varying_components) RESOURCE(MaxTessControlInputComponents,maxTessControlInputComponents,max_tess_control_input_components) RESOURCE(MaxTessControlOutputComponents,maxTessControlOutputComponents,max_tess_control_output_components) RESOURCE(MaxTessControlTextureImageUnits,maxTessControlTextureImageUnits,max_tess_control_texture_image_units) RESOURCE(MaxTessControlUniformComponents,maxTessControlUniformComponents,max_tess_control_uniform_components) RESOURCE(MaxTessControlTotalOutputComponents,maxTessControlTotalOutputComponents,max_tess_control_total_output_components) RESOURCE(MaxTessEvaluationInputComponents,maxTessEvaluationInputComponents,max_tess_evaluation_input_components) RESOURCE(MaxTessEvaluationOutputComponents,maxTessEvaluationOutputComponents,max_tess_evaluation_output_components) RESOURCE(MaxTessEvaluationTextureImageUnits,maxTessEvaluationTextureImageUnits,max_tess_evaluation_texture_image_units) RESOURCE(MaxTessEvaluationUniformComponents,maxTessEvaluationUniformComponents,max_tess_evaluation_uniform_components) RESOURCE(MaxTessPatchComponents,maxTessPatchComponents,max_tess_patch_components) RESOURCE(MaxPatchVertices,maxPatchVertices,max_patch_vertices) RESOURCE(MaxTessGenLevel,maxTessGenLevel,max_tess_gen_level) RESOURCE(MaxViewports,maxViewports,max_viewports) RESOURCE(MaxVertexAtomicCounters,maxVertexAtomicCounters,max_vertex_atomic_counters) RESOURCE(MaxTessControlAtomicCounters,maxTessControlAtomicCounters,max_tess_control_atomic_counters) RESOURCE(MaxTessEvaluationAtomicCounters,maxTessEvaluationAtomicCounters,max_tess_evaluation_atomic_counters) RESOURCE(MaxGeometryAtomicCounters,maxGeometryAtomicCounters,max_geometry_atomic_counters) RESOURCE(MaxFragmentAtomicCounters,maxFragmentAtomicCounters,max_fragment_atomic_counters) RESOURCE(MaxCombinedAtomicCounters,maxCombinedAtomicCounters,max_combined_atomic_counters) RESOURCE(MaxAtomicCounterBindings,maxAtomicCounterBindings,max_atomic_counter_bindings) RESOURCE(MaxVertexAtomicCounterBuffers,maxVertexAtomicCounterBuffers,max_vertex_atomic_counter_buffers) RESOURCE(MaxTessControlAtomicCounterBuffers,maxTessControlAtomicCounterBuffers,max_tess_control_atomic_counter_buffers) RESOURCE(MaxTessEvaluationAtomicCounterBuffers,maxTessEvaluationAtomicCounterBuffers,max_tess_evaluation_atomic_counter_buffers) RESOURCE(MaxGeometryAtomicCounterBuffers,maxGeometryAtomicCounterBuffers,max_geometry_atomic_counter_buffers) RESOURCE(MaxFragmentAtomicCounterBuffers,maxFragmentAtomicCounterBuffers,max_fragment_atomic_counter_buffers) RESOURCE(MaxCombinedAtomicCounterBuffers,maxCombinedAtomicCounterBuffers,max_combined_atomic_counter_buffers) RESOURCE(MaxAtomicCounterBufferSize,maxAtomicCounterBufferSize,max_atomic_counter_buffer_size) RESOURCE(MaxTransformFeedbackBuffers,maxTransformFeedbackBuffers,max_transform_feedback_buffers) RESOURCE(MaxTransformFeedbackInterleavedComponents,maxTransformFeedbackInterleavedComponents,max_transform_feedback_interleaved_components) RESOURCE(MaxCullDistances,maxCullDistances,max_cull_distances) RESOURCE(MaxCombinedClipAndCullDistances,maxCombinedClipAndCullDistances,max_combined_clip_and_cull_distances) RESOURCE(MaxSamples,maxSamples,max_samples) RESOURCE(MaxMeshOutputVerticesNV, maxMeshOutputVerticesNV, max_mesh_output_vertices_nv) RESOURCE(MaxMeshOutputPrimitivesNV, maxMeshOutputPrimitivesNV, max_mesh_output_primitives_nv) RESOURCE(MaxMeshWorkGroupSizeX_NV, maxMeshWorkGroupSizeX_NV, max_mesh_work_group_size_x_nv) RESOURCE(MaxMeshWorkGroupSizeY_NV, maxMeshWorkGroupSizeY_NV, max_mesh_work_group_size_y_nv) RESOURCE(MaxMeshWorkGroupSizeZ_NV, maxMeshWorkGroupSizeZ_NV, max_mesh_work_group_size_z_nv) RESOURCE(MaxTaskWorkGroupSizeX_NV, maxTaskWorkGroupSizeX_NV, max_task_work_group_size_x_nv) RESOURCE(MaxTaskWorkGroupSizeY_NV, maxTaskWorkGroupSizeY_NV, max_task_work_group_size_y_nv) RESOURCE(MaxTaskWorkGroupSizeZ_NV, maxTaskWorkGroupSizeZ_NV, max_task_work_group_size_z_nv) RESOURCE(MaxMeshViewCountNV, maxMeshViewCountNV, max_mesh_view_count_nv) RESOURCE(MaxMeshOutputVerticesEXT, maxMeshOutputVerticesEXT, max_mesh_output_vertices_ext) RESOURCE(MaxMeshOutputPrimitivesEXT, maxMeshOutputPrimitivesEXT, max_mesh_output_primitives_ext) RESOURCE(MaxMeshWorkGroupSizeX_EXT, maxMeshWorkGroupSizeX_EXT, max_mesh_work_group_size_x_ext) RESOURCE(MaxMeshWorkGroupSizeY_EXT, maxMeshWorkGroupSizeY_EXT, max_mesh_work_group_size_y_ext) RESOURCE(MaxMeshWorkGroupSizeZ_EXT, maxMeshWorkGroupSizeZ_EXT, max_mesh_work_group_size_z_ext) RESOURCE(MaxTaskWorkGroupSizeX_EXT, maxTaskWorkGroupSizeX_EXT, max_task_work_group_size_x_ext) RESOURCE(MaxTaskWorkGroupSizeY_EXT, maxTaskWorkGroupSizeY_EXT, max_task_work_group_size_y_ext) RESOURCE(MaxTaskWorkGroupSizeZ_EXT, maxTaskWorkGroupSizeZ_EXT, max_task_work_group_size_z_ext) RESOURCE(MaxMeshViewCountEXT, maxMeshViewCountEXT, max_mesh_view_count_ext) RESOURCE(MaxDualSourceDrawBuffersEXT, maxDualSourceDrawBuffersEXT, max_dual_source_draw_buffers_ext) shaderc-2025.2/libshaderc_util/include/libshaderc_util/shader_stage.h000066400000000000000000000022451500222170200257260ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_SHADER_STAGE_H_ #define LIBSHADERC_UTIL_SHADER_STAGE_H_ #include #include #include #include #include "glslang/Public/ShaderLang.h" #include "libshaderc_util/string_piece.h" namespace shaderc_util { // Given a string representing a stage, returns the glslang EShLanguage for it. // If the stage string is not recognized, returns EShLangCount. EShLanguage MapStageNameToLanguage( const shaderc_util::string_piece& stage_name); } // namespace shaderc_util #endif // LIBSHADERC_UTIL_SHADER_STAGE_H_ shaderc-2025.2/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h000066400000000000000000000051631500222170200274220ustar00rootroot00000000000000// Copyright 2016 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_INC_SPIRV_TOOLS_WRAPPER_H #define LIBSHADERC_UTIL_INC_SPIRV_TOOLS_WRAPPER_H #include #include #include "spirv-tools/libspirv.hpp" #include "libshaderc_util/compiler.h" #include "libshaderc_util/string_piece.h" namespace shaderc_util { // Assembles the given assembly. On success, returns true, writes the assembled // binary to *binary, and clears *errors. Otherwise, writes the error message // into *errors. bool SpirvToolsAssemble(Compiler::TargetEnv env, Compiler::TargetEnvVersion version, const string_piece assembly, spv_binary* binary, std::string* errors); // Disassembles the given binary. Returns true and writes the disassembled text // to *text_or_error if successful. Otherwise, writes the error message to // *text_or_error. bool SpirvToolsDisassemble(Compiler::TargetEnv env, Compiler::TargetEnvVersion version, const std::vector& binary, std::string* text_or_error); // The ids of a list of supported optimization passes. enum class PassId { // SPIRV-Tools standard recipes kLegalizationPasses, kPerformancePasses, kSizePasses, // SPIRV-Tools specific passes kNullPass, kStripDebugInfo, kCompactIds, }; // Optimizes the given binary. Passes are registered in the exact order as shown // in enabled_passes, without de-duplication. Returns true and writes the // optimized binary back to *binary if successful. Otherwise, writes errors to // *errors and the content of binary may be in an invalid state. bool SpirvToolsOptimize(Compiler::TargetEnv env, Compiler::TargetEnvVersion version, const std::vector& enabled_passes, spvtools::OptimizerOptions& optimizer_options, std::vector* binary, std::string* errors); } // namespace shaderc_util #endif // LIBSHADERC_UTIL_INC_SPIRV_TOOLS_WRAPPER_H shaderc-2025.2/libshaderc_util/include/libshaderc_util/string_piece.h000066400000000000000000000270141500222170200257510ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_STRING_PIECE_H_ #define LIBSHADERC_UTIL_STRING_PIECE_H_ #include #include #include #include namespace shaderc_util { // Provides a read-only view into a string (cstring or std::string). // This must be created after the string in question, and cannot // outlive the memory of the string in question. // Any operations that may modify the location or size of the // original data render the associated string_piece invalid. class string_piece { public: typedef const char* iterator; static const size_t npos = -1; string_piece() {} string_piece(const char* begin, const char* end) : begin_(begin), end_(end) { assert((begin == nullptr) == (end == nullptr) && "either both begin and end must be nullptr or neither must be"); } string_piece(const char* string) : begin_(string), end_(string) { if (string) { end_ += strlen(string); } } string_piece(const std::string& str) { if (!str.empty()) { begin_ = &(str.front()); end_ = &(str.back()) + 1; } } string_piece(const string_piece& other) { begin_ = other.begin_; end_ = other.end_; } string_piece& operator=(const string_piece& other) = default; // Clears the string_piece removing any reference to the original string. void clear() { begin_ = nullptr; end_ = nullptr; } // Returns a pointer to the data contained in the underlying string. // If there is no underlying string, returns a nullptr. const char* data() const { return begin_; } // Returns an std::string copy of the internal data. std::string str() const { return std::string(begin_, end_); } // Returns a string_piece that points to a substring in the original string. string_piece substr(size_t pos, size_t len = npos) const { assert(len == npos || pos + len <= size()); return string_piece(begin_ + pos, len == npos ? end_ : begin_ + pos + len); } // Takes any function object predicate that takes a char and returns a // boolean. // Returns the index of the first element that does not return true for the // predicate. // Returns string_piece::npos if all elements match. template size_t find_first_not_matching(T callee) { for (auto it = begin_; it != end_; ++it) { if (!callee(*it)) { return it - begin_; } } return npos; } // Returns the index of the first character that does not match any character // in the input string_piece. // The search only includes characters at or after position pos. // Returns string_piece::npos if all match. size_t find_first_not_of(const string_piece& to_search, size_t pos = 0) const { if (pos >= size()) { return npos; } for (auto it = begin_ + pos; it != end_; ++it) { if (to_search.find_first_of(*it) == npos) { return it - begin_; } } return npos; } // Returns find_first_not_of(str, pos) where str is a string_piece // containing only to_search. size_t find_first_not_of(char to_search, size_t pos = 0) const { return find_first_not_of(string_piece(&to_search, &to_search + 1), pos); } // Returns the index of the first character that matches any character in the // input string_piece. // The search only includes characters at or after position pos. // Returns string_piece::npos if there is no match. size_t find_first_of(const string_piece& to_search, size_t pos = 0) const { if (pos >= size()) { return npos; } for (auto it = begin_ + pos; it != end_; ++it) { for (char c : to_search) { if (c == *it) { return it - begin_; } } } return npos; } // Returns find_first_of(str, pos) where str is a string_piece // containing only to_search. size_t find_first_of(char to_search, size_t pos = 0) const { return find_first_of(string_piece(&to_search, &to_search + 1), pos); } // Returns the index of the last character that matches any character in the // input string_piece. // The search only includes characters at or before position pos. // Returns string_piece::npos if there is no match. size_t find_last_of(const string_piece& to_search, size_t pos = npos) const { if (empty()) return npos; if (pos >= size()) { pos = size(); } auto it = begin_ + pos + 1; do { --it; if (to_search.find_first_of(*it) != npos) { return it - begin_; } } while (it != begin_); return npos; } // Returns find_last_of(str, pos) where str is a string_piece // containing only to_search. size_t find_last_of(char to_search, size_t pos = npos) const { return find_last_of(string_piece(&to_search, &to_search + 1), pos); } // Returns the index of the last character that does not match any character // in the input string_piece. // The search only includes characters at or before position pos. // Returns string_piece::npos if there is no match. size_t find_last_not_of(const string_piece& to_search, size_t pos = npos) const { if (empty()) return npos; if (pos >= size()) { pos = size(); } auto it = begin_ + pos + 1; do { --it; if (to_search.find_first_of(*it) == npos) { return it - begin_; } } while (it != begin_); return npos; } // Returns find_last_not_of(str, pos) where str is a string_piece // containing only to_search. size_t find_last_not_of(char to_search, size_t pos = 0) const { return find_last_not_of(string_piece(&to_search, &to_search + 1), pos); } // Continuously removes characters appearing in chars_to_strip from the left. string_piece lstrip(const string_piece& chars_to_strip) const { iterator begin = begin_; for (; begin < end_; ++begin) if (chars_to_strip.find_first_of(*begin) == npos) break; if (begin >= end_) return string_piece(); return string_piece(begin, end_); } // Continuously removes characters appearing in chars_to_strip from the right. string_piece rstrip(const string_piece& chars_to_strip) const { iterator end = end_; for (; begin_ < end; --end) if (chars_to_strip.find_first_of(*(end - 1)) == npos) break; if (begin_ >= end) return string_piece(); return string_piece(begin_, end); } // Continuously removes characters appearing in chars_to_strip from both // sides. string_piece strip(const string_piece& chars_to_strip) const { return lstrip(chars_to_strip).rstrip(chars_to_strip); } string_piece strip_whitespace() const { return strip(" \t\n\r\f\v"); } // Returns the character at index i in the string_piece. const char& operator[](size_t i) const { return *(begin_ + i); } // Standard comparison operator. bool operator==(const string_piece& other) const { // Either end_ and _begin_ are nullptr or neither of them are. assert(((end_ == nullptr) == (begin_ == nullptr))); assert(((other.end_ == nullptr) == (other.begin_ == nullptr))); if (size() != other.size()) { return false; } return (memcmp(begin_, other.begin_, end_ - begin_) == 0); } bool operator!=(const string_piece& other) const { return !operator==(other); } // Returns an iterator to the first element. iterator begin() const { return begin_; } // Returns an iterator to one past the last element. iterator end() const { return end_; } const char& front() const { assert(!empty()); return *begin_; } const char& back() const { assert(!empty()); return *(end_ - 1); } // Returns true is this string_piece starts with the same // characters as other. bool starts_with(const string_piece& other) const { const char* iter = begin_; const char* other_iter = other.begin(); while (iter != end_ && other_iter != other.end()) { if (*iter++ != *other_iter++) { return false; } } return other_iter == other.end(); } // Returns the index of the start of the first substring that matches // the input string_piece. // The search only includes substrings starting at or after position pos. // Returns npos if the string cannot be found. size_t find(const string_piece& substr, size_t pos = 0) const { if (empty()) return npos; if (pos >= size()) return npos; if (substr.empty()) return 0; for (auto it = begin_ + pos; end() - it >= static_cast(substr.size()); ++it) { if (string_piece(it, end()).starts_with(substr)) return it - begin_; } return npos; } // Returns the index of the start of the first character that matches // the input character. // The search only includes substrings starting at or after position pos. // Returns npos if the character cannot be found. size_t find(char character, size_t pos = 0) const { return find_first_of(character, pos); } // Returns true if the string_piece is empty. bool empty() const { return begin_ == end_; } // Returns the number of characters in the string_piece. size_t size() const { return end_ - begin_; } // Returns a vector of string_pieces representing delimiter delimited // fields found. If the keep_delimiter parameter is true, then each // delimiter character is kept with the string to its left. std::vector get_fields(char delimiter, bool keep_delimiter = false) const { std::vector fields; size_t first = 0; size_t field_break = find_first_of(delimiter); while (field_break != npos) { fields.push_back(substr(first, field_break - first + keep_delimiter)); first = field_break + 1; field_break = find_first_of(delimiter, first); } if (size() - first > 0) { fields.push_back(substr(first, size() - first)); } return fields; } friend std::ostream& operator<<(std::ostream& os, const string_piece& piece); private: // It is expected that begin_ and end_ will both be null or // they will both point to valid pieces of memory, but it is invalid // to have one of them being nullptr and the other not. string_piece::iterator begin_ = nullptr; string_piece::iterator end_ = nullptr; }; inline std::ostream& operator<<(std::ostream& os, const string_piece& piece) { // Either end_ and _begin_ are nullptr or neither of them are. assert(((piece.end_ == nullptr) == (piece.begin_ == nullptr))); if (piece.end_ != piece.begin_) { os.write(piece.begin_, piece.end_ - piece.begin_); } return os; } inline bool operator==(const char* first, const string_piece second) { return second == string_piece(first); } inline bool operator!=(const char* first, const string_piece second) { return !operator==(first, second); } } namespace std { template <> struct hash { size_t operator()(const shaderc_util::string_piece& piece) const { // djb2 algorithm. size_t hash = 5381; for (char c : piece) { hash = ((hash << 5) + hash) + c; } return hash; } }; } #endif // LIBSHADERC_UTIL_STRING_PIECE_H_ shaderc-2025.2/libshaderc_util/include/libshaderc_util/universal_unistd.h000066400000000000000000000020061500222170200266660ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_UNIVERSAL_UNISTD_H_ #define LIBSHADERC_UTIL_UNIVERSAL_UNISTD_H_ #ifndef _MSC_VER #include #else // Minimal set of needed to compile on windows. #include #define access _access // https://msdn.microsoft.com/en-us/library/1w06ktdy.aspx // Defines these constants. #define R_OK 4 #define W_OK 2 #endif //_MSC_VER #endif // LIBSHADERC_UTIL_UNIVERSAL_UNISTD_H_ shaderc-2025.2/libshaderc_util/include/libshaderc_util/version_profile.h000066400000000000000000000034401500222170200265000ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_INC_VERSION_PROFILE_H_ #define LIBSHADERC_UTIL_INC_VERSION_PROFILE_H_ #include #include "glslang/MachineIndependent/Versions.h" namespace shaderc_util { // Returns true if the given version is an accepted GLSL (ES) version. inline bool IsKnownVersion(int version) { switch (version) { case 100: case 110: case 120: case 130: case 140: case 150: case 300: case 310: case 320: case 330: case 400: case 410: case 420: case 430: case 440: case 450: case 460: return true; default: break; } return false; } // Given a string version_profile containing both version and profile, decodes // it and puts the decoded version in version, decoded profile in profile. // Returns true if decoding is successful and version and profile are accepted. // This does not validate the version number against the profile. For example, // "460es" doesn't make sense (yet), but is still accepted. bool ParseVersionProfile(const std::string& version_profile, int* version, EProfile* profile); } // namespace shaderc_util #endif // LIBSHADERC_UTIL_INC_VERSION_PROFILE_H_ shaderc-2025.2/libshaderc_util/src/000077500000000000000000000000001500222170200171305ustar00rootroot00000000000000shaderc-2025.2/libshaderc_util/src/args.cc000066400000000000000000000033541500222170200204000ustar00rootroot00000000000000// Copyright 2019 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/args.h" #include #include namespace shaderc_util { bool GetOptionArgument(int argc, char** argv, int* index, const std::string& option, string_piece* option_argument) { const string_piece arg = argv[*index]; assert(arg.starts_with(option)); if (arg.size() != option.size()) { *option_argument = arg.substr(option.size()); return true; } if (option.back() == '=') { *option_argument = ""; return true; } if (++(*index) >= argc) return false; *option_argument = argv[*index]; return true; } bool ParseUint32(const std::string& str, uint32_t* value) { std::istringstream iss(str); iss >> std::setbase(0); iss >> *value; // We should have read something. bool ok = !str.empty() && !iss.bad(); // It should have been all the text. ok = ok && iss.eof(); // It should have been in range. ok = ok && !iss.fail(); // Work around a bugs in various C++ standard libraries. // Count any negative number as an error, including "-0". ok = ok && (str[0] != '-'); return ok; } } // namespace shaderc_util shaderc-2025.2/libshaderc_util/src/compiler.cc000066400000000000000000001002731500222170200212540ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/compiler.h" #include #include #include #include #include #include "SPIRV/GlslangToSpv.h" #include "libshaderc_util/format.h" #include "libshaderc_util/io_shaderc.h" #include "libshaderc_util/message.h" #include "libshaderc_util/resources.h" #include "libshaderc_util/shader_stage.h" #include "libshaderc_util/spirv_tools_wrapper.h" #include "libshaderc_util/string_piece.h" #include "libshaderc_util/version_profile.h" #include "spirv-tools/libspirv.hpp" namespace { using shaderc_util::string_piece; // For use with glslang parsing calls. const bool kNotForwardCompatible = false; // Returns true if #line directive sets the line number for the next line in the // given version and profile. inline bool LineDirectiveIsForNextLine(int version, EProfile profile) { return profile == EEsProfile || version >= 330; } // Returns a #line directive whose arguments are line and filename. inline std::string GetLineDirective(int line, const string_piece& filename) { return "#line " + std::to_string(line) + " \"" + filename.str() + "\"\n"; } // Given a canonicalized #line directive (starting exactly with "#line", using // single spaces to separate different components, and having an optional // newline at the end), returns the line number and string name/number. If no // string name/number is provided, the second element in the returned pair is an // empty string_piece. Behavior is undefined if the directive parameter is not a // canonicalized #line directive. std::pair DecodeLineDirective(string_piece directive) { const string_piece kLineDirective = "#line "; assert(directive.starts_with(kLineDirective)); directive = directive.substr(kLineDirective.size()); const int line = std::atoi(directive.data()); const size_t space_loc = directive.find_first_of(' '); if (space_loc == string_piece::npos) return std::make_pair(line, ""); directive = directive.substr(space_loc); directive = directive.strip("\" \n"); return std::make_pair(line, directive); } // Returns the Glslang message rules for the given target environment, // source language, and whether we want HLSL offset rules. We assume // only valid combinations are used. EShMessages GetMessageRules(shaderc_util::Compiler::TargetEnv env, shaderc_util::Compiler::SourceLanguage lang, bool hlsl_offsets, bool hlsl_16bit_types, bool debug_info) { using shaderc_util::Compiler; EShMessages result = EShMsgCascadingErrors; if (lang == Compiler::SourceLanguage::HLSL) { result = static_cast(result | EShMsgReadHlsl); } switch (env) { case Compiler::TargetEnv::OpenGLCompat: // The compiler will have already errored out before now. // But we need to handle this enum. break; case Compiler::TargetEnv::OpenGL: result = static_cast(result | EShMsgSpvRules); break; case Compiler::TargetEnv::Vulkan: result = static_cast(result | EShMsgSpvRules | EShMsgVulkanRules); break; } if (hlsl_offsets) { result = static_cast(result | EShMsgHlslOffsets); } if (hlsl_16bit_types) { result = static_cast(result | EShMsgHlslEnable16BitTypes); } if (debug_info) { result = static_cast(result | EShMsgDebugInfo); } return result; } } // anonymous namespace namespace shaderc_util { unsigned int GlslangInitializer::initialize_count_ = 0; std::mutex* GlslangInitializer::glslang_mutex_ = nullptr; GlslangInitializer::GlslangInitializer() { static std::mutex first_call_mutex; // If this is the first call, glslang_mutex_ needs to be created, but in // thread safe manner. { const std::lock_guard first_call_lock(first_call_mutex); if (glslang_mutex_ == nullptr) { glslang_mutex_ = new std::mutex(); } } const std::lock_guard glslang_lock(*glslang_mutex_); if (initialize_count_ == 0) { glslang::InitializeProcess(); } initialize_count_++; } GlslangInitializer::~GlslangInitializer() { const std::lock_guard glslang_lock(*glslang_mutex_); initialize_count_--; if (initialize_count_ == 0) { glslang::FinalizeProcess(); // There is no delete for glslang_mutex_ here, because we cannot guarantee // there isn't a caller waiting for glslang_mutex_ in GlslangInitializer(). // // This means that this class does leak one std::mutex worth of memory after // the final instance is destroyed, but this allows us to defer allocating // and constructing until we are sure we need to. } } void Compiler::SetLimit(Compiler::Limit limit, int value) { switch (limit) { #define RESOURCE(NAME, FIELD, CNAME) \ case Limit::NAME: \ limits_.FIELD = value; \ break; #include "libshaderc_util/resources.inc" #undef RESOURCE } } int Compiler::GetLimit(Compiler::Limit limit) const { switch (limit) { #define RESOURCE(NAME, FIELD, CNAME) \ case Limit::NAME: \ return limits_.FIELD; #include "libshaderc_util/resources.inc" #undef RESOURCE } return 0; // Unreachable } std::tuple, size_t> Compiler::Compile( const string_piece& input_source_string, EShLanguage forced_shader_stage, const std::string& error_tag, const char* entry_point_name, const std::function& stage_callback, CountingIncluder& includer, OutputType output_type, std::ostream* error_stream, size_t* total_warnings, size_t* total_errors) const { // Compilation results to be returned: // Initialize the result tuple as a failed compilation. In error cases, we // should return result_tuple directly without setting its members. auto result_tuple = std::make_tuple(false, std::vector(), (size_t)0u); // Get the reference of the members of the result tuple. We should set their // values for succeeded compilation before returning the result tuple. bool& succeeded = std::get<0>(result_tuple); std::vector& compilation_output_data = std::get<1>(result_tuple); size_t& compilation_output_data_size_in_bytes = std::get<2>(result_tuple); // Check target environment. const auto target_client_info = GetGlslangClientInfo( error_tag, target_env_, target_env_version_, target_spirv_version_, target_spirv_version_is_forced_); if (!target_client_info.error.empty()) { *error_stream << target_client_info.error; *total_warnings = 0; *total_errors = 1; return result_tuple; } EShLanguage used_shader_stage = forced_shader_stage; const std::string macro_definitions = shaderc_util::format(predefined_macros_, "#define ", " ", "\n"); const std::string pound_extension = "#extension GL_GOOGLE_include_directive : enable\n"; const std::string preamble = macro_definitions + pound_extension; std::string preprocessed_shader; // If only preprocessing, we definitely need to preprocess. Otherwise, if // we don't know the stage until now, we need the preprocessed shader to // deduce the shader stage. if (output_type == OutputType::PreprocessedText || used_shader_stage == EShLangCount) { bool success; std::string glslang_errors; std::tie(success, preprocessed_shader, glslang_errors) = PreprocessShader(error_tag, input_source_string, preamble, includer); success &= PrintFilteredErrors(error_tag, error_stream, warnings_as_errors_, /* suppress_warnings = */ true, glslang_errors.c_str(), total_warnings, total_errors); if (!success) return result_tuple; // Because of the behavior change of the #line directive, the #line // directive introducing each file's content must use the syntax for the // specified version. So we need to probe this shader's version and // profile. int version; EProfile profile; std::tie(version, profile) = DeduceVersionProfile(preprocessed_shader); const bool is_for_next_line = LineDirectiveIsForNextLine(version, profile); preprocessed_shader = CleanupPreamble(preprocessed_shader, error_tag, pound_extension, includer.num_include_directives(), is_for_next_line); if (output_type == OutputType::PreprocessedText) { // Set the values of the result tuple. succeeded = true; compilation_output_data = ConvertStringToVector(preprocessed_shader); compilation_output_data_size_in_bytes = preprocessed_shader.size(); return result_tuple; } else if (used_shader_stage == EShLangCount) { std::string errors; std::tie(used_shader_stage, errors) = GetShaderStageFromSourceCode(error_tag, preprocessed_shader); if (!errors.empty()) { *error_stream << errors; return result_tuple; } if (used_shader_stage == EShLangCount) { if ((used_shader_stage = stage_callback(error_stream, error_tag)) == EShLangCount) { return result_tuple; } } } } // Parsing requires its own Glslang symbol tables. glslang::TShader shader(used_shader_stage); const char* shader_strings = input_source_string.data(); const int shader_lengths = static_cast(input_source_string.size()); const char* string_names = error_tag.c_str(); shader.setStringsWithLengthsAndNames(&shader_strings, &shader_lengths, &string_names, 1); shader.setPreamble(preamble.c_str()); shader.setEntryPoint(entry_point_name); shader.setAutoMapBindings(auto_bind_uniforms_); if (auto_combined_image_sampler_) { shader.setTextureSamplerTransformMode( EShTexSampTransUpgradeTextureRemoveSampler); } shader.setAutoMapLocations(auto_map_locations_); const auto& bases = auto_binding_base_[static_cast(used_shader_stage)]; shader.setShiftImageBinding(bases[static_cast(UniformKind::Image)]); shader.setShiftSamplerBinding(bases[static_cast(UniformKind::Sampler)]); shader.setShiftTextureBinding(bases[static_cast(UniformKind::Texture)]); shader.setShiftUboBinding(bases[static_cast(UniformKind::Buffer)]); shader.setShiftSsboBinding( bases[static_cast(UniformKind::StorageBuffer)]); shader.setShiftUavBinding( bases[static_cast(UniformKind::UnorderedAccessView)]); shader.setHlslIoMapping(hlsl_iomap_); shader.setResourceSetBinding( hlsl_explicit_bindings_[static_cast(used_shader_stage)]); shader.setEnvClient(target_client_info.client, target_client_info.client_version); shader.setEnvTarget(target_client_info.target_language, target_client_info.target_language_version); if (hlsl_functionality1_enabled_) { shader.setEnvTargetHlslFunctionality1(); } if (vulkan_rules_relaxed_) { glslang::EShSource language = glslang::EShSourceNone; switch (source_language_) { case SourceLanguage::GLSL: language = glslang::EShSourceGlsl; break; case SourceLanguage::HLSL: language = glslang::EShSourceHlsl; break; } // This option will only be used if the Vulkan client is used. // If new versions of GL_KHR_vulkan_glsl come out, it would make sense to // let callers specify which version to use. For now, just use 100. shader.setEnvInput(language, used_shader_stage, glslang::EShClientVulkan, 100); shader.setEnvInputVulkanRulesRelaxed(); } shader.setInvertY(invert_y_enabled_); shader.setNanMinMaxClamp(nan_clamp_); const EShMessages rules = GetMessageRules(target_env_, source_language_, hlsl_offsets_, hlsl_16bit_types_enabled_, generate_debug_info_); bool success = shader.parse(&limits_, default_version_, default_profile_, force_version_profile_, kNotForwardCompatible, rules, includer); success &= PrintFilteredErrors(error_tag, error_stream, warnings_as_errors_, suppress_warnings_, shader.getInfoLog(), total_warnings, total_errors); if (!success) return result_tuple; glslang::TProgram program; program.addShader(&shader); success = program.link(EShMsgDefault) && program.mapIO(); success &= PrintFilteredErrors(error_tag, error_stream, warnings_as_errors_, suppress_warnings_, program.getInfoLog(), total_warnings, total_errors); if (!success) return result_tuple; // 'spirv' is an alias for the compilation_output_data. This alias is added // to serve as an input for the call to DissassemblyBinary. std::vector& spirv = compilation_output_data; glslang::SpvOptions options; options.generateDebugInfo = generate_debug_info_; options.disableOptimizer = true; options.optimizeSize = false; // Note the call to GlslangToSpv also populates compilation_output_data. glslang::GlslangToSpv(*program.getIntermediate(used_shader_stage), spirv, &options); // Set the tool field (the top 16-bits) in the generator word to // 'Shaderc over Glslang'. const uint32_t shaderc_generator_word = 13; // From SPIR-V XML Registry const uint32_t generator_word_index = 2; // SPIR-V 2.3: Physical layout assert(spirv.size() > generator_word_index); spirv[generator_word_index] = (spirv[generator_word_index] & 0xffff) | (shaderc_generator_word << 16); std::vector opt_passes; if (hlsl_legalization_enabled_ && source_language_ == SourceLanguage::HLSL) { // If from HLSL, run this passes to "legalize" the SPIR-V for Vulkan // eg. forward and remove memory writes of opaque types. opt_passes.push_back(PassId::kLegalizationPasses); } opt_passes.insert(opt_passes.end(), enabled_opt_passes_.begin(), enabled_opt_passes_.end()); if (!opt_passes.empty()) { spvtools::OptimizerOptions opt_options; opt_options.set_preserve_bindings(preserve_bindings_); std::string opt_errors; if (!SpirvToolsOptimize(target_env_, target_env_version_, opt_passes, opt_options, &spirv, &opt_errors)) { *error_stream << "shaderc: internal error: compilation succeeded but " "failed to optimize: " << opt_errors << "\n"; return result_tuple; } } if (output_type == OutputType::SpirvAssemblyText) { std::string text_or_error; if (!SpirvToolsDisassemble(target_env_, target_env_version_, spirv, &text_or_error)) { *error_stream << "shaderc: internal error: compilation succeeded but " "failed to disassemble: " << text_or_error << "\n"; return result_tuple; } succeeded = true; compilation_output_data = ConvertStringToVector(text_or_error); compilation_output_data_size_in_bytes = text_or_error.size(); return result_tuple; } else { succeeded = true; // Note compilation_output_data is already populated in GlslangToSpv(). compilation_output_data_size_in_bytes = spirv.size() * sizeof(spirv[0]); return result_tuple; } } void Compiler::AddMacroDefinition(const char* macro, size_t macro_length, const char* definition, size_t definition_length) { predefined_macros_[std::string(macro, macro_length)] = definition ? std::string(definition, definition_length) : ""; } void Compiler::SetTargetEnv(Compiler::TargetEnv env, Compiler::TargetEnvVersion version) { target_env_ = env; target_env_version_ = version; } void Compiler::SetTargetSpirv(Compiler::SpirvVersion version) { target_spirv_version_ = version; target_spirv_version_is_forced_ = true; } void Compiler::SetSourceLanguage(Compiler::SourceLanguage lang) { source_language_ = lang; } void Compiler::SetForcedVersionProfile(int version, EProfile profile) { default_version_ = version; default_profile_ = profile; force_version_profile_ = true; } void Compiler::SetWarningsAsErrors() { warnings_as_errors_ = true; } void Compiler::SetGenerateDebugInfo() { generate_debug_info_ = true; for (size_t i = 0; i < enabled_opt_passes_.size(); ++i) { if (enabled_opt_passes_[i] == PassId::kStripDebugInfo) { enabled_opt_passes_[i] = PassId::kNullPass; } } } void Compiler::SetOptimizationLevel(Compiler::OptimizationLevel level) { // Clear previous settings first. enabled_opt_passes_.clear(); switch (level) { case OptimizationLevel::Size: if (!generate_debug_info_) { enabled_opt_passes_.push_back(PassId::kStripDebugInfo); } enabled_opt_passes_.push_back(PassId::kSizePasses); break; case OptimizationLevel::Performance: if (!generate_debug_info_) { enabled_opt_passes_.push_back(PassId::kStripDebugInfo); } enabled_opt_passes_.push_back(PassId::kPerformancePasses); break; default: break; } } void Compiler::EnableHlslLegalization(bool hlsl_legalization_enabled) { hlsl_legalization_enabled_ = hlsl_legalization_enabled; } void Compiler::EnableHlslFunctionality1(bool enable) { hlsl_functionality1_enabled_ = enable; } void Compiler::SetVulkanRulesRelaxed(bool enable) { vulkan_rules_relaxed_ = enable; } void Compiler::EnableHlsl16BitTypes(bool enable) { hlsl_16bit_types_enabled_ = enable; } void Compiler::EnableInvertY(bool enable) { invert_y_enabled_ = enable; } void Compiler::SetNanClamp(bool enable) { nan_clamp_ = enable; } void Compiler::SetSuppressWarnings() { suppress_warnings_ = true; } std::tuple Compiler::PreprocessShader( const std::string& error_tag, const string_piece& shader_source, const string_piece& shader_preamble, CountingIncluder& includer) const { // The stage does not matter for preprocessing. glslang::TShader shader(EShLangVertex); const char* shader_strings = shader_source.data(); const int shader_lengths = static_cast(shader_source.size()); const char* string_names = error_tag.c_str(); shader.setStringsWithLengthsAndNames(&shader_strings, &shader_lengths, &string_names, 1); shader.setPreamble(shader_preamble.data()); auto target_client_info = GetGlslangClientInfo( error_tag, target_env_, target_env_version_, target_spirv_version_, target_spirv_version_is_forced_); if (!target_client_info.error.empty()) { return std::make_tuple(false, "", target_client_info.error); } shader.setEnvClient(target_client_info.client, target_client_info.client_version); if (hlsl_functionality1_enabled_) { shader.setEnvTargetHlslFunctionality1(); } shader.setInvertY(invert_y_enabled_); shader.setNanMinMaxClamp(nan_clamp_); // The preprocessor might be sensitive to the target environment. // So combine the existing rules with the just-give-me-preprocessor-output // flag. const auto rules = static_cast( EShMsgOnlyPreprocessor | GetMessageRules(target_env_, source_language_, hlsl_offsets_, hlsl_16bit_types_enabled_, false)); std::string preprocessed_shader; const bool success = shader.preprocess( &limits_, default_version_, default_profile_, force_version_profile_, kNotForwardCompatible, rules, &preprocessed_shader, includer); if (success) { return std::make_tuple(true, preprocessed_shader, shader.getInfoLog()); } return std::make_tuple(false, "", shader.getInfoLog()); } std::string Compiler::CleanupPreamble(const string_piece& preprocessed_shader, const string_piece& error_tag, const string_piece& pound_extension, int num_include_directives, bool is_for_next_line) const { // Those #define directives in preamble will become empty lines after // preprocessing. We also injected an #extension directive to turn on #include // directive support. In the original preprocessing output from glslang, it // appears before the user source string. We need to do proper adjustment: // * Remove empty lines generated from #define directives in preamble. // * If there is no #include directive in the source code, we do not need to // output the injected #extension directive. Otherwise, // * If there exists a #version directive in the source code, it should be // placed at the first line. Its original line will be filled with an empty // line as placeholder to maintain the code structure. const std::vector lines = preprocessed_shader.get_fields('\n', /* keep_delimiter = */ true); std::ostringstream output_stream; size_t pound_extension_index = lines.size(); size_t pound_version_index = lines.size(); for (size_t i = 0; i < lines.size(); ++i) { if (lines[i] == pound_extension) { pound_extension_index = std::min(i, pound_extension_index); } else if (lines[i].starts_with("#version")) { // In a preprocessed shader, directives are in a canonical format, so we // can confidently compare to '#version' verbatim, without worrying about // whitespace. pound_version_index = i; if (num_include_directives > 0) output_stream << lines[i]; break; } } // We know that #extension directive exists and appears before #version // directive (if any). assert(pound_extension_index < lines.size()); for (size_t i = 0; i < pound_extension_index; ++i) { // All empty lines before the #line directive we injected are generated by // preprocessing preamble. Do not output them. if (lines[i].strip_whitespace().empty()) continue; output_stream << lines[i]; } if (num_include_directives > 0) { output_stream << pound_extension; // Also output a #line directive for the main file. output_stream << GetLineDirective(is_for_next_line, error_tag); } for (size_t i = pound_extension_index + 1; i < lines.size(); ++i) { if (i == pound_version_index) { if (num_include_directives > 0) { output_stream << "\n"; } else { output_stream << lines[i]; } } else { output_stream << lines[i]; } } return output_stream.str(); } std::pair Compiler::GetShaderStageFromSourceCode( string_piece filename, const std::string& preprocessed_shader) const { const string_piece kPragmaShaderStageDirective = "#pragma shader_stage"; const string_piece kLineDirective = "#line"; int version; EProfile profile; std::tie(version, profile) = DeduceVersionProfile(preprocessed_shader); const bool is_for_next_line = LineDirectiveIsForNextLine(version, profile); std::vector lines = string_piece(preprocessed_shader).get_fields('\n'); // The filename, logical line number (which starts from 1 and is sensitive to // #line directives), and stage value for #pragma shader_stage() directives. std::vector> stages; // The physical line numbers of the first #pragma shader_stage() line and // first non-preprocessing line in the preprocessed shader text. size_t first_pragma_physical_line = lines.size() + 1; size_t first_non_pp_line = lines.size() + 1; for (size_t i = 0, logical_line_no = 1; i < lines.size(); ++i) { const string_piece current_line = lines[i].strip_whitespace(); if (current_line.starts_with(kPragmaShaderStageDirective)) { const string_piece stage_value = current_line.substr(kPragmaShaderStageDirective.size()).strip("()"); stages.emplace_back(filename, logical_line_no, stage_value); first_pragma_physical_line = std::min(first_pragma_physical_line, i + 1); } else if (!current_line.empty() && !current_line.starts_with("#")) { first_non_pp_line = std::min(first_non_pp_line, i + 1); } // Update logical line number for the next line. if (current_line.starts_with(kLineDirective)) { string_piece name; std::tie(logical_line_no, name) = DecodeLineDirective(current_line); if (!name.empty()) filename = name; // Note that for core profile, the meaning of #line changed since version // 330. The line number given by #line used to mean the logical line // number of the #line line. Now it means the logical line number of the // next line after the #line line. if (!is_for_next_line) ++logical_line_no; } else { ++logical_line_no; } } if (stages.empty()) return std::make_pair(EShLangCount, ""); std::string error_message; const string_piece& first_pragma_filename = std::get<0>(stages[0]); const std::string first_pragma_line = std::to_string(std::get<1>(stages[0])); const string_piece& first_pragma_stage = std::get<2>(stages[0]); if (first_pragma_physical_line > first_non_pp_line) { error_message += first_pragma_filename.str() + ":" + first_pragma_line + ": error: '#pragma': the first 'shader_stage' #pragma " "must appear before any non-preprocessing code\n"; } EShLanguage stage = MapStageNameToLanguage(first_pragma_stage); if (stage == EShLangCount) { error_message += first_pragma_filename.str() + ":" + first_pragma_line + ": error: '#pragma': invalid stage for 'shader_stage' #pragma: '" + first_pragma_stage.str() + "'\n"; } for (size_t i = 1; i < stages.size(); ++i) { const string_piece& current_stage = std::get<2>(stages[i]); if (current_stage != first_pragma_stage) { const string_piece& current_filename = std::get<0>(stages[i]); const std::string current_line = std::to_string(std::get<1>(stages[i])); error_message += current_filename.str() + ":" + current_line + ": error: '#pragma': conflicting stages for " "'shader_stage' #pragma: '" + current_stage.str() + "' (was '" + first_pragma_stage.str() + "' at " + first_pragma_filename.str() + ":" + first_pragma_line + ")\n"; } } return std::make_pair(error_message.empty() ? stage : EShLangCount, error_message); } std::pair Compiler::DeduceVersionProfile( const std::string& preprocessed_shader) const { int version = default_version_; EProfile profile = default_profile_; if (!force_version_profile_) { std::tie(version, profile) = GetVersionProfileFromSourceCode(preprocessed_shader); if (version == 0 && profile == ENoProfile) { version = default_version_; profile = default_profile_; } } return std::make_pair(version, profile); } std::pair Compiler::GetVersionProfileFromSourceCode( const std::string& preprocessed_shader) const { string_piece pound_version = preprocessed_shader; const size_t pound_version_loc = pound_version.find("#version"); if (pound_version_loc == string_piece::npos) { return std::make_pair(0, ENoProfile); } pound_version = pound_version.substr(pound_version_loc + std::strlen("#version")); pound_version = pound_version.substr(0, pound_version.find_first_of("\n")); std::string version_profile; for (const auto character : pound_version) { if (character != ' ') version_profile += character; } int version; EProfile profile; if (!ParseVersionProfile(version_profile, &version, &profile)) { return std::make_pair(0, ENoProfile); } return std::make_pair(version, profile); } // Converts a string to a vector of uint32_t by copying the content of a given // string to a vector and returns it. Appends '\0' at the end if extra // bytes are required to complete the last element. std::vector ConvertStringToVector(const std::string& str) { size_t num_bytes_str = str.size() + 1u; size_t vector_length = (num_bytes_str + sizeof(uint32_t) - 1) / sizeof(uint32_t); std::vector result_vec(vector_length, 0); std::strncpy(reinterpret_cast(result_vec.data()), str.c_str(), str.size()); return result_vec; } GlslangClientInfo GetGlslangClientInfo( const std::string& error_tag, shaderc_util::Compiler::TargetEnv env, shaderc_util::Compiler::TargetEnvVersion env_version, shaderc_util::Compiler::SpirvVersion spv_version, bool spv_version_is_forced) { GlslangClientInfo result; std::ostringstream errs; using shaderc_util::Compiler; switch (env) { case Compiler::TargetEnv::Vulkan: result.client = glslang::EShClientVulkan; if (env_version == Compiler::TargetEnvVersion::Default || env_version == Compiler::TargetEnvVersion::Vulkan_1_0) { result.client_version = glslang::EShTargetVulkan_1_0; } else if (env_version == Compiler::TargetEnvVersion::Vulkan_1_1) { result.client_version = glslang::EShTargetVulkan_1_1; result.target_language_version = glslang::EShTargetSpv_1_3; } else if (env_version == Compiler::TargetEnvVersion::Vulkan_1_2) { result.client_version = glslang::EShTargetVulkan_1_2; result.target_language_version = glslang::EShTargetSpv_1_5; } else if (env_version == Compiler::TargetEnvVersion::Vulkan_1_3) { result.client_version = glslang::EShTargetVulkan_1_3; result.target_language_version = glslang::EShTargetSpv_1_6; } else if (env_version == Compiler::TargetEnvVersion::Vulkan_1_4) { result.client_version = glslang::EShTargetVulkan_1_4; result.target_language_version = glslang::EShTargetSpv_1_6; } else { errs << "error:" << error_tag << ": Invalid target client version " << static_cast(env_version) << " for Vulkan environment " << int(env); } break; case Compiler::TargetEnv::OpenGLCompat: errs << "error: OpenGL compatibility profile is not supported"; break; case Compiler::TargetEnv::OpenGL: result.client = glslang::EShClientOpenGL; if (env_version == Compiler::TargetEnvVersion::Default || env_version == Compiler::TargetEnvVersion::OpenGL_4_5) { result.client_version = glslang::EShTargetOpenGL_450; } else { errs << "error:" << error_tag << ": Invalid target client version " << static_cast(env_version) << " for OpenGL environment " << int(env); } break; default: errs << "error:" << error_tag << ": Invalid target client environment " << int(env); break; } if (spv_version_is_forced && errs.str().empty()) { switch (spv_version) { case Compiler::SpirvVersion::v1_0: result.target_language_version = glslang::EShTargetSpv_1_0; break; case Compiler::SpirvVersion::v1_1: result.target_language_version = glslang::EShTargetSpv_1_1; break; case Compiler::SpirvVersion::v1_2: result.target_language_version = glslang::EShTargetSpv_1_2; break; case Compiler::SpirvVersion::v1_3: result.target_language_version = glslang::EShTargetSpv_1_3; break; case Compiler::SpirvVersion::v1_4: result.target_language_version = glslang::EShTargetSpv_1_4; break; case Compiler::SpirvVersion::v1_5: result.target_language_version = glslang::EShTargetSpv_1_5; break; case Compiler::SpirvVersion::v1_6: result.target_language_version = glslang::EShTargetSpv_1_6; break; default: errs << "error:" << error_tag << ": Unknown SPIR-V version " << std::hex << uint32_t(spv_version); break; } } result.error = errs.str(); return result; } } // namespace shaderc_util shaderc-2025.2/libshaderc_util/src/compiler_test.cc000066400000000000000000001152721500222170200223200ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/compiler.h" #include #include #include "death_test.h" #include "libshaderc_util/counting_includer.h" #include "libshaderc_util/spirv_tools_wrapper.h" namespace { using shaderc_util::Compiler; using shaderc_util::GlslangClientInfo; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Not; // A trivial vertex shader const char kVertexShader[] = "#version 140\n" "void main() {}"; // A shader that parses under OpenGL compatibility profile rules. // It does not compile because Glslang does not support SPIR-V // code generation for OpenGL compatibility profile. const char kOpenGLCompatibilityFragShader[] = R"(#version 140 uniform highp sampler2D tex; void main() { gl_FragColor = texture2D(tex, vec2(0.0,0.0)); })"; // A shader that compiles under OpenGL core profile rules. const char kOpenGLVertexShader[] = R"(#version 330 void main() { int t = gl_VertexID; })"; // A shader that compiles under OpenGL core profile rules, even when // deducing the stage. const char kOpenGLVertexShaderDeducibleStage[] = R"(#version 330 #pragma shader_stage(vertex) void main() { int t = gl_VertexID; })"; // A shader that compiles under Vulkan rules. // See the GL_KHR_vuklan_glsl extension to GLSL. const char kVulkanVertexShader[] = R"(#version 310 es void main() { int t = gl_VertexIndex; })"; // A shader that needs valueless macro predefinition E, to be compiled // successfully. const std::string kValuelessPredefinitionShader = "#version 140\n" "#ifdef E\n" "void main(){}\n" "#else\n" "#error\n" "#endif"; // An HLSL vertex shader. const char kHlslVertexShader[] = R"(float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION { return float4(1.0, 2.0, 3.0, 4.0); })"; // A GLSL fragment shader without bindings for its uniforms. // This also can be compiled as a vertex or compute shader. const char kGlslFragShaderNoExplicitBinding[] = R"(#version 450 #extension GL_ARB_sparse_texture2: enable uniform texture2D my_tex; uniform sampler my_sam; layout(rgba32f) uniform image2D my_img; layout(rgba32f) uniform imageBuffer my_imbuf; uniform block { float x; float y; } my_ubo; void main() { texture(sampler2D(my_tex,my_sam),vec2(1.0)); vec4 t = vec4(1.0); sparseImageLoadARB(my_img,ivec2(0),t); imageLoad(my_imbuf,2); float x = my_ubo.x; })"; // A GLSL vertex shader with the location defined for its non-opaque uniform // variable. const char kGlslVertShaderExplicitLocation[] = R"(#version 450 layout(location = 10) uniform mat4 my_mat; layout(location = 0) in vec4 my_vec; void main(void) { gl_Position = my_mat * my_vec; })"; // A GLSL fragment shader with the location defined for its non-opaque uniform // variable. const char kGlslFragShaderOpaqueUniforms[] = R"(#version 320 es precision lowp float; layout(location = 0) out vec4 oColor; layout(location = 0) uniform float a; void main(void) { oColor = vec4(1.0, 0.0, 0.0, a); })"; // A GLSL vertex shader without the location defined for its non-opaque uniform // variable. const char kGlslVertShaderNoExplicitLocation[] = R"(#version 450 uniform mat4 my_mat; layout(location = 0) in vec4 my_vec; void main(void) { gl_Position = my_mat * my_vec; })"; // A GLSL vertex shader with a weirdly packed block. const char kGlslShaderWeirdPacking[] = R"(#version 450 layout(set = 0, binding = 0) buffer B { float x; vec3 foo; } my_ssbo; void main() { my_ssbo.x = 1.0; })"; const char kHlslShaderForLegalizationTest[] = R"( struct CombinedTextureSampler { Texture2D tex; SamplerState sampl; }; float4 sampleTexture(CombinedTextureSampler c, float2 loc) { return c.tex.Sample(c.sampl, loc); }; [[vk::binding(0,0)]] Texture2D gTex; [[vk::binding(0,1)]] SamplerState gSampler; float4 main(float2 loc: A) : SV_Target { CombinedTextureSampler cts; cts.tex = gTex; cts.sampl = gSampler; return sampleTexture(cts, loc); })"; const char kHlslShaderWithCounterBuffer[] = R"( [[vk::binding(0,0)]] RWStructuredBuffer Ainc; float4 main() : SV_Target0 { return float4(Ainc.IncrementCounter(), 0, 0, 0); } )"; const char kGlslShaderWithClamp[] = R"(#version 450 layout(location=0) in vec4 i; layout(location=0) out vec4 o; void main() { o = clamp(i, vec4(0.5), vec4(1.0)); } )"; // Returns the disassembly of the given SPIR-V binary, as a string. // Assumes the disassembly will be successful when targeting Vulkan. std::string Disassemble(const std::vector binary) { std::string result; shaderc_util::SpirvToolsDisassemble(Compiler::TargetEnv::Vulkan, Compiler::TargetEnvVersion::Vulkan_1_3, binary, &result); return result; } // A CountingIncluder that never returns valid content for a requested // file inclusion. class DummyCountingIncluder : public shaderc_util::CountingIncluder { private: // Returns a pair of empty strings. virtual glslang::TShader::Includer::IncludeResult* include_delegate( const char*, const char*, IncludeType, size_t) override { return nullptr; } virtual void release_delegate( glslang::TShader::Includer::IncludeResult*) override {} }; // A test fixture for compiling GLSL shaders. class CompilerTest : public testing::Test { public: // Returns true if the given compiler successfully compiles the given shader // source for the given shader stage to the specified output type. No // includes are permitted, and shader stage deduction falls back to an invalid // shader stage. bool SimpleCompilationSucceedsForOutputType( std::string source, EShLanguage stage, Compiler::OutputType output_type) { shaderc_util::GlslangInitializer initializer; std::stringstream errors; size_t total_warnings = 0; size_t total_errors = 0; bool result = false; DummyCountingIncluder dummy_includer; std::tie(result, std::ignore, std::ignore) = compiler_.Compile( source, stage, "shader", "main", dummy_stage_callback_, dummy_includer, Compiler::OutputType::SpirvBinary, &errors, &total_warnings, &total_errors); errors_ = errors.str(); return result; } // Returns the result of SimpleCompilationSucceedsForOutputType, where // the output type is a SPIR-V binary module. bool SimpleCompilationSucceeds(std::string source, EShLanguage stage) { return SimpleCompilationSucceedsForOutputType( source, stage, Compiler::OutputType::SpirvBinary); } // Returns the SPIR-V binary for a successful compilation of a shader. std::vector SimpleCompilationBinary(std::string source, EShLanguage stage) { shaderc_util::GlslangInitializer initializer; std::stringstream errors; size_t total_warnings = 0; size_t total_errors = 0; bool result = false; DummyCountingIncluder dummy_includer; std::vector words; std::tie(result, words, std::ignore) = compiler_.Compile( source, stage, "shader", "main", dummy_stage_callback_, dummy_includer, Compiler::OutputType::SpirvBinary, &errors, &total_warnings, &total_errors); errors_ = errors.str(); EXPECT_TRUE(result) << errors_; return words; } protected: Compiler compiler_; // The error string from the most recent compilation. std::string errors_; std::function dummy_stage_callback_ = [](std::ostream*, const shaderc_util::string_piece&) { return EShLangCount; }; }; TEST_F(CompilerTest, SimpleVertexShaderCompilesSuccessfullyToBinary) { EXPECT_TRUE(SimpleCompilationSucceeds(kVertexShader, EShLangVertex)); } TEST_F(CompilerTest, SimpleVertexShaderCompilesSuccessfullyToAssembly) { EXPECT_TRUE(SimpleCompilationSucceedsForOutputType( kVertexShader, EShLangVertex, Compiler::OutputType::SpirvAssemblyText)); } TEST_F(CompilerTest, SimpleVertexShaderPreprocessesSuccessfully) { EXPECT_TRUE(SimpleCompilationSucceedsForOutputType( kVertexShader, EShLangVertex, Compiler::OutputType::PreprocessedText)); } TEST_F(CompilerTest, BadVertexShaderFailsCompilation) { EXPECT_FALSE(SimpleCompilationSucceeds(" bogus ", EShLangVertex)); } TEST_F(CompilerTest, SimpleVulkanShaderCompilesWithDefaultCompilerSettings) { EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); } TEST_F(CompilerTest, OpenGLCompatibilityProfileNotSupported) { const EShLanguage stage = EShLangVertex; compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat); EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, stage)); EXPECT_EQ(errors_, "error: OpenGL compatibility profile is not supported"); } TEST_F(CompilerTest, RespectTargetEnvOnOpenGLShaderForOpenGLShader) { const EShLanguage stage = EShLangVertex; compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL); EXPECT_TRUE(SimpleCompilationSucceeds(kOpenGLVertexShader, stage)); } TEST_F(CompilerTest, RespectTargetEnvOnOpenGLShaderWhenDeducingStage) { const EShLanguage stage = EShLangVertex; compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL); EXPECT_TRUE( SimpleCompilationSucceeds(kOpenGLVertexShaderDeducibleStage, stage)); } TEST_F(CompilerTest, RespectTargetEnvOnVulkanShader) { compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan); EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); } TEST_F(CompilerTest, VulkanSpecificShaderFailsUnderOpenGLCompatibilityRules) { compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat); EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); } TEST_F(CompilerTest, VulkanSpecificShaderFailsUnderOpenGLRules) { compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL); EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); } TEST_F(CompilerTest, OpenGLSpecificShaderFailsUnderDefaultRules) { EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, EShLangVertex)); } TEST_F(CompilerTest, OpenGLCompatibilitySpecificShaderFailsUnderOpenGLCompatibilityRules) { // OpenGLCompat mode now errors out. It's been deprecated for a long time. compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat); EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader, EShLangFragment)); } TEST_F(CompilerTest, OpenGLCompatibilitySpecificShaderFailsUnderOpenGLRules) { compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL); EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader, EShLangFragment)); } TEST_F(CompilerTest, OpenGLCompatibilitySpecificShaderFailsUnderVulkanRules) { compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan); EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader, EShLangFragment)); } TEST_F(CompilerTest, OpenGLSpecificShaderFailsUnderVulkanRules) { compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan); EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, EShLangVertex)); } TEST_F(CompilerTest, BadTargetEnvFails) { compiler_.SetTargetEnv(static_cast(32767)); EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); EXPECT_THAT(errors_, HasSubstr("Invalid target client environment 32767")); } TEST_F(CompilerTest, BadTargetEnvVulkanVersionFails) { compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan, static_cast(123)); EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); EXPECT_THAT( errors_, HasSubstr("Invalid target client version 123 for Vulkan environment 0")); } TEST_F(CompilerTest, BadTargetEnvOpenGLVersionFails) { compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL, static_cast(123)); EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); EXPECT_THAT( errors_, HasSubstr("Invalid target client version 123 for OpenGL environment 1")); } TEST_F(CompilerTest, SpirvTargetVersion1_0Succeeds) { compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_0); EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); EXPECT_THAT(errors_, Eq("")); } TEST_F(CompilerTest, SpirvTargetVersion1_1Succeeds) { compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_1); EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); EXPECT_THAT(errors_, Eq("")); } TEST_F(CompilerTest, SpirvTargetVersion1_2Succeeds) { compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_2); EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); EXPECT_THAT(errors_, Eq("")); } TEST_F(CompilerTest, SpirvTargetVersion1_3Succeeds) { compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_3); EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); EXPECT_THAT(errors_, Eq("")); } TEST_F(CompilerTest, SpirvTargetVersion1_4Succeeds) { compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_4); EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); EXPECT_THAT(errors_, Eq("")); } TEST_F(CompilerTest, SpirvTargetVersion1_5Succeeds) { compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_5); EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); EXPECT_THAT(errors_, Eq("")); } TEST_F(CompilerTest, SpirvTargetVersion1_6Succeeds) { compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_6); EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); EXPECT_THAT(errors_, Eq("")); } TEST_F(CompilerTest, SpirvTargetBadVersionFails) { compiler_.SetTargetSpirv(static_cast(0x090900)); EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); EXPECT_THAT(errors_, HasSubstr(": Unknown SPIR-V version 90900")); } TEST_F(CompilerTest, AddMacroDefinition) { const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}"; compiler_.AddMacroDefinition("E", 1u, "main", 4u); EXPECT_TRUE(SimpleCompilationSucceeds(kMinimalExpandedShader, EShLangVertex)); } TEST_F(CompilerTest, AddValuelessMacroDefinitionNullPointer) { compiler_.AddMacroDefinition("E", 1u, nullptr, 100u); EXPECT_TRUE( SimpleCompilationSucceeds(kValuelessPredefinitionShader, EShLangVertex)); } TEST_F(CompilerTest, AddValuelessMacroDefinitionZeroLength) { compiler_.AddMacroDefinition("E", 1u, "something", 0u); EXPECT_TRUE( SimpleCompilationSucceeds(kValuelessPredefinitionShader, EShLangVertex)); } TEST_F(CompilerTest, AddMacroDefinitionNotNullTerminated) { const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}"; compiler_.AddMacroDefinition("EFGH", 1u, "mainnnnnn", 4u); EXPECT_TRUE(SimpleCompilationSucceeds(kMinimalExpandedShader, EShLangVertex)); } // A convert-string-to-vector test case consists of 1) an input string; 2) an // expected vector after the conversion. struct ConvertStringToVectorTestCase { std::string input_str; std::vector expected_output_vec; }; // Test the shaderc_util::ConvertStringToVector() function. The content of the // input string, including the null terminator, should be packed into uint32_t // cells and stored in the returned vector of uint32_t. In case extra bytes are // required to complete the ending uint32_t element, bytes with value 0x00 // should be used to fill the space. using ConvertStringToVectorTestFixture = testing::TestWithParam; TEST_P(ConvertStringToVectorTestFixture, VariousStringSize) { const ConvertStringToVectorTestCase& test_case = GetParam(); EXPECT_EQ(test_case.expected_output_vec, shaderc_util::ConvertStringToVector(test_case.input_str)) << "test_case.input_str: " << test_case.input_str << std::endl; } INSTANTIATE_TEST_SUITE_P( ConvertStringToVectorTest, ConvertStringToVectorTestFixture, testing::ValuesIn(std::vector{ {"", {0x00000000}}, {"1", {0x00000031}}, {"12", {0x00003231}}, {"123", {0x00333231}}, {"1234", {0x34333231, 0x00000000}}, {"12345", {0x34333231, 0x00000035}}, {"123456", {0x34333231, 0x00003635}}, {"1234567", {0x34333231, 0x00373635}}, {"12345678", {0x34333231, 0x38373635, 0x00000000}}, {"123456789", {0x34333231, 0x38373635, 0x00000039}}, })); TEST_F(CompilerTest, SetSourceLanguageToGLSLSucceeds) { compiler_.SetSourceLanguage(Compiler::SourceLanguage::GLSL); EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); } TEST_F(CompilerTest, SetSourceLanguageToGLSLFailsOnHLSL) { compiler_.SetSourceLanguage(Compiler::SourceLanguage::GLSL); EXPECT_FALSE(SimpleCompilationSucceeds(kHlslVertexShader, EShLangVertex)); } TEST_F(CompilerTest, SetSourceLanguageToHLSLSucceeds) { compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL); EXPECT_TRUE(SimpleCompilationSucceeds(kHlslVertexShader, EShLangVertex)) << errors_; } TEST_F(CompilerTest, SetSourceLanguageToHLSLFailsOnGLSL) { compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL); EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex)); } TEST_F(CompilerTest, EntryPointParameterTakesEffectForHLSL) { compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL); std::stringstream errors; size_t total_warnings = 0; size_t total_errors = 0; shaderc_util::GlslangInitializer initializer; bool result = false; DummyCountingIncluder dummy_includer; std::vector words; std::tie(result, words, std::ignore) = compiler_.Compile(kHlslVertexShader, EShLangVertex, "shader", "EntryPoint", dummy_stage_callback_, dummy_includer, Compiler::OutputType::SpirvAssemblyText, &errors, &total_warnings, &total_errors); EXPECT_TRUE(result); std::string assembly(reinterpret_cast(words.data())); EXPECT_THAT(assembly, HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\"")) << assembly; } // A test case for setting resource limits. struct SetLimitCase { Compiler::Limit limit; int default_value; int value; }; using LimitTest = testing::TestWithParam; TEST_P(LimitTest, Sample) { Compiler compiler; EXPECT_THAT(compiler.GetLimit(GetParam().limit), Eq(GetParam().default_value)); compiler.SetLimit(GetParam().limit, GetParam().value); EXPECT_THAT(compiler.GetLimit(GetParam().limit), Eq(GetParam().value)); } #define CASE(LIMIT, DEFAULT, NEW) \ { Compiler::Limit::LIMIT, DEFAULT, NEW } INSTANTIATE_TEST_SUITE_P(CompilerTest, LimitTest, // See resources.cc for the defaults. testing::ValuesIn(std::vector{ // clang-format off // This is just a sampling of the possible values. CASE(MaxLights, 8, 99), CASE(MaxClipPlanes, 6, 10929), CASE(MaxTessControlAtomicCounters, 0, 72), CASE(MaxSamples, 4, 8), // clang-format on })); #undef CASE // Returns a fragment shader accessing a texture with the given // offset. std::string ShaderWithTexOffset(int offset) { std::ostringstream oss; oss << "#version 450\n" "layout (binding=0) uniform sampler1D tex;\n" "void main() { vec4 x = textureOffset(tex, 1.0, " << offset << "); }\n"; return oss.str(); } // Ensure compilation is sensitive to limit setting. Sample just // two particular limits. The default minimum texel offset is -8, // and the default maximum texel offset is 7. TEST_F(CompilerTest, TexelOffsetDefaults) { const EShLanguage stage = EShLangFragment; EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(-9), stage)); EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(-8), stage)); EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(7), stage)); EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(8), stage)); } TEST_F(CompilerTest, TexelOffsetLowerTheMinimum) { const EShLanguage stage = EShLangFragment; compiler_.SetLimit(Compiler::Limit::MinProgramTexelOffset, -99); EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(-100), stage)); EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(-99), stage)); } TEST_F(CompilerTest, TexelOffsetRaiseTheMaximum) { const EShLanguage stage = EShLangFragment; compiler_.SetLimit(Compiler::Limit::MaxProgramTexelOffset, 100); EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(100), stage)); EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(101), stage)); } TEST_F(CompilerTest, GeneratorWordIsShadercOverGlslang) { const auto words = SimpleCompilationBinary(kVertexShader, EShLangVertex); const uint32_t shaderc_over_glslang = 13; // From SPIR-V XML Registry const uint32_t generator_word_index = 2; // From SPIR-V binary layout EXPECT_EQ(shaderc_over_glslang, words[generator_word_index] >> 16u); } TEST_F(CompilerTest, NoBindingsAndNoAutoMapBindingsFailsCompile) { compiler_.SetAutoBindUniforms(false); EXPECT_FALSE(SimpleCompilationSucceeds(kGlslFragShaderNoExplicitBinding, EShLangFragment)); EXPECT_THAT(errors_, HasSubstr("sampler/texture/image requires layout(binding=X)")); } TEST_F(CompilerTest, AutoMapBindingsSetsBindings) { compiler_.SetAutoBindUniforms(true); const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding, EShLangFragment); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0")) << disassembly; EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 2")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 3")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 4")); } TEST_F(CompilerTest, SetBindingBaseForTextureAdjustsTextureBindingsOnly) { compiler_.SetAutoBindUniforms(true); compiler_.SetAutoBindingBase(Compiler::UniformKind::Texture, 42); const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding, EShLangFragment); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 42")) << disassembly; EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 0")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 1")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 2")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 3")); } TEST_F(CompilerTest, SetBindingBaseForSamplersAdjustsSamplerBindingsOnly) { compiler_.SetAutoBindUniforms(true); compiler_.SetAutoBindingBase(Compiler::UniformKind::Sampler, 42); const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding, EShLangFragment); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0")) << disassembly; EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 42")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 1")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 2")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 3")); } TEST_F(CompilerTest, SetBindingBaseForImagesAdjustsImageBindingsOnly) { compiler_.SetAutoBindUniforms(true); compiler_.SetAutoBindingBase(Compiler::UniformKind::Image, 42); const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding, EShLangFragment); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0")) << disassembly; EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 42")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 43")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 2")); } TEST_F(CompilerTest, SetBindingBaseForBufferAdjustsBufferBindingsOnly) { compiler_.SetAutoBindUniforms(true); compiler_.SetAutoBindingBase(Compiler::UniformKind::Buffer, 42); const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding, EShLangFragment); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0")) << disassembly; EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 2")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 3")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 42")); } TEST_F(CompilerTest, AutoMapBindingsSetsBindingsSetFragTextureBindingBaseCompiledAsFrag) { compiler_.SetAutoBindUniforms(true); compiler_.SetAutoBindingBaseForStage(Compiler::Stage::Fragment, Compiler::UniformKind::Texture, 100); const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding, EShLangFragment); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 100")) << disassembly; EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 0")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 1")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 2")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 3")); } TEST_F(CompilerTest, AutoMapBindingsSetsBindingsSetFragImageBindingBaseCompiledAsVert) { compiler_.SetAutoBindUniforms(true); // This is ignored because we're compiling the shader as a vertex shader, not // as a fragment shader. compiler_.SetAutoBindingBaseForStage(Compiler::Stage::Fragment, Compiler::UniformKind::Image, 100); const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding, EShLangVertex); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0")) << disassembly; EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 2")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 3")); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 4")); } TEST_F(CompilerTest, NoAutoMapLocationsFailsCompilationOnOpenGLShader) { compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL); compiler_.SetAutoMapLocations(false); const auto words = SimpleCompilationBinary(kGlslVertShaderExplicitLocation, EShLangVertex); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_mat Location 10")) << disassembly; EXPECT_FALSE(SimpleCompilationSucceeds(kGlslVertShaderNoExplicitLocation, EShLangVertex)); } TEST_F(CompilerTest, AutoMapLocationsSetsLocationsOnOpenGLShader) { compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL); compiler_.SetAutoMapLocations(true); const auto words_no_auto = SimpleCompilationBinary(kGlslVertShaderExplicitLocation, EShLangVertex); const auto disassembly_no_auto = Disassemble(words_no_auto); EXPECT_THAT(disassembly_no_auto, HasSubstr("OpDecorate %my_mat Location 10")) << disassembly_no_auto; const auto words_auto = SimpleCompilationBinary(kGlslVertShaderNoExplicitLocation, EShLangVertex); const auto disassembly_auto = Disassemble(words_auto); EXPECT_THAT(disassembly_auto, HasSubstr("OpDecorate %my_mat Location 0")) << disassembly_auto; } TEST_F(CompilerTest, EmitMessageTextOnlyOnce) { // Emit a warning by compiling a shader without a default entry point name. // The warning should only be emitted once even though we do parsing, linking, // and IO mapping. Compiler c; std::stringstream errors; size_t total_warnings = 0; size_t total_errors = 0; shaderc_util::GlslangInitializer initializer; bool result = false; DummyCountingIncluder dummy_includer; std::tie(result, std::ignore, std::ignore) = c.Compile( "#version 150\nvoid MyEntryPoint(){}", EShLangVertex, "shader", "", dummy_stage_callback_, dummy_includer, Compiler::OutputType::SpirvBinary, &errors, &total_warnings, &total_errors); const std::string errs = errors.str(); EXPECT_THAT(errs, Eq("shader: error: Linking vertex stage: Missing entry " "point: Each stage requires one entry point\n")) << errs; } TEST_F(CompilerTest, GlslDefaultPackingUsed) { const auto words = SimpleCompilationBinary(kGlslShaderWeirdPacking, EShLangVertex); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpMemberDecorate %B 1 Offset 16")) << disassembly; } TEST_F(CompilerTest, HlslOffsetsOptionDisableRespected) { compiler_.SetHlslOffsets(false); const auto words = SimpleCompilationBinary(kGlslShaderWeirdPacking, EShLangVertex); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpMemberDecorate %B 1 Offset 16")) << disassembly; } TEST_F(CompilerTest, HlslOffsetsOptionEnableRespected) { compiler_.SetHlslOffsets(true); const auto words = SimpleCompilationBinary(kGlslShaderWeirdPacking, EShLangVertex); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpMemberDecorate %B 1 Offset 4")) << disassembly; } TEST_F(CompilerTest, HlslLegalizationEnabledNoSizeOpt) { compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL); const auto words = SimpleCompilationBinary(kHlslShaderForLegalizationTest, EShLangFragment); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, Not(HasSubstr("OpFunctionCall"))) << disassembly; EXPECT_THAT(disassembly, HasSubstr("OpName")) << disassembly; } TEST_F(CompilerTest, HlslLegalizationEnabledWithSizeOpt) { compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL); compiler_.SetOptimizationLevel(Compiler::OptimizationLevel::Size); const auto words = SimpleCompilationBinary(kHlslShaderForLegalizationTest, EShLangFragment); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, Not(HasSubstr("OpFunctionCall"))) << disassembly; EXPECT_THAT(disassembly, Not(HasSubstr("OpName"))) << disassembly; } TEST_F(CompilerTest, HlslLegalizationDisabled) { compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL); compiler_.EnableHlslLegalization(false); const auto words = SimpleCompilationBinary(kHlslShaderForLegalizationTest, EShLangFragment); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpFunctionCall")) << disassembly; } TEST_F(CompilerTest, HlslFunctionality1Enabled) { compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL); compiler_.EnableHlslFunctionality1(true); compiler_.SetAutoBindUniforms(true); // Counter variable needs a binding. const auto words = SimpleCompilationBinary(kHlslShaderWithCounterBuffer, EShLangFragment); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpExtension \"SPV_GOOGLE_hlsl_functionality1\"")) << disassembly; EXPECT_THAT(disassembly, HasSubstr("OpDecorateString %_entryPointOutput " "UserSemantic \"SV_TARGET0\"")) << disassembly; } TEST_F(CompilerTest, RelaxedVulkanRulesEnabled) { compiler_.SetSourceLanguage(Compiler::SourceLanguage::GLSL); compiler_.SetAutoBindUniforms(true); // Uniform variable needs a binding compiler_.SetVulkanRulesRelaxed(true); const auto words = SimpleCompilationBinary(kGlslFragShaderOpaqueUniforms, EShLangFragment); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpMemberName %gl_DefaultUniformBlock 0 \"a\"")) << disassembly; } TEST_F(CompilerTest, ClampMapsToFClampByDefault) { const auto words = SimpleCompilationBinary(kGlslShaderWithClamp, EShLangFragment); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpExtInst %v4float %1 FClamp")) << disassembly; } TEST_F(CompilerTest, ClampMapsToFClampWithNanClamp) { compiler_.SetNanClamp(true); const auto words = SimpleCompilationBinary(kGlslShaderWithClamp, EShLangFragment); const auto disassembly = Disassemble(words); EXPECT_THAT(disassembly, HasSubstr("OpExtInst %v4float %1 NClamp")) << disassembly; } // A test coase for Glslang // expected vector after the conversion. struct GetGlslangClientInfoCase { std::string prefix; Compiler::TargetEnv env; Compiler::TargetEnvVersion env_version; Compiler::SpirvVersion spv_version; bool spv_forced; // Expected results. The error field is matched as a substring. GlslangClientInfo expected; }; // Test the shaderc_util::GetGlslangClientInfo function. using GetGlslangClientInfoTest = testing::TestWithParam; TEST_P(GetGlslangClientInfoTest, Sample) { const auto& c = GetParam(); const auto& expected = c.expected; auto result = shaderc_util::GetGlslangClientInfo( c.prefix, c.env, c.env_version, c.spv_version, c.spv_forced); EXPECT_THAT(result.error.empty(), Eq(expected.error.empty())); if (result.error.empty()) { EXPECT_THAT(result.client, Eq(expected.client)); EXPECT_THAT(result.client_version, Eq(expected.client_version)); EXPECT_THAT(result.target_language, Eq(expected.target_language)); EXPECT_THAT(result.target_language_version, Eq(expected.target_language_version)); } else { EXPECT_THAT(result.error, HasSubstr(expected.error)); } } #define CASE_VK(VKVER, SPVVER) \ "", Compiler::TargetEnv::Vulkan, Compiler::TargetEnvVersion::Vulkan_##VKVER, \ Compiler::SpirvVersion::v##SPVVER #define BADCASE_VK(STR, VKVER, SPVVER) \ STR, Compiler::TargetEnv::Vulkan, \ static_cast(VKVER), \ static_cast(SPVVER) #define CASE_GL(GLVER, SPVVER) \ "", Compiler::TargetEnv::OpenGL, Compiler::TargetEnvVersion::OpenGL_##GLVER, \ Compiler::SpirvVersion::v##SPVVER #define BADCASE_GL(STR, GLVER, SPVVER) \ STR, Compiler::TargetEnv::OpenGL, \ static_cast(GLVER), \ static_cast(SPVVER) #define GCASE_VK(STR, VKVER, SPVVER) \ shaderc_util::GlslangClientInfo { \ std::string(STR), glslang::EShClientVulkan, \ glslang::EShTargetVulkan_##VKVER, glslang::EShTargetSpv, \ glslang::EShTargetSpv_##SPVVER \ } #define GCASE_GL(STR, GLVER, SPVVER) \ shaderc_util::GlslangClientInfo { \ std::string(STR), glslang::EShClientOpenGL, \ glslang::EShTargetOpenGL_##GLVER, glslang::EShTargetSpv, \ glslang::EShTargetSpv_##SPVVER \ } INSTANTIATE_TEST_SUITE_P( UnforcedSpirvSuccess, GetGlslangClientInfoTest, testing::ValuesIn(std::vector{ // Unforced SPIR-V version. Success cases. {CASE_VK(1_0, 1_4), false, GCASE_VK("", 1_0, 1_0)}, {CASE_VK(1_1, 1_4), false, GCASE_VK("", 1_1, 1_3)}, {CASE_VK(1_3, 1_6), false, GCASE_VK("", 1_3, 1_6)}, {CASE_VK(1_4, 1_6), false, GCASE_VK("", 1_4, 1_6)}, {CASE_GL(4_5, 1_4), false, GCASE_GL("", 450, 1_0)}, })); INSTANTIATE_TEST_SUITE_P( ForcedSpirvSuccess, GetGlslangClientInfoTest, testing::ValuesIn(std::vector{ // Forced SPIR-V version. Success cases. {CASE_VK(1_0, 1_0), true, GCASE_VK("", 1_0, 1_0)}, {CASE_VK(1_0, 1_1), true, GCASE_VK("", 1_0, 1_1)}, {CASE_VK(1_0, 1_2), true, GCASE_VK("", 1_0, 1_2)}, {CASE_VK(1_0, 1_3), true, GCASE_VK("", 1_0, 1_3)}, {CASE_VK(1_1, 1_0), true, GCASE_VK("", 1_1, 1_0)}, {CASE_VK(1_1, 1_1), true, GCASE_VK("", 1_1, 1_1)}, {CASE_VK(1_1, 1_2), true, GCASE_VK("", 1_1, 1_2)}, {CASE_VK(1_1, 1_3), true, GCASE_VK("", 1_1, 1_3)}, {CASE_VK(1_3, 1_4), true, GCASE_VK("", 1_3, 1_4)}, {CASE_VK(1_3, 1_5), true, GCASE_VK("", 1_3, 1_5)}, {CASE_VK(1_3, 1_6), true, GCASE_VK("", 1_3, 1_6)}, {CASE_VK(1_4, 1_4), true, GCASE_VK("", 1_4, 1_4)}, {CASE_VK(1_4, 1_5), true, GCASE_VK("", 1_4, 1_5)}, {CASE_VK(1_4, 1_6), true, GCASE_VK("", 1_4, 1_6)}, {CASE_GL(4_5, 1_0), true, GCASE_GL("", 450, 1_0)}, {CASE_GL(4_5, 1_1), true, GCASE_GL("", 450, 1_1)}, {CASE_GL(4_5, 1_2), true, GCASE_GL("", 450, 1_2)}, })); INSTANTIATE_TEST_SUITE_P( Failure, GetGlslangClientInfoTest, testing::ValuesIn(std::vector{ // Failure cases. {BADCASE_VK("foo", 999, Compiler::SpirvVersion::v1_0), false, GCASE_VK("error:foo: Invalid target client version 999 for Vulkan " "environment 0", 1_0, 1_0)}, {BADCASE_GL("foo", 999, Compiler::SpirvVersion::v1_0), false, GCASE_GL("error:foo: Invalid target client version 999 for OpenGL " "environment 1", 450, 1_0)}, // For bad SPIR-V versions, have to force=true to make it pay attention. {BADCASE_VK("foo", Compiler::TargetEnvVersion::Vulkan_1_0, 999), true, GCASE_VK("error:foo: Unknown SPIR-V version 3e7", 1_0, 1_0)}, {BADCASE_GL("foo", Compiler::TargetEnvVersion::OpenGL_4_5, 999), true, GCASE_GL("error:foo: Unknown SPIR-V version 3e7", 450, 1_0)}, })); #undef CASE_VK #undef CASE_GL #undef BADCASE_VK #undef BADCASE_GL #undef GCASE_VK #undef GCASE_GL } // anonymous namespace shaderc-2025.2/libshaderc_util/src/counting_includer_test.cc000066400000000000000000000056511500222170200242200ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/counting_includer.h" #include #include #include namespace { // A trivial implementation of CountingIncluder's virtual methods, so tests can // instantiate. class ConcreteCountingIncluder : public shaderc_util::CountingIncluder { public: using IncludeResult = glslang::TShader::Includer::IncludeResult; ~ConcreteCountingIncluder() { // Avoid leaks. for (auto result : results_) { release_delegate(result); } } virtual IncludeResult* include_delegate( const char* requested, const char* requestor, IncludeType, size_t) override { const char kError[] = "Unexpected #include"; results_.push_back(new IncludeResult{"", kError, strlen(kError), nullptr}); return results_.back(); } virtual void release_delegate(IncludeResult* include_result) override { delete include_result; } private: // All the results we've returned so far. std::vector results_; }; TEST(CountingIncluderTest, InitialCount) { EXPECT_EQ(0, ConcreteCountingIncluder().num_include_directives()); } TEST(CountingIncluderTest, OneIncludeLocal) { ConcreteCountingIncluder includer; includer.includeLocal("random file name", "from me", 0); EXPECT_EQ(1, includer.num_include_directives()); } TEST(CountingIncluderTest, TwoIncludesAnyIncludeType) { ConcreteCountingIncluder includer; includer.includeSystem("name1", "from me", 0); includer.includeLocal("name2", "me", 0); EXPECT_EQ(2, includer.num_include_directives()); } TEST(CountingIncluderTest, ManyIncludes) { ConcreteCountingIncluder includer; for (int i = 0; i < 100; ++i) { includer.includeLocal("filename", "from me", i); includer.includeSystem("filename", "from me", i); } EXPECT_EQ(200, includer.num_include_directives()); } #ifndef SHADERC_DISABLE_THREADED_TESTS TEST(CountingIncluderTest, ThreadedIncludes) { ConcreteCountingIncluder includer; std::thread t1( [&includer]() { includer.includeLocal("name1", "me", 0); }); std::thread t2( [&includer]() { includer.includeSystem("name2", "me", 1); }); std::thread t3( [&includer]() { includer.includeLocal("name3", "me", 2); }); t1.join(); t2.join(); t3.join(); EXPECT_EQ(3, includer.num_include_directives()); } #endif // SHADERC_DISABLE_THREADED_TESTS } // anonymous namespace shaderc-2025.2/libshaderc_util/src/death_test.h000066400000000000000000000016551500222170200214340ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSHADERC_UTIL_SRC_DEATH_TEST_H #define LIBSHADERC_UTIL_SRC_DEATH_TEST_H #ifdef NDEBUG #define EXPECT_DEBUG_DEATH_IF_SUPPORTED(statement, regexp) #else #define EXPECT_DEBUG_DEATH_IF_SUPPORTED(statement, regexp) \ EXPECT_DEATH_IF_SUPPORTED(statement, regexp) #endif #endif // LIBSHADERC_UTIL_SRC_DEATH_TEST_H shaderc-2025.2/libshaderc_util/src/file_finder.cc000066400000000000000000000043441500222170200217120ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/file_finder.h" #include "libshaderc_util/string_piece.h" #include #include #include namespace { // Returns "" if path is empty or ends in '/'. Otherwise, returns "/". std::string MaybeSlash(const shaderc_util::string_piece& path) { return (path.empty() || path.back() == '/') ? "" : "/"; } } // anonymous namespace namespace shaderc_util { std::string FileFinder::FindReadableFilepath( const std::string& filename) const { assert(!filename.empty()); static const auto for_reading = std::ios_base::in; std::filebuf opener; for (const auto& prefix : search_path_) { const std::string prefixed_filename = prefix + MaybeSlash(prefix) + filename; if (opener.open(prefixed_filename, for_reading)) return prefixed_filename; } return ""; } std::string FileFinder::FindRelativeReadableFilepath( const std::string& requesting_file, const std::string& filename) const { assert(!filename.empty()); string_piece dir_name(requesting_file); size_t last_slash = requesting_file.find_last_of("/\\"); if (last_slash != std::string::npos) { dir_name = string_piece(requesting_file.c_str(), requesting_file.c_str() + last_slash); } if (dir_name.size() == requesting_file.size()) { dir_name.clear(); } static const auto for_reading = std::ios_base::in; std::filebuf opener; const std::string relative_filename = dir_name.str() + MaybeSlash(dir_name) + filename; if (opener.open(relative_filename, for_reading)) return relative_filename; return FindReadableFilepath(filename); } } // namespace shaderc_util shaderc-2025.2/libshaderc_util/src/file_finder_test.cc000066400000000000000000000111351500222170200227450ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/file_finder.h" #include // We need getcwd #if WIN32 #include #else #include #endif #include "death_test.h" namespace { using shaderc_util::FileFinder; // Returns the absolute path of the current working directory. std::string GetCurrentDir() { // Provide generous space to write the path. char buf[1000]; #if WIN32 return _getcwd(buf, sizeof(buf)); #else return getcwd(buf, sizeof(buf)); #endif } class FileFinderTest : public testing::Test { protected: FileFinder finder; // Absolute path of the current working directory. const std::string current_dir = GetCurrentDir(); }; TEST_F(FileFinderTest, PathStartsEmpty) { EXPECT_TRUE(FileFinder().search_path().empty()); } TEST_F(FileFinderTest, EmptyPath) { finder.search_path().clear(); EXPECT_EQ("", finder.FindReadableFilepath("include_file.1")); } TEST_F(FileFinderTest, EmptyStringInPath) { finder.search_path() = {""}; EXPECT_EQ("include_file.1", finder.FindReadableFilepath("include_file.1")); EXPECT_EQ("dir/subdir/include_file.2", finder.FindReadableFilepath("dir/subdir/include_file.2")); } TEST_F(FileFinderTest, SimplePath) { finder.search_path() = {"dir"}; EXPECT_EQ("dir/subdir/include_file.2", finder.FindReadableFilepath("subdir/include_file.2")); } TEST_F(FileFinderTest, PathEndsInSlash) { finder.search_path() = {"dir/"}; EXPECT_EQ("dir/subdir/include_file.2", finder.FindReadableFilepath("subdir/include_file.2")); } TEST_F(FileFinderTest, ParentDir) { finder.search_path() = {"dir"}; EXPECT_EQ("dir/../include_file.1", finder.FindReadableFilepath("../include_file.1")); } TEST_F(FileFinderTest, EntirePathIsActive) { finder.search_path() = {"", "dir/subdir/"}; EXPECT_EQ("include_file.1", finder.FindReadableFilepath("include_file.1")); EXPECT_EQ("dir/subdir/include_file.2", finder.FindReadableFilepath("include_file.2")); } TEST_F(FileFinderTest, NonExistingFile) { finder.search_path() = {"", "dir/subdir/"}; EXPECT_EQ("", finder.FindReadableFilepath("garbage.xyxyxyxyxyxz")); } TEST_F(FileFinderTest, FirstHitReturned) { finder.search_path() = {".", "", "dir/../"}; EXPECT_EQ("./include_file.1", finder.FindReadableFilepath("include_file.1")); } TEST_F(FileFinderTest, IrrelevantPaths) { finder.search_path() = {".", "garbage.xyxyxyxyxyz", "dir/../"}; EXPECT_EQ("", finder.FindReadableFilepath("include_file.2")); finder.search_path().push_back("dir/subdir"); EXPECT_EQ("dir/subdir/include_file.2", finder.FindReadableFilepath("include_file.2")); } TEST_F(FileFinderTest, CurrentDirectory) { ASSERT_GE(current_dir.size(), 0u); // Either the directory should start with / (if we are on Linux), // Or it should beither X:/ or X:\ or // (if we are on Windows). ASSERT_TRUE(current_dir.front() == '\\' || current_dir.front() == '/' || (current_dir.size() >= 3u && current_dir[1] == ':' && (current_dir[2] == '\\' || current_dir[2] == '/'))); } TEST_F(FileFinderTest, AbsolutePath) { ASSERT_NE('/', current_dir.back()); finder.search_path() = {current_dir}; EXPECT_EQ(current_dir + "/include_file.1", finder.FindReadableFilepath("include_file.1")); EXPECT_EQ(current_dir + "/dir/subdir/include_file.2", finder.FindReadableFilepath("dir/subdir/include_file.2")); } TEST_F(FileFinderTest, AbsoluteFilename) { ASSERT_NE('/', current_dir.back()); finder.search_path() = {""}; const std::string absolute_file1 = current_dir + "/include_file.1"; EXPECT_EQ(absolute_file1, finder.FindReadableFilepath(absolute_file1)); EXPECT_EQ("", finder.FindReadableFilepath("/dir/subdir/include_file.2")); finder.search_path().push_back("."); EXPECT_EQ(".//dir/subdir/include_file.2", finder.FindReadableFilepath("/dir/subdir/include_file.2")); } TEST(FileFinderDeathTest, EmptyFilename) { EXPECT_DEBUG_DEATH_IF_SUPPORTED(FileFinder().FindReadableFilepath(""), "Assertion"); } } // anonymous namespace shaderc-2025.2/libshaderc_util/src/format_test.cc000066400000000000000000000070221500222170200217670ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/format.h" #include #include #include #include namespace { using testing::AllOf; using testing::HasSubstr; using testing::IsEmpty; class FormatMap : public testing::Test { public: FormatMap() : map1({{"one", 1}}), umap1({map1.begin(), map1.end()}), map8({{1, "one"}, {2, "two"}, {3, "three"}, {4, "four"}, {5, "five"}, {6, "six"}, {7, "seven"}, {8, "eight"}}), umap8({map8.begin(), map8.end()}), mmap({{1, 100}, {1, 200}, {2, 100}, {2, 200}}), ummap({mmap.begin(), mmap.end()}) {} protected: std::map empty_map; std::unordered_map empty_umap; std::map map1; std::unordered_map umap1; std::map map8; std::unordered_map umap8; std::multimap mmap; std::unordered_multimap ummap; }; TEST_F(FormatMap, EmptyMap) { EXPECT_THAT(shaderc_util::format(empty_map, "pre", "in", "post"), IsEmpty()); EXPECT_THAT(shaderc_util::format(empty_umap, "pre", "in", "post"), IsEmpty()); } TEST_F(FormatMap, SingleEntry) { EXPECT_EQ("PREoneIN1POST", shaderc_util::format(map1, "PRE", "IN", "POST")); EXPECT_EQ("PREoneIN1POST", shaderc_util::format(umap1, "PRE", "IN", "POST")); } TEST_F(FormatMap, EmptyPrefix) { EXPECT_EQ("oneIN1POST", shaderc_util::format(map1, "", "IN", "POST")); EXPECT_EQ("oneIN1POST", shaderc_util::format(umap1, "", "IN", "POST")); } TEST_F(FormatMap, EmptyInfix) { EXPECT_EQ("PREone1POST", shaderc_util::format(map1, "PRE", "", "POST")); EXPECT_EQ("PREone1POST", shaderc_util::format(umap1, "PRE", "", "POST")); } TEST_F(FormatMap, EmptyPostfix) { EXPECT_EQ("PREoneIN1", shaderc_util::format(map1, "PRE", "IN", "")); EXPECT_EQ("PREoneIN1", shaderc_util::format(umap1, "PRE", "IN", "")); } TEST_F(FormatMap, LargerMap) { const std::string result = shaderc_util::format(map8, "", "", "\n"), uresult = shaderc_util::format(umap8, "", "", "\n"); auto has_all = AllOf(HasSubstr("1one\n"), HasSubstr("2two\n"), HasSubstr("3three\n"), HasSubstr("4four\n"), HasSubstr("5five\n"), HasSubstr("6six\n"), HasSubstr("7seven\n"), HasSubstr("8eight\n")); EXPECT_THAT(result, has_all); EXPECT_EQ(48u, result.size()); EXPECT_THAT(uresult, has_all); EXPECT_EQ(48u, uresult.size()); } TEST_F(FormatMap, Multimap) { const std::string result = shaderc_util::format(mmap, " ", "&", ""), uresult = shaderc_util::format(ummap, " ", "&", ""); auto has_all = AllOf(HasSubstr(" 1&100"), HasSubstr(" 1&200"), HasSubstr(" 2&100"), HasSubstr(" 2&200")); EXPECT_THAT(result, has_all); EXPECT_EQ(4 * 6u, result.size()); EXPECT_THAT(uresult, has_all); EXPECT_EQ(4 * 6u, uresult.size()); } } // anonymous namespace shaderc-2025.2/libshaderc_util/src/io_shaderc.cc000066400000000000000000000100171500222170200215360ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/io_shaderc.h" #include "libshaderc_util/universal_unistd.h" #if _WIN32 // Need _fileno from stdio.h // Need _O_BINARY and _O_TEXT from fcntl.h #include #include #endif #include #include #include #include #include namespace { // Outputs a descriptive message for errno_value to cerr. // This may be truncated to 1023 bytes on certain platforms. void OutputFileErrorMessage(int errno_value) { #ifdef _MSC_VER // If the error message is more than 1023 bytes it will be truncated. char buffer[1024]; strerror_s(buffer, errno_value); std::cerr << ": " << buffer << std::endl; #else std::cerr << ": " << strerror(errno_value) << std::endl; #endif } } // anonymous namespace namespace shaderc_util { bool IsAbsolutePath(const std::string& path) { if (path.empty()) return false; // Unix-like OS: /path/to/file if (path.front() == '/') return true; // Windows: \\server\user\file if (path.size() > 1 && path[0] == '\\' && path[1] == '\\') { return true; } // Windows: X:\path\to\file if (path.size() > 2 && ::isalpha(path[0]) && path[1] == ':' && path[2] == '\\') { return true; } return false; } std::string GetBaseFileName(const std::string& file_path) { size_t loc_slash = file_path.find_last_of("/\\"); std::string base_name = file_path.substr((loc_slash == std::string::npos ? -1 : loc_slash) + 1); if (base_name == ".." || base_name == ".") { base_name = ""; } return base_name; } bool ReadFile(const std::string& input_file_name, std::vector* input_data) { std::istream* stream = &std::cin; std::ifstream input_file; if (input_file_name != "-") { input_file.open(input_file_name, std::ios_base::binary); stream = &input_file; if (input_file.fail()) { std::cerr << "glslc: error: cannot open input file: '" << input_file_name << "'"; if (access(input_file_name.c_str(), R_OK) != 0) { OutputFileErrorMessage(errno); return false; } std::cerr << std::endl; return false; } } *input_data = std::vector((std::istreambuf_iterator(*stream)), std::istreambuf_iterator()); return true; } std::ostream* GetOutputStream(const string_piece& output_filename, std::ofstream* file_stream, std::ostream* err) { std::ostream* stream = &std::cout; if (output_filename != "-") { file_stream->open(output_filename.str(), std::ios_base::binary); stream = file_stream; if (file_stream->fail()) { *err << "glslc: error: cannot open output file: '" << output_filename << "'"; if (access(output_filename.str().c_str(), W_OK) != 0) { OutputFileErrorMessage(errno); return nullptr; } std::cerr << std::endl; return nullptr; } } return stream; } bool WriteFile(std::ostream* stream, const string_piece& output_data) { if (output_data.size() > 0) { stream->write(output_data.data(), output_data.size()); if (!stream->good()) { return false; } } stream->flush(); return true; } void FlushAndSetBinaryModeOnStdout() { std::fflush(stdout); #if _WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif } void FlushAndSetTextModeOnStdout() { std::fflush(stdout); #if _WIN32 _setmode(_fileno(stdout), _O_TEXT); #endif } } // namespace shaderc_util shaderc-2025.2/libshaderc_util/src/io_shaderc_test.cc000066400000000000000000000113161500222170200226000ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/io_shaderc.h" #include #include namespace { using shaderc_util::GetBaseFileName; using shaderc_util::GetOutputStream; using shaderc_util::IsAbsolutePath; using shaderc_util::ReadFile; using shaderc_util::WriteFile; using testing::Eq; using testing::HasSubstr; std::string ToString(const std::vector& v) { return std::string(v.data(), v.size()); } class ReadFileTest : public testing::Test { protected: // A vector to pass to ReadFile. std::vector read_data; }; TEST(IsAbsolutePathTest, Linux) { EXPECT_FALSE(IsAbsolutePath("")); EXPECT_TRUE(IsAbsolutePath("/")); EXPECT_FALSE(IsAbsolutePath(".")); EXPECT_FALSE(IsAbsolutePath("..")); EXPECT_TRUE(IsAbsolutePath("/bin/echo")); EXPECT_TRUE(IsAbsolutePath("//etc/shadow")); EXPECT_TRUE(IsAbsolutePath("/../../../lib")); EXPECT_FALSE(IsAbsolutePath("./something")); EXPECT_FALSE(IsAbsolutePath("input")); EXPECT_FALSE(IsAbsolutePath("../test")); EXPECT_FALSE(IsAbsolutePath(" /abc")); EXPECT_TRUE(IsAbsolutePath("/abc def/ttt")); } TEST(IsAbsolutePathTest, Windows) { EXPECT_TRUE(IsAbsolutePath(R"(\\Server1000\superuser\file)")); EXPECT_TRUE(IsAbsolutePath(R"(\\zzzz 1000\user with space\file with space)")); EXPECT_TRUE( IsAbsolutePath(R"(C:\Program Files (x86)\Windows Folder\shader.glsl)")); EXPECT_FALSE(IsAbsolutePath(R"(third_party\gmock)")); EXPECT_FALSE(IsAbsolutePath(R"(C:..\File.txt)")); } TEST(GetBaseFileName, Linux) { EXPECT_EQ("", GetBaseFileName("")); EXPECT_EQ("", GetBaseFileName("/")); EXPECT_EQ("", GetBaseFileName(".")); EXPECT_EQ("", GetBaseFileName("..")); EXPECT_EQ("echo", GetBaseFileName("/bin/echo")); EXPECT_EQ("shadow", GetBaseFileName("//etc/shadow")); EXPECT_EQ("lib", GetBaseFileName("/../../../lib")); EXPECT_EQ("something", GetBaseFileName("./something")); EXPECT_EQ("input", GetBaseFileName("input")); EXPECT_EQ("test", GetBaseFileName("../test")); EXPECT_EQ("abc", GetBaseFileName(" /abc")); EXPECT_EQ("ttt", GetBaseFileName("/abc def/ttt")); } TEST(GetBaseFileName, Windows) { EXPECT_EQ("file", GetBaseFileName(R"(\\Server1000\superuser\file)")); EXPECT_EQ("file with space", GetBaseFileName(R"(\\zzzz 1000\user with space\file with space)")); EXPECT_EQ( "shader.glsl", GetBaseFileName(R"(C:\Program Files (x86)\Windows Folder\shader.glsl)")); EXPECT_EQ("gmock", GetBaseFileName(R"(third_party\gmock)")); EXPECT_EQ("File.txt", GetBaseFileName(R"(C:..\File.txt)")); } TEST_F(ReadFileTest, CorrectContent) { ASSERT_TRUE(ReadFile("include_file.1", &read_data)); EXPECT_EQ("The quick brown fox jumps over a lazy dog.", ToString(read_data)); } TEST_F(ReadFileTest, EmptyContent) { ASSERT_TRUE(ReadFile("dir/subdir/include_file.2", &read_data)); EXPECT_TRUE(read_data.empty()); } TEST_F(ReadFileTest, FileNotFound) { EXPECT_FALSE(ReadFile("garbage garbage vjoiarhiupo hrfewi", &read_data)); } TEST_F(ReadFileTest, EmptyFilename) { EXPECT_FALSE(ReadFile("", &read_data)); } TEST(WriteFiletest, BadStream) { std::ofstream fstream; std::ostringstream err; std::ostream* output_stream = GetOutputStream( "/this/should/not/be/writable/asdfasdfasdfasdf", &fstream, &err); EXPECT_EQ(nullptr, output_stream); EXPECT_TRUE(fstream.fail()); EXPECT_EQ(nullptr, output_stream); EXPECT_THAT(err.str(), HasSubstr("cannot open output file")); } TEST(WriteFileTest, Roundtrip) { const std::string content = "random content 12345"; const std::string filename = "WriteFileTestOutput.tmp"; std::ofstream fstream; std::ostringstream err; std::ostream* output_stream = GetOutputStream(filename, &fstream, &err); ASSERT_EQ(output_stream, &fstream); EXPECT_THAT(err.str(), Eq("")); ASSERT_TRUE(WriteFile(output_stream, content)); std::vector read_data; ASSERT_TRUE(ReadFile(filename, &read_data)); EXPECT_EQ(content, ToString(read_data)); } TEST(OutputStreamTest, Stdout) { std::ofstream fstream; std::ostringstream err; std::ostream* output_stream = GetOutputStream("-", &fstream, &err); EXPECT_EQ(&std::cout, output_stream); EXPECT_THAT(err.str(), Eq("")); } } // anonymous namespace shaderc-2025.2/libshaderc_util/src/message.cc000066400000000000000000000274111500222170200210700ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/message.h" #include #include #include #include namespace shaderc_util { namespace { // Given a message, deduces and returns its type. If the message type is // recognized, advances *message past the prefix indicating the type. Otherwise, // leaves *message unchanged and returns MessageType::Unknown. MessageType DeduceMessageType(string_piece* message) { static const char kErrorMessage[] = "ERROR: "; static const char kWarningMessage[] = "WARNING: "; static const char kGlobalWarningMessage[] = "Warning, "; if (message->starts_with(kErrorMessage)) { *message = message->substr(::strlen(kErrorMessage)); return MessageType::Error; } else if (message->starts_with(kWarningMessage)) { *message = message->substr(::strlen(kWarningMessage)); return MessageType::Warning; } else if (message->starts_with(kGlobalWarningMessage)) { *message = message->substr(::strlen(kGlobalWarningMessage)); return MessageType::GlobalWarning; } return MessageType::Unknown; } // Deduces a location specification from the given message. A location // specification is of the form "::" and a trailing // space. If the deduction is successful, returns true and updates source_name // and line_number to the deduced source name and line numer respectively. The // prefix standing for the location specification in message is skipped. // Otherwise, returns false and keeps all parameters untouched. bool DeduceLocationSpec(string_piece* message, string_piece* source_name, string_piece* line_number) { if (!message || message->empty()) { return false; } // When we find a pattern like this: // colon // digits // colon // space // Then deduce that the source_name is the text before the first colon, // the line number is the digits, and the message is the text after the // second colon. const size_t size = message->size(); if (size <= 4) { // A valid message must have a colon, a digit, a colon, and a space. return false; } // The last possible position of the first colon. const size_t first_colon_cutoff = size - 4; // The last possible position of the second colon. const size_t next_colon_cutoff = size - 2; for (size_t first_colon_pos = message->find_first_of(':'), next_colon_pos = 0; // There is a first colon, and it's not too close to the end (first_colon_pos != string_piece::npos) && (first_colon_pos <= first_colon_cutoff); // Try the next pair of colons. first_colon_pos = next_colon_pos) { // We're guaranteed to have at least 3 more characters. // Guarantee progress toward the end of the string. next_colon_pos = message->find_first_of(':', first_colon_pos + 1); if ((next_colon_pos == string_piece::npos) || (next_colon_pos > next_colon_cutoff)) { // No valid solution. return false; } if (first_colon_pos + 1 == next_colon_pos) { // There is no room for digits. continue; } if ((message->data()[next_colon_pos + 1] != ' ')) { // There is no space character after the second colon. continue; } if (message->find_first_not_of("0123456789", first_colon_pos + 1) == next_colon_pos) { // We found the first solution. *source_name = message->substr(0, first_colon_pos); *line_number = message->substr(first_colon_pos + 1, next_colon_pos - 1 - first_colon_pos); *message = message->substr(next_colon_pos + 2); return true; } } return false; } // Returns true if the given message is a summary message. bool IsSummaryMessage(const string_piece& message) { const size_t space_loc = message.find_first_of(' '); if (space_loc == string_piece::npos) return false; const string_piece number = message.substr(0, space_loc); const string_piece rest = message.substr(space_loc + 1); if (!std::all_of(number.begin(), number.end(), ::isdigit)) return false; if (!rest.starts_with("compilation errors.")) return false; return true; } } // anonymous namespace MessageType ParseGlslangOutput(const string_piece& message, bool warnings_as_errors, bool suppress_warnings, string_piece* source_name, string_piece* line_number, string_piece* rest) { string_piece rest_of_message(message); source_name->clear(); line_number->clear(); rest->clear(); // The glslang warning/error messages are typically of the following form: // // // can be "WARNING:", "ERROR:", or "Warning, ". "WARNING:" // means a warning message for a certain line, while "Warning, " means a // global one. // // is of the form: // :: // It doesn't exist if the warning/error message is a global one. // // See Glslang's TInfoSink class implementation for details. bool is_error = false; // Handle . switch (DeduceMessageType(&rest_of_message)) { case MessageType::Warning: if (suppress_warnings) return MessageType::Ignored; break; case MessageType::Error: is_error = true; break; case MessageType::GlobalWarning: if (suppress_warnings) return MessageType::Ignored; *rest = rest_of_message; return warnings_as_errors ? MessageType::GlobalError : MessageType::GlobalWarning; case MessageType::Unknown: *rest = rest_of_message; return MessageType::Unknown; default: break; } rest_of_message = rest_of_message.strip_whitespace(); if (rest_of_message.empty()) return MessageType::Unknown; // Now we have stripped the . Try to see if we can find // a . if (DeduceLocationSpec(&rest_of_message, source_name, line_number)) { *rest = rest_of_message; return (is_error || warnings_as_errors) ? MessageType::Error : MessageType::Warning; } else { // No . This is a global warning/error message. // A special kind of global message is summary message, which should // start with a number. *rest = rest_of_message; if (IsSummaryMessage(rest_of_message)) { return (is_error || warnings_as_errors) ? MessageType::ErrorSummary : MessageType::WarningSummary; } return (is_error || warnings_as_errors) ? MessageType::GlobalError : MessageType::GlobalWarning; } return MessageType::Unknown; } bool PrintFilteredErrors(const string_piece& file_name, std::ostream* error_stream, bool warnings_as_errors, bool suppress_warnings, const char* error_list, size_t* total_warnings, size_t* total_errors) { const char* ignored_error_strings[] = { "Warning, version 310 is not yet complete; most version-specific " "features are present, but some are missing.", "Warning, version 400 is not yet complete; most version-specific " "features are present, but some are missing.", "Warning, version 410 is not yet complete; most version-specific " "features are present, but some are missing.", "Warning, version 420 is not yet complete; most version-specific " "features are present, but some are missing.", "Warning, version 430 is not yet complete; most version-specific " "features are present, but some are missing.", "Warning, version 440 is not yet complete; most version-specific " "features are present, but some are missing.", "Warning, version 450 is not yet complete; most version-specific " "features are present, but some are missing.", "Linked vertex stage:", "Linked fragment stage:", "Linked tessellation control stage:", "Linked tessellation evaluation stage:", "Linked geometry stage:", "Linked compute stage:", ""}; size_t existing_total_errors = *total_errors; string_piece error_messages(error_list); for (const string_piece& message : error_messages.get_fields('\n')) { if (std::find(std::begin(ignored_error_strings), std::end(ignored_error_strings), message) == std::end(ignored_error_strings)) { string_piece source_name; string_piece line_number; string_piece rest; const MessageType type = ParseGlslangOutput(message, warnings_as_errors, suppress_warnings, &source_name, &line_number, &rest); string_piece name = file_name; if (!source_name.empty()) { // -1 is the string number for the preamble injected by us. name = source_name == "-1" ? "" : source_name; } switch (type) { case MessageType::Error: case MessageType::Warning: assert(!name.empty() && !line_number.empty() && !rest.empty()); *error_stream << name << ":" << line_number << ": " << (type == MessageType::Error ? "error: " : "warning: ") << rest.strip_whitespace() << std::endl; *total_errors += type == MessageType::Error; *total_warnings += type == MessageType::Warning; break; case MessageType::ErrorSummary: case MessageType::WarningSummary: break; case MessageType::GlobalError: case MessageType::GlobalWarning: assert(!rest.empty()); *total_errors += type == MessageType::GlobalError; *total_warnings += type == MessageType::GlobalWarning; *error_stream << name << ": " << (type == MessageType::GlobalError ? "error" : "warning") << ": " << rest.strip_whitespace() << std::endl; break; case MessageType::Unknown: *error_stream << name << ":"; *error_stream << " " << message << std::endl; break; case MessageType::Ignored: break; } } } return (existing_total_errors == *total_errors); } // Outputs the number of warnings and errors if there are any. void OutputMessages(std::ostream* error_stream, size_t total_warnings, size_t total_errors) { if (total_warnings > 0 || total_errors > 0) { if (total_warnings > 0 && total_errors > 0) { *error_stream << total_warnings << " warning" << (total_warnings > 1 ? "s" : "") << " and " << total_errors << " error" << (total_errors > 1 ? "s" : "") << " generated." << std::endl; } else if (total_warnings > 0) { *error_stream << total_warnings << " warning" << (total_warnings > 1 ? "s" : "") << " generated." << std::endl; } else if (total_errors > 0) { *error_stream << total_errors << " error" << (total_errors > 1 ? "s" : "") << " generated." << std::endl; } } } } // namespace glslc shaderc-2025.2/libshaderc_util/src/message_test.cc000066400000000000000000000240461500222170200221300ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Some of the tests here check code paths that are not checked by // integration tests. // Generally, these would be conditions not generated by the Glslang // compiler. It's easier to write these unit tests than to inject // a dependency on a fake compiler. #include "libshaderc_util/message.h" #include using shaderc_util::MessageType; using shaderc_util::ParseGlslangOutput; using shaderc_util::string_piece; namespace { TEST(ParseGlslangOutputTest, EmptyMessageBody) { string_piece segment_number; string_piece line_number; string_piece rest; EXPECT_EQ(MessageType::Unknown, ParseGlslangOutput("WARNING: ", false, false, &segment_number, &line_number, &rest)); EXPECT_EQ(MessageType::Unknown, ParseGlslangOutput("ERROR: ", false, false, &segment_number, &line_number, &rest)); } TEST(ParseGlslangOutputTest, GlobalError) { string_piece segment_number; string_piece line_number; string_piece rest; EXPECT_EQ( MessageType::GlobalError, ParseGlslangOutput("ERROR: too many functions: got 1666473 of them", false, false, &segment_number, &line_number, &rest)); EXPECT_EQ("too many functions: got 1666473 of them", rest.str()); EXPECT_EQ( MessageType::GlobalError, ParseGlslangOutput( "ERROR: #version: versions before 150 do not allow a profile token", false, false, &segment_number, &line_number, &rest)); EXPECT_EQ("#version: versions before 150 do not allow a profile token", rest.str()); } TEST(ParseGlslangOutputTest, GlobalWarning) { string_piece segment_number; string_piece line_number; string_piece rest; EXPECT_EQ(MessageType::GlobalWarning, ParseGlslangOutput("Warning, version 1000 is unknown.", false, false, &segment_number, &line_number, &rest)); EXPECT_EQ("version 1000 is unknown.", rest.str()); } TEST(ParseGlslangOutputTest, InvalidSuffixAfterSegmentNumber) { string_piece segment_number; string_piece line_number; string_piece rest; EXPECT_EQ(MessageType::GlobalWarning, ParseGlslangOutput("WARNING: 12a", false, false, &segment_number, &line_number, &rest)); EXPECT_EQ(MessageType::GlobalError, ParseGlslangOutput("WARNING: 12a", true, false, &segment_number, &line_number, &rest)); EXPECT_EQ(MessageType::GlobalError, ParseGlslangOutput("ERROR: 42!", false, false, &segment_number, &line_number, &rest)); } TEST(ParseGlslangOutputTest, OnlyANumber) { string_piece source_name; string_piece line_number; string_piece rest; EXPECT_EQ(MessageType::GlobalWarning, ParseGlslangOutput("WARNING: 12", false, false, &source_name, &line_number, &rest)); EXPECT_TRUE(source_name.empty()); EXPECT_TRUE(line_number.empty()); EXPECT_EQ("12", rest.str()); EXPECT_EQ(MessageType::GlobalError, ParseGlslangOutput("WARNING: 12", true, false, &source_name, &line_number, &rest)); EXPECT_TRUE(source_name.empty()); EXPECT_TRUE(line_number.empty()); EXPECT_EQ("12", rest.str()); EXPECT_EQ(MessageType::GlobalError, ParseGlslangOutput("ERROR: 42", false, false, &source_name, &line_number, &rest)); EXPECT_TRUE(source_name.empty()); EXPECT_TRUE(line_number.empty()); EXPECT_EQ("42", rest.str()); } TEST(ParseGlslangOutputTest, InvalidSuffixAfterSegmentNumberColon) { string_piece segment_number; string_piece line_number; string_piece rest; EXPECT_EQ(MessageType::GlobalWarning, ParseGlslangOutput("WARNING: 12:0", false, false, &segment_number, &line_number, &rest)); EXPECT_EQ(MessageType::GlobalError, ParseGlslangOutput("ERROR: 42:1234", false, false, &segment_number, &line_number, &rest)); } TEST(ParseGlslangOutputTest, CompletelyUnrecognized) { string_piece segment_number; string_piece line_number; string_piece rest; EXPECT_EQ(MessageType::Unknown, ParseGlslangOutput("hello world!", false, false, &segment_number, &line_number, &rest)); } TEST(ParseGlslangOutputTest, LocationSpecification) { string_piece segment_number; string_piece line_number; string_piece rest; // Glslang reading from strings can give string segment numbers as // the filename part. EXPECT_EQ( MessageType::Error, ParseGlslangOutput("ERROR: 0:2: '#' : invalid directive: foo", false, false, &segment_number, &line_number, &rest)); EXPECT_EQ("0", segment_number.str()); EXPECT_EQ("2", line_number.str()); EXPECT_EQ("'#' : invalid directive: foo", rest.str()); EXPECT_EQ( MessageType::Warning, ParseGlslangOutput("WARNING: 15:36: The following extension must be " "enabled to use this feature:", false, false, &segment_number, &line_number, &rest)); EXPECT_EQ("15", segment_number.str()); EXPECT_EQ("36", line_number.str()); EXPECT_EQ("The following extension must be enabled to use this feature:", rest.str()); } TEST(ParseGlslangOutputTest, FileName_BaseAndExtension) { string_piece source_name; string_piece line_number; string_piece rest; EXPECT_EQ(MessageType::Error, ParseGlslangOutput("ERROR: shader.vert:5: something wrong", false, false, &source_name, &line_number, &rest)); EXPECT_EQ("shader.vert", source_name.str()); EXPECT_EQ("5", line_number.str()); EXPECT_EQ("something wrong", rest.str()); } TEST(ParseGlslangOutputTest, FileName_BaseOnly) { string_piece source_name; string_piece line_number; string_piece rest; EXPECT_EQ(MessageType::Warning, ParseGlslangOutput("WARNING: file:42: something wrong", false, false, &source_name, &line_number, &rest)); EXPECT_EQ("file", source_name.str()); EXPECT_EQ("42", line_number.str()); EXPECT_EQ("something wrong", rest.str()); } TEST(ParseGlslangOutputTest, FileName_HexNumber) { string_piece source_name; string_piece line_number; string_piece rest; EXPECT_EQ(MessageType::Warning, ParseGlslangOutput("WARNING: 0xdeedbeef:0: wa:ha:ha", false, false, &source_name, &line_number, &rest)); EXPECT_EQ("0xdeedbeef", source_name.str()); EXPECT_EQ("0", line_number.str()); EXPECT_EQ("wa:ha:ha", rest.str()); } TEST(ParseGlslangOutputTest, FileName_ContainsColons) { string_piece source_name; string_piece line_number; string_piece rest; EXPECT_EQ(MessageType::Warning, ParseGlslangOutput("WARNING: foo:bar:0: wa:ha:ha", false, false, &source_name, &line_number, &rest)); EXPECT_EQ("foo:bar", source_name.str()); EXPECT_EQ("0", line_number.str()); EXPECT_EQ("wa:ha:ha", rest.str()); } TEST(ParseGlslangOutputTest, NoFile) { string_piece source_name; string_piece line_number; string_piece rest; EXPECT_EQ(MessageType::Warning, ParseGlslangOutput("WARNING: :12: abc", false, false, &source_name, &line_number, &rest)); EXPECT_EQ("", source_name.str()); EXPECT_EQ("12", line_number.str()); EXPECT_EQ("abc", rest.str()); } TEST(ParseGlslangOutputTest, NoLineNumber_InferredAsGlobalNoLocation) { string_piece source_name; string_piece line_number; string_piece rest; // No solution since there is no room for digits. EXPECT_EQ(MessageType::GlobalWarning, ParseGlslangOutput("WARNING: foo:: abc", false, false, &source_name, &line_number, &rest)); EXPECT_EQ("", source_name.str()); EXPECT_EQ("", line_number.str()); EXPECT_EQ("foo:: abc", rest.str()); } TEST(ParseGlslangOutputTest, NoSpaceAfterColon_InferredAsGlobalNoLocation) { string_piece source_name; string_piece line_number; string_piece rest; // No solution since there is no space after the line-number-and-colon. EXPECT_EQ(MessageType::GlobalWarning, ParseGlslangOutput("WARNING: foo:12:abc", false, false, &source_name, &line_number, &rest)); EXPECT_EQ("", source_name.str()); EXPECT_EQ("", line_number.str()); EXPECT_EQ("foo:12:abc", rest.str()); } TEST(ParseGlslangOutputTest, WindowsPath) { string_piece source_name; string_piece line_number; string_piece rest; EXPECT_EQ( MessageType::Error, ParseGlslangOutput(R"(ERROR: C:\path\to\shader.glsl:5: something wrong)", false, false, &source_name, &line_number, &rest)); EXPECT_EQ(R"(C:\path\to\shader.glsl)", source_name.str()); EXPECT_EQ("5", line_number.str()); EXPECT_EQ("something wrong", rest.str()); EXPECT_EQ( MessageType::Warning, ParseGlslangOutput(R"(WARNING: \\path\without\drive.vert:42: BOOM!)", false, false, &source_name, &line_number, &rest)); EXPECT_EQ(R"(\\path\without\drive.vert)", source_name.str()); EXPECT_EQ("42", line_number.str()); EXPECT_EQ("BOOM!", rest.str()); EXPECT_EQ(MessageType::Warning, ParseGlslangOutput(R"(WARNING: X:\123.456\789:0: wa:ha:ha)", false, false, &source_name, &line_number, &rest)); EXPECT_EQ(R"(X:\123.456\789)", source_name.str()); EXPECT_EQ("0", line_number.str()); EXPECT_EQ("wa:ha:ha", rest.str()); } } // anonymous namespace shaderc-2025.2/libshaderc_util/src/mutex_test.cc000066400000000000000000000026001500222170200216360ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/mutex.h" #include #include namespace { TEST(MutexTest, CanCreateMutex) { shaderc_util::mutex mutex; mutex.lock(); mutex.unlock(); } #ifndef SHADERC_DISABLE_THREADED_TESTS void increment_by_1000(shaderc_util::mutex& mut, int& i) { for(size_t j = 0; j < 1000; ++j) { mut.lock(); i = i + 1; mut.unlock(); } } TEST(MutexTest, MutexLocks) { shaderc_util::mutex mutex; int i = 0; std::thread t1([&mutex, &i]() { increment_by_1000(mutex, i); }); std::thread t2([&mutex, &i]() { increment_by_1000(mutex, i); }); std::thread t3([&mutex, &i]() { increment_by_1000(mutex, i); }); t1.join(); t2.join(); t3.join(); EXPECT_EQ(3000, i); } #endif // SHADERC_DISABLE_THREADED_TESTS } // anonymous namespace shaderc-2025.2/libshaderc_util/src/resources.cc000066400000000000000000000150331500222170200214530ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/resources.h" #include "glslang/Include/ResourceLimits.h" namespace shaderc_util { // These numbers come from the OpenGL 4.4 core profile specification Chapter 23 // unless otherwise specified. const TBuiltInResource kDefaultTBuiltInResource = { /*.maxLights = */ 8, // From OpenGL 3.0 table 6.46. /*.maxClipPlanes = */ 6, // From OpenGL 3.0 table 6.46. /*.maxTextureUnits = */ 2, // From OpenGL 3.0 table 6.50. /*.maxTextureCoords = */ 8, // From OpenGL 3.0 table 6.50. /*.maxVertexAttribs = */ 16, /*.maxVertexUniformComponents = */ 4096, /*.maxVaryingFloats = */ 60, // From OpenGLES 3.1 table 6.44. /*.maxVertexTextureImageUnits = */ 16, /*.maxCombinedTextureImageUnits = */ 80, /*.maxTextureImageUnits = */ 16, /*.maxFragmentUniformComponents = */ 1024, // glslang has 32 maxDrawBuffers. // Pixel phone Vulkan driver in Android N has 8 // maxFragmentOutputAttachments. /*.maxDrawBuffers = */ 8, /*.maxVertexUniformVectors = */ 256, /*.maxVaryingVectors = */ 15, // From OpenGLES 3.1 table 6.44. /*.maxFragmentUniformVectors = */ 256, /*.maxVertexOutputVectors = */ 16, // maxVertexOutputComponents / 4 /*.maxFragmentInputVectors = */ 15, // maxFragmentInputComponents / 4 /*.minProgramTexelOffset = */ -8, /*.maxProgramTexelOffset = */ 7, /*.maxClipDistances = */ 8, /*.maxComputeWorkGroupCountX = */ 65535, /*.maxComputeWorkGroupCountY = */ 65535, /*.maxComputeWorkGroupCountZ = */ 65535, /*.maxComputeWorkGroupSizeX = */ 1024, /*.maxComputeWorkGroupSizeX = */ 1024, /*.maxComputeWorkGroupSizeZ = */ 64, /*.maxComputeUniformComponents = */ 512, /*.maxComputeTextureImageUnits = */ 16, /*.maxComputeImageUniforms = */ 8, /*.maxComputeAtomicCounters = */ 8, /*.maxComputeAtomicCounterBuffers = */ 1, // From OpenGLES 3.1 Table 6.43 /*.maxVaryingComponents = */ 60, /*.maxVertexOutputComponents = */ 64, /*.maxGeometryInputComponents = */ 64, /*.maxGeometryOutputComponents = */ 128, /*.maxFragmentInputComponents = */ 128, /*.maxImageUnits = */ 8, // This does not seem to be defined anywhere, // set to ImageUnits. /*.maxCombinedImageUnitsAndFragmentOutputs = */ 8, /*.maxCombinedShaderOutputResources = */ 8, /*.maxImageSamples = */ 0, /*.maxVertexImageUniforms = */ 0, /*.maxTessControlImageUniforms = */ 0, /*.maxTessEvaluationImageUniforms = */ 0, /*.maxGeometryImageUniforms = */ 0, /*.maxFragmentImageUniforms = */ 8, /*.maxCombinedImageUniforms = */ 8, /*.maxGeometryTextureImageUnits = */ 16, /*.maxGeometryOutputVertices = */ 256, /*.maxGeometryTotalOutputComponents = */ 1024, /*.maxGeometryUniformComponents = */ 512, /*.maxGeometryVaryingComponents = */ 60, // Does not seem to be defined // anywhere, set equal to // maxVaryingComponents. /*.maxTessControlInputComponents = */ 128, /*.maxTessControlOutputComponents = */ 128, /*.maxTessControlTextureImageUnits = */ 16, /*.maxTessControlUniformComponents = */ 1024, /*.maxTessControlTotalOutputComponents = */ 4096, /*.maxTessEvaluationInputComponents = */ 128, /*.maxTessEvaluationOutputComponents = */ 128, /*.maxTessEvaluationTextureImageUnits = */ 16, /*.maxTessEvaluationUniformComponents = */ 1024, /*.maxTessPatchComponents = */ 120, /*.maxPatchVertices = */ 32, /*.maxTessGenLevel = */ 64, /*.maxViewports = */ 16, /*.maxVertexAtomicCounters = */ 0, /*.maxTessControlAtomicCounters = */ 0, /*.maxTessEvaluationAtomicCounters = */ 0, /*.maxGeometryAtomicCounters = */ 0, /*.maxFragmentAtomicCounters = */ 8, /*.maxCombinedAtomicCounters = */ 8, /*.maxAtomicCounterBindings = */ 1, /*.maxVertexAtomicCounterBuffers = */ 0, // From OpenGLES 3.1 Table 6.41. // ARB_shader_atomic_counters. /*.maxTessControlAtomicCounterBuffers = */ 0, /*.maxTessEvaluationAtomicCounterBuffers = */ 0, /*.maxGeometryAtomicCounterBuffers = */ 0, // /ARB_shader_atomic_counters. /*.maxFragmentAtomicCounterBuffers = */ 0, // From OpenGLES 3.1 Table 6.43. /*.maxCombinedAtomicCounterBuffers = */ 1, /*.maxAtomicCounterBufferSize = */ 32, /*.maxTransformFeedbackBuffers = */ 4, /*.maxTransformFeedbackInterleavedComponents = */ 64, /*.maxCullDistances = */ 8, // ARB_cull_distance. /*.maxCombinedClipAndCullDistances = */ 8, // ARB_cull_distance. /*.maxSamples = */ 4, /* .maxMeshOutputVerticesNV = */ 256, /* .maxMeshOutputPrimitivesNV = */ 512, /* .maxMeshWorkGroupSizeX_NV = */ 32, /* .maxMeshWorkGroupSizeY_NV = */ 1, /* .maxMeshWorkGroupSizeZ_NV = */ 1, /* .maxTaskWorkGroupSizeX_NV = */ 32, /* .maxTaskWorkGroupSizeY_NV = */ 1, /* .maxTaskWorkGroupSizeZ_NV = */ 1, /* .maxMeshViewCountNV = */ 4, /* .maxMeshOutputVerticesEXT = */ 256, /* .maxMeshOutputPrimitivesEXT = */ 256, /* .maxMeshWorkGroupSizeX_EXT = */ 128, /* .maxMeshWorkGroupSizeY_EXT = */ 128, /* .maxMeshWorkGroupSizeZ_EXT = */ 128, /* .maxTaskWorkGroupSizeX_EXT = */ 128, /* .maxTaskWorkGroupSizeY_EXT = */ 128, /* .maxTaskWorkGroupSizeZ_EXT = */ 128, /* .maxMeshViewCountEXT = */ 4, /* .maxDualSourceDrawBuffersEXT = */ 1, // This is the glslang TLimits structure. // It defines whether or not the following features are enabled. // We want them to all be enabled. /*.limits = */ { /*.nonInductiveForLoops = */ 1, /*.whileLoops = */ 1, /*.doWhileLoops = */ 1, /*.generalUniformIndexing = */ 1, /*.generalAttributeMatrixVectorIndexing = */ 1, /*.generalVaryingIndexing = */ 1, /*.generalSamplerIndexing = */ 1, /*.generalVariableIndexing = */ 1, /*.generalConstantMatrixVectorIndexing = */ 1, }}; } // namespace shaderc_util shaderc-2025.2/libshaderc_util/src/shader_stage.cc000066400000000000000000000031341500222170200220710ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/shader_stage.h" namespace { // Maps an identifier to a language. struct LanguageMapping { const char* id; EShLanguage language; }; } // anonymous namespace namespace shaderc_util { EShLanguage MapStageNameToLanguage(const string_piece& stage_name) { const LanguageMapping string_to_stage[] = { {"vertex", EShLangVertex}, {"fragment", EShLangFragment}, {"tesscontrol", EShLangTessControl}, {"tesseval", EShLangTessEvaluation}, {"geometry", EShLangGeometry}, {"compute", EShLangCompute}, {"raygen", EShLangRayGenNV}, {"intersect", EShLangIntersectNV}, {"anyhit", EShLangAnyHitNV}, {"closest", EShLangClosestHitNV}, {"miss", EShLangMissNV}, {"callable", EShLangCallableNV}, {"task", EShLangTaskNV}, {"mesh", EShLangMeshNV}, }; for (const auto& entry : string_to_stage) { if (stage_name == entry.id) return entry.language; } return EShLangCount; } } // namespace shaderc_util shaderc-2025.2/libshaderc_util/src/spirv_tools_wrapper.cc000066400000000000000000000142041500222170200235630ustar00rootroot00000000000000// Copyright 2016 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/spirv_tools_wrapper.h" #include #include #include "spirv-tools/libspirv.hpp" #include "spirv-tools/optimizer.hpp" namespace shaderc_util { namespace { // Gets the corresponding target environment used in SPIRV-Tools. spv_target_env GetSpirvToolsTargetEnv(Compiler::TargetEnv env, Compiler::TargetEnvVersion version) { switch (env) { case Compiler::TargetEnv::Vulkan: switch (version) { case Compiler::TargetEnvVersion::Default: return SPV_ENV_VULKAN_1_0; case Compiler::TargetEnvVersion::Vulkan_1_0: return SPV_ENV_VULKAN_1_0; case Compiler::TargetEnvVersion::Vulkan_1_1: return SPV_ENV_VULKAN_1_1; case Compiler::TargetEnvVersion::Vulkan_1_2: return SPV_ENV_VULKAN_1_2; case Compiler::TargetEnvVersion::Vulkan_1_3: return SPV_ENV_VULKAN_1_3; case Compiler::TargetEnvVersion::Vulkan_1_4: return SPV_ENV_VULKAN_1_4; default: break; } break; case Compiler::TargetEnv::OpenGL: return SPV_ENV_OPENGL_4_5; case Compiler::TargetEnv::OpenGLCompat: // Errors out before getting here. But the compiler wants us to handle // enum anyway. return SPV_ENV_OPENGL_4_5; } assert(false && "unexpected target environment or version"); return SPV_ENV_VULKAN_1_0; } } // anonymous namespace bool SpirvToolsDisassemble(Compiler::TargetEnv env, Compiler::TargetEnvVersion version, const std::vector& binary, std::string* text_or_error) { spvtools::SpirvTools tools(GetSpirvToolsTargetEnv(env, version)); std::ostringstream oss; tools.SetMessageConsumer([&oss](spv_message_level_t, const char*, const spv_position_t& position, const char* message) { oss << position.index << ": " << message; }); const bool success = tools.Disassemble(binary, text_or_error, SPV_BINARY_TO_TEXT_OPTION_INDENT | SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES); if (!success) { *text_or_error = oss.str(); } return success; } bool SpirvToolsAssemble(Compiler::TargetEnv env, Compiler::TargetEnvVersion version, const string_piece assembly, spv_binary* binary, std::string* errors) { auto spvtools_context = spvContextCreate(GetSpirvToolsTargetEnv(env, version)); spv_diagnostic spvtools_diagnostic = nullptr; *binary = nullptr; errors->clear(); const bool success = spvTextToBinary(spvtools_context, assembly.data(), assembly.size(), binary, &spvtools_diagnostic) == SPV_SUCCESS; if (!success) { std::ostringstream oss; oss << spvtools_diagnostic->position.line + 1 << ":" << spvtools_diagnostic->position.column + 1 << ": " << spvtools_diagnostic->error; *errors = oss.str(); } spvDiagnosticDestroy(spvtools_diagnostic); spvContextDestroy(spvtools_context); return success; } bool SpirvToolsOptimize(Compiler::TargetEnv env, Compiler::TargetEnvVersion version, const std::vector& enabled_passes, spvtools::OptimizerOptions& optimizer_options, std::vector* binary, std::string* errors) { errors->clear(); if (enabled_passes.empty()) return true; if (std::all_of( enabled_passes.cbegin(), enabled_passes.cend(), [](const PassId& pass) { return pass == PassId::kNullPass; })) { return true; } spvtools::ValidatorOptions val_opts; // This allows flexible memory layout for HLSL. val_opts.SetSkipBlockLayout(true); // This allows HLSL legalization regarding resources. val_opts.SetRelaxLogicalPointer(true); // This uses relaxed rules for pre-legalized HLSL. val_opts.SetBeforeHlslLegalization(true); // Don't use friendly names when printing validation errors. // It incurs a high startup cost whether or not there is an // error. Validation failures are compiler bugs, and so they // should be rare anyway. val_opts.SetFriendlyNames(false); // Set additional optimizer options. optimizer_options.set_validator_options(val_opts); optimizer_options.set_run_validator(true); spvtools::Optimizer optimizer(GetSpirvToolsTargetEnv(env, version)); std::ostringstream oss; optimizer.SetMessageConsumer( [&oss](spv_message_level_t, const char*, const spv_position_t&, const char* message) { oss << message << "\n"; }); for (const auto& pass : enabled_passes) { switch (pass) { case PassId::kLegalizationPasses: optimizer.RegisterLegalizationPasses(); break; case PassId::kPerformancePasses: optimizer.RegisterPerformancePasses(); break; case PassId::kSizePasses: optimizer.RegisterSizePasses(); break; case PassId::kNullPass: // We actually don't need to do anything for null pass. break; case PassId::kStripDebugInfo: optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass()); break; case PassId::kCompactIds: optimizer.RegisterPass(spvtools::CreateCompactIdsPass()); break; } } if (!optimizer.Run(binary->data(), binary->size(), binary, optimizer_options)) { *errors = oss.str(); return false; } return true; } } // namespace shaderc_util shaderc-2025.2/libshaderc_util/src/string_piece_test.cc000066400000000000000000000376521500222170200231660ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/string_piece.h" #include #include #include #include "death_test.h" namespace { using shaderc_util::string_piece; TEST(string_piece, creation) { std::string my_string("std::string"); const char* my_c_string = "c::string"; string_piece my_string_piece(my_string); string_piece my_c_string_piece(my_c_string); string_piece my_partial_c_string_piece(my_c_string, my_c_string + 3); string_piece my_string_piece_string_piece(my_string_piece); EXPECT_EQ("std::string", my_string_piece); EXPECT_EQ("c::string", my_c_string_piece); EXPECT_EQ("c::", my_partial_c_string_piece); EXPECT_EQ("std::string", my_string_piece_string_piece); } TEST(string_piece, creation_with_empty_data) { string_piece my_string_piece(nullptr, nullptr); EXPECT_EQ("", my_string_piece); } TEST(string_piece, creation_with_nullptr) { string_piece my_string_piece(nullptr); EXPECT_EQ("", my_string_piece); } TEST(string_pieceDeathTest, creation_causing_assert) { EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece("my_cstring", nullptr), ".*"); EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr, "my_cstring"), ".*"); } TEST(string_pieceDeathTest, front) { EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr).front(), "Assertion"); EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr, nullptr).front(), "Assertion"); EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece("").front(), "Assertion"); string_piece s("nonempty"); s.clear(); EXPECT_DEBUG_DEATH_IF_SUPPORTED(s.front(), "Assertion"); } TEST(string_pieceDeathTest, back) { EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr).back(), "Assertion"); EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr, nullptr).back(), "Assertion"); EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece("").back(), "Assertion"); string_piece s("nonempty"); s.clear(); EXPECT_DEBUG_DEATH_IF_SUPPORTED(s.back(), "Assertion"); } TEST(string_piece, substr) { string_piece my_string("my really long string"); EXPECT_EQ("my really long string", my_string.substr(0, string_piece::npos)); EXPECT_EQ("my really long string", my_string.substr(0)); EXPECT_EQ("really long string", my_string.substr(3, string_piece::npos)); EXPECT_EQ("really long string", my_string.substr(3)); EXPECT_EQ("really", my_string.substr(3, 6)); } TEST(string_piece, length) { EXPECT_EQ(0u, string_piece().size()); EXPECT_TRUE(string_piece().empty()); EXPECT_EQ(10u, string_piece("0123456789").size()); std::string my_string("std::string"); EXPECT_EQ(my_string.size(), string_piece(my_string).size()); } TEST(string_piece, clear) { string_piece my_string("my really long string"); EXPECT_EQ("my really long string", my_string); string_piece other_string(my_string); EXPECT_EQ("my really long string", other_string); my_string.clear(); EXPECT_EQ("", my_string); EXPECT_EQ("my really long string", other_string); } TEST(string_piece, str) { std::string test_string; { std::string temporary_string("my really long string"); string_piece my_stringpiece(temporary_string); string_piece my_substring = my_stringpiece.substr(3, 6); EXPECT_EQ("really", my_substring); test_string = my_substring.str(); } EXPECT_EQ("really", test_string); } template bool find_char(char c) { return c == C; } TEST(string_piece, find_first_not_matching) { string_piece my_string("aaaaaaa b"); EXPECT_EQ(7u, my_string.find_first_not_matching(find_char<'a'>)); EXPECT_EQ(0u, my_string.find_first_not_matching(find_char<'b'>)); EXPECT_EQ(0u, string_piece(" ").find_first_not_matching(::isdigit)); size_t npos = string_piece::npos; EXPECT_EQ(npos, string_piece("").find_first_not_matching(::isdigit)); EXPECT_EQ(npos, string_piece("123").find_first_not_matching(::isdigit)); EXPECT_EQ(3u, string_piece("123 ").find_first_not_matching(::isdigit)); } TEST(string_piece, find_first_not_of) { size_t npos = string_piece::npos; string_piece my_string("aaaaaaa b"); EXPECT_EQ(7u, my_string.find_first_not_of("a")); EXPECT_EQ(0u, my_string.find_first_not_of("b")); EXPECT_EQ(7u, my_string.find_first_not_of('a')); EXPECT_EQ(0u, my_string.find_first_not_of('b')); EXPECT_EQ(0u, string_piece(" ").find_first_not_of("0123456789")); EXPECT_EQ(7u, my_string.find_first_not_of("a", 2)); EXPECT_EQ(2u, my_string.find_first_not_of("b", 2)); EXPECT_EQ(7u, my_string.find_first_not_of('a', 2)); EXPECT_EQ(4u, my_string.find_first_not_of('b', 4)); EXPECT_EQ(0u, string_piece(" ").find_first_not_of("0123456789")); EXPECT_EQ(npos, string_piece(" ").find_first_not_of("0123456789", 5)); EXPECT_EQ(npos, string_piece("").find_first_not_of("012345689")); EXPECT_EQ(npos, string_piece("").find_first_not_of("012345689", 1)); EXPECT_EQ(npos, string_piece("123").find_first_not_of("0123456789")); EXPECT_EQ(npos, string_piece("123").find_first_not_of("0123456789", 1)); EXPECT_EQ(3u, string_piece("123 ").find_first_not_of("0123456789", 2)); EXPECT_EQ(npos, string_piece("123 ").find_first_not_of("0123456789", 4)); EXPECT_EQ(npos, string_piece("").find_first_not_of("1")); EXPECT_EQ(npos, string_piece("111").find_first_not_of('1')); } TEST(string_piece, find_first_of_char) { const size_t npos = string_piece::npos; string_piece my_string("my really long string"); EXPECT_EQ(0u, my_string.find_first_of('m')); EXPECT_EQ(3u, my_string.find_first_of('r')); EXPECT_EQ(npos, my_string.find_first_of('z')); size_t pos = my_string.find_first_of('l'); EXPECT_EQ(6u, pos); // If pos points to a 'l' then we should just find that one EXPECT_EQ(6u, my_string.find_first_of('l', pos)); EXPECT_EQ(7u, my_string.find_first_of('l', pos + 1)); EXPECT_EQ(10u, my_string.find_first_of('l', pos + 2)); EXPECT_EQ(npos, my_string.find_first_of('l', pos + 5)); EXPECT_EQ(npos, my_string.find_first_of('z', 0)); EXPECT_EQ(npos, my_string.find_first_of('z', npos)); my_string.clear(); EXPECT_EQ(npos, my_string.find_first_of('a')); EXPECT_EQ(npos, my_string.find_first_of('a', 0)); } TEST(string_piece, find_first_of) { string_piece my_string("aaaaaa b"); EXPECT_EQ(0u, my_string.find_first_of("a")); EXPECT_EQ(7u, my_string.find_first_of("b")); EXPECT_EQ(6u, my_string.find_first_of(" ")); size_t npos = string_piece::npos; EXPECT_EQ(npos, my_string.find_first_of("xh")); EXPECT_EQ(6u, my_string.find_first_of(" x")); EXPECT_EQ(6u, my_string.find_first_of(" b")); EXPECT_EQ(0u, my_string.find_first_of("ab")); EXPECT_EQ(6u, my_string.find_first_of(" x", 2)); EXPECT_EQ(6u, my_string.find_first_of(" b", 2)); EXPECT_EQ(2u, my_string.find_first_of("ab", 2)); EXPECT_EQ(npos, my_string.find_first_of("ab", 10)); EXPECT_EQ(npos, my_string.find_first_of("c")); EXPECT_EQ(npos, my_string.find_first_of("c", 1)); EXPECT_EQ(npos, string_piece(" ").find_first_of("a")); EXPECT_EQ(npos, string_piece(" ").find_first_of("a", 10)); EXPECT_EQ(npos, string_piece("aa").find_first_of("")); EXPECT_EQ(npos, string_piece("aa").find_first_of("", 1)); EXPECT_EQ(npos, string_piece("").find_first_of("")); EXPECT_EQ(npos, string_piece("").find_first_of("", 1)); EXPECT_EQ(npos, string_piece("").find_first_of("a")); EXPECT_EQ(npos, string_piece("").find_first_of("ae")); EXPECT_EQ(npos, string_piece("").find_first_of("ae", 32)); } TEST(string_piece, find_last_of) { string_piece my_string("aaaaaa b"); EXPECT_EQ(5u, my_string.find_last_of('a')); EXPECT_EQ(7u, my_string.find_last_of('b')); EXPECT_EQ(6u, my_string.find_last_of(' ')); EXPECT_EQ(5u, my_string.find_last_of("a")); EXPECT_EQ(7u, my_string.find_last_of("b")); EXPECT_EQ(6u, my_string.find_last_of(" ")); size_t npos = string_piece::npos; EXPECT_EQ(npos, my_string.find_last_of("xh")); EXPECT_EQ(6u, my_string.find_last_of(" x")); EXPECT_EQ(7u, my_string.find_last_of(" b")); EXPECT_EQ(7u, my_string.find_last_of("ab")); EXPECT_EQ(4u, my_string.find_last_of('a', 4)); EXPECT_EQ(5u, my_string.find_last_of('a', 6)); EXPECT_EQ(0u, string_piece("abbbaa").find_last_of('a', 3)); EXPECT_EQ(4u, string_piece("abbbaa").find_last_of('a', 4)); EXPECT_EQ(5u, string_piece("abbbaa").find_last_of('a', 5)); EXPECT_EQ(5u, string_piece("abbbaa").find_last_of('a', 6)); EXPECT_EQ(npos, string_piece("abbbaa").find_last_of('c', 2)); EXPECT_EQ(npos, my_string.find_last_of("c")); EXPECT_EQ(npos, string_piece(" ").find_last_of("a")); EXPECT_EQ(npos, string_piece("aa").find_last_of("")); EXPECT_EQ(npos, string_piece("").find_last_of("")); EXPECT_EQ(npos, string_piece("").find_last_of("a")); EXPECT_EQ(npos, my_string.find_last_of('c')); EXPECT_EQ(npos, string_piece(" ").find_last_of('a')); EXPECT_EQ(npos, string_piece("").find_last_of('a')); EXPECT_EQ(npos, string_piece("").find_last_of("ae")); } TEST(string_piece, begin_end) { const char* my_string = "my really long string"; string_piece p(my_string); size_t pos = 0; for (auto it = p.begin(); it != p.end(); ++it) { EXPECT_EQ(my_string[pos++], *it); } pos = 0; for (auto c : p) { EXPECT_EQ(my_string[pos++], c); } } TEST(string_piece, front_back) { // EXPECT_TRUE() is used here because gtest will think we are comparing // between pointer and integer here if EXPECT_EQ() is used. const string_piece one_char("a"); EXPECT_TRUE(one_char.front() == 'a'); EXPECT_TRUE(one_char.back() == 'a'); const string_piece two_chars("bc"); EXPECT_TRUE(two_chars.front() == 'b'); EXPECT_TRUE(two_chars.back() == 'c'); const string_piece multi_chars("w vm g gg t\t"); EXPECT_TRUE(multi_chars.front() == 'w'); EXPECT_TRUE(multi_chars.back() == '\t'); } TEST(string_piece, starts_with) { EXPECT_TRUE(string_piece("my string").starts_with("my")); EXPECT_TRUE(string_piece("my string").starts_with("my s")); EXPECT_TRUE(string_piece("my string").starts_with("m")); EXPECT_TRUE(string_piece("my string").starts_with("")); EXPECT_TRUE(string_piece("my string").starts_with("my string")); EXPECT_TRUE(string_piece("").starts_with("")); EXPECT_FALSE(string_piece("").starts_with("a")); EXPECT_FALSE(string_piece("my string").starts_with(" ")); EXPECT_FALSE(string_piece("my string").starts_with("my stq")); EXPECT_FALSE(string_piece("my string").starts_with("a")); EXPECT_FALSE(string_piece("my string").starts_with("my strings")); } TEST(string_piece, find) { const size_t npos = string_piece::npos; string_piece my_string("gooogle gooogle"); EXPECT_EQ(0u, my_string.find("")); EXPECT_EQ(0u, my_string.find("g")); EXPECT_EQ(4u, my_string.find("g", 1)); EXPECT_EQ(0u, my_string.find("go")); EXPECT_EQ(8u, my_string.find("go", 1)); EXPECT_EQ(1u, my_string.find("oo")); EXPECT_EQ(1u, my_string.find("oo", 1)); EXPECT_EQ(2u, my_string.find("oo", 2)); EXPECT_EQ(9u, my_string.find("oo", 3)); EXPECT_EQ(4u, my_string.find("gle")); EXPECT_EQ(12u, my_string.find("gle", 5)); EXPECT_EQ(npos, my_string.find("0")); EXPECT_EQ(npos, my_string.find("does-not-exist")); EXPECT_EQ(npos, my_string.find("longer than gooogle gooogle")); EXPECT_EQ(npos, my_string.find("", npos)); EXPECT_EQ(npos, my_string.find("gle", npos)); } TEST(string_piece, get_fields) { string_piece input; std::vector expected_lines; EXPECT_EQ(expected_lines, input.get_fields('\n')); EXPECT_EQ(expected_lines, input.get_fields('\n', true)); input = "first line"; expected_lines = {"first line"}; EXPECT_EQ(expected_lines, input.get_fields('\n')); EXPECT_EQ(expected_lines, input.get_fields('\n', true)); input = "first line\n"; expected_lines = {"first line"}; EXPECT_EQ(expected_lines, input.get_fields('\n')); expected_lines = {"first line\n"}; EXPECT_EQ(expected_lines, input.get_fields('\n', true)); input = "\nfirst line"; expected_lines = {"", "first line"}; EXPECT_EQ(expected_lines, input.get_fields('\n')); expected_lines = {"\n", "first line"}; EXPECT_EQ(expected_lines, input.get_fields('\n', true)); input = "first line\nsecond line\nthird line\n"; expected_lines = {"first line", "second line", "third line"}; EXPECT_EQ(expected_lines, input.get_fields('\n')); expected_lines = {"first line\n", "second line\n", "third line\n"}; EXPECT_EQ(expected_lines, input.get_fields('\n', true)); input = "first line\n\nsecond line\n\nthird line\n\n"; expected_lines = {"first line", "", "second line", "", "third line", ""}; EXPECT_EQ(expected_lines, input.get_fields('\n')); expected_lines = {"first line\n", "\n", "second line\n", "\n", "third line\n", "\n"}; EXPECT_EQ(expected_lines, input.get_fields('\n', true)); } TEST(string_piece, operator_stream_out) { std::stringstream stream; string_piece my_string("my really long string"); stream << my_string; EXPECT_EQ("my really long string", stream.str()); stream.str(""); stream << my_string.substr(3, 6); EXPECT_EQ("really", stream.str()); stream.str(""); stream << string_piece(); EXPECT_EQ("", stream.str()); } TEST(string_piece, lrstrip) { string_piece nothing_to_remove("abcdefg"); EXPECT_EQ("abcdefg", nothing_to_remove.lstrip("hijklmn")); EXPECT_EQ("abcdefg", nothing_to_remove.rstrip("hijklmn")); EXPECT_EQ("abcdefg", nothing_to_remove.strip("hijklmn")); string_piece empty_string(""); EXPECT_EQ(0u, empty_string.lstrip("google").size()); EXPECT_EQ(0u, empty_string.rstrip("google").size()); EXPECT_EQ(0u, empty_string.strip("google").size()); string_piece remove_nothing("asdfghjkl"); EXPECT_EQ("asdfghjkl", remove_nothing.lstrip("")); EXPECT_EQ("asdfghjkl", remove_nothing.rstrip("")); EXPECT_EQ("asdfghjkl", remove_nothing.strip("")); string_piece strip_numbers("0123g4o5o6g7l8e9"); EXPECT_EQ("g4o5o6g7l8e9", strip_numbers.lstrip("0123456789")); EXPECT_EQ("0123g4o5o6g7l8e", strip_numbers.rstrip("0123456789")); EXPECT_EQ("g4o5o6g7l8e", strip_numbers.strip("0123456789")); } TEST(string_piece, strip_whitespace) { string_piece lots_of_space(" b i n g o "); EXPECT_EQ("b i n g o", lots_of_space.strip_whitespace()); string_piece whitespaces("\v\t\f\n\rleft\r\t\f\n\vright\f\n\t\v\r"); EXPECT_EQ("left\r\t\f\n\vright", whitespaces.strip_whitespace()); string_piece remove_all(" \t "); EXPECT_EQ(0u, remove_all.strip_whitespace().size()); } TEST(string_piece, not_equal) { EXPECT_FALSE(string_piece() != string_piece()); EXPECT_FALSE(string_piece("") != string_piece()); EXPECT_TRUE(string_piece() != string_piece(" ")); EXPECT_FALSE(string_piece("abc") != string_piece("abc")); EXPECT_TRUE(string_piece("abc") != string_piece("abc ")); EXPECT_TRUE(string_piece("abc") != string_piece("abd")); EXPECT_FALSE("" != string_piece()); EXPECT_FALSE("" != string_piece("")); EXPECT_TRUE(" " != string_piece("")); EXPECT_FALSE("abc" != string_piece("abc")); EXPECT_TRUE(" abc" != string_piece("abc")); EXPECT_TRUE("abd" != string_piece("abc")); } TEST(string_piece, data) { EXPECT_EQ(nullptr, string_piece().data()); const char* empty = ""; EXPECT_EQ(empty, string_piece(empty).data()); const char* space = " "; EXPECT_EQ(space, string_piece(space).data()); const char* a = "a"; EXPECT_EQ(a, string_piece(a).data()); const char* abc = "abc"; EXPECT_EQ(abc, string_piece(abc).data()); EXPECT_EQ(abc + 1, string_piece(abc).substr(1).data()); EXPECT_EQ(abc + 3, string_piece(abc).substr(3).data()); } TEST(string_piece, unordered_map) { std::unordered_map dict; dict["abc"] = 123; EXPECT_EQ(123, dict["abc"]); } } // anonymous namespace shaderc-2025.2/libshaderc_util/src/version_profile.cc000066400000000000000000000034421500222170200226470ustar00rootroot00000000000000// Copyright 2015 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/version_profile.h" #include #include namespace { const int kVersionNumberLength = 3; const int kMaxProfileLength = 13; // strlen(compatibility) const int kMaxVersionProfileLength = kVersionNumberLength + kMaxProfileLength; const int kMinVersionProfileLength = kVersionNumberLength; } // anonymous namespace namespace shaderc_util { bool ParseVersionProfile(const std::string& version_profile, int* version, EProfile* profile) { if (version_profile.size() < kMinVersionProfileLength || version_profile.size() > kMaxVersionProfileLength || !::isdigit(version_profile.front())) return false; std::string profile_string; std::istringstream(version_profile) >> *version >> profile_string; if (!IsKnownVersion(*version)) { return false; } if (profile_string.empty()) { *profile = ENoProfile; } else if (profile_string == "core") { *profile = ECoreProfile; } else if (profile_string == "es") { *profile = EEsProfile; } else if (profile_string == "compatibility") { *profile = ECompatibilityProfile; } else { return false; } return true; } } // namespace shaderc_util shaderc-2025.2/libshaderc_util/src/version_profile_test.cc000066400000000000000000000125001500222170200237010ustar00rootroot00000000000000// Copyright 2017 The Shaderc Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "libshaderc_util/version_profile.h" #include "gmock/gmock.h" namespace { using shaderc_util::IsKnownVersion; using shaderc_util::ParseVersionProfile; using ::testing::Eq; using ::testing::ValuesIn; TEST(IsKnownVersionTest, Samples) { EXPECT_TRUE(IsKnownVersion(100)); EXPECT_TRUE(IsKnownVersion(110)); EXPECT_TRUE(IsKnownVersion(120)); EXPECT_TRUE(IsKnownVersion(130)); EXPECT_TRUE(IsKnownVersion(140)); EXPECT_TRUE(IsKnownVersion(150)); EXPECT_TRUE(IsKnownVersion(300)); EXPECT_TRUE(IsKnownVersion(330)); EXPECT_TRUE(IsKnownVersion(310)); EXPECT_TRUE(IsKnownVersion(400)); EXPECT_TRUE(IsKnownVersion(410)); EXPECT_TRUE(IsKnownVersion(420)); EXPECT_TRUE(IsKnownVersion(430)); EXPECT_TRUE(IsKnownVersion(440)); EXPECT_TRUE(IsKnownVersion(450)); EXPECT_TRUE(IsKnownVersion(460)); EXPECT_FALSE(IsKnownVersion(101)); EXPECT_FALSE(IsKnownVersion(470)); } struct ParseVersionProfileCase { std::string input; bool success; // The following are only used when success is true. int expected_version; EProfile expected_profile; }; using ParseVersionProfileTest = ::testing::TestWithParam; TEST_P(ParseVersionProfileTest, Sample) { int version = 0; EProfile profile = EBadProfile; const bool result = ParseVersionProfile(GetParam().input, &version, &profile); EXPECT_THAT(result, GetParam().success); if (result) { EXPECT_THAT(version, GetParam().expected_version); EXPECT_THAT(profile, GetParam().expected_profile); } } // For OpenGL ES GLSL (ESSL) versions, see // https://www.khronos.org/registry/OpenGL/index_e.php INSTANTIATE_TEST_SUITE_P(OpenGLESCases, ParseVersionProfileTest, ValuesIn(std::vector{ {"100es", true, 100, EEsProfile}, {"300es", true, 300, EEsProfile}, {"310es", true, 310, EEsProfile}, {"320es", true, 320, EEsProfile}, {"99es", false, 0, EBadProfile}, {"500es", false, 0, EBadProfile}, })); // For OpenGL GLSL versions, see // https://www.khronos.org/registry/OpenGL/index_gl.php INSTANTIATE_TEST_SUITE_P(OpenGLBlankCases, ParseVersionProfileTest, ValuesIn(std::vector{ {"110", true, 110, ENoProfile}, {"120", true, 120, ENoProfile}, {"130", true, 130, ENoProfile}, {"140", true, 140, ENoProfile}, {"150", true, 150, ENoProfile}, {"330", true, 330, ENoProfile}, {"400", true, 400, ENoProfile}, {"410", true, 410, ENoProfile}, {"420", true, 420, ENoProfile}, {"430", true, 430, ENoProfile}, {"440", true, 440, ENoProfile}, {"450", true, 450, ENoProfile}, {"460", true, 460, ENoProfile}, {"99", false, 0, EBadProfile}, {"500", false, 0, EBadProfile}, })); INSTANTIATE_TEST_SUITE_P(OpenGLCoreCases, ParseVersionProfileTest, ValuesIn(std::vector{ {"320core", true, 320, ECoreProfile}, {"330core", true, 330, ECoreProfile}, {"400core", true, 400, ECoreProfile}, {"410core", true, 410, ECoreProfile}, {"420core", true, 420, ECoreProfile}, {"430core", true, 430, ECoreProfile}, {"440core", true, 440, ECoreProfile}, {"450core", true, 450, ECoreProfile}, {"460core", true, 460, ECoreProfile}, })); INSTANTIATE_TEST_SUITE_P( OpenGLCompatibilityCases, ParseVersionProfileTest, ValuesIn(std::vector{ {"320compatibility", true, 320, ECompatibilityProfile}, {"330compatibility", true, 330, ECompatibilityProfile}, {"400compatibility", true, 400, ECompatibilityProfile}, {"410compatibility", true, 410, ECompatibilityProfile}, {"420compatibility", true, 420, ECompatibilityProfile}, {"430compatibility", true, 430, ECompatibilityProfile}, {"440compatibility", true, 440, ECompatibilityProfile}, {"450compatibility", true, 450, ECompatibilityProfile}, {"460compatibility", true, 460, ECompatibilityProfile}, })); } // anonymous namespace shaderc-2025.2/libshaderc_util/testdata/000077500000000000000000000000001500222170200201525ustar00rootroot00000000000000shaderc-2025.2/libshaderc_util/testdata/copy-to-build.cmake000066400000000000000000000012641500222170200236460ustar00rootroot00000000000000# Copyright 2020 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. file(GLOB all_files ${CMAKE_CURRENT_LIST_DIR}/*) file(COPY ${all_files} DESTINATION .)shaderc-2025.2/libshaderc_util/testdata/dir/000077500000000000000000000000001500222170200207305ustar00rootroot00000000000000shaderc-2025.2/libshaderc_util/testdata/dir/subdir/000077500000000000000000000000001500222170200222205ustar00rootroot00000000000000shaderc-2025.2/libshaderc_util/testdata/dir/subdir/include_file.2000066400000000000000000000000001500222170200247130ustar00rootroot00000000000000shaderc-2025.2/libshaderc_util/testdata/include_file.1000066400000000000000000000000521500222170200226530ustar00rootroot00000000000000The quick brown fox jumps over a lazy dog.shaderc-2025.2/license-checker.cfg000066400000000000000000000015501500222170200167120ustar00rootroot00000000000000[ { "licenses": [ "Apache-2.0" ], "paths": [ { "exclude": [ "**.md", "**.png", "**/README.asciidoc", ".*", "AUTHORS", "CHANGES", "CONTRIBUTORS", "DEPS", "LICENSE", "cmake/*.pc.in", "libshaderc_util/testdata/dir/subdir/include_file.2", "libshaderc_util/testdata/include_file.1", "utils/git-sync-deps", "third_party/**" ] } ] }, { "licenses": [ "BSD-3-Clause" ], "paths": [ { "exclude": [ "**" ] }, { "include": [ "utils/git-sync-deps" ] } ] } ] shaderc-2025.2/third_party/000077500000000000000000000000001500222170200155355ustar00rootroot00000000000000shaderc-2025.2/third_party/Android.mk000066400000000000000000000021771500222170200174550ustar00rootroot00000000000000THIRD_PARTY_PATH := $(call my-dir) # Set the location of glslang ifeq ($(GLSLANG_LOCAL_PATH),) GLSLANG_LOCAL_PATH:=$(THIRD_PARTY_PATH)/glslang endif include $(GLSLANG_LOCAL_PATH)/Android.mk # Set the location of SPIRV-Tools. # Allow the user to override it, but default it to under our third_party directory. ifeq ($(SPVTOOLS_LOCAL_PATH),) SPVTOOLS_LOCAL_PATH:=$(THIRD_PARTY_PATH)/spirv-tools endif ifeq ($(SPVHEADERS_LOCAL_PATH),) # Use the third party dir if it exists. ifneq ($(wildcard $(THIRD_PARTY_PATH)/spirv-headers/include/spirv/spir-v.xml),) SPVHEADERS_LOCAL_PATH:=$(THIRD_PARTY_PATH)/spirv-headers else # Let SPIRV-Tools find its own headers and hope for the best. endif endif # Now include the SPIRV-Tools dependency include $(SPVTOOLS_LOCAL_PATH)/Android.mk ifeq ($(SHADERC_ENABLE_SPVC),1) # Set the location of SPIRV-Cross. # Allow the user to override it, but default it to under our third_party directory. ifeq ($(SPVCROSS_LOCAL_PATH),) SPVCROSS_LOCAL_PATH:=$(THIRD_PARTY_PATH)/spirv-cross endif # Now include the SPIRV-Cross dependency include $(SPVCROSS_LOCAL_PATH)/jni/Android.mk endif shaderc-2025.2/third_party/CMakeLists.txt000066400000000000000000000116031500222170200202760ustar00rootroot00000000000000# Suppress all warnings from third-party projects. set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS -w) set(SHADERC_THIRD_PARTY_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE STRING "Root location of all third_party projects") set(SHADERC_GOOGLE_TEST_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/googletest" CACHE STRING "Location of googletest source") set(SHADERC_SPIRV_TOOLS_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/spirv-tools" CACHE STRING "Location of spirv-tools source") set(SHADERC_SPIRV_HEADERS_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/spirv-headers" CACHE STRING "Location of spirv-headers source") set(SHADERC_GLSLANG_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/glslang" CACHE STRING "Location of glslang source") set(SHADERC_EFFCEE_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/effcee" CACHE STRING "Location of effcee source") set(SHADERC_RE2_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/re2" CACHE STRING "Location of re2 source") set(SHADERC_TINT_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/tint" CACHE STRING "Location of tint source") set(SHADERC_ABSL_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/abseil_cpp" CACHE STRING "Location of re2 source") set( SKIP_GLSLANG_INSTALL ${SHADERC_SKIP_INSTALL} ) set( SKIP_SPIRV_TOOLS_INSTALL ${SHADERC_SKIP_INSTALL} ) set( SKIP_GOOGLETEST_INSTALL ${SHADERC_SKIP_INSTALL} ) # Configure third party projects. if(${SHADERC_ENABLE_TESTS}) if (IS_DIRECTORY ${SHADERC_GOOGLE_TEST_DIR}) add_subdirectory(${SHADERC_GOOGLE_TEST_DIR} googletest) endif() if (NOT TARGET gmock) message(FATAL_ERROR "gmock was not found - required for tests") endif() endif() set(OLD_PLATFORM_TOOLSET ${CMAKE_GENERATOR_TOOLSET}) check_cxx_compiler_flag(-fPIC COMPILER_SUPPORTS_PIC) if (IS_DIRECTORY ${SHADERC_SPIRV_HEADERS_DIR}) set(SPIRV_HEADERS_SKIP_EXAMPLES ON) add_subdirectory(${SHADERC_SPIRV_HEADERS_DIR} spirv-headers) endif() if (NOT TARGET SPIRV-Tools) # Check SPIRV-Tools before glslang so that it is linked into glslang. # we control optimizations via glslang API calls directly. if (IS_DIRECTORY ${SHADERC_SPIRV_TOOLS_DIR}) if ("${SHADERC_SKIP_TESTS}") # Also skip building tests in SPIRV-Tools. set(SPIRV_SKIP_TESTS ON CACHE BOOL "Skip building SPIRV-Tools tests") elseif(NOT "${SPIRV_SKIP_TESTS}") # SPIRV-Tools requires effcee, re2, and abseil to build tests. # re2 depends on abseil, so abseil must be added first. set(ABSL_INTERNAL_AT_LEAST_CXX17 ON) set(ABSL_PROPAGATE_CXX_STD ON) set(ABSL_ENABLE_INSTALL ON) add_subdirectory(${SHADERC_ABSL_DIR} absl EXCLUDE_FROM_ALL) # re2 tests take a long time and do not add much value, since re2 is a # dependency of a dependency, so not running them. set(RE2_BUILD_TESTING OFF CACHE STRING "Run RE2 Tests") add_subdirectory(${SHADERC_RE2_DIR} re2) add_subdirectory(${SHADERC_EFFCEE_DIR} effcee) endif() add_subdirectory(${SHADERC_SPIRV_TOOLS_DIR} spirv-tools) if (NOT "${SPIRV_SKIP_TESTS}") if (MSVC) if (${MSVC_VERSION} LESS 1920) # VS 2017 requires /bigobj on test_opt # https://github.com/google/shaderc/issues/1345 # https://github.com/KhronosGroup/SPIRV-Tools/issues/5335 target_compile_options(test_opt PRIVATE /bigobj) endif() endif() endif() endif() if (NOT TARGET SPIRV-Tools) message(FATAL_ERROR "SPIRV-Tools was not found - required for compilation") endif() endif() if (NOT TARGET glslang) if (IS_DIRECTORY ${SHADERC_GLSLANG_DIR}) if (SHADERC_ENABLE_TESTS) # Glslang tests are off by default. Turn them on if testing Shaderc. set(GLSLANG_TESTS ON) endif() set(GLSLANG_ENABLE_INSTALL $) add_subdirectory(${SHADERC_GLSLANG_DIR} glslang) endif() if (NOT TARGET glslang) message(FATAL_ERROR "glslang was not found - required for compilation") endif() if(WIN32) # This is unfortunate but glslang forces our # platform toolset to be v110, which we may not even have # installed, undo anything glslang has done to it. set(CMAKE_GENERATOR_TOOLSET "${OLD_PLATFORM_TOOLSET}" CACHE STRING "Platform Toolset" FORCE) endif() endif() if (SHADERC_ENABLE_WGSL_OUTPUT) # Use Google Tint for WGSL output. if (NOT TARGET libtint) if (IS_DIRECTORY ${SHADERC_TINT_DIR}) if (NOT IS_DIRECTORY ${SHADERC_TINT_DIR}/out/docs) # The Tint Doxygen configuration assumes it can write to the out/docs # source directory. message(STATUS "Tint source directory out/docs does not exist. Disabling doc generation") set(TINT_BUILD_DOCS OFF) endif() set(TINT_BUILD_SPV_READER ON CACHE BOOL "Built Tint SPIR-V reader" FORCE) set(TINT_BUILD_WGSL_WRITER ON CACHE BOOL "Build Tint WGSL writer" FORCE) add_subdirectory(${SHADERC_TINT_DIR} tint) endif() endif() if (NOT TARGET libtint) message(FATAL_ERROR "Tint was not found - required for WGSL output") endif() endif (SHADERC_ENABLE_WGSL_OUTPUT) shaderc-2025.2/third_party/LICENSE.glslang000066400000000000000000000201301500222170200201640ustar00rootroot00000000000000----- Most code has one of the following copyrights: Copyright (C) 2002-2005 3Dlabs Inc. Ltd. Copyright (C) 2012-2014 LunarG, Inc. Copyright (C) 2002-2010 The ANGLE Project Authors. Copyright (C) 2015-2016 Google, Inc. and is covered under the following license (BSD): // //All rights reserved. // //Redistribution and use in source and binary forms, with or without //modification, are permitted provided that the following conditionsA //are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // // Neither the name of 3Dlabs Inc. Ltd. nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //POSSIBILITY OF SUCH DAMAGE. // ----- Files under glslang/MachineIndependent/preprocessor used under the following license (BSD-like): /****************************************************************************\ Copyright (c) 2002, NVIDIA Corporation. NVIDIA Corporation("NVIDIA") supplies this software to you in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this NVIDIA software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this NVIDIA software. In consideration of your agreement to abide by the following terms, and subject to these terms, NVIDIA grants you a personal, non-exclusive license, under NVIDIA's copyrights in this original NVIDIA software (the "NVIDIA Software"), to use, reproduce, modify and redistribute the NVIDIA Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the NVIDIA Software, you must retain the copyright notice of NVIDIA, this notice and the following text and disclaimers in all such redistributions of the NVIDIA Software. Neither the name, trademarks, service marks nor logos of NVIDIA Corporation may be used to endorse or promote products derived from the NVIDIA Software without specific prior written permission from NVIDIA. Except as expressly stated in this notice, no other rights or licenses express or implied, are granted by NVIDIA herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the NVIDIA Software may be incorporated. No hardware is licensed hereunder. THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER PRODUCTS. IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \****************************************************************************/ ----- The file glslang/MachineIndependent/gl_types.h has the following license (MIT): /* ** Copyright (c) 2013 The Khronos Group Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and/or associated documentation files (the ** "Materials"), to deal in the Materials without restriction, including ** without limitation the rights to use, copy, modify, merge, publish, ** distribute, sublicense, and/or sell copies of the Materials, and to ** permit persons to whom the Materials are furnished to do so, subject to ** the following conditions: ** ** The above copyright notice and this permission notice shall be included ** in all copies or substantial portions of the Materials. ** ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ ----- The files glslang/SPIRV/GLSL.std.450.h and glslang/SPIRV/spirv.hpp have the following license. /* ** Copyright (c) 2014-2016 The Khronos Group Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and/or associated documentation files (the "Materials"), ** to deal in the Materials without restriction, including without limitation ** the rights to use, copy, modify, merge, publish, distribute, sublicense, ** and/or sell copies of the Materials, and to permit persons to whom the ** Materials are furnished to do so, subject to the following conditions: ** ** The above copyright notice and this permission notice shall be included in ** all copies or substantial portions of the Materials. ** ** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS ** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND ** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ ** ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS ** IN THE MATERIALS. */ ----- Files under tools/data contain portions of GNU Bison, and are used under the following license (GPL v3), with an exception as described at at http://www.gnu.org/software/bison/manual/bison.html#Conditions. In particular, when parsers are generated from the template files, an exception clause is inserted into the generated source files which allows their use in non-free programs. # Copyright (C) 1984, 1989-1990, 1999-2012 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . shaderc-2025.2/third_party/LICENSE.spirv-tools000066400000000000000000000266021500222170200210500ustar00rootroot00000000000000Note: The license for SPIRV-Tools changed to Apache 2.0 via this commit: https://github.com/KhronosGroup/SPIRV-Tools/commit/9fc8658ef301b0f03b2173d274c52f011b5c73e5 // Copyright (c) 2015-2016 The Khronos Group Inc. // Copyright (c) 2015-2016 Google Inc. // Copyright (c) 2016 LunarG Inc. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. shaderc-2025.2/utils/000077500000000000000000000000001500222170200143445ustar00rootroot00000000000000shaderc-2025.2/utils/add_copyright.py000077500000000000000000000117551500222170200175520ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Adds copyright notices to all the files that need them under the current directory. usage: add_copyright.py [--check] With --check, prints out all the files missing the copyright notice and exits with status 1 if any such files are found, 0 if none. """ import fileinput import fnmatch import os import re import sys COPYRIGHTRE = re.compile( r'Copyright \d+ The Shaderc Authors. All rights reserved.') COPYRIGHT = 'Copyright 2016 The Shaderc Authors. All rights reserved.' LICENSED = """ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.""" def find(top, filename_glob, skip_glob_list): """Returns files in the tree rooted at top matching filename_glob but not in directories matching skip_glob_list.""" file_list = [] for path, dirs, files in os.walk(top): for glob in skip_glob_list: for match in fnmatch.filter(dirs, glob): dirs.remove(match) for filename in fnmatch.filter(files, filename_glob): file_list.append(os.path.join(path, filename)) return file_list def filtered_descendants(glob): """Returns glob-matching filenames under the current directory, but skips some irrelevant paths.""" return find('.', glob, ['third_party', 'external', 'build*', 'out*', 'CompilerIdCXX', '.venv', 'glslang']) def skip(line): """Returns true if line is all whitespace or shebang.""" stripped = line.lstrip() return stripped == '' or stripped.startswith('#!') def comment(text, prefix): """Returns commented-out text. Each line of text will be prefixed by prefix and a space character. Any trailing whitespace will be trimmed. """ accum = [] for line in text.split('\n'): accum.append((prefix + ' ' + line).rstrip()) return '\n'.join(accum) def insert_copyright(glob, comment_prefix): """Finds all glob-matching files under the current directory and inserts the copyright message into them unless they already have it or are empty. The copyright message goes into the first non-whitespace, non- shebang line in a file. It is prefixed on each line by comment_prefix and a space. """ copyright = comment(COPYRIGHT, comment_prefix) + '\n' licensed = comment(LICENSED, comment_prefix) + '\n\n' for file in filtered_descendants(glob): has_copyright = False for line in fileinput.input(file, inplace=1): has_copyright = has_copyright or COPYRIGHTRE.search(line) if not has_copyright and not skip(line): sys.stdout.write(copyright) sys.stdout.write(licensed) has_copyright = True sys.stdout.write(line) if not has_copyright: open(file, 'a').write(copyright + licensed) def alert_if_no_copyright(glob, comment_prefix): """Prints names of all files missing a copyright message. Finds all glob-matching files under the current directory and checks if they contain the copyright message. Prints the names of all the files that don't. Returns the total number of file names printed. """ printed_count = 0 for file in filtered_descendants(glob): has_copyright = False with open(file) as contents: for line in contents: if COPYRIGHTRE.search(line): has_copyright = True break if not has_copyright: print(file, ' has no copyright message.') printed_count += 1 return printed_count def main(): glob_comment_pairs = [('*.h', '//'), ('*.hpp', '//'), ('*.cc', '//'), ('*.py', '#'), ('*.cpp', '//')] if '--check' in sys.argv: count = 0 for pair in glob_comment_pairs: count += alert_if_no_copyright(*pair) sys.exit(count > 0) else: for pair in glob_comment_pairs: insert_copyright(*pair) if __name__ == '__main__': main() shaderc-2025.2/utils/git-sync-deps000077500000000000000000000222031500222170200167570ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2014 Google Inc. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Parse a DEPS file and git checkout all of the dependencies. Args: An optional list of deps_os values. Environment Variables: GIT_EXECUTABLE: path to "git" binary; if unset, will look for one of ['git', 'git.exe', 'git.bat'] in your default path. GIT_SYNC_DEPS_PATH: file to get the dependency list from; if unset, will use the file ../DEPS relative to this script's directory. GIT_SYNC_DEPS_QUIET: if set to non-empty string, suppress messages. Git Config: To disable syncing of a single repository: cd path/to/repository git config sync-deps.disable true To re-enable sync: cd path/to/repository git config --unset sync-deps.disable """ import os import re import subprocess import sys import threading from builtins import bytes def git_executable(): """Find the git executable. Returns: A string suitable for passing to subprocess functions, or None. """ envgit = os.environ.get('GIT_EXECUTABLE') searchlist = ['git', 'git.exe', 'git.bat'] if envgit: searchlist.insert(0, envgit) with open(os.devnull, 'w') as devnull: for git in searchlist: try: subprocess.call([git, '--version'], stdout=devnull) except (OSError,): continue return git return None DEFAULT_DEPS_PATH = os.path.normpath( os.path.join(os.path.dirname(__file__), os.pardir, 'DEPS')) def usage(deps_file_path = None): sys.stderr.write( 'Usage: run to grab dependencies, with optional platform support:\n') sys.stderr.write(' %s %s' % (sys.executable, __file__)) if deps_file_path: parsed_deps = parse_file_to_dict(deps_file_path) if 'deps_os' in parsed_deps: for deps_os in parsed_deps['deps_os']: sys.stderr.write(' [%s]' % deps_os) sys.stderr.write('\n\n') sys.stderr.write(__doc__) def git_repository_sync_is_disabled(git, directory): try: disable = subprocess.check_output( [git, 'config', 'sync-deps.disable'], cwd=directory) return disable.lower().strip() in ['true', '1', 'yes', 'on'] except subprocess.CalledProcessError: return False def is_git_toplevel(git, directory): """Return true iff the directory is the top level of a Git repository. Args: git (string) the git executable directory (string) the path into which the repository is expected to be checked out. """ try: toplevel = subprocess.check_output( [git, 'rev-parse', '--show-toplevel'], cwd=directory).strip() return os.path.realpath(bytes(directory, 'utf8')) == os.path.realpath(toplevel) except subprocess.CalledProcessError: return False def status(directory, checkoutable): def truncate(s, length): return s if len(s) <= length else s[:(length - 3)] + '...' dlen = 36 directory = truncate(directory, dlen) checkoutable = truncate(checkoutable, 40) sys.stdout.write('%-*s @ %s\n' % (dlen, directory, checkoutable)) def git_checkout_to_directory(git, repo, checkoutable, directory, verbose): """Checkout (and clone if needed) a Git repository. Args: git (string) the git executable repo (string) the location of the repository, suitable for passing to `git clone`. checkoutable (string) a tag, branch, or commit, suitable for passing to `git checkout` directory (string) the path into which the repository should be checked out. verbose (boolean) Raises an exception if any calls to git fail. """ if not os.path.isdir(directory): subprocess.check_call( [git, 'clone', '--quiet', repo, directory]) if not is_git_toplevel(git, directory): # if the directory exists, but isn't a git repo, you will modify # the parent repostory, which isn't what you want. sys.stdout.write('%s\n IS NOT TOP-LEVEL GIT DIRECTORY.\n' % directory) return # Check to see if this repo is disabled. Quick return. if git_repository_sync_is_disabled(git, directory): sys.stdout.write('%s\n SYNC IS DISABLED.\n' % directory) return with open(os.devnull, 'w') as devnull: # If this fails, we will fetch before trying again. Don't spam user # with error infomation. if 0 == subprocess.call([git, 'checkout', '--quiet', checkoutable], cwd=directory, stderr=devnull): # if this succeeds, skip slow `git fetch`. if verbose: status(directory, checkoutable) # Success. return # If the repo has changed, always force use of the correct repo. # If origin already points to repo, this is a quick no-op. subprocess.check_call( [git, 'remote', 'set-url', 'origin', repo], cwd=directory) subprocess.check_call([git, 'fetch', '--quiet'], cwd=directory) subprocess.check_call([git, 'checkout', '--quiet', checkoutable], cwd=directory) if verbose: status(directory, checkoutable) # Success. def parse_file_to_dict(path): dictionary = {} contents = open(path).read() # Need to convert Var() to vars[], so that the DEPS is actually Python. Var() # comes from Autoroller using gclient which has a slightly different DEPS # format. contents = re.sub(r"Var\((.*?)\)", r"vars[\1]", contents) exec(contents, dictionary) return dictionary def git_sync_deps(deps_file_path, command_line_os_requests, verbose): """Grab dependencies, with optional platform support. Args: deps_file_path (string) Path to the DEPS file. command_line_os_requests (list of strings) Can be empty list. List of strings that should each be a key in the deps_os dictionary in the DEPS file. Raises git Exceptions. """ git = git_executable() assert git deps_file_directory = os.path.dirname(deps_file_path) deps_file = parse_file_to_dict(deps_file_path) dependencies = deps_file['deps'].copy() os_specific_dependencies = deps_file.get('deps_os', dict()) if 'all' in command_line_os_requests: for value in list(os_specific_dependencies.values()): dependencies.update(value) else: for os_name in command_line_os_requests: # Add OS-specific dependencies if os_name in os_specific_dependencies: dependencies.update(os_specific_dependencies[os_name]) for directory in dependencies: for other_dir in dependencies: if directory.startswith(other_dir + '/'): raise Exception('%r is parent of %r' % (other_dir, directory)) list_of_arg_lists = [] for directory in sorted(dependencies): if '@' in dependencies[directory]: repo, checkoutable = dependencies[directory].split('@', 1) else: raise Exception("please specify commit or tag") relative_directory = os.path.join(deps_file_directory, directory) list_of_arg_lists.append( (git, repo, checkoutable, relative_directory, verbose)) multithread(git_checkout_to_directory, list_of_arg_lists) for directory in deps_file.get('recursedeps', []): recursive_path = os.path.join(deps_file_directory, directory, 'DEPS') git_sync_deps(recursive_path, command_line_os_requests, verbose) def multithread(function, list_of_arg_lists): # for args in list_of_arg_lists: # function(*args) # return threads = [] for args in list_of_arg_lists: thread = threading.Thread(None, function, None, args) thread.start() threads.append(thread) for thread in threads: thread.join() def main(argv): deps_file_path = os.environ.get('GIT_SYNC_DEPS_PATH', DEFAULT_DEPS_PATH) verbose = not bool(os.environ.get('GIT_SYNC_DEPS_QUIET', False)) if '--help' in argv or '-h' in argv: usage(deps_file_path) return 1 git_sync_deps(deps_file_path, argv, verbose) # subprocess.check_call( # [sys.executable, # os.path.join(os.path.dirname(deps_file_path), 'bin', 'fetch-gn')]) return 0 if __name__ == '__main__': exit(main(sys.argv[1:])) shaderc-2025.2/utils/remove-file-by-suffix.py000077500000000000000000000020051500222170200210420ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2015 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Removes all files with a certain suffix in a given path recursively. # Arguments: path suffix import os import sys def main(): path = sys.argv[1] suffix = sys.argv[2] for root, _, filenames in os.walk(path): for filename in filenames: if filename.endswith(suffix): os.remove(os.path.join(root, filename)) if __name__ == '__main__': main() shaderc-2025.2/utils/roll-deps000077500000000000000000000031761500222170200162020ustar00rootroot00000000000000#!/usr/bin/env bash # Copyright 2019 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Attempts to roll all entries in DEPS to tip-of-tree and create a commit. # # Depends on roll-dep from depot_path being in PATH. set -eo pipefail function ExitIfIsInterestingError() { local return_code=$1 if [[ ${return_code} -ne 0 && ${return_code} -ne 2 ]]; then exit ${return_code} fi return 0 } dependencies=("third_party/effcee/" "third_party/glslang/" "third_party/googletest/" "third_party/re2/" "third_party/spirv-headers/" "third_party/spirv-tools/") branch="origin/main" # This script assumes it's parent directory is the repo root. repo_path=$(dirname "$0")/.. cd "$repo_path" if [[ $(git diff --stat) != '' ]]; then echo "Working tree is dirty, commit changes before attempting to roll DEPS" exit 1 fi echo "*** Ignore messages about running 'git cl upload' ***" set +e for dep in ${dependencies[@]}; do echo "Rolling $dep" roll-dep --ignore-dirty-tree --roll-to="${branch}" "${dep}" ExitIfIsInterestingError $? done shaderc-2025.2/utils/update_build_version.py000077500000000000000000000126301500222170200211310ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2016 The Shaderc Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Updates build-version.inc in the current directory, unless the update is # identical to the existing content. # # Args: # # For each directory, there will be a line in build-version.inc containing that # directory's "git describe" output enclosed in double quotes and appropriately # escaped. import datetime import errno import os.path import re import subprocess import sys import time def mkdir_p(directory): """Make the directory, and all its ancestors as required. Any of the directories are allowed to already exist.""" if directory == "": # We're being asked to make the current directory. return try: os.makedirs(directory) except OSError as e: if e.errno == errno.EEXIST and os.path.isdir(directory): pass else: raise def command_output(cmd, directory): """Runs a command in a directory and returns its standard output stream. Captures the standard error stream. Raises a RuntimeError if the command fails to launch or otherwise fails. """ p = subprocess.Popen(cmd, cwd=directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, _) = p.communicate() if p.returncode != 0: raise RuntimeError('Failed to run {} in {}'.format(cmd, directory)) return stdout def deduce_software_version(directory): """Returns a software version number parsed from the CHANGES file in the given directory. The CHANGES file describes most recent versions first. """ # Match the first well-formed version-and-date line. # Allow trailing whitespace in the checked-out source code has # unexpected carriage returns on a linefeed-only system such as # Linux. pattern = re.compile(r'^(v\d+\.\d+(-dev|[\.-]rc\d+)?) \d\d\d\d-\d\d-\d\d\s*$') changes_file = os.path.join(directory, 'CHANGES') with open(changes_file, errors='replace') as f: for line in f.readlines(): match = pattern.match(line) if match: return match.group(1) raise Exception('No version number found in {}'.format(changes_file)) def describe(directory): """Returns a string describing the current Git HEAD version as descriptively as possible. Runs 'git describe', or alternately 'git rev-parse HEAD', in directory. If successful, returns the output; otherwise returns 'unknown hash, '. """ try: # decode() is needed here for Python3 compatibility. In Python2, # str and bytes are the same type, but not in Python3. # Popen.communicate() returns a bytes instance, which needs to be # decoded into text data first in Python3. And this decode() won't # hurt Python2. return command_output(['git', 'describe'], directory).rstrip().decode() except: try: return command_output( ['git', 'rev-parse', 'HEAD'], directory).rstrip().decode() except: # This is the fallback case where git gives us no information, # e.g. because the source tree might not be in a git tree. # In this case, usually use a timestamp. However, to ensure # reproducible builds, allow the builder to override the wall # clock time with enviornment variable SOURCE_DATE_EPOCH # containing a (presumably) fixed timestamp. timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', time.time())) formatted = datetime.date.fromtimestamp(timestamp).isoformat() return 'unknown hash, {}'.format(formatted) def get_version_string(project, directory): """Returns a detailed version string for a given project with its directory, which consists of software version string and git description string.""" detailed_version_string_lst = [project] if project != 'glslang': detailed_version_string_lst.append(deduce_software_version(directory)) detailed_version_string_lst.append(describe(directory).replace('"', '\\"')) return ' '.join(detailed_version_string_lst) def main(): if len(sys.argv) != 5: print(('usage: {} '.format( sys.argv[0]))) sys.exit(1) projects = ['shaderc', 'spirv-tools', 'glslang'] new_content = ''.join([ '"{}\\n"\n'.format(get_version_string(p, d)) for (p, d) in zip(projects, sys.argv[1:]) ]) output_file = sys.argv[4] mkdir_p(os.path.dirname(output_file)) if os.path.isfile(output_file): with open(output_file, 'r') as f: if new_content == f.read(): return with open(output_file, 'w') as f: f.write(new_content) if __name__ == '__main__': main()