Merge remote-tracking branch 'origin/main' into HEAD
Change-Id: I6c263be000d8cf1ab51fb9c82e0b112298f2fc78
diff --git a/.appveyor.yml b/.appveyor.yml
deleted file mode 100644
index 50446ac..0000000
--- a/.appveyor.yml
+++ /dev/null
@@ -1,58 +0,0 @@
-# Windows Build Configuration for AppVeyor
-# http://www.appveyor.com/docs/appveyor-yml
-
-# version format
-version: "{build}"
-
-platform:
- - x64
-
-environment:
- PYTHON_PATH: "C:/Python27"
- PYTHON_PACKAGE_PATH: "C:/Python27/Scripts"
-
-configuration:
- - Debug
- - Release
-
-branches:
- only:
- - master
-
-# scripts that are called at very beginning, before repo cloning
-init:
- - ps: (new-object net.webclient).DownloadFile('https://bootstrap.pypa.io/get-pip.py', 'C:/get-pip.py')
- - "%PYTHON_PATH%/python.exe C:/get-pip.py"
- - "%PYTHON_PACKAGE_PATH%/pip.exe install nose"
-
-# scripts that run after cloning repository
-install:
- - git clone https://github.com/google/googletest.git third_party/googletest
- - git clone https://github.com/google/glslang.git third_party/glslang
- - git clone https://github.com/KhronosGroup/SPIRV-Tools.git third_party/spirv-tools
- - git clone https://github.com/KhronosGroup/SPIRV-Headers.git third_party/spirv-tools/external/spirv-headers
-
-build:
- parallel: true # enable MSBuild parallel builds
- verbosity: minimal
-
-build_script:
- - mkdir build && cd build
- - cmake ..
- - cmake --build . --config %CONFIGURATION%
-
-test_script:
- - ctest -C %CONFIGURATION% --output-on-failure
-
-notifications:
- - provider: Email
- to:
- - antiagainst@google.com
- - awoloszyn@google.com
- - deki@google.com
- - dneto@google.com
- - qining@google.com
- subject: 'Shaderc Windows Build #{{buildVersion}}: {{status}}'
- on_build_success: false
- on_build_failure: true
- on_build_status_changed: true
diff --git a/glslc/.clang-format b/.clang-format
similarity index 100%
rename from glslc/.clang-format
rename to .clang-format
diff --git a/.gitignore b/.gitignore
index 61cc44f..2565dcd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,19 @@
build/
build-*/
+out/
*.pyc
*.swp
compile_commands.json
.ycm_extra_conf.py
cscope.*
-third_party/glslang/
-third_party/googletest/
-third_party/spirv-tools/
+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
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 7a88559..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,118 +0,0 @@
-# Linux Build Configuration for Travis
-
-language: cpp
-
-os:
- - linux
- - osx
-
-# Use Ubuntu 14.04 LTS (Trusty) as the Linux testing environment.
-sudo: required
-dist: trusty
-
-env:
- - SHADERC_BUILD_TYPE=Release
- - SHADERC_BUILD_TYPE=Debug
-
-compiler:
- - clang
- - gcc
-
-matrix:
- fast_finish: true # Show final status immediately if a test fails.
- exclude:
- # Skip GCC builds on Mac OS X.
- - os: osx
- compiler: gcc
- include:
- # Additional GCC builds for code coverage.
- - os: linux
- compiler: gcc
- env: SHADERC_CODE_COVERAGE=ON
- # Additional build using Android NDK
- - env: BUILD_NDK=ON
-
-
-cache:
- apt: true
-
-branches:
- only:
- - master
-
-addons:
- apt:
- packages:
- - clang-3.6
- - ninja-build
- - lcov
-
-before_install:
- # Install ninja on Mac OS X.
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update && brew install ninja; fi
- - if [[ "$BUILD_NDK" == "ON" ]]; then
- git clone --depth=1 https://github.com/urho3d/android-ndk.git $HOME/android-ndk;
- export ANDROID_NDK=$HOME/android-ndk;
- git clone --depth=1 https://github.com/taka-no-me/android-cmake.git $HOME/android-cmake;
- export TOOLCHAIN_PATH=$HOME/android-cmake/android.toolchain.cmake;
- fi
-
-install:
- - pip install --user nose
- - pip install --user cpp-coveralls
-
- - export PATH=$HOME/.local/bin:$PATH # Make sure we can find the above Python packages
- # Make sure that clang-3.6 is selected.
- - if [[ "$TRAVIS_OS_NAME" == "linux" && "$CC" == "clang" ]]; then
- export CC=clang-3.6 CXX=clang++-3.6;
- fi
-
-before_script:
- - git clone https://github.com/google/googletest.git third_party/googletest
- - git clone https://github.com/google/glslang.git third_party/glslang
- - git clone https://github.com/KhronosGroup/SPIRV-Tools.git third_party/spirv-tools
- - git clone https://github.com/KhronosGroup/SPIRV-Headers.git third_party/spirv-tools/external/spirv-headers
-
-script:
- - mkdir build && cd build
- - if [[ "$BUILD_NDK" == "ON" ]]; then
- cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_PATH}
- -DANDROID_NATIVE_API_LEVEL=android-9
- -DCMAKE_BUILD_TYPE=Release
- -DANDROID_ABI="armeabi-v7a with NEON"
- -DSHADERC_SKIP_TESTS=ON
- -GNinja ..;
- else
- cmake -DCMAKE_BUILD_TYPE=${SHADERC_BUILD_TYPE:-Debug}
- -DENABLE_CODE_COVERAGE=${SHADERC_CODE_COVERAGE:-OFF}
- -GNinja ..;
- fi
- - ninja
- - if [[ "$BUILD_NDK" != "ON" ]]; then ctest -j`nproc` --output_on_failure; fi
-
-after_success:
- # Collect coverage and push to coveralls.info.
- # Ignore third party source code and tests.
- - if [[ "$CC" == "gcc" && "$SHADERC_CODE_COVERAGE" == "ON" ]]; then
- coveralls
- --root ../
- --build-root ./
- --exclude-pattern '.+/third_party/'
- --exclude-pattern '.+/.+_test\.cc'
- --exclude-pattern '.+/CMakeFiles/'
- --gcov /usr/bin/gcov
- --gcov-options '\--long-file-names --preserve-paths'
- --verbose;
- fi
-
-
-notifications:
- email:
- recipients:
- - antiagainst@google.com
- - awoloszyn@google.com
- - deki@google.com
- - dneto@google.com
- - qining@google.com
- on_success: change
- on_failure: always
diff --git a/Android.mk b/Android.mk
index e23b77a..e1ad18a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,3 +1,17 @@
+# 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
@@ -14,7 +28,20 @@
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
+$(NDK_APP_LIBS_OUT)/../include/shaderc/$(1) : \
+ $(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/$(1)
+ $(call host-mkdir,$(NDK_APP_LIBS_OUT)/../include/shaderc)
+ $(call host-cp,$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/$(1) \
+ ,$(NDK_APP_LIBS_OUT)/../include/shaderc/$(1))
+
+endef
+
define gen_libshaderc
+
$(1)/combine.ar: $(addprefix $(1)/, $(ALL_LIBS))
@echo "create libshaderc_combined.a" > $(1)/combine.ar
$(foreach lib,$(ALL_LIBS),
@@ -36,24 +63,14 @@
ifndef HEADER_TARGET
HEADER_TARGET=1
-$(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.hpp: \
- $(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/shaderc.hpp
- $(call host-mkdir,$(NDK_APP_LIBS_OUT)/../include/shaderc)
- $(call host-cp,$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/shaderc.hpp \
- ,$(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.hpp)
-
-$(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.h: \
- $(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/shaderc.h
- $(call host-mkdir,$(NDK_APP_LIBS_OUT)/../include/shaderc)
- $(call host-cp,$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/shaderc.h \
- ,$(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.h)
+$(eval $(foreach H,$(SHADERC_HEADERS),$(call gen_libshaderc_header,$(H))))
endif
libshaderc_combined: \
$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a
endef
-libshaderc_combined: $(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.hpp \
- $(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.h
+
+libshaderc_combined: $(SHADERC_HEADERS_IN_OUT_DIR)
$(eval $(call gen_libshaderc,$(TARGET_OUT),$(TOOLCHAIN_PREFIX)))
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000..7b40d1d
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,101 @@
+# 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.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.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" ]
+ }
+}
diff --git a/CHANGES b/CHANGES
index 4cf6bd4..83e8382 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,11 +1,240 @@
Revision history for Shaderc
-v2016.2-dev 2016-10-12
+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=<number>
+ --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=<name>" to set entry point name,
overriding default value "main".
+ - Support setting shader resource limits in C, C++ APIs, and in
+ glslc
+ - glslc adds -flimit=<setting>
+ - glslc adds --show-limits to display defaults and valid resource
+ limit syntax.
+ - glslc adds "-flimit-file <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
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a4c2fac..0c8d1ae 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,9 +1,35 @@
+# 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 2.8.12)
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)
@@ -14,17 +40,56 @@
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_ENABLE_WERROR_COMPILE "Enable passing -Werror to compiler, if available" ON)
+
+set (CMAKE_CXX_STANDARD 11)
+
+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_host_package(PythonInterp 3 REQUIRED)
add_custom_target(check-copyright ALL
- ${PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/utils/add_copyright.py
+ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/utils/add_copyright.py
--check
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Check copyright")
add_custom_target(add-copyright
- ${PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/utils/add_copyright.py
+ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/utils/add_copyright.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Add copyright")
@@ -44,6 +109,7 @@
endif(NOT SHADERC_ENABLE_SHARED_CRT)
endif(MSVC)
+
# Configure subdirectories.
# We depend on these for later projects, so they should come first.
add_subdirectory(third_party)
@@ -51,10 +117,38 @@
add_subdirectory(libshaderc_util)
add_subdirectory(libshaderc)
add_subdirectory(glslc)
-add_subdirectory(examples)
+if(${SHADERC_ENABLE_EXAMPLES})
+ add_subdirectory(examples)
+endif()
add_custom_target(build-version
- ${PYTHON_EXE}
+ ${PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/utils/update_build_version.py
- ${shaderc_SOURCE_DIR} ${spirv-tools_SOURCE_DIR} ${glslang_SOURCE_DIR}
+ ${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)
diff --git a/DEPS b/DEPS
new file mode 100644
index 0000000..46f4e6e
--- /dev/null
+++ b/DEPS
@@ -0,0 +1,33 @@
+use_relative_paths = True
+
+vars = {
+ 'google_git': 'https://github.com/google',
+ 'khronos_git': 'https://github.com/KhronosGroup',
+
+ 'effcee_revision' : '2ec8f8738118cc483b67c04a759fee53496c5659',
+ 'glslang_revision': 'e56beaee736863ce48455955158f1839e6e4c1a1',
+ 'googletest_revision': '389cb68b87193358358ae87cc56d257fd0d80189',
+ 're2_revision': '7107ebc4fbf7205151d8d2a57b2fc6e7853125d4',
+ 'spirv_headers_revision': 'a3fdfe81465d57efc97cfd28ac6c8190fb31a6c8',
+ 'spirv_tools_revision': 'ef3290bbea35935ba8fd623970511ed9f045bbd7',
+}
+
+deps = {
+ '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'),
+}
diff --git a/DEVELOPMENT.howto.md b/DEVELOPMENT.howto.md
index 0abb405..b2c9d80 100644
--- a/DEVELOPMENT.howto.md
+++ b/DEVELOPMENT.howto.md
@@ -24,7 +24,7 @@
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. But coverage will be expected. As a matter of development philosophy,
+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
@@ -50,41 +50,3 @@
| 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") |
-
-## glslang
-
-Some Shaderc changes require concomitant changes to glslang. It is our policy
-to upstream such work to glslang by following the official glslang project's
-procedures. At the same time, we would like to have those changes available to
-all Shaderc developers immediately upon passing our code review. Currently this
-is best done by maintaining
-[our own GitHub fork](https://github.com/google/glslang) of glslang, landing
-Shaderc-supporting changes there<sup>\*</sup>, building Shaderc against it, and
-generating pull requests from there to the glslang's original GitHub repository.
-Although a separate repository, this should be treated as essentially a part of
-Shaderc: the Shaderc master should always<sup>\**</sup> build against our
-glslang fork's master.
-
-Changes made to glslang in the course of Shaderc development must build and test
-correctly on their own, independently of Shaderc code, so they don't break other
-users of glslang when sent upstream. We will periodically upstream the content
-of our fork's `master` branch to the official glslang `master` branch, so all
-the contributions we accept will find their way to glslang.
-
-We aim to keep our fork up to date with the official glslang by pulling their
-changes frequently and merging them into our `master` branch.
-
-<hr><small>
-
-\*: Please note that GitHub uses the term "fork" as a routine part of
-[contributing to another project](https://help.github.com/articles/using-pull-requests/#types-of-collaborative-development-models),
-_not_ in the sense of scary open-source schism. This is why you'll hear us
-speak of "our fork" and see "forked from KhronosGroup/glslang" atop the
-[google/glslang](https://github.com/google/glslang) GitHub page. It does _not_
-mean that we're divorcing our glslang development from the original -- quite the
-opposite. As stated above, we intend to upstream all our work to the original
-glslang repository.
-
-\*\*: with one small exception: if a Shaderc and glslang pull requests need each
-other and are simultaneously cherry-picked, then a `HEAD`s inconsistency will be
-tolerated for the short moment that one has landed while the other hasn't.
diff --git a/Dockerfile b/Dockerfile
index 7e7b1e0..8821239 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -21,17 +21,15 @@
cmake \
git \
ninja \
- python \
+ python3 \
py-pip \
&& rm -rf /var/cache/apk/*
WORKDIR /root
RUN git clone https://github.com/google/shaderc
+
WORKDIR shaderc
-RUN git clone https://github.com/google/googletest.git third_party/googletest
-RUN git clone https://github.com/google/glslang.git third_party/glslang
-RUN git clone https://github.com/KhronosGroup/SPIRV-Tools.git third_party/spirv-tools
-RUN git clone https://github.com/KhronosGroup/SPIRV-Headers.git third_party/spirv-tools/external/spirv-headers
+RUN ./utils/git-sync-deps
WORKDIR build
RUN cmake -GNinja \
diff --git a/OWNERS b/OWNERS
index 8ab9c85..b5ae8b9 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,6 @@
+cfontas@google.com
+cstout@google.com
+jbauman@google.com
jjosh@google.com
liyl@google.com
-cfontas@google.com
+rosasco@google.com
diff --git a/README.md b/README.md
index ab68e49..2262272 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,18 @@
# Shaderc
-[![Linux and Mac Build Status](https://travis-ci.org/google/shaderc.svg)](https://travis-ci.org/google/shaderc "Linux and Mac Build Status")
-[![Windows Build status](https://ci.appveyor.com/api/projects/status/g6c372blna7vnk1l?svg=true)](https://ci.appveyor.com/project/dneto0/shaderc "Windows Build Status")
-[![Coverage Status](https://coveralls.io/repos/google/shaderc/badge.svg?branch=master&service=github)](https://coveralls.io/github/google/shaderc?branch=master)
-
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 doing the same.
+- [`libshaderc`](libshaderc), a library API for accessing `glslc` functionality.
-Shaderc wraps around core functionality in [glslang][khr-glslang]
-and [SPIRV-Tools][spirv-tools]. Shaderc aims to
+**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
@@ -20,14 +21,28 @@
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.**
+
+<img alt="Linux" src="kokoro/img/linux.png" width="20px" height="20px" hspace="2px"/>[![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)
+<img alt="MacOS" src="kokoro/img/macos.png" width="20px" height="20px" hspace="2px"/>[![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)
+<img alt="Windows" src="kokoro/img/windows.png" width="20px" height="20px" hspace="2px"/>[![Windows Build Status](https://storage.googleapis.com/shaderc/badges/build_status_windows_vs2017_release.svg)](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2017_release.html)
+
+[More downloads](downloads.md)
+
## Status
-Shaderc is approaching maturity, but is still subject to incompatible changes.
+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 r18b.
For licensing terms, please see the [`LICENSE`](LICENSE) file. If interested in
contributing to this project, please see [`CONTRIBUTING.md`](CONTRIBUTING.md).
@@ -50,13 +65,6 @@
- `utils/`: utility scripts for Shaderc
Shaderc depends on glslang, the Khronos reference compiler for GLSL.
-Sometimes a change updates both Shaderc and glslang. In that case the
-glslang change will appear in [google/glslang][google-glslang]
-before it appears upstream in [KhronosGroup/glslang][khr-glslang]
-We intend to upstream all changes to glslang. We maintain the separate
-copy only to stage those changes for review, and to provide something for
-Shaderc to build against in the meantime. Please see
-[DEVELOPMENT.howto.md](DEVELOPMENT.howto.md) for more details.
Shaderc depends on [SPIRV-Tools][spirv-tools] for assembling, disassembling,
and transforming SPIR-V binaries.
@@ -69,18 +77,39 @@
## 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/third_party
-git clone https://github.com/google/googletest.git
-git clone https://github.com/google/glslang.git
-git clone https://github.com/KhronosGroup/SPIRV-Tools.git spirv-tools
-git clone https://github.com/KhronosGroup/SPIRV-Headers.git spirv-tools/external/spirv-headers
+cd $SOURCE_DIR
+./utils/git-sync-deps
cd $SOURCE_DIR/
```
+**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
@@ -135,7 +164,7 @@
installed regardless of your OS:
- [CMake](http://www.cmake.org/): for generating compilation targets.
-- [Python](http://www.python.org/): for utility scripts and running the test suite.
+- [Python 3](http://www.python.org/): for utility scripts and running the test suite.
On Linux, the following tools should be installed:
@@ -152,18 +181,17 @@
On Windows, the following tools should be installed and available on your path:
-- Visual Studio 2013 Update 4 or later. Previous versions of Visual Studio
- will likely work but are untested.
+- Visual Studio 2015 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 documenation.
+ - [`asciidoctor`](http://asciidoctor.org/): for generating documentation.
- [`pygments.rb`](https://rubygems.org/gems/pygments.rb) required by
`asciidoctor` for syntax highlighting.
- - [`nosetests`](https://nose.readthedocs.io): for testing the Python code.
-### Building and running Shderc using Docker
+### Building and running Shaderc using Docker
Please make sure you have the Docker engine
[installed](https://docs.docker.com/engine/installation/) on your machine.
@@ -171,7 +199,7 @@
To create a Docker image containing Shaderc command line tools, issue the
following command in `${SOURCE_DIR}`: `docker build -t <IMAGE-NAME> .`.
The created image will have all the command line tools installed at
-`/usr/local` interally, and a data volume mounted at `/code`.
+`/usr/local` internally, and a data volume mounted at `/code`.
Assume `<IMAGE-NAME>` is `shaderc/shaderc` from now on.
@@ -211,6 +239,23 @@
Then the coverage report can be found under the `$BUILD_DIR/coverage-report`
directory.
+## 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]
+
[khr-glslang]: https://github.com/KhronosGroup/glslang
-[google-glslang]: https://github.com/google/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
diff --git a/android_test/Android.mk b/android_test/Android.mk
index 4959331..31ad381 100644
--- a/android_test/Android.mk
+++ b/android_test/Android.mk
@@ -1,3 +1,17 @@
+# 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)
diff --git a/android_test/jni/Android.mk b/android_test/jni/Android.mk
index 8a36259..1360751 100644
--- a/android_test/jni/Android.mk
+++ b/android_test/jni/Android.mk
@@ -1,2 +1,16 @@
+# 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
diff --git a/android_test/jni/Application.mk b/android_test/jni/Application.mk
index 1f3808b..ef50946 100644
--- a/android_test/jni/Application.mk
+++ b/android_test/jni/Application.mk
@@ -1,4 +1,18 @@
+# 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 := gnustl_static
-APP_PLATFORM := android-9
+APP_STL := c++_static
+APP_PLATFORM := android-16
diff --git a/android_test/test.cpp b/android_test/test.cpp
index 23df9b8..b4b9f93 100644
--- a/android_test/test.cpp
+++ b/android_test/test.cpp
@@ -16,7 +16,6 @@
#include <android_native_app_glue.h>
void android_main(struct android_app* state) {
- app_dummy();
shaderc::Compiler compiler;
const char* test_program = "void main() {}";
compiler.CompileGlslToSpv(test_program, strlen(test_program),
diff --git a/build_overrides/build.gni b/build_overrides/build.gni
new file mode 100644
index 0000000..abfb5d1
--- /dev/null
+++ b/build_overrides/build.gni
@@ -0,0 +1,18 @@
+# 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
diff --git a/build_overrides/shaderc.gni b/build_overrides/shaderc.gni
new file mode 100644
index 0000000..fea75fd
--- /dev/null
+++ b/build_overrides/shaderc.gni
@@ -0,0 +1,21 @@
+# 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"
+
diff --git a/cmake/linux-mingw-toolchain.cmake b/cmake/linux-mingw-toolchain.cmake
index 400b9a0..60e965e 100644
--- a/cmake/linux-mingw-toolchain.cmake
+++ b/cmake/linux-mingw-toolchain.cmake
@@ -1,3 +1,17 @@
+# 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
@@ -8,8 +22,12 @@
# 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)
-find_program(CMAKE_CXX_COMPILER NAMES ${MINGW_COMPILER_PREFIX}-g++)
+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})
diff --git a/cmake/setup_build.cmake b/cmake/setup_build.cmake
index b46d920..5dab384 100644
--- a/cmake/setup_build.cmake
+++ b/cmake/setup_build.cmake
@@ -1,8 +1,26 @@
-# Find nosetests; see shaderc_add_nosetests() from utils.cmake for opting in to
-# nosetests in a specific directory.
-find_program(NOSETESTS_EXE NAMES nosetests PATHS $ENV{PYTHON_PACKAGE_PATH})
-if (NOT NOSETESTS_EXE)
- message(STATUS "nosetests was not found - python code will not be tested")
+# 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
@@ -24,18 +42,16 @@
if (ANDROID)
# For android let's preemptively find the correct packages so that
# child projects (glslang, googletest) do not fail to find them.
-find_host_package(PythonInterp)
+
+# 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(PythonInterp 3 REQUIRED)
endif()
-foreach(PROGRAM echo python)
- string(TOUPPER ${PROGRAM} PROG_UC)
- if (ANDROID)
- find_host_program(${PROG_UC}_EXE ${PROGRAM} REQUIRED)
- else()
- find_program(${PROG_UC}_EXE ${PROGRAM} REQUIRED)
- endif()
-endforeach(PROGRAM)
option(ENABLE_CODE_COVERAGE "Enable collecting code coverage." OFF)
if (ENABLE_CODE_COVERAGE)
@@ -71,7 +87,7 @@
# The symptom is that some .gcno files are wrong after code change and
# recompiling. We don't know the exact reason yet. Figure it out.
# Remove all .gcno files in the directory recursively.
- COMMAND ${PYTHON_EXE}
+ COMMAND ${PYTHON_EXECUTABLE}
${shaderc_SOURCE_DIR}/utils/remove-file-by-suffix.py . ".gcno"
# .gcno files are not tracked by CMake. So no recompiling is triggered
# even if they are missing. Unfortunately, we just removed all of them
diff --git a/cmake/shaderc.pc.in b/cmake/shaderc.pc.in
new file mode 100644
index 0000000..6d217bf
--- /dev/null
+++ b/cmake/shaderc.pc.in
@@ -0,0 +1,12 @@
+prefix=@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}
diff --git a/cmake/shaderc_combined.pc.in b/cmake/shaderc_combined.pc.in
new file mode 100644
index 0000000..6d217bf
--- /dev/null
+++ b/cmake/shaderc_combined.pc.in
@@ -0,0 +1,12 @@
+prefix=@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}
diff --git a/cmake/shaderc_static.pc.in b/cmake/shaderc_static.pc.in
new file mode 100644
index 0000000..6d217bf
--- /dev/null
+++ b/cmake/shaderc_static.pc.in
@@ -0,0 +1,12 @@
+prefix=@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}
diff --git a/cmake/utils.cmake b/cmake/utils.cmake
index f807d9f..d64757d 100644
--- a/cmake/utils.cmake
+++ b/cmake/utils.cmake
@@ -1,3 +1,17 @@
+# 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)
@@ -9,7 +23,15 @@
function(shaderc_default_c_compile_options TARGET)
if (NOT "${MSVC}")
- target_compile_options(${TARGET} PRIVATE -Wall -Werror)
+ 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.
@@ -59,22 +81,13 @@
${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.asciidoc
DEPENDS ${FILE}.asciidoc ${ARGN}
OUTPUT ${DEST})
- add_custom_target(${TARGET} ALL DEPENDS ${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()
-# Run nosetests on file ${PREFIX}_nosetest.py. Nosetests will look for classes
-# and functions whose names start with "nosetest". The test name will be
-# ${PREFIX}_nosetests.
-function(shaderc_add_nosetests PREFIX)
- if("${SHADERC_ENABLE_TESTS}" AND NOSETESTS_EXE)
- add_test(
- NAME ${PREFIX}_nosetests
- COMMAND ${NOSETESTS_EXE} -m "^[Nn]ose[Tt]est" -v
- ${CMAKE_CURRENT_SOURCE_DIR}/${PREFIX}_nosetest.py)
- endif()
-endfunction()
-
# Adds a set of tests.
# This function accepts the following parameters:
# TEST_PREFIX: a prefix for each test target name
@@ -103,6 +116,11 @@
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})
@@ -128,7 +146,18 @@
get_target_property(libtype ${target} TYPE)
# If this target is a static library, get anything it depends on.
if ("${libtype}" STREQUAL "STATIC_LIBRARY")
- list(INSERT ${out_list} 0 "${target}")
+ # 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})
@@ -150,15 +179,7 @@
shaderc_get_transitive_libs(${target} all_libs)
set(libname
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${new_target}${CMAKE_STATIC_LIBRARY_SUFFIX})
-
- if (CMAKE_CONFIGURATION_TYPES)
- list(LENGTH CMAKE_CONFIGURATION_TYPES num_configurations)
- if (${num_configurations} GREATER 1)
- set(libname
- ${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${new_target}${CMAKE_STATIC_LIBRARY_SUFFIX})
- endif()
- endif()
+ ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${new_target}${CMAKE_STATIC_LIBRARY_SUFFIX})
if (MSVC)
string(REPLACE ";" ">;$<TARGET_FILE:" temp_string "${all_libs}")
diff --git a/cmake/write_pkg_config.cmake b/cmake/write_pkg_config.cmake
new file mode 100644
index 0000000..d367ce3
--- /dev/null
+++ b/cmake/write_pkg_config.cmake
@@ -0,0 +1,31 @@
+# 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)
diff --git a/downloads.md b/downloads.md
new file mode 100644
index 0000000..1738668
--- /dev/null
+++ b/downloads.md
@@ -0,0 +1,17 @@
+# 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 2017](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2017_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) |
+| [MSVC 2015](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2015_release.html) | [gcc](https://storage.googleapis.com/shaderc/badges/build_link_linux_gcc_release.html) | |
+
+## Debug
+| Windows | Linux | MacOS |
+| --- | --- | --- |
+| [MSVC 2017](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2017_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) | |
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 176c40b..ce1f4c0 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1 +1,15 @@
+# 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)
diff --git a/examples/online-compile/CMakeLists.txt b/examples/online-compile/CMakeLists.txt
index e4541e0..6cceb6b 100644
--- a/examples/online-compile/CMakeLists.txt
+++ b/examples/online-compile/CMakeLists.txt
@@ -1,3 +1,18 @@
+# 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)
diff --git a/examples/online-compile/main.cc b/examples/online-compile/main.cc
index 92d9835..9e1ca5b 100644
--- a/examples/online-compile/main.cc
+++ b/examples/online-compile/main.cc
@@ -23,6 +23,7 @@
// - Setting basic options: setting a preprocessor symbol.
// - Checking compilation status and extracting an error message.
+#include <cstring>
#include <iostream>
#include <string>
#include <vector>
@@ -143,5 +144,28 @@
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;
}
diff --git a/glslc/CMakeLists.txt b/glslc/CMakeLists.txt
index ba4d4c5..31664d1 100644
--- a/glslc/CMakeLists.txt
+++ b/glslc/CMakeLists.txt
@@ -1,3 +1,17 @@
+# 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
@@ -7,6 +21,8 @@
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
@@ -15,9 +31,22 @@
shaderc_default_compile_options(glslc)
target_include_directories(glslc PUBLIC ${glslang_SOURCE_DIR})
-target_link_libraries(glslc PRIVATE glslang OSDependent OGLCompiler
- HLSL glslang SPIRV ${CMAKE_THREAD_LIBS_INIT})
-target_link_libraries(glslc PRIVATE shaderc_util shaderc)
+
+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 OSDependent OGLCompiler HLSL glslang SPIRV # Glslang libraries
+ $<$<BOOL:${SHADERC_ENABLE_WGSL_OUTPUT}>: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)
@@ -31,11 +60,14 @@
LINK_LIBS glslc shaderc_util shaderc
TEST_NAMES
file
+ resource_parse
stage)
shaderc_add_asciidoc(glslc_doc_README README)
-install(TARGETS glslc_exe
- RUNTIME DESTINATION bin)
+if(SHADERC_ENABLE_INSTALL)
+ install(TARGETS glslc_exe
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+endif(SHADERC_ENABLE_INSTALL)
add_subdirectory(test)
diff --git a/glslc/README.asciidoc b/glslc/README.asciidoc
index a8f22c9..dfd105b 100644
--- a/glslc/README.asciidoc
+++ b/glslc/README.asciidoc
@@ -1,5 +1,6 @@
= glslc Manual
-
+:toc:
+:toclevels: 3
:numbered:
:source-highlighter: pygments
@@ -11,11 +12,24 @@
== Synopsis
----
+glslc [--help]
+glslc [-h]
+
+glslc [--show-limits]
+
glslc [-c|-S|-E]
[-x ...] [-std=standard]
+ [ ... options for resource bindings ... ]
+ [-fhlsl-offsets]
+ [-fhlsl-functionality1]
+ [-fentry-point=<name>]
+ [-fauto-map-locations]
+ [-finvert-y]
+ [-flimit=...]
+ [-flimit-file <resource-limits-file>]
[-fshader-stage=...]
- [-fentry-point=...]
[--target-env=...]
+ [--target-spv=...]
[-g]
[-O0|-Os]
[-Idirectory...]
@@ -43,7 +57,7 @@
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
-<<option-f-shader-stage,its own section>>.
+<<option-fshader-stage,its own section>>.
[[shader-stage-selection]]
.Shader Stage Selection
@@ -94,11 +108,11 @@
** If the input file has a <<shader-stage-selection,shader stage selection
extension>>, 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
+ 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
+ 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`.
@@ -106,9 +120,15 @@
=== Overall Options
-==== `--help`
+==== `--help`, `-h`
-`--help` tells the glslc compiler to display all available options and exit.
+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`
@@ -117,7 +137,34 @@
=== Language and Mode Selection Options
-[[option-f-shader-stage]]
+[[option-finvert-y]]
+==== `-finvert-y`
+
+Inverts position.Y output in a vertex shader.
+
+[[option-flimit]]
+==== `-flimit=`
+
+`-flimit=<resource-limits>` 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 <resource-limits-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=<stage>` lets you specify the shader stage for one or more
@@ -151,12 +198,6 @@
`-fshader-stage=`, since `-fshader-stage=` only affects the treatment of
subsequent files.
-[[option-f-entry-point]]
-==== `-fentry-point=`
-
-`-fentry-point=<name>` lets you specify the entry point name. This is only
-significant for HLSL compilation. The default is "main".
-
==== `-std=`
`-std=<value>` lets you specify a shader version and profile on the command
@@ -185,16 +226,39 @@
==== `--target-env=`
`--target-env=<value>` lets you specify a target environment on the command line.
-This affects the generation of warnings and errors. ``<value>`` can be one of
+This affects the generation of warnings and errors. The ``<value>`` can be one of
the following:
-* `vulkan`: create SPIR-V under Vulkan semantics.
-* `opengl`: create SPIR-V under OpenGL semantics.
+* `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.
+* `opengl`: create SPIR-V under OpenGL 4.5 semantics.
+* `opengl4.5`: create SPIR-V under OpenGL 4.5 semantics.
* `opengl_compat`: create SPIR-V under OpenGL semantics, including compatibility
profile functions.
-By default, the ``<value>`` is set to `vulkan` and the compiler creates SPIR-V
-under Vulkan 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.5, which uses SPIR-V 1.5.
+
+If this option is not specified, a default of `vulkan1.0` is used.
+
+==== `--target-spv=`
+
+`--target-spv=<value>` 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 ``<value>`` can be one of the following:
+
+* `spv1.0`
+* `spv1.1`
+* `spv1.2`
+* `spv1.3`
+* `spv1.4`
+* `spv1.5`
==== `-x`
@@ -202,6 +266,10 @@
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
@@ -272,6 +340,7 @@
`-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=<format>`
@@ -307,6 +376,60 @@
{0x07230203, 0x00010000, 0x00080001, 0x00000006...}
|===
+[[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=<name>`
+
+`-fentry-point=<name>` 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;
+}
+----
+
=== Warning and Error Options
==== `-w`
@@ -405,6 +528,113 @@
|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] <reg0> <set0> <binding0>` 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__`
diff --git a/glslc/src/dependency_info.cc b/glslc/src/dependency_info.cc
index 10169d9..2622629 100644
--- a/glslc/src/dependency_info.cc
+++ b/glslc/src/dependency_info.cc
@@ -49,7 +49,7 @@
} 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);
+ 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 "
diff --git a/glslc/src/dependency_info.h b/glslc/src/dependency_info.h
index b0b4756..b7c7d8d 100644
--- a/glslc/src/dependency_info.h
+++ b/glslc/src/dependency_info.h
@@ -40,7 +40,7 @@
// 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
@@ -70,7 +70,7 @@
// 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; };
+ 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
diff --git a/glslc/src/file_compiler.cc b/glslc/src/file_compiler.cc
index 5469736..5d67be1 100644
--- a/glslc/src/file_compiler.cc
+++ b/glslc/src/file_compiler.cc
@@ -20,6 +20,10 @@
#include <iostream>
#include <sstream>
+#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"
@@ -69,15 +73,7 @@
return false;
}
- std::string output_name = GetOutputFileName(input_file.name);
-
- std::ofstream potential_file_stream;
- std::ostream* output_stream =
- shaderc_util::GetOutputStream(output_name, &potential_file_stream);
- if (!output_stream) {
- // An error message has already been emitted to the stderr stream.
- return false;
- }
+ std::string output_file_name = GetOutputFileName(input_file.name);
string_piece error_file_name = input_file.name;
if (error_file_name == "-") {
@@ -103,8 +99,8 @@
if (output_type_ == OutputType::SpirvBinary) {
const auto result =
compiler_.AssembleToSpv(source_string.data(), source_string.size());
- return EmitCompiledResult(result, input_file.name, error_file_name,
- used_source_files, output_stream);
+ return EmitCompiledResult(result, input_file.name, output_file_name,
+ error_file_name, used_source_files);
} else {
return true;
}
@@ -121,23 +117,23 @@
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, error_file_name,
- used_source_files, output_stream);
+ 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, error_file_name,
- used_source_files, output_stream);
+ 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, error_file_name,
- used_source_files, output_stream);
+ return EmitCompiledResult(result, input_file.name, output_file_name,
+ error_file_name, used_source_files);
}
}
return false;
@@ -146,9 +142,8 @@
template <typename CompilationResultType>
bool FileCompiler::EmitCompiledResult(
const CompilationResultType& result, const std::string& input_file,
- string_piece error_file_name,
- const std::unordered_set<std::string>& used_source_files,
- std::ostream* out) {
+ const std::string& output_file_name, string_piece error_file_name,
+ const std::unordered_set<std::string>& used_source_files) {
total_errors_ += result.GetNumErrors();
total_warnings_ += result.GetNumWarnings();
@@ -207,43 +202,80 @@
}
}
- // 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.
- out->write(compilation_output.data(), compilation_output.size());
- 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;
+ 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<uint32_t>(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;
}
- 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;
+ }
}
// Write error message to std::cerr.
std::cerr << result.GetErrorMessage();
- if (out->fail()) {
+ if (out && out->fail()) {
// Something wrong happened on output.
if (out == &std::cout) {
std::cerr << "glslc: error: error writing to standard output"
@@ -336,12 +368,15 @@
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 the output is not SPIR-V binary code" << std::endl;
+ std::cerr << " when only preprocessing the source" << std::endl;
return false;
}
if (dependency_info_dumping_handler_ &&
@@ -349,9 +384,19 @@
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;
}
diff --git a/glslc/src/file_compiler.h b/glslc/src/file_compiler.h
index 2f45e92..cd41f73 100644
--- a/glslc/src/file_compiler.h
+++ b/glslc/src/file_compiler.h
@@ -43,8 +43,10 @@
// 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 bianry code as a C-style initializer list
+ 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()
@@ -116,7 +118,7 @@
// Gets the reference of the compiler options which reflects the command-line
// arguments.
- shaderc::CompileOptions& options() { return options_; };
+ 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.
@@ -126,7 +128,7 @@
new DependencyInfoDumpingHandler());
}
return dependency_info_dumping_handler_.get();
- };
+ }
private:
enum class OutputType {
@@ -136,16 +138,16 @@
};
// Emits the compilation output from the given result to the given output
- // stream and returns true if the result represents a successful compilation
- // step. Otherwise returns false and possibly emits messages to the standard
- // error stream. Accumulates error and warning counts for use by the
- // OutputMessages() method.
+ // 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 <typename CompilationResultType>
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<std::string>& used_source_files,
- std::ostream* out);
+ const std::unordered_set<std::string>& used_source_files);
// Returns the final file name to be used for the output file.
//
diff --git a/glslc/src/file_includer.cc b/glslc/src/file_includer.cc
index ea42e81..448bfba 100644
--- a/glslc/src/file_includer.cc
+++ b/glslc/src/file_includer.cc
@@ -25,6 +25,8 @@
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) {
diff --git a/glslc/src/file_includer.h b/glslc/src/file_includer.h
index ae42730..5032e11 100644
--- a/glslc/src/file_includer.h
+++ b/glslc/src/file_includer.h
@@ -38,6 +38,9 @@
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.
@@ -51,7 +54,7 @@
// Returns a reference to the member storing the set of included files.
const std::unordered_set<std::string>& file_path_trace() const {
return included_files_;
- };
+ }
private:
// Used by GetInclude() to get the full filepath.
diff --git a/glslc/src/main.cc b/glslc/src/main.cc
index 571e65f..2b1c03e 100644
--- a/glslc/src/main.cc
+++ b/glslc/src/main.cc
@@ -16,18 +16,25 @@
#include <cctype>
#include <cstdint>
#include <cstring>
+#include <iomanip>
#include <iostream>
#include <list>
+#include <sstream>
#include <string>
+#include <tuple>
#include <utility>
-#include "libshaderc_util/string_piece.h"
-#include "shaderc/shaderc.h"
-#include "spirv-tools/libspirv.h"
-
#include "file.h"
#include "file_compiler.h"
+#include "libshaderc_util/args.h"
+#include "libshaderc_util/compiler.h"
+#include "libshaderc_util/io.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;
@@ -46,38 +53,123 @@
-Dmacro[=defn] Add an implicit macro definition.
-E Outputs only the results of the preprocessing step.
Output defaults to standard output.
- -fshader-stage=<stage>
- Treat subsequent input files as having stage <stage>.
- Valid stages are vertex, fragment, tesscontrol, tesseval,
- geometry, and compute.
+ -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.
-fentry-point=<name>
Specify the entry point name for HLSL compilation, for
all subsequent source files. Default is "main".
+ -fhlsl_functionality1, -fhlsl-functionality1
+ Enable extension SPV_GOOGLE_hlsl_functionality1 for HLSL
+ compilation.
+ -finvert-y Invert position.Y output in vertex shader.
+ -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.
+ -flimit=<settings>
+ 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 <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.
+ -fresource-set-binding [stage] <reg0> <set0> <binding0>
+ [<reg1> <set1> <binding1>...]
+ Explicitly sets the descriptor set and binding for
+ HLSL resources, by register name. Optionally restrict
+ it to a single stage.
+ -fcbuffer-binding-base [stage] <value>
+ Same as -fubo-binding-base.
+ -fimage-binding-base [stage] <value>
+ 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] <value>
+ 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] <value>
+ 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] <value>
+ 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] <value>
+ 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] <value>
+ 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=<stage>
+ Treat subsequent input files as having stage <stage>.
+ Valid stages are vertex, vert, fragment, frag, tesscontrol,
+ tesc, tesseval, tese, geometry, geom, compute, and comp.
-g Generate source-level debug information.
Currently this option has no effect.
+ -h Display available options.
--help Display available options.
- --version Display compiler version information.
-I <value> Add directory to include search path.
- -o <file> Write output to <file>.
- A file name of '-' represents standard output.
- -std=<value> Version and profile for GLSL input files. Possible values
- are concatenations of version and profile, e.g. 310es,
- 450core, etc. Ignored for HLSL files.
-mfmt=<format> 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 include bin, c
- and num. By default the binary output format is bin.
+ 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 <file> Write dependency output to the given file.
-MT <target> Specify the target of the rule emitted by dependency
generation.
- -S Only run preprocess and compilation steps.
+ -O Optimize the generated SPIR-V code for better performance.
+ -Os Optimize the generated SPIR-V code for smaller size.
+ -O0 Disable optimization.
+ -o <file> Write output to <file>.
+ A file name of '-' represents standard output.
+ -std=<value> 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=<environment>
- Set the target shader environment, and the semantics
- of warnings and errors. Valid values are 'opengl',
- 'opengl_compat' and 'vulkan'. The default value is 'vulkan'.
+ 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
+ vulkan # Same as vulkan1.0
+ opengl4.5
+ opengl # Same as opengl4.5
+ --target-spv=<spirv-version>
+ 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.
+ Values are:
+ spv1.0, spv1.1, spv1.2, spv1.3, spv1.4, spv1.5
+ --version Display compiler version information.
-w Suppresses all warning messages.
-Werror Treat all warnings as errors.
-x <language> Treat subsequent input files as having type <language>.
@@ -87,32 +179,61 @@
)";
}
-// 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 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) {
- const string_piece arg = argv[*index];
- assert(arg.starts_with(option));
- if (arg.size() != option.size()) {
- *option_argument = arg.substr(option.size());
- return true;
- } else {
- if (option.back() == '=') {
- *option_argument = "";
- return true;
- }
- if (++(*index) >= argc) return false;
- *option_argument = argv[*index];
- return true;
+// 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<glslc::ResourceSetting> 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) {
@@ -125,12 +246,43 @@
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") {
+ 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_util::Compiler::Limit>( \
+ 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)
@@ -138,7 +290,7 @@
return 0;
} else if (arg.starts_with("-o")) {
string_piece file_name;
- if (!GetOptionArgument(argc, argv, &i, "-o", &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;
@@ -153,9 +305,108 @@
<< std::endl;
return 1;
}
+ } else if (arg == "-fauto-bind-uniforms") {
+ compiler.options().SetAutoBindUniforms(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 == "-finvert-y") {
+ compiler.options().SetInvertY(true);
+ } else if (arg == "-fnan-clamp") {
+ compiler.options().SetNanClamp(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<char> 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;
@@ -171,10 +422,23 @@
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 == "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;
} else {
@@ -183,7 +447,28 @@
<< std::endl;
return 1;
}
- compiler.options().SetTargetEnvironment(target_env, 0);
+ 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 {
+ 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="));
@@ -196,6 +481,9 @@
} 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;
@@ -203,7 +491,7 @@
}
} else if (arg.starts_with("-x")) {
string_piece option_arg;
- if (!GetOptionArgument(argc, argv, &i, "-x", &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;
@@ -249,7 +537,8 @@
}
} else if (arg == "-MF") {
string_piece dep_file_name;
- if (!GetOptionArgument(argc, argv, &i, "-MF", &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;
@@ -259,7 +548,8 @@
std::string(dep_file_name.data(), dep_file_name.size()));
} else if (arg == "-MT") {
string_piece dep_file_name;
- if (!GetOptionArgument(argc, argv, &i, "-MT", &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;
@@ -305,7 +595,7 @@
}
} else if (arg.starts_with("-I")) {
string_piece option_arg;
- if (!GetOptionArgument(argc, argv, &i, "-I", &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;
@@ -316,7 +606,10 @@
} else if (arg == "-g") {
compiler.options().SetGenerateDebugInfo();
} else if (arg.starts_with("-O")) {
- if (arg == "-Os") {
+ 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") {
diff --git a/glslc/src/resource_parse.cc b/glslc/src/resource_parse.cc
new file mode 100644
index 0000000..7109333
--- /dev/null
+++ b/glslc/src/resource_parse.cc
@@ -0,0 +1,97 @@
+// 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 <algorithm>
+#include <cstring>
+#include <iterator>
+#include <sstream>
+#include <vector>
+
+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<ResourceSetting>* 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<std::string> pos((input_stream));
+ limits->clear();
+
+ while (pos != std::istream_iterator<std::string>()) {
+ const std::string limit_name = *pos++;
+ shaderc_limit limit = static_cast<shaderc_limit>(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<std::string>())
+ 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
diff --git a/glslc/src/resource_parse.h b/glslc/src/resource_parse.h
new file mode 100644
index 0000000..9794ce4
--- /dev/null
+++ b/glslc/src/resource_parse.h
@@ -0,0 +1,60 @@
+// 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 <string>
+#include <vector>
+
+#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<ResourceSetting>* limits,
+ std::string* err);
+} // namespace glslc
+
+
+#endif // GLSLC_FILE_H_
diff --git a/glslc/src/resource_parse_test.cc b/glslc/src/resource_parse_test.cc
new file mode 100644
index 0000000..4714106
--- /dev/null
+++ b/glslc/src/resource_parse_test.cc
@@ -0,0 +1,75 @@
+// 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 <gmock/gmock.h>
+
+namespace {
+
+using glslc::ParseResourceSettings;
+using glslc::ResourceSetting;
+using testing::Eq;
+
+struct ResourceSettingsCase {
+ std::string input;
+ bool success;
+ std::vector<ResourceSetting> settings;
+ std::string message;
+};
+
+using ParseResourceSettingsTest = ::testing::TestWithParam<ResourceSettingsCase>;
+
+TEST_P(ParseResourceSettingsTest, Sample) {
+ std::vector<ResourceSetting> 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<ResourceSettingsCase>{
+ {"", 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
diff --git a/glslc/src/shader_stage.cc b/glslc/src/shader_stage.cc
index f6b227d..23f15b1 100644
--- a/glslc/src/shader_stage.cc
+++ b/glslc/src/shader_stage.cc
@@ -33,11 +33,26 @@
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},
- {"compute", shaderc_glsl_compute_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;
}
@@ -62,6 +77,14 @@
{"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);
diff --git a/glslc/src/shader_stage.h b/glslc/src/shader_stage.h
index 4900c6f..8e4ffde 100644
--- a/glslc/src/shader_stage.h
+++ b/glslc/src/shader_stage.h
@@ -22,10 +22,15 @@
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' and an error should be emitted at
-// the caller site.
+// 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);
diff --git a/glslc/src/stage_test.cc b/glslc/src/stage_test.cc
index 9b1c254..3177673 100644
--- a/glslc/src/stage_test.cc
+++ b/glslc/src/stage_test.cc
@@ -48,6 +48,30 @@
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) {
diff --git a/glslc/test/CMakeLists.txt b/glslc/test/CMakeLists.txt
index cca9314..ac001bd 100644
--- a/glslc/test/CMakeLists.txt
+++ b/glslc/test/CMakeLists.txt
@@ -1,9 +1,27 @@
-shaderc_add_nosetests(expect)
-shaderc_add_nosetests(glslc_test_framework)
+# 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_EXE}
+ COMMAND ${PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/glslc_test_framework.py
$<TARGET_FILE:glslc_exe> $<TARGET_FILE:spirv-dis>
--test-dir ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/glslc/test/assembly.py b/glslc/test/assembly.py
index 2a0e47f..30fdba4 100644
--- a/glslc/test/assembly.py
+++ b/glslc/test/assembly.py
@@ -21,7 +21,7 @@
return """
; SPIR-V
; Version: 1.0
- ; Generator: Khronos Glslang Reference Front End; 1
+ ; Generator: Google Shaderc over Glslang; 10
; Bound: 6
; Schema: 0"""
@@ -126,8 +126,10 @@
expected_error = [
shader, ": error: #version: Desktop shaders for Vulkan SPIR-V require "
"version 140 or higher\n",
- shader, ":2: error: '' : syntax error\n",
- '2 errors generated.\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')
diff --git a/glslc/test/error_no_object.py b/glslc/test/error_no_object.py
new file mode 100644
index 0000000..b55ebfd
--- /dev/null
+++ b/glslc/test/error_no_object.py
@@ -0,0 +1,59 @@
+# 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']
diff --git a/glslc/test/expect.py b/glslc/test/expect.py
index cfd0524..7410f73 100644
--- a/glslc/test/expect.py
+++ b/glslc/test/expect.py
@@ -19,10 +19,33 @@
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=10
+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):
@@ -113,21 +136,30 @@
return False, 'Extra files generated: {}'.format(generated_files)
-class CorrectObjectFilePreamble(GlslCTest):
- """Provides methods for verifying preamble for a SPV object file."""
+class CorrectBinaryLengthAndPreamble(GlslCTest):
+ """Provides methods for verifying preamble for a SPIR-V binary."""
- def verify_object_file_preamble(self, filename):
- """Checks that the given SPIR-V binary file has correct preamble."""
+ 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 reduce(lambda w, b: (w << 8) | ord(b), word, 0)
+ return functools.reduce(lambda w, b: (w << 8) | b, word, 0)
def check_endianness(binary):
- """Checks the endianness of the given SPIR-V binary file.
+ """Checks the endianness of the given SPIR-V binary.
Returns:
True if it's little endian, False if it's big endian.
@@ -141,6 +173,45 @@
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
@@ -148,31 +219,11 @@
with open(filename, 'rb') as object_file:
object_file.seek(0, os.SEEK_END)
num_bytes = object_file.tell()
- 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'
object_file.seek(0)
- preamble = bytes(object_file.read(20))
- 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
- if read_word(preamble, 1, little_endian) != 0x00010000:
- return False, 'Incorrect SPV binary: wrong version number'
- # glslang (0x0008....) or SPIRV-Tools (0x0007....) generator number
- if read_word(preamble, 2, little_endian) != 0x00080001 and \
- read_word(preamble, 2, little_endian) != 0x00070000:
- 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'
+ binary = bytes(object_file.read())
+ return self.verify_binary_length_and_header(binary, spv_version)
return True, ''
@@ -192,15 +243,15 @@
if (line1 != '; SPIR-V\n' or
line2 != '; Version: 1.0\n' or
- line3 != '; Generator: Khronos Glslang Reference Front End; 1\n'):
+ (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 object
- file following the object file naming rule, and there is no output on
+ """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):
@@ -213,6 +264,54 @@
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 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
@@ -233,7 +332,7 @@
disassembly = output[0]
if not isinstance(an_input.assembly_substr, str):
return False, "Missing assembly_substr member"
- if an_input.assembly_substr not in disassembly:
+ 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))
@@ -334,6 +433,32 @@
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.
@@ -372,7 +497,7 @@
'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(status.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))
@@ -401,7 +526,7 @@
'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(status.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))
@@ -421,7 +546,7 @@
' glslc')
if not status.stderr:
return False, 'Expected warning message, but no output on stderr'
- if self.expected_warning != convert_to_unix_line_endings(status.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))
@@ -480,16 +605,16 @@
return False, 'Expected something on stdout'
elif type(self.expected_stdout) == str:
if self.expected_stdout != convert_to_unix_line_endings(
- status.stdout):
+ 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(
- status.stdout)):
+ convert_to_string(status.stdout))):
return False, ('Incorrect stdout output:\n{ac}\n'
'Expected to match regex:\n{ex}'.format(
- ac=status.stdout,
+ ac=convert_to_string(status.stdout),
ex=self.expected_stdout.pattern))
return True, ''
@@ -513,7 +638,7 @@
return False, 'Expected something on stderr'
else:
if self.expected_stderr != convert_to_unix_line_endings(
- status.stderr):
+ convert_to_string(status.stderr)):
return False, ('Incorrect stderr output:\n{ac}\n'
'Expected:\n{ex}'.format(
ac=status.stderr, ex=self.expected_stderr))
@@ -536,3 +661,31 @@
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, ''
diff --git a/glslc/test/expect_nosetest.py b/glslc/test/expect_nosetest.py
deleted file mode 100644
index 567b0a0..0000000
--- a/glslc/test/expect_nosetest.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# 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.
-
-"""Tests for the expect module."""
-
-import expect
-from glslc_test_framework import TestStatus
-from nose.tools import assert_equal, assert_true, assert_false
-import re
-
-def nosetest_get_object_name():
- """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]
-
- assert_equal(actual_object_names, expected_object_names)
-
-
-class TestStdoutMatchADotC(expect.StdoutMatch):
- expected_stdout = re.compile("a.c")
-
-
-def nosetest_stdout_match_regex_has_match():
- test = TestStdoutMatchADotC()
- status = TestStatus(test_manager=None, returncode=0, stdout='0abc1',
- stderr=None, directory=None, inputs=None, input_filenames=None)
- assert_true(test.check_stdout_match(status)[0])
-
-
-def nosetest_stdout_match_regex_no_match():
- test = TestStdoutMatchADotC()
- status = TestStatus(test_manager=None, returncode=0, stdout='ab',
- stderr=None, directory=None, inputs=None, input_filenames=None)
- assert_false(test.check_stdout_match(status)[0])
-
-
-def nosetest_stdout_match_regex_empty_stdout():
- test = TestStdoutMatchADotC()
- status = TestStatus(test_manager=None, returncode=0, stdout='', stderr=None,
- directory=None, inputs=None, input_filenames=None)
- assert_false(test.check_stdout_match(status)[0])
diff --git a/glslc/test/expect_unittest.py b/glslc/test/expect_unittest.py
new file mode 100644
index 0000000..1a49c0c
--- /dev/null
+++ b/glslc/test/expect_unittest.py
@@ -0,0 +1,83 @@
+# 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])
diff --git a/glslc/test/glslc_test_framework.py b/glslc/test/glslc_test_framework.py
index 6bf43a7..3d4bc17 100755
--- a/glslc/test/glslc_test_framework.py
+++ b/glslc/test/glslc_test_framework.py
@@ -45,8 +45,6 @@
be deleted.
"""
-from __future__ import print_function
-
import argparse
import fnmatch
import inspect
@@ -74,7 +72,7 @@
def get_all_superclasses(cls):
- """Returns all superclasses of a given class.
+ """Returns all superclasses of a given class. Omits root 'object' superclass.
Returns:
A list of superclasses of the given class. The order guarantees that
@@ -87,10 +85,10 @@
classes = []
for superclass in cls.__bases__:
for c in get_all_superclasses(superclass):
- if c not in classes:
+ if c is not object and c not in classes:
classes.append(c)
for superclass in cls.__bases__:
- if superclass not in classes:
+ if superclass is not object and superclass not in classes:
classes.append(superclass)
return classes
@@ -305,7 +303,7 @@
run_results = [getattr(self.test, test_method)(test_status)
for test_method in get_all_test_methods(
self.test.__class__)]
- success, message = zip(*run_results)
+ success, message = list(zip(*run_results))
success = all(success)
message = '\n'.join(message)
except Exception as e:
@@ -335,8 +333,8 @@
manager.leave_output = True
for root, _, filenames in os.walk(root_dir):
for filename in fnmatch.filter(filenames, '*.py'):
- if filename.endswith('nosetest.py'):
- # Skip nose tests, which are for testing functions of
+ if filename.endswith('unittest.py'):
+ # Skip unit tests, which are for testing functions of
# the test framework.
continue
sys.path = default_path
diff --git a/glslc/test/glslc_test_framework_nosetest.py b/glslc/test/glslc_test_framework_nosetest.py
deleted file mode 100644
index b6bded5..0000000
--- a/glslc/test/glslc_test_framework_nosetest.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# 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.
-
-from glslc_test_framework import get_all_test_methods, get_all_superclasses
-from nose.tools import assert_equal, with_setup
-
-
-# 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
-
-def nosetest_get_all_superclasses():
- """Tests get_all_superclasses()."""
-
- assert_equal(get_all_superclasses(A), [Root])
- assert_equal(get_all_superclasses(B), [Root])
- assert_equal(get_all_superclasses(C), [Root])
- assert_equal(get_all_superclasses(D), [Root])
- assert_equal(get_all_superclasses(E), [Root])
-
- assert_equal(get_all_superclasses(H), [Root, B, C, D])
- assert_equal(get_all_superclasses(I), [Root, E])
-
- assert_equal(get_all_superclasses(O), [Root, B, C, D, E, H, I])
-
- assert_equal(get_all_superclasses(U), [Root, B, C, D, E, H, I, A, O])
- assert_equal(get_all_superclasses(X), [Root, B, C, D, E, H, I, A, O, U])
-
- assert_equal(get_all_superclasses(Multi), [R1, R2])
-
-
-def nosetest_get_all_methods():
- """Tests get_all_test_methods()."""
- assert_equal(get_all_test_methods(A), ['check_root', 'check_a'])
- assert_equal(get_all_test_methods(B), ['check_root', 'check_b'])
- assert_equal(get_all_test_methods(C), ['check_root', 'check_c'])
- assert_equal(get_all_test_methods(D), ['check_root', 'check_d'])
- assert_equal(get_all_test_methods(E), ['check_root', 'check_e'])
-
- assert_equal(
- get_all_test_methods(H),
- ['check_root', 'check_b', 'check_c', 'check_d', 'check_h'])
- assert_equal(get_all_test_methods(I), ['check_root', 'check_e', 'check_i'])
-
- assert_equal(
- get_all_test_methods(O),
- ['check_root', 'check_b', 'check_c', 'check_d',
- 'check_e', 'check_h', 'check_i', 'check_o'])
-
- assert_equal(
- 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'])
- assert_equal(
- 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'])
-
- assert_equal(
- get_all_test_methods(Multi), ['check_r1', 'check_r2', 'check_multi'])
diff --git a/glslc/test/glslc_test_framework_unittest.py b/glslc/test/glslc_test_framework_unittest.py
new file mode 100644
index 0000000..3f58432
--- /dev/null
+++ b/glslc/test/glslc_test_framework_unittest.py
@@ -0,0 +1,159 @@
+# 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'])
\ No newline at end of file
diff --git a/glslc/test/include.py b/glslc/test/include.py
index a965032..798ff22 100644
--- a/glslc/test/include.py
+++ b/glslc/test/include.py
@@ -49,7 +49,7 @@
glslc_args = ['-E', 'a.vert']
expected_error = [
- "a.vert:3: error: '#include' : Cannot find or open include file.\n",
+ "a.vert:3: error: '#include' : Cannot find or open include file. for header name: b\n",
'1 error generated.\n'
]
@@ -64,7 +64,7 @@
glslc_args = ['a.vert']
@inside_glslc_testsuite('Include')
-class VerifyIncludeWithoutNewline(expect.StdoutMatch):
+class VerifyIncludeWithoutNewline(expect.ErrorMessageSubstr):
"""Tests a #include without a newline."""
environment = Directory('.', [
@@ -73,16 +73,8 @@
glslc_args = ['-E', 'a.vert']
- expected_stdout = \
-"""#version 140
-#extension GL_GOOGLE_include_directive : enable
-#line 0 "a.vert"
+ expected_error_substr = 'expected newline after header name: b'
-#line 0 "b"
-content b
-#line 2 "a.vert"
-
-"""
@inside_glslc_testsuite('Include')
class VerifyCompileIncludeWithoutNewline(expect.ValidObjectFile):
@@ -282,10 +274,11 @@
environment = Directory('.', [
File('a.vert', '#version 100000000\n#include "b.glsl"\n'),
File('b.glsl', 'void main() {}\n')])
- glslc_args = ['-c', 'a.vert']
+ glslc_args = ['-c', '-std=400', 'a.vert']
expected_warning = [
- 'a.vert: warning: version 100000000 is unknown.\n',
+ 'a.vert: warning: (version, profile) forced to be (400, none),'
+ ' while in source code it is (100000000, none)\n'
'1 warning generated.\n'
]
@@ -506,7 +499,8 @@
glslc_args = ['-E', 'a.vert']
expected_error = [
- "foo/b.glsl:1: error: '#include' : Cannot find or open include file.\n",
+ "foo/b.glsl:1: error: '#include' : "
+ 'Cannot find or open include file. for header name: c.glsl\n',
'1 error generated.\n'
]
diff --git a/glslc/test/line.py b/glslc/test/line.py
index a74cb11..0b4cd2c 100644
--- a/glslc/test/line.py
+++ b/glslc/test/line.py
@@ -243,7 +243,8 @@
including_file = '''#version 310 es
#include "error.glsl"
int no_return() {}
-#include "main.glsl"'''
+#include "main.glsl"
+'''
environment = Directory('.', [
File('a.vert', including_file),
@@ -256,8 +257,8 @@
"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",
+ "main.glsl:2: error: '=' : cannot convert from ' const float' to "
+ "' temp highp int'\n",
"4 errors generated.\n"]
@@ -272,7 +273,8 @@
#include "inc.glsl"
int plus2(int a) { return a + 2; }
#line 55555
-#include "main.glsl"'''
+#include "main.glsl"
+'''
environment = Directory('.', [
File('a.vert', including_file),
diff --git a/glslc/test/messages_tests.py b/glslc/test/messages_tests.py
index 21c1bbc..401f3db 100644
--- a/glslc/test/messages_tests.py
+++ b/glslc/test/messages_tests.py
@@ -84,10 +84,11 @@
void main() {
}
""", '.vert')
- glslc_args = ['-c', shader]
+ glslc_args = ['-c', '-std=400', shader]
expected_warning = [
- shader, ': warning: version 550 is unknown.\n1 warning generated.\n']
+ 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):
@@ -99,7 +100,7 @@
void main() {
}
""", '.vert')
- glslc_args = ['-c', shader, '-w']
+ glslc_args = ['-c', '-std=400', shader, '-w']
@inside_glslc_testsuite('ErrorMessages')
@@ -112,18 +113,19 @@
void main() {
}
""", '.vert')
- glslc_args = ['-c', shader, '-Werror']
+ glslc_args = ['-c', '-std=400', shader, '-Werror']
expected_error= [
- shader, ': error: version 550 is unknown.\n1 error generated.\n']
+ 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 140
- attribute float x;
+ """#version 400
+ layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
@@ -139,8 +141,8 @@
presence of -w."""
shader = FileShader(
- """#version 140
- attribute float x;
+ """#version 400
+ layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
@@ -152,8 +154,8 @@
number is emitted instead of a warning."""
shader = FileShader(
- """#version 140
- attribute float x;
+ """#version 400
+ layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
@@ -168,8 +170,8 @@
"""Tests that both warnings and errors are emitted together."""
shader = FileShader(
- """#version 140
- attribute float x;
+ """#version 400
+ layout(location = 0) attribute float x;
int main() {
}
""", '.vert')
@@ -187,8 +189,8 @@
"""Tests that only warnings are suppressed in the presence of -w."""
shader = FileShader(
- """#version 140
- attribute float x;
+ """#version 400
+ layout(location = 0) attribute float x;
int main() {
}
""", '.vert')
@@ -204,8 +206,8 @@
"""Tests that with -Werror an warnings and errors are emitted as errors."""
shader = FileShader(
- """#version 140
- attribute float x;
+ """#version 400
+ layout(location = 0) attribute float x;
int main() {
}
""", '.vert')
@@ -243,8 +245,8 @@
"""
shader = FileShader(
- """#version 140
- attribute float x;
+ """#version 400
+ layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
@@ -255,21 +257,23 @@
}
""", '.vert')
- glslc_args = ['-c', shader, '-Werror', shader2]
+ 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 550 is unknown.\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 140
- attribute float x;
+ """#version 400
+ layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
@@ -280,8 +284,8 @@
"""Tests that multiple -w arguments are supported."""
shader = FileShader(
- """#version 140
- attribute float x;
+ """#version 400
+ layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
@@ -292,15 +296,15 @@
"""Tests that -w suppresses warnings from all files."""
shader = FileShader(
- """#version 140
- attribute float x;
+ """#version 400
+ layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
shader2 = FileShader(
- """#version 140
- attribute float x;
+ """#version 400
+ layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
diff --git a/glslc/test/option_dash_M.py b/glslc/test/option_dash_M.py
index b7d77ba..9fadb01 100644
--- a/glslc/test/option_dash_M.py
+++ b/glslc/test/option_dash_M.py
@@ -14,6 +14,7 @@
import expect
import os.path
+import sys
from environment import File, Directory
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
@@ -100,7 +101,12 @@
if not status.stdout:
return False, 'Expect dependency rules on stdout'
- rules = parse_text_rules(status.stdout.split('\n'))
+ 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)
@@ -309,7 +315,7 @@
environment = Directory('.', [
Directory('include', [File('b.vert', 'void foo(){}\n')]),
])
- shader_main = FileShader('#version 140\n#include "include/b.vert"',
+ shader_main = FileShader('#version 140\n#include "include/b.vert"\n',
'.vert')
glslc_args = ['-M', shader_main]
dependency_rules_expected = [{
@@ -381,7 +387,9 @@
<no warning message should be generated>
"""
environment = Directory('.', [File(
- 'shader.vert', '#version 140\nattribute float x;\nvoid main() {}')])
+ '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'}}]
@@ -412,7 +420,10 @@
<no warning message should be generated>
"""
environment = Directory('.', [File(
- 'shader.vert', '#version 140\nattribute float x;\nvoid main() {}')])
+ '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'}}]
diff --git a/glslc/test/option_dash_cap_O.py b/glslc/test/option_dash_cap_O.py
index 8a7f234..9655a39 100644
--- a/glslc/test/option_dash_cap_O.py
+++ b/glslc/test/option_dash_cap_O.py
@@ -20,10 +20,38 @@
MINIMAL_SHADER = '#version 310 es\nvoid main() {}'
EMPTY_SHADER_IN_CWD = Directory('.', [File('shader.vert', MINIMAL_SHADER)])
+ASSEMBLY_WITH_DEBUG_SOURCE = [
+ '; SPIR-V\n',
+ '; Version: 1.0\n',
+ '; Generator: Google Shaderc over Glslang; 10\n',
+ '; Bound: 7\n',
+ '; Schema: 0\n',
+ ' OpCapability Shader\n',
+ ' %2 = OpExtInstImport "GLSL.std.450"\n',
+ ' OpMemoryModel Logical GLSL450\n',
+ ' OpEntryPoint Vertex %main "main"\n',
+ ' %1 = OpString "shader.vert"\n',
+ ' OpSource ESSL 310 %1 "// OpModuleProcessed entry-point main\n',
+ '// OpModuleProcessed client vulkan100\n',
+ '// OpModuleProcessed target-env vulkan1.0\n',
+ '// OpModuleProcessed entry-point main\n',
+ '#line 1\n',
+ '#version 310 es\n',
+ 'void main() {}"\n',
+ ' OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"\n',
+ ' OpSourceExtension "GL_GOOGLE_include_directive"\n',
+ ' OpName %main "main"\n',
+ ' %void = OpTypeVoid\n',
+ ' %4 = OpTypeFunction %void\n',
+ ' %main = OpFunction %void None %4\n',
+ ' %6 = OpLabel\n',
+ ' OpReturn\n',
+ ' OpFunctionEnd\n']
+
ASSEMBLY_WITH_DEBUG = [
'; SPIR-V\n',
'; Version: 1.0\n',
- '; Generator: Khronos Glslang Reference Front End; 1\n',
+ '; Generator: Google Shaderc over Glslang; 10\n',
'; Bound: 6\n',
'; Schema: 0\n',
' OpCapability Shader\n',
@@ -44,7 +72,7 @@
ASSEMBLY_WITHOUT_DEBUG = [
'; SPIR-V\n',
'; Version: 1.0\n',
- '; Generator: Khronos Glslang Reference Front End; 1\n',
+ '; Generator: Google Shaderc over Glslang; 10\n',
'; Bound: 6\n',
'; Schema: 0\n',
' OpCapability Shader\n',
@@ -68,6 +96,14 @@
target_filename = 'shader.vert.spvasm'
expected_file_contents = ASSEMBLY_WITH_DEBUG
+@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_WITHOUT_DEBUG
@inside_glslc_testsuite('OptionDashCapO')
class TestDashCapOs(expect.ValidFileContents):
@@ -96,7 +132,7 @@
environment = EMPTY_SHADER_IN_CWD
glslc_args = ['-S', '-Os', '-g', 'shader.vert']
target_filename = 'shader.vert.spvasm'
- expected_file_contents = ASSEMBLY_WITH_DEBUG
+ expected_file_contents = ASSEMBLY_WITH_DEBUG_SOURCE
@inside_glslc_testsuite('OptionDashCapO')
@@ -106,7 +142,7 @@
environment = EMPTY_SHADER_IN_CWD
glslc_args = ['-S', '-g', '-Os', 'shader.vert']
target_filename = 'shader.vert.spvasm'
- expected_file_contents = ASSEMBLY_WITH_DEBUG
+ expected_file_contents = ASSEMBLY_WITH_DEBUG_SOURCE
@inside_glslc_testsuite('OptionDashCapO')
diff --git a/glslc/test/option_dash_fhlsl_offsets.py b/glslc/test/option_dash_fhlsl_offsets.py
new file mode 100644
index 0000000..4682d31
--- /dev/null
+++ b/glslc/test/option_dash_fhlsl_offsets.py
@@ -0,0 +1,44 @@
+# 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"
diff --git a/glslc/test/option_dash_fnan_clamp.py b/glslc/test/option_dash_fnan_clamp.py
new file mode 100644
index 0000000..36b9006
--- /dev/null
+++ b/glslc/test/option_dash_fnan_clamp.py
@@ -0,0 +1,69 @@
+# 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'
diff --git a/glslc/test/option_dash_o.py b/glslc/test/option_dash_o.py
index 1a32c12..cd7f1d1 100644
--- a/glslc/test/option_dash_o.py
+++ b/glslc/test/option_dash_o.py
@@ -16,6 +16,7 @@
import os.path
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader, TempFileName
+from builtins import bytes
@inside_glslc_testsuite('OptionDashO')
@@ -63,3 +64,35 @@
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 != 3:
+ 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))
diff --git a/glslc/test/option_dash_x.py b/glslc/test/option_dash_x.py
index 3645340..4c0bbdf 100644
--- a/glslc/test/option_dash_x.py
+++ b/glslc/test/option_dash_x.py
@@ -19,8 +19,12 @@
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.
-HLSL_VERTEX_SHADER = "float4 EntryPoint() : SV_POSITION { return float4(1.0); }"
+# 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):
@@ -56,6 +60,15 @@
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"]
diff --git a/glslc/test/option_fauto_bind_uniforms.py b/glslc/test/option_fauto_bind_uniforms.py
new file mode 100644
index 0000000..3f90a12
--- /dev/null
+++ b/glslc/test/option_fauto_bind_uniforms.py
@@ -0,0 +1,431 @@
+# 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 <float4> t2 : register(t12);
+Texture3D <float2> t3 : register(t13);
+StructuredBuffer<float4> t4 : register(t14);
+ByteAddressBuffer t5 : register(t15);
+Buffer<float4> t6 : register(t16);
+
+RWTexture1D <float4> u1 : register(u21);
+RWTexture1D <float4> u2 : register(u22);
+RWTexture1D <float4> u3 : register(u23);
+RWBuffer <float4> u4 : register(u24);
+RWByteAddressBuffer u5 : register(u25);
+RWStructuredBuffer<float> u6 : register(u26);
+AppendStructuredBuffer<float> u7 : register(u27);
+ConsumeStructuredBuffer<float> 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;
+ return float4(u8.Consume() + t2.SampleCmp(s2, 1.0, 2.0)) + 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 %s2 Binding 102"
+
+
+@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 %s2 Binding 102"
+
+
+@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 %s2 Binding 2"
+
+
+@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"
diff --git a/glslc/test/option_fauto_map_locations.py b/glslc/test/option_fauto_map_locations.py
new file mode 100644
index 0000000..24ef496
--- /dev/null
+++ b/glslc/test/option_fauto_map_locations.py
@@ -0,0 +1,87 @@
+# 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"
diff --git a/glslc/test/option_fentry_point.py b/glslc/test/option_fentry_point.py
index 5d8f96f..8625732 100644
--- a/glslc/test/option_fentry_point.py
+++ b/glslc/test/option_fentry_point.py
@@ -58,17 +58,21 @@
@inside_glslc_testsuite('OptionFEntryPoint')
-class TestFEntryPointMainOnHlslShader(expect.ValidAssemblyFileWithSubstr):
- """Tests -x hlsl on an HLSL shader with -fentry-point=main and -S."""
+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', '-S', shader]
- expected_assembly_substr = ASSEMBLY_MAIN
+ 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."""
+ """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]
diff --git a/glslc/test/option_fhlsl_functionality1.py b/glslc/test/option_fhlsl_functionality1.py
new file mode 100644
index 0000000..51453ee
--- /dev/null
+++ b/glslc/test/option_fhlsl_functionality1.py
@@ -0,0 +1,71 @@
+# 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<int> 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'
diff --git a/glslc/test/option_flimit.py b/glslc/test/option_flimit.py
new file mode 100644
index 0000000..30a0e02
--- /dev/null
+++ b/glslc/test/option_flimit.py
@@ -0,0 +1,136 @@
+# 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'
diff --git a/glslc/test/option_fresource_set_binding.py b/glslc/test/option_fresource_set_binding.py
new file mode 100644
index 0000000..254004e
--- /dev/null
+++ b/glslc/test/option_fresource_set_binding.py
@@ -0,0 +1,121 @@
+# 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<float4> t4 : register(t4);
+Buffer<float4> 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 DescriptorSet 9
+ OpDecorate %t4 Binding 16
+ OpDecorate %t5 DescriptorSet 17
+ OpDecorate %t5 Binding 18"""
+
+
+@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 DescriptorSet 9
+ OpDecorate %t4 Binding 16
+ OpDecorate %t5 DescriptorSet 0
+ OpDecorate %t5 Binding 5"""
+
+
+@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 DescriptorSet 0
+ OpDecorate %t4 Binding 4
+ OpDecorate %t5 DescriptorSet 0
+ OpDecorate %t5 Binding 5"""
+
+
+@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 DescriptorSet 9
+ OpDecorate %t4 Binding 16
+ OpDecorate %t5 DescriptorSet 17
+ OpDecorate %t5 Binding 18"""
+
+
+@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
diff --git a/glslc/test/option_mfmt.py b/glslc/test/option_mfmt.py
index 2466319..bd58478 100644
--- a/glslc/test/option_mfmt.py
+++ b/glslc/test/option_mfmt.py
@@ -90,8 +90,7 @@
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 the output is not SPIR-V "
- "binary code\n")
+ "initializer list when only preprocessing the source\n")
@inside_glslc_testsuite('OptionMfmt')
@@ -103,7 +102,7 @@
glslc_args = [shader, '-mfmt=num', '-S', '-o', 'output_file']
expected_error = (
"glslc: error: cannot emit output as a list of hex numbers "
- "when the output is not SPIR-V binary code\n")
+ "when only preprocessing the source\n")
@inside_glslc_testsuite('OptionMfmt')
@@ -114,7 +113,7 @@
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 the output is not SPIR-V binary code\n")
+ "when only preprocessing the source\n")
@inside_glslc_testsuite('OptionMfmt')
@@ -126,7 +125,7 @@
glslc_args = [shader, '-mfmt=num', '-E', '-o', 'output_file']
expected_error = (
"glslc: error: cannot emit output as a list of hex numbers "
- "when the output is not SPIR-V binary code\n")
+ "when only preprocessing the source\n")
@inside_glslc_testsuite('OptionMfmt')
@@ -138,8 +137,7 @@
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 the output is not SPIR-V "
- "binary code\n")
+ "initializer list when only preprocessing the source\n")
@inside_glslc_testsuite('OptionMfmt')
diff --git a/glslc/test/option_shader_stage.py b/glslc/test/option_shader_stage.py
index 5114173..6b2ec0b 100644
--- a/glslc/test/option_shader_stage.py
+++ b/glslc/test/option_shader_stage.py
@@ -25,7 +25,8 @@
def simple_hlsl_vertex_shader():
- return """float4 EntryPoint() : SV_POSITION { return float4(1.0); } """
+ # Use "main" so we don't have to specify -fentry-point
+ return """float4 main() : SV_POSITION { return float4(1.0); } """
def simple_fragment_shader():
diff --git a/glslc/test/option_std.py b/glslc/test/option_std.py
index 865a4d2..ff65a4b 100644
--- a/glslc/test/option_std.py
+++ b/glslc/test/option_std.py
@@ -29,7 +29,8 @@
def hlsl_compute_shader_with_barriers():
- return 'void Entry() { AllMemoryBarrierWithGroupSync(); }'
+ # Use "main" to avoid the need for -fentry-point
+ return 'void main() { AllMemoryBarrierWithGroupSync(); }'
@inside_glslc_testsuite('OptionStd')
@@ -76,6 +77,30 @@
@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."""
@@ -271,7 +296,7 @@
glslc_args = ['-c', '-std=310', shader]
expected_error = [
- shader, ': error: #version: versions 300 and 310 require ',
+ shader, ': error: #version: versions 300, 310, and 320 require ',
"specifying the 'es' profile\n1 error generated.\n"]
diff --git a/glslc/test/option_target_env.py b/glslc/test/option_target_env.py
index 7c0b67a..334a95f 100644
--- a/glslc/test/option_target_env.py
+++ b/glslc/test/option_target_env.py
@@ -35,6 +35,13 @@
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.ValidObjectFile):
"""Tests that compiling OpenGL Compatibility Fragment shader with
@@ -50,8 +57,9 @@
shader = FileShader(opengl_compat_fragment_shader(), '.frag')
glslc_args = ['--target-env=opengl', shader]
expected_error_substr = [shader, ":4: error: 'assign' : ",
- "cannot convert from 'const float' to ",
- "'fragColor"]
+ "cannot convert from ' const float' to ",
+ "'layout( location=0) out 4-component ",
+ "vector of float"]
@inside_glslc_testsuite('OptionTargetEnv')
@@ -79,13 +87,62 @@
@inside_glslc_testsuite('OptionTargetEnv')
-class TestTargetEnvEqVulkanWithVulkanShader(expect.ValidObjectFile):
- """Tests that compiling a Vulkan-specific shader succeeds with
+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 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
diff --git a/glslc/test/option_target_spv.py b/glslc/test/option_target_spv.py
new file mode 100644
index 0000000..870025b
--- /dev/null
+++ b/glslc/test/option_target_spv.py
@@ -0,0 +1,118 @@
+# 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]
+
+
+### 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"]
diff --git a/glslc/test/parameter_tests.py b/glslc/test/parameter_tests.py
index cbb6f11..18b43f4 100644
--- a/glslc/test/parameter_tests.py
+++ b/glslc/test/parameter_tests.py
@@ -57,38 +57,123 @@
-Dmacro[=defn] Add an implicit macro definition.
-E Outputs only the results of the preprocessing step.
Output defaults to standard output.
- -fshader-stage=<stage>
- Treat subsequent input files as having stage <stage>.
- Valid stages are vertex, fragment, tesscontrol, tesseval,
- geometry, and compute.
+ -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.
-fentry-point=<name>
Specify the entry point name for HLSL compilation, for
all subsequent source files. Default is "main".
+ -fhlsl_functionality1, -fhlsl-functionality1
+ Enable extension SPV_GOOGLE_hlsl_functionality1 for HLSL
+ compilation.
+ -finvert-y Invert position.Y output in vertex shader.
+ -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.
+ -flimit=<settings>
+ 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 <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.
+ -fresource-set-binding [stage] <reg0> <set0> <binding0>
+ [<reg1> <set1> <binding1>...]
+ Explicitly sets the descriptor set and binding for
+ HLSL resources, by register name. Optionally restrict
+ it to a single stage.
+ -fcbuffer-binding-base [stage] <value>
+ Same as -fubo-binding-base.
+ -fimage-binding-base [stage] <value>
+ 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] <value>
+ 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] <value>
+ 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] <value>
+ 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] <value>
+ 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] <value>
+ 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=<stage>
+ Treat subsequent input files as having stage <stage>.
+ Valid stages are vertex, vert, fragment, frag, tesscontrol,
+ tesc, tesseval, tese, geometry, geom, compute, and comp.
-g Generate source-level debug information.
Currently this option has no effect.
+ -h Display available options.
--help Display available options.
- --version Display compiler version information.
-I <value> Add directory to include search path.
- -o <file> Write output to <file>.
- A file name of '-' represents standard output.
- -std=<value> Version and profile for GLSL input files. Possible values
- are concatenations of version and profile, e.g. 310es,
- 450core, etc. Ignored for HLSL files.
-mfmt=<format> 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 include bin, c
- and num. By default the binary output format is bin.
+ 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 <file> Write dependency output to the given file.
-MT <target> Specify the target of the rule emitted by dependency
generation.
- -S Only run preprocess and compilation steps.
+ -O Optimize the generated SPIR-V code for better performance.
+ -Os Optimize the generated SPIR-V code for smaller size.
+ -O0 Disable optimization.
+ -o <file> Write output to <file>.
+ A file name of '-' represents standard output.
+ -std=<value> 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=<environment>
- Set the target shader environment, and the semantics
- of warnings and errors. Valid values are 'opengl',
- 'opengl_compat' and 'vulkan'. The default value is 'vulkan'.
+ 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
+ vulkan # Same as vulkan1.0
+ opengl4.5
+ opengl # Same as opengl4.5
+ --target-spv=<spirv-version>
+ 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.
+ Values are:
+ spv1.0, spv1.1, spv1.2, spv1.3, spv1.4, spv1.5
+ --version Display compiler version information.
-w Suppresses all warning messages.
-Werror Treat all warnings as errors.
-x <language> Treat subsequent input files as having type <language>.
@@ -182,3 +267,96 @@
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
+"""
diff --git a/glslc/test/placeholder.py b/glslc/test/placeholder.py
index 8a701bf..4bff75c 100644
--- a/glslc/test/placeholder.py
+++ b/glslc/test/placeholder.py
@@ -23,6 +23,7 @@
import os
import tempfile
from string import Template
+from builtins import bytes
class PlaceHolderException(Exception):
@@ -97,7 +98,7 @@
def instantiate_for_glslc_args(self, testcase):
"""Writes the source code back to the TestCase instance."""
- testcase.stdin_shader = self.source
+ testcase.stdin_shader = bytes(self.source, 'utf-8')
self.filename = '-'
return self.filename
diff --git a/kokoro/android-release/build.sh b/kokoro/android-release/build.sh
new file mode 100644
index 0000000..0443c8a
--- /dev/null
+++ b/kokoro/android-release/build.sh
@@ -0,0 +1,59 @@
+#!/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
+
+BUILD_ROOT=$PWD
+SRC=$PWD/github/shaderc
+TARGET_ARCH=$1
+
+# Get NINJA.
+wget -q https://github.com/ninja-build/ninja/releases/download/v1.7.2/ninja-linux.zip
+unzip -q ninja-linux.zip
+NINJA=$PWD/ninja
+
+# Get Android NDK.
+wget -q https://dl.google.com/android/repository/android-ndk-r18b-linux-x86_64.zip
+unzip -q android-ndk-r18b-linux-x86_64.zip
+NDK=$PWD/android-ndk-r18b
+
+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_BUILD_TYPE=Release -DCMAKE_MAKE_PROGRAM=$NINJA -DANDROID_ABI=$TARGET_ARCH -DSHADERC_SKIP_TESTS=ON -DSPIRV_SKIP_TESTS=ON -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake -DANDROID_NDK=$NDK ..
+
+echo $(date): Build glslang...
+$NINJA glslangValidator
+
+echo $(date): Build everything...
+$NINJA
+
+echo $(date): Check Shaderc for copyright notices...
+$NINJA check-copyright
+
+echo $(date): Build completed.
diff --git a/kokoro/android-release/build_arm.sh b/kokoro/android-release/build_arm.sh
new file mode 100644
index 0000000..6d43504
--- /dev/null
+++ b/kokoro/android-release/build_arm.sh
@@ -0,0 +1,25 @@
+#!/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"
diff --git a/kokoro/android-release/build_x86.sh b/kokoro/android-release/build_x86.sh
new file mode 100644
index 0000000..c642ab1
--- /dev/null
+++ b/kokoro/android-release/build_x86.sh
@@ -0,0 +1,26 @@
+#!/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
+
diff --git a/kokoro/android-release/continuous_arm.cfg b/kokoro/android-release/continuous_arm.cfg
new file mode 100644
index 0000000..a4f931a
--- /dev/null
+++ b/kokoro/android-release/continuous_arm.cfg
@@ -0,0 +1,17 @@
+# 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"
diff --git a/kokoro/android-release/continuous_x86.cfg b/kokoro/android-release/continuous_x86.cfg
new file mode 100644
index 0000000..a8643d5
--- /dev/null
+++ b/kokoro/android-release/continuous_x86.cfg
@@ -0,0 +1,17 @@
+# 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"
diff --git a/kokoro/android-release/presubmit_arm.cfg b/kokoro/android-release/presubmit_arm.cfg
new file mode 100644
index 0000000..b88294d
--- /dev/null
+++ b/kokoro/android-release/presubmit_arm.cfg
@@ -0,0 +1,16 @@
+# 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"
diff --git a/kokoro/android-release/presubmit_x86.cfg b/kokoro/android-release/presubmit_x86.cfg
new file mode 100644
index 0000000..590753e
--- /dev/null
+++ b/kokoro/android-release/presubmit_x86.cfg
@@ -0,0 +1,16 @@
+# 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"
diff --git a/kokoro/img/linux.png b/kokoro/img/linux.png
new file mode 100644
index 0000000..ff066d9
--- /dev/null
+++ b/kokoro/img/linux.png
Binary files differ
diff --git a/kokoro/img/macos.png b/kokoro/img/macos.png
new file mode 100644
index 0000000..d1349c0
--- /dev/null
+++ b/kokoro/img/macos.png
Binary files differ
diff --git a/kokoro/img/windows.png b/kokoro/img/windows.png
new file mode 100644
index 0000000..a378469
--- /dev/null
+++ b/kokoro/img/windows.png
Binary files differ
diff --git a/kokoro/linux/build-docker.sh b/kokoro/linux/build-docker.sh
new file mode 100755
index 0000000..fb65f81
--- /dev/null
+++ b/kokoro/linux/build-docker.sh
@@ -0,0 +1,98 @@
+#!/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.17.2
+using ninja-1.10.0
+
+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="-Dgtest_disable_pthreads=ON -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 -DSHADERC_ENABLE_SPVC=ON -DRE2_BUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=$BUILD_TYPE $ADDITIONAL_CMAKE_FLAGS ..
+
+echo $(date): Build glslang...
+ninja glslangValidator
+
+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.
+
+# Package the build.
+ninja install
+cd $KOKORO_ARTIFACTS_DIR
+tar czf install.tgz install
diff --git a/kokoro/linux/build.sh b/kokoro/linux/build.sh
new file mode 100755
index 0000000..765a387
--- /dev/null
+++ b/kokoro/linux/build.sh
@@ -0,0 +1,37 @@
+#!/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
+
+docker run --rm -i \
+ --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" \
+ "gcr.io/shaderc-build/radial-build:latest"
diff --git a/kokoro/linux/build_clang_asan.sh b/kokoro/linux/build_clang_asan.sh
new file mode 100755
index 0000000..9110bc5
--- /dev/null
+++ b/kokoro/linux/build_clang_asan.sh
@@ -0,0 +1,25 @@
+#!/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-10.0.0"
diff --git a/kokoro/linux/build_clang_debug.sh b/kokoro/linux/build_clang_debug.sh
new file mode 100755
index 0000000..227237e
--- /dev/null
+++ b/kokoro/linux/build_clang_debug.sh
@@ -0,0 +1,25 @@
+#!/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-10.0.0"
diff --git a/kokoro/linux/build_clang_release.sh b/kokoro/linux/build_clang_release.sh
new file mode 100755
index 0000000..126f5d4
--- /dev/null
+++ b/kokoro/linux/build_clang_release.sh
@@ -0,0 +1,25 @@
+#!/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-10.0.0"
diff --git a/kokoro/linux/build_gcc_coverage.sh b/kokoro/linux/build_gcc_coverage.sh
new file mode 100755
index 0000000..7270334
--- /dev/null
+++ b/kokoro/linux/build_gcc_coverage.sh
@@ -0,0 +1,25 @@
+#!/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
diff --git a/kokoro/linux/build_gcc_debug.sh b/kokoro/linux/build_gcc_debug.sh
new file mode 100755
index 0000000..3a96cf7
--- /dev/null
+++ b/kokoro/linux/build_gcc_debug.sh
@@ -0,0 +1,25 @@
+#!/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-9"
diff --git a/kokoro/linux/build_gcc_debug_exception.sh b/kokoro/linux/build_gcc_debug_exception.sh
new file mode 100755
index 0000000..9849336
--- /dev/null
+++ b/kokoro/linux/build_gcc_debug_exception.sh
@@ -0,0 +1,25 @@
+#!/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-9"
diff --git a/kokoro/linux/build_gcc_release.sh b/kokoro/linux/build_gcc_release.sh
new file mode 100755
index 0000000..9123604
--- /dev/null
+++ b/kokoro/linux/build_gcc_release.sh
@@ -0,0 +1,25 @@
+#!/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-9"
diff --git a/kokoro/linux/build_mingw_release.sh b/kokoro/linux/build_mingw_release.sh
new file mode 100755
index 0000000..0b54dc6
--- /dev/null
+++ b/kokoro/linux/build_mingw_release.sh
@@ -0,0 +1,25 @@
+#!/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
diff --git a/kokoro/linux/continuous_clang_asan.cfg b/kokoro/linux/continuous_clang_asan.cfg
new file mode 100644
index 0000000..1291151
--- /dev/null
+++ b/kokoro/linux/continuous_clang_asan.cfg
@@ -0,0 +1,16 @@
+# 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"
diff --git a/kokoro/linux/continuous_clang_debug.cfg b/kokoro/linux/continuous_clang_debug.cfg
new file mode 100644
index 0000000..1021c44
--- /dev/null
+++ b/kokoro/linux/continuous_clang_debug.cfg
@@ -0,0 +1,22 @@
+# 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"
+ }
+}
diff --git a/kokoro/linux/continuous_clang_release.cfg b/kokoro/linux/continuous_clang_release.cfg
new file mode 100644
index 0000000..cffba60
--- /dev/null
+++ b/kokoro/linux/continuous_clang_release.cfg
@@ -0,0 +1,22 @@
+# 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"
+ }
+}
diff --git a/kokoro/linux/continuous_gcc_coverage.cfg b/kokoro/linux/continuous_gcc_coverage.cfg
new file mode 100644
index 0000000..ab2878c
--- /dev/null
+++ b/kokoro/linux/continuous_gcc_coverage.cfg
@@ -0,0 +1,16 @@
+# 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_coverage.sh"
diff --git a/kokoro/linux/continuous_gcc_debug.cfg b/kokoro/linux/continuous_gcc_debug.cfg
new file mode 100644
index 0000000..526f08f
--- /dev/null
+++ b/kokoro/linux/continuous_gcc_debug.cfg
@@ -0,0 +1,22 @@
+# 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"
+ }
+}
diff --git a/kokoro/linux/continuous_gcc_debug_exception.cfg b/kokoro/linux/continuous_gcc_debug_exception.cfg
new file mode 100644
index 0000000..cecd155
--- /dev/null
+++ b/kokoro/linux/continuous_gcc_debug_exception.cfg
@@ -0,0 +1,16 @@
+# 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"
diff --git a/kokoro/linux/continuous_gcc_release.cfg b/kokoro/linux/continuous_gcc_release.cfg
new file mode 100644
index 0000000..8e0cde8
--- /dev/null
+++ b/kokoro/linux/continuous_gcc_release.cfg
@@ -0,0 +1,22 @@
+# 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"
+ }
+}
diff --git a/kokoro/linux/continuous_license_check.cfg b/kokoro/linux/continuous_license_check.cfg
new file mode 100644
index 0000000..066a4d3
--- /dev/null
+++ b/kokoro/linux/continuous_license_check.cfg
@@ -0,0 +1,16 @@
+# 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"
diff --git a/kokoro/linux/continuous_mingw_release.cfg b/kokoro/linux/continuous_mingw_release.cfg
new file mode 100644
index 0000000..a0d4e76
--- /dev/null
+++ b/kokoro/linux/continuous_mingw_release.cfg
@@ -0,0 +1,16 @@
+# 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"
diff --git a/kokoro/linux/license_check.sh b/kokoro/linux/license_check.sh
new file mode 100755
index 0000000..a36e4ff
--- /dev/null
+++ b/kokoro/linux/license_check.sh
@@ -0,0 +1,28 @@
+#!/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}" \
+ --env ROOT_DIR="${ROOT_DIR}" \
+ --env SCRIPT_DIR="${SCRIPT_DIR}" \
+ --entrypoint "${SCRIPT_DIR}/license_check_docker.sh" \
+ "gcr.io/shaderc-build/radial-build:latest"
diff --git a/kokoro/linux/license_check_docker.sh b/kokoro/linux/license_check_docker.sh
new file mode 100755
index 0000000..f88077e
--- /dev/null
+++ b/kokoro/linux/license_check_docker.sh
@@ -0,0 +1,20 @@
+#!/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.
+set -x # Display commands being run.
+
+license-checker --dir="$ROOT_DIR"
\ No newline at end of file
diff --git a/kokoro/linux/presubmit_clang_asan.cfg b/kokoro/linux/presubmit_clang_asan.cfg
new file mode 100644
index 0000000..fcaaa36
--- /dev/null
+++ b/kokoro/linux/presubmit_clang_asan.cfg
@@ -0,0 +1,16 @@
+# 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"
diff --git a/kokoro/linux/presubmit_clang_debug.cfg b/kokoro/linux/presubmit_clang_debug.cfg
new file mode 100644
index 0000000..87abaf7
--- /dev/null
+++ b/kokoro/linux/presubmit_clang_debug.cfg
@@ -0,0 +1,16 @@
+# 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"
diff --git a/kokoro/linux/presubmit_clang_release.cfg b/kokoro/linux/presubmit_clang_release.cfg
new file mode 100644
index 0000000..81ba77d
--- /dev/null
+++ b/kokoro/linux/presubmit_clang_release.cfg
@@ -0,0 +1,16 @@
+# 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"
diff --git a/kokoro/linux/presubmit_gcc_coverage.cfg b/kokoro/linux/presubmit_gcc_coverage.cfg
new file mode 100644
index 0000000..54733b0
--- /dev/null
+++ b/kokoro/linux/presubmit_gcc_coverage.cfg
@@ -0,0 +1,16 @@
+# 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_coverage.sh"
diff --git a/kokoro/linux/presubmit_gcc_debug.cfg b/kokoro/linux/presubmit_gcc_debug.cfg
new file mode 100644
index 0000000..f0eec27
--- /dev/null
+++ b/kokoro/linux/presubmit_gcc_debug.cfg
@@ -0,0 +1,17 @@
+# 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"
+
diff --git a/kokoro/linux/presubmit_gcc_release.cfg b/kokoro/linux/presubmit_gcc_release.cfg
new file mode 100644
index 0000000..fda4333
--- /dev/null
+++ b/kokoro/linux/presubmit_gcc_release.cfg
@@ -0,0 +1,16 @@
+# 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"
diff --git a/kokoro/linux/presubmit_license_check.cfg b/kokoro/linux/presubmit_license_check.cfg
new file mode 100644
index 0000000..38db8f5
--- /dev/null
+++ b/kokoro/linux/presubmit_license_check.cfg
@@ -0,0 +1,16 @@
+# 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"
diff --git a/kokoro/macos/build.sh b/kokoro/macos/build.sh
new file mode 100644
index 0000000..ff2d38c
--- /dev/null
+++ b/kokoro/macos/build.sh
@@ -0,0 +1,63 @@
+#!/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 -DSHADERC_ENABLE_SPVC=ON -DRE2_BUILD_TESTING=OFF -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
+
+echo $(date): Build glslang...
+ninja glslangValidator
+
+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
diff --git a/kokoro/macos/build_clang_debug.sh b/kokoro/macos/build_clang_debug.sh
new file mode 100644
index 0000000..ed889ff
--- /dev/null
+++ b/kokoro/macos/build_clang_debug.sh
@@ -0,0 +1,26 @@
+#!/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
+
diff --git a/kokoro/macos/build_clang_release.sh b/kokoro/macos/build_clang_release.sh
new file mode 100644
index 0000000..9599bac
--- /dev/null
+++ b/kokoro/macos/build_clang_release.sh
@@ -0,0 +1,26 @@
+#!/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
+
diff --git a/kokoro/macos/continuous_clang_debug.cfg b/kokoro/macos/continuous_clang_debug.cfg
new file mode 100644
index 0000000..d8000a9
--- /dev/null
+++ b/kokoro/macos/continuous_clang_debug.cfg
@@ -0,0 +1,22 @@
+# 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"
+ }
+}
diff --git a/kokoro/macos/continuous_clang_release.cfg b/kokoro/macos/continuous_clang_release.cfg
new file mode 100644
index 0000000..101d06e
--- /dev/null
+++ b/kokoro/macos/continuous_clang_release.cfg
@@ -0,0 +1,22 @@
+# 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"
+ }
+}
diff --git a/kokoro/macos/presubmit_clang_debug.cfg b/kokoro/macos/presubmit_clang_debug.cfg
new file mode 100644
index 0000000..d2748ae
--- /dev/null
+++ b/kokoro/macos/presubmit_clang_debug.cfg
@@ -0,0 +1,16 @@
+# 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"
diff --git a/kokoro/macos/presubmit_clang_release.cfg b/kokoro/macos/presubmit_clang_release.cfg
new file mode 100644
index 0000000..3041155
--- /dev/null
+++ b/kokoro/macos/presubmit_clang_release.cfg
@@ -0,0 +1,16 @@
+# 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"
diff --git a/kokoro/ndk-build/build.sh b/kokoro/ndk-build/build.sh
new file mode 100644
index 0000000..edf361c
--- /dev/null
+++ b/kokoro/ndk-build/build.sh
@@ -0,0 +1,56 @@
+#!/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
+
+BUILD_ROOT=$PWD
+SRC=$PWD/github/shaderc
+
+# Get NINJA.
+wget -q https://github.com/ninja-build/ninja/releases/download/v1.7.2/ninja-linux.zip
+unzip -q ninja-linux.zip
+export PATH="$PWD:$PATH"
+
+# Get Android NDK.
+wget -q https://dl.google.com/android/repository/android-ndk-r18b-linux-x86_64.zip
+unzip -q android-ndk-r18b-linux-x86_64.zip
+export ANDROID_NDK=$PWD/android-ndk-r18b
+
+# Get shaderc dependencies.
+cd $SRC
+./utils/git-sync-deps
+
+cd $SRC
+mkdir build
+cd $SRC/build
+
+# Invoke the build.
+BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
+echo $(date): Starting ndk-build ...
+$ANDROID_NDK/ndk-build \
+ -C $SRC/android_test \
+ NDK_APP_OUT=`pwd` \
+ V=1 \
+ SPVTOOLS_LOCAL_PATH=$SRC/third_party/spirv-tools \
+ SPVHEADERS_LOCAL_PATH=$SRC/third_party/spirv-headers \
+ -j 8
+
+echo $(date): ndk-build completed.
diff --git a/kokoro/ndk-build/build_khronos.sh b/kokoro/ndk-build/build_khronos.sh
new file mode 100644
index 0000000..b84052d
--- /dev/null
+++ b/kokoro/ndk-build/build_khronos.sh
@@ -0,0 +1,25 @@
+#!/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
diff --git a/kokoro/ndk-build/continuous_khronos.cfg b/kokoro/ndk-build/continuous_khronos.cfg
new file mode 100644
index 0000000..4821383
--- /dev/null
+++ b/kokoro/ndk-build/continuous_khronos.cfg
@@ -0,0 +1,17 @@
+# 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"
diff --git a/kokoro/ndk-build/presubmit_khronos.cfg b/kokoro/ndk-build/presubmit_khronos.cfg
new file mode 100644
index 0000000..854a5d0
--- /dev/null
+++ b/kokoro/ndk-build/presubmit_khronos.cfg
@@ -0,0 +1,17 @@
+# 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"
diff --git a/kokoro/windows/build.bat b/kokoro/windows/build.bat
new file mode 100644
index 0000000..077caef
--- /dev/null
+++ b/kokoro/windows/build.bat
@@ -0,0 +1,97 @@
+:: 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
+
+:: Force usage of python 3.6.
+set PATH=C:\python36;%PATH%
+
+cd %SRC%
+python utils\git-sync-deps
+
+cmake --version
+
+mkdir build
+cd %SRC%\build
+
+:: #########################################
+:: set up msvc build env
+:: #########################################
+if %VS_VERSION% == 2017 (
+ call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64
+ echo "Using VS 2017..."
+) else if %VS_VERSION% == 2015 (
+ call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
+ echo "Using VS 2015..."
+)
+
+:: #########################################
+:: 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 -DSHADERC_ENABLE_SPVC=ON -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 glslangValidator
+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
diff --git a/kokoro/windows/build_debug_2017.bat b/kokoro/windows/build_debug_2017.bat
new file mode 100644
index 0000000..c1ecf87
--- /dev/null
+++ b/kokoro/windows/build_debug_2017.bat
@@ -0,0 +1,23 @@
+:: 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
+
+:: Find out the directory of the common build script.
+set SCRIPT_DIR=%~dp0
+
+:: Call with correct parameter
+call %SCRIPT_DIR%\build.bat Debug 2017
diff --git a/kokoro/windows/build_release_2015.bat b/kokoro/windows/build_release_2015.bat
new file mode 100644
index 0000000..ea156fe
--- /dev/null
+++ b/kokoro/windows/build_release_2015.bat
@@ -0,0 +1,24 @@
+:: 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
+
+:: Find out the directory of the common build script.
+set SCRIPT_DIR=%~dp0
+
+:: Call with correct parameter
+call %SCRIPT_DIR%\build.bat RelWithDebInfo 2015
+
diff --git a/kokoro/windows/build_release_2017.bat b/kokoro/windows/build_release_2017.bat
new file mode 100644
index 0000000..4102eaa
--- /dev/null
+++ b/kokoro/windows/build_release_2017.bat
@@ -0,0 +1,24 @@
+:: 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
+
+:: Find out the directory of the common build script.
+set SCRIPT_DIR=%~dp0
+
+:: Call with correct parameter
+call %SCRIPT_DIR%\build.bat RelWithDebInfo 2017
+
diff --git a/kokoro/windows/continuous_debug_2017.cfg b/kokoro/windows/continuous_debug_2017.cfg
new file mode 100644
index 0000000..34c3b06
--- /dev/null
+++ b/kokoro/windows/continuous_debug_2017.cfg
@@ -0,0 +1,22 @@
+# 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/windows/build_debug_2017.bat"
+
+action {
+ define_artifacts {
+ regex: "install.zip"
+ }
+}
diff --git a/kokoro/windows/continuous_release_2015.cfg b/kokoro/windows/continuous_release_2015.cfg
new file mode 100644
index 0000000..9017c86
--- /dev/null
+++ b/kokoro/windows/continuous_release_2015.cfg
@@ -0,0 +1,22 @@
+# 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/windows/build_release_2015.bat"
+
+action {
+ define_artifacts {
+ regex: "install.zip"
+ }
+}
diff --git a/kokoro/windows/continuous_release_2017.cfg b/kokoro/windows/continuous_release_2017.cfg
new file mode 100644
index 0000000..b3249d4
--- /dev/null
+++ b/kokoro/windows/continuous_release_2017.cfg
@@ -0,0 +1,22 @@
+# 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/windows/build_release_2017.bat"
+
+action {
+ define_artifacts {
+ regex: "install.zip"
+ }
+}
diff --git a/kokoro/windows/presubmit_debug_2017.cfg b/kokoro/windows/presubmit_debug_2017.cfg
new file mode 100644
index 0000000..57168d3
--- /dev/null
+++ b/kokoro/windows/presubmit_debug_2017.cfg
@@ -0,0 +1,16 @@
+# 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/windows/build_debug_2017.bat"
diff --git a/kokoro/windows/presubmit_release_2015.cfg b/kokoro/windows/presubmit_release_2015.cfg
new file mode 100644
index 0000000..bd24415
--- /dev/null
+++ b/kokoro/windows/presubmit_release_2015.cfg
@@ -0,0 +1,16 @@
+# 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/windows/build_release_2015.bat"
diff --git a/kokoro/windows/presubmit_release_2017.cfg b/kokoro/windows/presubmit_release_2017.cfg
new file mode 100644
index 0000000..16499fc
--- /dev/null
+++ b/kokoro/windows/presubmit_release_2017.cfg
@@ -0,0 +1,16 @@
+# 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/windows/build_release_2017.bat"
diff --git a/libshaderc/.clang-format b/libshaderc/.clang-format
deleted file mode 100644
index e209e8c..0000000
--- a/libshaderc/.clang-format
+++ /dev/null
@@ -1,5 +0,0 @@
----
-# Use Google code formatting rules.
-Language: Cpp
-BasedOnStyle: Google
-...
diff --git a/libshaderc/Android.mk b/libshaderc/Android.mk
index 13d5057..294af69 100644
--- a/libshaderc/Android.mk
+++ b/libshaderc/Android.mk
@@ -1,3 +1,17 @@
+# 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)
@@ -5,9 +19,11 @@
LOCAL_MODULE:=shaderc
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/include
LOCAL_SRC_FILES:=src/shaderc.cc
-LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include
+# 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++11 -fno-exceptions -fno-rtti
+LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -DENABLE_HLSL=1
LOCAL_EXPORT_CPPFLAGS:=-std=c++11
LOCAL_EXPORT_LDFLAGS:=-latomic
include $(BUILD_STATIC_LIBRARY)
diff --git a/libshaderc/CMakeLists.txt b/libshaderc/CMakeLists.txt
index 888c858..3ada419 100644
--- a/libshaderc/CMakeLists.txt
+++ b/libshaderc/CMakeLists.txt
@@ -1,40 +1,123 @@
+# 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.
-add_library(shaderc STATIC
+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})
-find_package(Threads)
-target_link_libraries(shaderc PRIVATE
- glslang OSDependent OGLCompiler glslang ${CMAKE_THREAD_LIBS_INIT})
-target_link_libraries(shaderc PRIVATE shaderc_util)
-target_link_libraries(shaderc PRIVATE SPIRV) # from glslang
-target_link_libraries(shaderc PRIVATE SPIRV-Tools)
+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}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+endif(SHADERC_ENABLE_INSTALL)
+
+find_package(Threads)
+set(SHADERC_LIBS
+ glslang OSDependent OGLCompiler 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 ${glslang_SOURCE_DIR} ${spirv-tools_SOURCE_DIR}/include
+ 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_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)
+ # Since shaderc_combined is defined as an imported library, we cannot use the
+ # install() directive to install it. Install it like a normal file.
+ get_target_property(generated_location shaderc_combined LOCATION)
+ string(REGEX MATCH "Visual Studio .*" vs_generator "${CMAKE_GENERATOR}")
+ if (NOT "${vs_generator}" STREQUAL "")
+ # With Visual Studio generators, the LOCATION property is not properly
+ # expanded according to the current build configuration. We need to work
+ # around this problem by manually substitution.
+ string(REPLACE "$(Configuration)" "\${CMAKE_INSTALL_CONFIG_NAME}"
+ install_location "${generated_location}")
+ install(FILES ${install_location} DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ else()
+ install(FILES ${generated_location} DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ endif()
+endif(SHADERC_ENABLE_INSTALL)
+
shaderc_add_tests(
TEST_PREFIX shaderc_combined
LINK_LIBS shaderc_combined ${CMAKE_THREAD_LIBS_INIT}
- INCLUDE_DIRS include ${glslang_SOURCE_DIR} ${spirv-tools_SOURCE_DIR}/include
+ 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)
@@ -42,6 +125,7 @@
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()
diff --git a/libshaderc/include/shaderc/env.h b/libshaderc/include/shaderc/env.h
new file mode 100644
index 0000000..5285b9e
--- /dev/null
+++ b/libshaderc/include/shaderc/env.h
@@ -0,0 +1,70 @@
+// 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 <stdint.h>
+
+#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)),
+ // 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;
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // SHADERC_ENV_H_
diff --git a/libshaderc/include/shaderc/shaderc.h b/libshaderc/include/shaderc/shaderc.h
index 26d5421..54a9f65 100644
--- a/libshaderc/include/shaderc/shaderc.h
+++ b/libshaderc/include/shaderc/shaderc.h
@@ -23,6 +23,10 @@
#include <stddef.h>
#include <stdint.h>
+#include "shaderc/env.h"
+#include "shaderc/status.h"
+#include "shaderc/visibility.h"
+
// Source language kind.
typedef enum {
shaderc_source_language_glsl,
@@ -32,12 +36,20 @@
typedef enum {
// Forced shader kinds. These shader kinds force the compiler to compile the
// source code as the specified kind of shader.
- shaderc_glsl_vertex_shader,
- shaderc_glsl_fragment_shader,
- shaderc_glsl_compute_shader,
- shaderc_glsl_geometry_shader,
- shaderc_glsl_tess_control_shader,
- shaderc_glsl_tess_evaluation_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,
@@ -51,18 +63,33 @@
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_target_env_vulkan, // create SPIR-V under Vulkan semantics
- shaderc_target_env_opengl, // create SPIR-V under OpenGL semantics
- shaderc_target_env_opengl_compat, // create SPIR-V under OpenGL semantics,
- // including compatibility profile
- // functions
- shaderc_target_env_default = shaderc_target_env_vulkan
-} shaderc_target_env;
-
-typedef enum {
shaderc_profile_none, // Used if and only if GLSL version did not specify
// profiles.
shaderc_profile_core,
@@ -70,20 +97,11 @@
shaderc_profile_es,
} shaderc_profile;
-// Indicate the status of a compilation.
-typedef enum {
- shaderc_compilation_status_success = 0,
- shaderc_compilation_status_invalid_stage, // error stage deduction
- shaderc_compilation_status_compilation_error,
- shaderc_compilation_status_internal_error, // unexpected failure
- shaderc_compilation_status_null_result_object,
- shaderc_compilation_status_invalid_assembly,
-} shaderc_compilation_status;
-
// 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.
@@ -173,13 +191,33 @@
shaderc_limit_max_samples,
} 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, "int main() {}", 13, shaderc_glsl_vertex_shader, "main");
+// 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);
@@ -189,7 +227,8 @@
// 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, "int main() {}", 13, shaderc_glsl_vertex_shader, "main");
+// 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.
@@ -207,12 +246,12 @@
// 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_compiler_t shaderc_compiler_initialize(void);
+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.
-void shaderc_compiler_release(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.
@@ -223,18 +262,20 @@
// 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_compile_options_t shaderc_compile_options_initialize(void);
+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_compile_options_t shaderc_compile_options_clone(
+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.
-void shaderc_compile_options_release(shaderc_compile_options_t options);
+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
@@ -247,21 +288,21 @@
// 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.
-void shaderc_compile_options_add_macro_definition(
+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.
-void shaderc_compile_options_set_source_language(
+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.
-void shaderc_compile_options_set_generate_debug_info(
+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.
-void shaderc_compile_options_set_optimization_level(
+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
@@ -269,7 +310,7 @@
// 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 shaderc_compile_options_set_forced_version_profile(
+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
@@ -278,6 +319,8 @@
// 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 {
@@ -285,9 +328,11 @@
// 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.
+ // 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.
@@ -317,7 +362,7 @@
void* user_data, shaderc_include_result* include_result);
// Sets includer callback functions.
-void shaderc_compile_options_set_include_callbacks(
+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);
@@ -325,27 +370,103 @@
// 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.
-void shaderc_compile_options_set_suppress_warnings(
+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. "0" is the only supported version at this point
-void shaderc_compile_options_set_target_env(shaderc_compile_options_t options,
- shaderc_target_env target,
- uint32_t version);
+// 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.
-void shaderc_compile_options_set_warnings_as_errors(
+SHADERC_EXPORT void shaderc_compile_options_set_warnings_as_errors(
shaderc_compile_options_t options);
// Sets a resource limit.
-void shaderc_compile_options_set_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 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 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 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;
@@ -369,7 +490,7 @@
// 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_compilation_result_t shaderc_compile_into_spv(
+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,
@@ -378,7 +499,7 @@
// 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_compilation_result_t shaderc_compile_into_spv_assembly(
+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,
@@ -386,7 +507,7 @@
// Like shaderc_compile_into_spv, but the result contains preprocessed source
// code instead of a SPIR-V binary module
-shaderc_compilation_result_t shaderc_compile_into_preprocessed_text(
+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,
@@ -401,7 +522,7 @@
// May be safely called from multiple threads without explicit synchronization.
// If there was failure in allocating the compiler object, null will be
// returned.
-shaderc_compilation_result_t shaderc_assemble_into_spv(
+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);
@@ -411,23 +532,23 @@
// Releases the resources held by the result object. It is invalid to use the
// result object for any further operations.
-void shaderc_result_release(shaderc_compilation_result_t result);
+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.
-size_t shaderc_result_get_length(const shaderc_compilation_result_t result);
+SHADERC_EXPORT size_t shaderc_result_get_length(const shaderc_compilation_result_t result);
// Returns the number of warnings generated during the compilation.
-size_t shaderc_result_get_num_warnings(
+SHADERC_EXPORT size_t shaderc_result_get_num_warnings(
const shaderc_compilation_result_t result);
// Returns the number of errors generated during the compilation.
-size_t shaderc_result_get_num_errors(const shaderc_compilation_result_t result);
+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_compilation_status shaderc_result_get_compilation_status(
+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
@@ -435,21 +556,21 @@
// 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.
-const char* shaderc_result_get_bytes(const shaderc_compilation_result_t result);
+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.
-const char* shaderc_result_get_error_message(
+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
-void shaderc_get_spv_version(unsigned int* version, unsigned int* revision);
+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.
-bool shaderc_parse_version_profile(const char* str, int* version,
+SHADERC_EXPORT bool shaderc_parse_version_profile(const char* str, int* version,
shaderc_profile* profile);
#ifdef __cplusplus
diff --git a/libshaderc/include/shaderc/shaderc.hpp b/libshaderc/include/shaderc/shaderc.hpp
index 3023ebb..1588dfe 100644
--- a/libshaderc/include/shaderc/shaderc.hpp
+++ b/libshaderc/include/shaderc/shaderc.hpp
@@ -47,11 +47,20 @@
// 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) {
+ 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.
@@ -180,6 +189,8 @@
// 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
@@ -191,14 +202,14 @@
options_,
[](void* user_data, const char* requested_source, int type,
const char* requesting_source, size_t include_depth) {
- auto* includer = static_cast<IncluderInterface*>(user_data);
- return includer->GetInclude(requested_source,
- (shaderc_include_type)type,
- requesting_source, include_depth);
+ auto* sub_includer = static_cast<IncluderInterface*>(user_data);
+ return sub_includer->GetInclude(
+ requested_source, static_cast<shaderc_include_type>(type),
+ requesting_source, include_depth);
},
[](void* user_data, shaderc_include_result* include_result) {
- auto* includer = static_cast<IncluderInterface*>(user_data);
- return includer->ReleaseInclude(include_result);
+ auto* sub_includer = static_cast<IncluderInterface*>(user_data);
+ return sub_includer->ReleaseInclude(include_result);
},
includer_.get());
}
@@ -227,14 +238,23 @@
}
// 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.
- // "0" is the only supported version at this point
+ // 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
@@ -248,6 +268,86 @@
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 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 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 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 generates code for max an 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_;
diff --git a/libshaderc/include/shaderc/status.h b/libshaderc/include/shaderc/status.h
new file mode 100644
index 0000000..57ac70d
--- /dev/null
+++ b/libshaderc/include/shaderc/status.h
@@ -0,0 +1,39 @@
+// 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_
diff --git a/libshaderc/include/shaderc/visibility.h b/libshaderc/include/shaderc/visibility.h
new file mode 100644
index 0000000..88ec151
--- /dev/null
+++ b/libshaderc/include/shaderc/visibility.h
@@ -0,0 +1,37 @@
+// 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_
diff --git a/libshaderc/src/common_shaders_for_test.h b/libshaderc/src/common_shaders_for_test.h
index a0120a2..e177797 100644
--- a/libshaderc/src/common_shaders_for_test.h
+++ b/libshaderc/src/common_shaders_for_test.h
@@ -47,8 +47,8 @@
// because some versions of glslang will error out for a too-low version
// when generating SPIR-V.
const char kDeprecatedAttributeShader[] =
- "#version 140\n"
- "attribute float x;\n"
+ "#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
@@ -80,9 +80,9 @@
// Compiler should generate two warnings.
const char kTwoWarningsShader[] =
- "#version 140\n"
- "attribute float x;\n"
- "attribute float y;\n"
+ "#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,
@@ -176,6 +176,50 @@
" 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"
@@ -189,7 +233,7 @@
const char* kMinimalShaderDisassemblySubstrings[] = {
"; SPIR-V\n"
"; Version: 1.0\n"
- "; Generator: Khronos Glslang Reference Front End; 1\n"
+ "; Generator: Google Shaderc over Glslang; 10\n"
"; Bound:",
" OpCapability Shader\n",
@@ -198,10 +242,22 @@
" OpReturn\n",
" OpFunctionEnd\n"};
+const char* kMinimalShaderDebugInfoDisassemblySubstrings[] = {
+ "; SPIR-V\n"
+ "; Version: 1.0\n"
+ "; Generator: Google Shaderc over Glslang; 10\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: Khronos Glslang Reference Front End; 1
+ ; Generator: Google Shaderc over Glslang; 10
; Bound: 6
; Schema: 0
@@ -218,6 +274,138 @@
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<float> t4 : register(t4);
+ Buffer<float> 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<uint> 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<S> 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
diff --git a/libshaderc/src/shaderc.cc b/libshaderc/src/shaderc.cc
index c7b6ef2..da0f3b2 100644
--- a/libshaderc/src/shaderc.cc
+++ b/libshaderc/src/shaderc.cc
@@ -12,21 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "shaderc_private.h"
-
#include <algorithm>
#include <cassert>
#include <cstdint>
+#include <memory>
#include <sstream>
#include <vector>
-#include "SPIRV/spirv.hpp"
-
#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
@@ -56,6 +55,24 @@
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:
@@ -63,6 +80,14 @@
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;
}
@@ -83,7 +108,7 @@
public:
explicit StageDeducer(
shaderc_shader_kind kind = shaderc_glsl_infer_from_source)
- : kind_(kind), error_(false){};
+ : 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
@@ -103,7 +128,7 @@
error_ = false;
}
return stage;
- };
+ }
// Returns true if there is error during shader stage deduction.
bool error() const { return error_; }
@@ -120,6 +145,14 @@
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;
@@ -133,6 +166,22 @@
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;
}
@@ -152,9 +201,9 @@
void* user_data)
: resolver_(resolver),
result_releaser_(result_releaser),
- user_data_(user_data){};
+ user_data_(user_data){}
InternalFileIncluder()
- : resolver_(nullptr), result_releaser_(nullptr), user_data_(nullptr){};
+ : resolver_(nullptr), result_releaser_(nullptr), user_data_(nullptr){}
private:
// Check the validity of the callbacks.
@@ -162,18 +211,18 @@
return resolver_ != nullptr && result_releaser_ != nullptr;
}
- // Maps a shaderc_include_type to the correpsonding Glslang include type.
- shaderc_include_type GetIncludeType(
- glslang::TShader::Includer::IncludeType type) {
+ // Maps CountingIncluder IncludeType value to a shaderc_include_type
+ // value.
+ shaderc_include_type GetIncludeType(IncludeType type) {
switch (type) {
- case glslang::TShader::Includer::EIncludeRelative:
+ case IncludeType::Local:
return shaderc_include_type_relative;
- case glslang::TShader::Includer::EIncludeStandard:
+ case IncludeType::System:
return shaderc_include_type_standard;
default:
break;
}
- assert(0 && "Unhandled shaderc_include_type");
+ assert(0 && "Unhandled IncludeType");
return shaderc_include_type_relative;
}
@@ -185,11 +234,10 @@
// 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,
- glslang::TShader::Includer::IncludeType type,
- const char* requesting_source, size_t include_depth) override {
+ const char* requested_source, const char* requesting_source,
+ IncludeType type, size_t include_depth) override {
if (!AreValidCallbacks()) {
- const char kUnexpectedIncludeError[] =
+ static const char kUnexpectedIncludeError[] =
"#error unexpected include directive";
return new glslang::TShader::Includer::IncludeResult{
"", kUnexpectedIncludeError, strlen(kUnexpectedIncludeError),
@@ -213,7 +261,7 @@
glslang::TShader::Includer::IncludeResult* result) override {
if (result && result_releaser_) {
result_releaser_(user_data_,
- static_cast<shaderc_include_result*>(result->user_data));
+ static_cast<shaderc_include_result*>(result->userData));
}
delete result;
}
@@ -230,6 +278,9 @@
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;
@@ -238,11 +289,36 @@
return shaderc_util::Compiler::TargetEnv::Vulkan;
}
+shaderc_util::Compiler::TargetEnvVersion GetCompilerTargetEnvVersion(
+ uint32_t version_number) {
+ using namespace shaderc_util;
+
+ if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_0) ==
+ version_number) {
+ return Compiler::TargetEnvVersion::Vulkan_1_0;
+ }
+ if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_1) ==
+ version_number) {
+ return Compiler::TargetEnvVersion::Vulkan_1_1;
+ }
+ if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_2) ==
+ version_number) {
+ return Compiler::TargetEnvVersion::Vulkan_1_2;
+ }
+ if (static_cast<uint32_t>(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;
+#define RESOURCE(NAME, FIELD, CNAME) \
+ case shaderc_limit_##CNAME: \
+ return shaderc_util::Compiler::Limit::NAME;
#include "libshaderc_util/resources.inc"
#undef RESOURCE
default:
@@ -252,10 +328,53 @@
return static_cast<shaderc_util::Compiler::Limit>(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<shaderc_util::Compiler::UniformKind>(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<shaderc_util::Compiler::Stage>(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;
@@ -285,8 +404,7 @@
}
void shaderc_compile_options_set_source_language(
- shaderc_compile_options_t options,
- shaderc_source_language set_lang) {
+ 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;
@@ -305,6 +423,9 @@
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;
}
@@ -349,10 +470,16 @@
void shaderc_compile_options_set_target_env(shaderc_compile_options_t options,
shaderc_target_env target,
uint32_t version) {
- // "version" reserved for future use, intended to distinguish between
- // different versions of a target environment
options->target_env = target;
- options->compiler.SetTargetEnv(GetCompilerTargetEnv(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<shaderc_util::Compiler::SpirvVersion>(ver));
}
void shaderc_compile_options_set_warnings_as_errors(
@@ -360,20 +487,83 @@
options->compiler.SetWarningsAsErrors();
}
-void shaderc_compile_options_set_limit(
- shaderc_compile_options_t options, shaderc_limit limit, int value) {
+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_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_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_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() {
- static shaderc_util::GlslangInitializer* initializer =
- new shaderc_util::GlslangInitializer;
shaderc_compiler_t compiler = new (std::nothrow) shaderc_compiler;
- compiler->initializer = initializer;
+ if (compiler) {
+ compiler->initializer.reset(new shaderc_util::GlslangInitializer);
+ }
return compiler;
}
-void shaderc_compiler_release(shaderc_compiler_t compiler) { delete compiler; }
+void shaderc_compiler_release(shaderc_compiler_t compiler) {
+ delete compiler;
+}
namespace {
shaderc_compilation_result_t CompileToSpecifiedOutputType(
@@ -418,7 +608,7 @@
// 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, compiler->initializer);
+ &total_warnings, &total_errors);
} else {
// Compile with default options.
InternalFileIncluder includer;
@@ -427,7 +617,7 @@
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, compiler->initializer);
+ &total_warnings, &total_errors);
}
result->messages = errors.str();
@@ -501,8 +691,11 @@
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;
@@ -582,6 +775,7 @@
*profile = shaderc_profile_none;
return true;
case EBadProfile:
+ case EProfileCount:
return false;
}
diff --git a/libshaderc/src/shaderc_cpp_test.cc b/libshaderc/src/shaderc_cpp_test.cc
index bf5aa33..af9ae30 100644
--- a/libshaderc/src/shaderc_cpp_test.cc
+++ b/libshaderc/src/shaderc_cpp_test.cc
@@ -14,25 +14,26 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+
#include <memory>
#include <thread>
#include <unordered_map>
-#include "SPIRV/spirv.hpp"
-#include "spirv-tools/libspirv.hpp"
-
#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 shaderc::CompileOptions;
using testing::Each;
using testing::Eq;
using testing::HasSubstr;
+using testing::Not;
// Helper function to check if the compilation result indicates a successful
// compilation.
@@ -362,7 +363,7 @@
const AssemblyCompilationResult result = compiler_.CompileGlslToSpvAssembly(
kMinimalShader, shaderc_glsl_vertex_shader, "shader", options_);
EXPECT_TRUE(CompilationResultIsSuccess(result));
- // This should work with both the glslang native disassembly format and the
+ // 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"));
@@ -429,9 +430,12 @@
// Forces the version and profile to 4242core, which is an unknown version.
options_.SetForcedVersionProfile(4242 /*unknown version*/,
shaderc_profile_core);
- EXPECT_THAT(
- CompilationWarnings(kMinimalShader, shaderc_glsl_vertex_shader, options_),
- HasSubstr("warning: version 4242 is unknown.\n"));
+ 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) {
@@ -454,21 +458,29 @@
TEST_F(CppInterface, GenerateDebugInfoBinary) {
options_.SetGenerateDebugInfo();
- // The output binary should contain the name of the vector: debug_info_sample
- // as char array.
- EXPECT_THAT(CompilationOutput(kMinimalDebugInfoShader,
- shaderc_glsl_vertex_shader, options_),
- HasSubstr("debug_info_sample"));
+ 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_);
- // The output binary should contain the name of the vector: debug_info_sample
- // as char array.
- EXPECT_THAT(CompilationOutput(kMinimalDebugInfoShader,
- shaderc_glsl_vertex_shader, cloned_options),
- HasSubstr("debug_info_sample"));
+ 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) {
@@ -502,6 +514,14 @@
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 =
@@ -514,6 +534,31 @@
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: "
+ "Invalid capability operand"));
+}
+
+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
@@ -534,7 +579,7 @@
options_.SetGenerateDebugInfo();
const std::string disassembly_text =
AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_);
- for (const auto& substring : kMinimalShaderDisassemblySubstrings) {
+ for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) {
EXPECT_THAT(disassembly_text, HasSubstr(substring));
}
// Check that we still have debug instructions.
@@ -548,7 +593,7 @@
options_.SetOptimizationLevel(shaderc_optimization_level_size);
const std::string disassembly_text =
AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_);
- for (const auto& substring : kMinimalShaderDisassemblySubstrings) {
+ for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) {
EXPECT_THAT(disassembly_text, HasSubstr(substring));
}
// Check that we still have debug instructions.
@@ -661,7 +706,7 @@
CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_));
}
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
CompileStringTest, ValidShaderKind,
testing::ValuesIn(std::vector<ShaderKindTestCase>{
// Valid default shader kinds.
@@ -698,7 +743,7 @@
CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_));
}
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
CompileStringTest, InvalidShaderKind,
testing::ValuesIn(std::vector<ShaderKindTestCase>{
// Invalid default shader kind.
@@ -799,7 +844,7 @@
HasSubstr(test_case.expected_substring()));
}
-INSTANTIATE_TEST_CASE_P(CppInterface, IncluderTests,
+INSTANTIATE_TEST_SUITE_P(CppInterface, IncluderTests,
testing::ValuesIn(std::vector<IncluderTestCase>{
IncluderTestCase(
// Fake file system.
@@ -890,17 +935,21 @@
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("warning: version 550 is unknown.\n"));
+ 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();
- EXPECT_EQ("", CompilationWarnings(kMinimalUnknownVersionShader,
- shaderc_glsl_vertex_shader, options_));
+ options_.SetForcedVersionProfile(400, shaderc_profile_core);
+ EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader,
+ shaderc_glsl_vertex_shader, options_),
+ Eq(""));
}
TEST_F(CppInterface, SuppressGlobalWarningsClonedOptions) {
@@ -908,29 +957,34 @@
// 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_EQ("",
- CompilationWarnings(kMinimalUnknownVersionShader,
- shaderc_glsl_vertex_shader, cloned_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("error: version 550 is unknown.\n"));
+ 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("error: version 550 is unknown.\n"));
+ HasSubstr("(version, profile) forced to be (400, core),"
+ " while in source code it is (550, none)\n"));
}
TEST_F(CppInterface, SuppressWarningsModeFirstOverridesWarningsAsErrorsMode) {
@@ -944,8 +998,10 @@
shaderc_glsl_vertex_shader, options_));
// Global warnings should be inhibited.
- EXPECT_EQ("", CompilationWarnings(kMinimalUnknownVersionShader,
- shaderc_glsl_vertex_shader, options_));
+ // 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) {
@@ -959,23 +1015,82 @@
shaderc_glsl_vertex_shader, options_));
// Global warnings should be inhibited.
- EXPECT_EQ("", CompilationWarnings(kMinimalUnknownVersionShader,
- shaderc_glsl_vertex_shader, options_));
+ // 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, TargetEnvCompileOptions) {
- // Test shader compilation which requires opengl compatibility environment
+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 100
+ R"(#version 150 compatibility
uniform highp sampler2D tex;
void main() {
gl_FragColor = texture2D(tex, vec2(0.0,0.0));
}
)";
- EXPECT_TRUE(
- CompilationSuccess(kGlslShader, shaderc_glsl_fragment_shader, options_));
+ EXPECT_THAT(
+ CompilationErrors(kGlslShader, shaderc_glsl_fragment_shader, options_),
+ HasSubstr(
+ "compilation for SPIR-V does not support the compatibility profile"));
+}
+
+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_));
+}
+
+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_));
}
TEST_F(CppInterface, BeginAndEndOnSpvCompilationResult) {
@@ -1104,10 +1219,10 @@
// offset.
std::string ShaderWithTexOffset(int offset) {
std::ostringstream oss;
- oss <<
- "#version 150\n"
- "uniform sampler1D tex;\n"
- "void main() { vec4 x = textureOffset(tex, 1.0, " << offset << "); }\n";
+ oss << "#version 450\n"
+ "layout (binding=0) uniform sampler1D tex;\n"
+ "void main() { vec4 x = textureOffset(tex, 1.0, "
+ << offset << "); }\n";
return oss.str();
}
@@ -1115,37 +1230,235 @@
// two particular limits.
TEST_F(CppInterface, LimitsTexelOffsetDefault) {
EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-9).c_str(),
- shaderc_glsl_fragment_shader,
- options_));
+ shaderc_glsl_fragment_shader, options_));
EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(),
- shaderc_glsl_fragment_shader,
- options_));
+ shaderc_glsl_fragment_shader, options_));
EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(),
- shaderc_glsl_fragment_shader,
- options_));
+ shaderc_glsl_fragment_shader, options_));
EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(8).c_str(),
- shaderc_glsl_fragment_shader,
- options_));
+ 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_));
+ shaderc_glsl_fragment_shader, options_));
EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-99).c_str(),
- shaderc_glsl_fragment_shader,
- options_));
+ 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_));
+ shaderc_glsl_fragment_shader, options_));
EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(11).c_str(),
- shaderc_glsl_fragment_shader,
- options_));
+ 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
diff --git a/libshaderc/src/shaderc_private.h b/libshaderc/src/shaderc_private.h
index de8fd07..ff35020 100644
--- a/libshaderc/src/shaderc_private.h
+++ b/libshaderc/src/shaderc_private.h
@@ -15,12 +15,14 @@
#ifndef LIBSHADERC_SRC_SHADERC_PRIVATE_H_
#define LIBSHADERC_SRC_SHADERC_PRIVATE_H_
+#include <cassert>
#include <cstdint>
#include <string>
#include <vector>
#include "shaderc/shaderc.h"
+#include "libshaderc_util/compiler.h"
#include "spirv-tools/libspirv.h"
// Described in shaderc.h.
@@ -88,7 +90,50 @@
}
struct shaderc_compiler {
- shaderc_util::GlslangInitializer* initializer;
+ std::unique_ptr<shaderc_util::GlslangInitializer> 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_
diff --git a/libshaderc/src/shaderc_private_test.cc b/libshaderc/src/shaderc_private_test.cc
new file mode 100644
index 0000000..72a7577
--- /dev/null
+++ b/libshaderc/src/shaderc_private_test.cc
@@ -0,0 +1,50 @@
+// 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 <gmock/gmock.h>
+#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
diff --git a/libshaderc/src/shaderc_test.cc b/libshaderc/src/shaderc_test.cc
index 927a53d..3162468 100644
--- a/libshaderc/src/shaderc_test.cc
+++ b/libshaderc/src/shaderc_test.cc
@@ -12,21 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "shaderc/shaderc.h"
+
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+
#include <memory>
#include <thread>
#include <unordered_map>
-#include "SPIRV/spirv.hpp"
-
#include "common_shaders_for_test.h"
-#include "shaderc/shaderc.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;
@@ -227,7 +229,7 @@
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(
@@ -241,7 +243,7 @@
<< 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(
@@ -251,7 +253,7 @@
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.
@@ -261,15 +263,18 @@
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;
+ 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_;
@@ -493,7 +498,7 @@
TEST_F(CompileStringWithOptionsTest, DisassemblyOption) {
ASSERT_NE(nullptr, compiler_.get_compiler_handle());
- // This should work with both the glslang native assembly format and the
+ // 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,
@@ -568,9 +573,15 @@
options_.get(), 4242 /*unknown version*/, shaderc_profile_core);
ASSERT_NE(nullptr, compiler_.get_compiler_handle());
// Warning message should complain about the unknown version.
- EXPECT_THAT(CompilationWarnings(kMinimalShader, shaderc_glsl_vertex_shader,
- options_.get()),
- HasSubstr("warning: version 4242 is unknown.\n"));
+ //
+ // 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) {
@@ -598,10 +609,15 @@
TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoBinary) {
shaderc_compile_options_set_generate_debug_info(options_.get());
ASSERT_NE(nullptr, compiler_.get_compiler_handle());
- // The binary output should contain the name of the vector: debug_info_sample.
- EXPECT_THAT(CompilationOutput(kMinimalDebugInfoShader,
- shaderc_glsl_vertex_shader, options_.get()),
- HasSubstr("debug_info_sample"));
+ 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) {
@@ -609,11 +625,15 @@
compile_options_ptr cloned_options(
shaderc_compile_options_clone(options_.get()));
ASSERT_NE(nullptr, compiler_.get_compiler_handle());
- // The binary output should contain the name of the vector: debug_info_sample.
- EXPECT_THAT(
- CompilationOutput(kMinimalDebugInfoShader, shaderc_glsl_vertex_shader,
- cloned_options.get()),
- HasSubstr("debug_info_sample"));
+ 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) {
@@ -642,6 +662,16 @@
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);
@@ -656,6 +686,34 @@
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);
@@ -682,7 +740,7 @@
const std::string disassembly_text =
CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,
options_.get(), OutputType::SpirvAssemblyText);
- for (const auto& substring : kMinimalShaderDisassemblySubstrings) {
+ for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) {
EXPECT_THAT(disassembly_text, HasSubstr(substring));
}
// Check that we still have debug instructions.
@@ -699,7 +757,7 @@
const std::string disassembly_text =
CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,
options_.get(), OutputType::SpirvAssemblyText);
- for (const auto& substring : kMinimalShaderDisassemblySubstrings) {
+ for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) {
EXPECT_THAT(disassembly_text, HasSubstr(substring));
}
// Check that we still have debug instructions.
@@ -755,7 +813,7 @@
CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_));
}
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
CompileStringTest, ValidShaderKind,
testing::ValuesIn(std::vector<ShaderKindTestCase>{
// Valid default shader kinds.
@@ -766,6 +824,8 @@
{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},
@@ -777,6 +837,13 @@
{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},
@@ -792,7 +859,7 @@
CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_));
}
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
CompileStringTest, InvalidShaderKind,
testing::ValuesIn(std::vector<ShaderKindTestCase>{
// Invalid default shader kind.
@@ -916,7 +983,7 @@
HasSubstr(test_case.expected_substring()));
}
-INSTANTIATE_TEST_CASE_P(CompileStringTest, IncluderTests,
+INSTANTIATE_TEST_SUITE_P(CompileStringTest, IncluderTests,
testing::ValuesIn(std::vector<IncluderTestCase>{
IncluderTestCase(
// Fake file system.
@@ -983,22 +1050,30 @@
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 550 is unknown.\n"));
+ 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("error: version 550 is unknown.\n"));
+ 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()));
@@ -1061,11 +1136,11 @@
shaderc_glsl_vertex_shader, options_.get()));
}
-TEST_F(CompileStringWithOptionsTest,
- TargetEnvRespectedWhenCompilingOpenGLCompatibilityShaderToBinary) {
- // Confirm that kOpenGLCompatibilityFragmentShader compiles with
- // shaderc_target_env_opengl_compat. When targeting OpenGL core profile
- // or Vulkan, it should fail to compile.
+TEST_F(
+ CompileStringWithOptionsTest,
+ TargetEnvRespectedWhenCompilingOpenGLCompatibilityShaderToBinaryAndAlwaysFails) {
+ // Glslang does not support generating SPIR-V for compatibility profile
+ // shaders.
EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader,
shaderc_glsl_fragment_shader,
@@ -1073,8 +1148,9 @@
shaderc_compile_options_set_target_env(options_.get(),
shaderc_target_env_opengl_compat, 0);
- EXPECT_TRUE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader,
- shaderc_glsl_fragment_shader, options_.get()));
+ EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader,
+ shaderc_glsl_fragment_shader,
+ options_.get()));
shaderc_compile_options_set_target_env(options_.get(),
shaderc_target_env_opengl, 0);
@@ -1103,8 +1179,116 @@
shaderc_target_env_opengl, 0);
EXPECT_TRUE(CompilesToValidSpv(compiler_, kOpenGLVertexShader,
shaderc_glsl_vertex_shader, options_.get()));
+}
- // TODO(dneto): Check what happens when targeting Vulkan.
+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()));
+}
+
+// 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,
@@ -1272,7 +1456,7 @@
}
}
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
HelperMethods, ParseVersionProfileTest,
testing::ValuesIn(std::vector<ParseVersionProfileTestCase>{
// Valid version profiles
@@ -1377,10 +1561,10 @@
// offset.
std::string ShaderWithTexOffset(int offset) {
std::ostringstream oss;
- oss <<
- "#version 150\n"
- "uniform sampler1D tex;\n"
- "void main() { vec4 x = textureOffset(tex, 1.0, " << offset << "); }\n";
+ oss << "#version 450\n"
+ "layout (binding=0) uniform sampler1D tex;\n"
+ "void main() { vec4 x = textureOffset(tex, 1.0, "
+ << offset << "); }\n";
return oss.str();
}
@@ -1391,38 +1575,296 @@
shaderc_glsl_fragment_shader,
options_.get()));
EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(),
- shaderc_glsl_fragment_shader,
- options_.get()));
+ shaderc_glsl_fragment_shader, options_.get()));
EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(),
- shaderc_glsl_fragment_shader,
- options_.get()));
+ 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);
+ 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()));
+ shaderc_glsl_fragment_shader, options_.get()));
}
TEST_F(CompileStringTest, LimitsTexelOffsetHigherMaximum) {
shaderc_compile_options_set_limit(options_.get(),
- shaderc_limit_max_program_texel_offset,
- 10);
+ shaderc_limit_max_program_texel_offset, 10);
EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(10).c_str(),
- shaderc_glsl_fragment_shader,
- options_.get()));
+ 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
diff --git a/libshaderc_util/.clang-format b/libshaderc_util/.clang-format
deleted file mode 100644
index e209e8c..0000000
--- a/libshaderc_util/.clang-format
+++ /dev/null
@@ -1,5 +0,0 @@
----
-# Use Google code formatting rules.
-Language: Cpp
-BasedOnStyle: Google
-...
diff --git a/libshaderc_util/Android.mk b/libshaderc_util/Android.mk
index 13c9f0a..a694787 100644
--- a/libshaderc_util/Android.mk
+++ b/libshaderc_util/Android.mk
@@ -1,10 +1,25 @@
+# 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++11 -fno-exceptions -fno-rtti
+LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -DENABLE_HLSL=1
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/include
-LOCAL_SRC_FILES:=src/compiler.cc \
+LOCAL_SRC_FILES:=src/args.cc \
+ src/compiler.cc \
src/file_finder.cc \
src/io.cc \
src/message.cc \
@@ -12,6 +27,6 @@
src/shader_stage.cc \
src/spirv_tools_wrapper.cc \
src/version_profile.cc
-LOCAL_STATIC_LIBRARIES:=glslang SPIRV-Tools-opt
+LOCAL_STATIC_LIBRARIES:=SPIRV SPIRV-Tools-opt
LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include
include $(BUILD_STATIC_LIBRARY)
diff --git a/libshaderc_util/CMakeLists.txt b/libshaderc_util/CMakeLists.txt
index cc6c927..48f9991 100644
--- a/libshaderc_util/CMakeLists.txt
+++ b/libshaderc_util/CMakeLists.txt
@@ -1,3 +1,17 @@
+# 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
@@ -12,6 +26,7 @@
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.cc
@@ -25,6 +40,10 @@
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 OSDependent OGLCompiler HLSL glslang SPIRV
@@ -40,11 +59,14 @@
file_finder
io
message
- mutex)
+ 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(
diff --git a/libshaderc_util/include/libshaderc_util/args.h b/libshaderc_util/include/libshaderc_util/args.h
new file mode 100644
index 0000000..1d08604
--- /dev/null
+++ b/libshaderc_util/include/libshaderc_util/args.h
@@ -0,0 +1,41 @@
+// 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 <cstdint>
+#include <string>
+
+#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
diff --git a/libshaderc_util/include/libshaderc_util/compiler.h b/libshaderc_util/include/libshaderc_util/compiler.h
index 50ab01c..3277a9b 100644
--- a/libshaderc_util/include/libshaderc_util/compiler.h
+++ b/libshaderc_util/include/libshaderc_util/compiler.h
@@ -15,7 +15,10 @@
#ifndef LIBSHADERC_UTIL_INC_COMPILER_H
#define LIBSHADERC_UTIL_INC_COMPILER_H
+#include <array>
+#include <cassert>
#include <functional>
+#include <mutex>
#include <ostream>
#include <string>
#include <unordered_map>
@@ -29,6 +32,9 @@
#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
@@ -36,54 +42,20 @@
enum class PassId;
// Initializes glslang on creation, and destroys it on completion.
-// This object is expected to be a singleton, so that internal
-// glslang state can be correctly handled.
-// TODO(awoloszyn): Once glslang no longer has static global mutable state
-// remove this class.
+// 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() { glslang::InitializeProcess(); }
-
- ~GlslangInitializer() { glslang::FinalizeProcess(); }
-
- // Calls release on GlslangInitializer used to intialize this object
- // when it is destroyed.
- class InitializationToken {
- public:
- ~InitializationToken() {
- if (initializer_) {
- initializer_->Release();
- }
- }
-
- InitializationToken(InitializationToken&& other)
- : initializer_(other.initializer_) {
- other.initializer_ = nullptr;
- }
-
- InitializationToken(const InitializationToken&) = delete;
-
- private:
- InitializationToken(GlslangInitializer* initializer)
- : initializer_(initializer) {}
-
- friend class GlslangInitializer;
- GlslangInitializer* initializer_;
- };
-
- // Obtains exclusive access to the glslang state. The state remains
- // exclusive until the Initialization Token has been destroyed.
- InitializationToken Acquire() {
- state_lock_.lock();
- return InitializationToken(this);
- }
+ GlslangInitializer();
+ ~GlslangInitializer();
private:
- void Release() { state_lock_.unlock(); }
+ static unsigned int initialize_count_;
- friend class InitializationToken;
-
- mutex state_lock_;
+ // 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
@@ -101,9 +73,30 @@
// Target environment.
enum class TargetEnv {
- Vulkan,
- OpenGL,
- OpenGLCompat,
+ Vulkan, // Default to Vulkan 1.0
+ OpenGL, // Default to OpenGL 4.5
+ OpenGLCompat, // Deprecated.
+ };
+
+ // 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
+ // 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,
};
enum class OutputType {
@@ -114,17 +107,81 @@
// Supported optimization levels.
enum class OptimizationLevel {
- Zero, // No optimization.
- Size, // Optimization towards reducing code size.
+ 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.
+ // Resource limits. These map to the "max*" fields in
+ // glslang::TBuiltInResource.
enum class Limit {
-#define RESOURCE(NAME,FIELD,CNAME) NAME,
+#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<Stage, kNumStages>& stages() const {
+ static std::array<Stage, kNumStages> 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()
@@ -138,8 +195,21 @@
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) {}
+ limits_(kDefaultTBuiltInResource),
+ auto_bind_uniforms_(false),
+ auto_binding_base_(),
+ auto_map_locations_(false),
+ hlsl_iomap_(false),
+ hlsl_offsets_(false),
+ hlsl_legalization_enabled_(true),
+ hlsl_functionality1_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.
@@ -149,6 +219,21 @@
// 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 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();
@@ -162,8 +247,18 @@
void AddMacroDefinition(const char* macro, size_t macro_length,
const char* definition, size_t definition_length);
- // Sets the target environment.
- void SetTargetEnv(TargetEnv env);
+ // 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);
@@ -178,6 +273,61 @@
// 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 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<int>(stage)][static_cast<int>(kind)] = base;
+ }
+
+ // 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<int>(stage)].push_back(reg);
+ hlsl_explicit_bindings_[static_cast<int>(stage)].push_back(set);
+ hlsl_explicit_bindings_[static_cast<int>(stage)].push_back(binding);
+ }
+
// Compiles the shader source in the input_source_string parameter.
//
// If the forced_shader stage parameter is not EShLangCount then
@@ -218,8 +368,7 @@
const string_piece& error_tag)>&
stage_callback,
CountingIncluder& includer, OutputType output_type,
- std::ostream* error_stream, size_t* total_warnings, size_t* total_errors,
- GlslangInitializer* initializer) const;
+ std::ostream* error_stream, size_t* total_warnings, size_t* total_errors) const;
static EShMessages GetDefaultRules() {
return static_cast<EShMessages>(EShMsgSpvRules | EShMsgVulkanRules |
@@ -322,11 +471,63 @@
// 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_;
+
+ // 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 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 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<std::string> hlsl_explicit_bindings_[kNumStages];
};
// Converts a string to a vector of uint32_t by copying the content of a given
@@ -334,5 +535,74 @@
// are required to complete the last element.
std::vector<uint32_t> 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
diff --git a/libshaderc_util/include/libshaderc_util/counting_includer.h b/libshaderc_util/include/libshaderc_util/counting_includer.h
index d341ad1..3e6b0a6 100644
--- a/libshaderc_util/include/libshaderc_util/counting_includer.h
+++ b/libshaderc_util/include/libshaderc_util/counting_includer.h
@@ -19,9 +19,13 @@
#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
@@ -33,18 +37,37 @@
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.
- glslang::TShader::Includer::IncludeResult* include(
- const char* requested_source, glslang::TShader::Includer::IncludeType type,
- const char* requesting_source,
+ // 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_;
- return include_delegate(requested_source, type, requesting_source,
- include_depth);
+ 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.
@@ -55,11 +78,12 @@
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, glslang::TShader::Includer::IncludeType type,
- const char* requesting_source, size_t include_depth) = 0;
+ const char* requested_source, const char* requesting_source,
+ IncludeType type, size_t include_depth) = 0;
// Release the given IncludeResult.
virtual void release_delegate(
@@ -67,6 +91,10 @@
// 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_;
};
}
diff --git a/libshaderc_util/include/libshaderc_util/exceptions.h b/libshaderc_util/include/libshaderc_util/exceptions.h
new file mode 100644
index 0000000..93a03aa
--- /dev/null
+++ b/libshaderc_util/include/libshaderc_util/exceptions.h
@@ -0,0 +1,26 @@
+// 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_
diff --git a/libshaderc_util/include/libshaderc_util/file_finder.h b/libshaderc_util/include/libshaderc_util/file_finder.h
index 2c1c9d1..a5f91cf 100644
--- a/libshaderc_util/include/libshaderc_util/file_finder.h
+++ b/libshaderc_util/include/libshaderc_util/file_finder.h
@@ -27,7 +27,7 @@
// 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, blind to whether the path is
+ // 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
diff --git a/libshaderc_util/include/libshaderc_util/io.h b/libshaderc_util/include/libshaderc_util/io.h
index b57e0dd..b9116c1 100644
--- a/libshaderc_util/include/libshaderc_util/io.h
+++ b/libshaderc_util/include/libshaderc_util/io.h
@@ -47,16 +47,23 @@
// 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 std::cout if the file could
+// 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::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_
diff --git a/libshaderc_util/include/libshaderc_util/message.h b/libshaderc_util/include/libshaderc_util/message.h
index f07a62c..8a77790 100644
--- a/libshaderc_util/include/libshaderc_util/message.h
+++ b/libshaderc_util/include/libshaderc_util/message.h
@@ -53,6 +53,9 @@
// 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,
diff --git a/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h b/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h
index b02e15d..09d8462 100644
--- a/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h
+++ b/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h
@@ -27,21 +27,30 @@
// 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, const string_piece assembly,
- spv_binary* binary, std::string* 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<uint32_t>& 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,
- kUnifyConstant,
+ kCompactIds,
};
// Optimizes the given binary. Passes are registered in the exact order as shown
@@ -49,6 +58,7 @@
// 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<PassId>& enabled_passes,
std::vector<uint32_t>* binary, std::string* errors);
diff --git a/libshaderc_util/include/libshaderc_util/universal_unistd.h b/libshaderc_util/include/libshaderc_util/universal_unistd.h
index bd14c5a..9f6e74f 100644
--- a/libshaderc_util/include/libshaderc_util/universal_unistd.h
+++ b/libshaderc_util/include/libshaderc_util/universal_unistd.h
@@ -29,4 +29,4 @@
#define W_OK 2
#endif //_MSC_VER
-#endif // LIBSHADERC_UTIL_UNIVERSAL_UNISTD_H_
\ No newline at end of file
+#endif // LIBSHADERC_UTIL_UNIVERSAL_UNISTD_H_
diff --git a/libshaderc_util/include/libshaderc_util/version_profile.h b/libshaderc_util/include/libshaderc_util/version_profile.h
index 78196b2..f536b30 100644
--- a/libshaderc_util/include/libshaderc_util/version_profile.h
+++ b/libshaderc_util/include/libshaderc_util/version_profile.h
@@ -23,15 +23,36 @@
// Returns true if the given version is an accepted GLSL (ES) version.
inline bool IsKnownVersion(int version) {
- return version == 100 || version == 110 || version == 120 || version == 130 ||
- version == 140 || version == 150 || version == 300 || version == 330 ||
- version == 310 || version == 400 || version == 410 || version == 420 ||
- version == 430 || version == 440 || version == 450;
+ 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);
diff --git a/libshaderc_util/src/args.cc b/libshaderc_util/src/args.cc
new file mode 100644
index 0000000..f1b36e7
--- /dev/null
+++ b/libshaderc_util/src/args.cc
@@ -0,0 +1,62 @@
+// 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 <iomanip>
+#include <sstream>
+
+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
diff --git a/libshaderc_util/src/compiler.cc b/libshaderc_util/src/compiler.cc
index 574ccfd..bf06589 100644
--- a/libshaderc_util/src/compiler.cc
+++ b/libshaderc_util/src/compiler.cc
@@ -15,8 +15,12 @@
#include "libshaderc_util/compiler.h"
#include <cstdint>
+#include <iomanip>
+#include <sstream>
+#include <thread>
#include <tuple>
+#include "SPIRV/GlslangToSpv.h"
#include "libshaderc_util/format.h"
#include "libshaderc_util/io.h"
#include "libshaderc_util/message.h"
@@ -26,8 +30,6 @@
#include "libshaderc_util/string_piece.h"
#include "libshaderc_util/version_profile.h"
-#include "SPIRV/GlslangToSpv.h"
-
namespace {
using shaderc_util::string_piece;
@@ -65,10 +67,12 @@
return std::make_pair(line, directive);
}
-// Returns the Glslang message rules for the given target environment
-// and source language. We assume only valid combinations are used.
+// 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) {
+ shaderc_util::Compiler::SourceLanguage lang,
+ bool hlsl_offsets, bool debug_info) {
using shaderc_util::Compiler;
EShMessages result = EShMsgCascadingErrors;
if (lang == Compiler::SourceLanguage::HLSL) {
@@ -85,6 +89,12 @@
static_cast<EShMessages>(result | EShMsgSpvRules | EShMsgVulkanRules);
break;
}
+ if (hlsl_offsets) {
+ result = static_cast<EShMessages>(result | EShMsgHlslOffsets);
+ }
+ if (debug_info) {
+ result = static_cast<EShMessages>(result | EShMsgDebugInfo);
+ }
return result;
}
@@ -92,6 +102,46 @@
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<std::mutex> first_call_lock(first_call_mutex);
+ if (glslang_mutex_ == nullptr) {
+ glslang_mutex_ = new std::mutex();
+ }
+ }
+
+ const std::lock_guard<std::mutex> glslang_lock(*glslang_mutex_);
+
+ if (initialize_count_ == 0) {
+ glslang::InitializeProcess();
+ }
+
+ initialize_count_++;
+}
+
+GlslangInitializer::~GlslangInitializer() {
+ const std::lock_guard<std::mutex> 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) \
@@ -121,8 +171,7 @@
const string_piece& error_tag)>&
stage_callback,
CountingIncluder& includer, OutputType output_type,
- std::ostream* error_stream, size_t* total_warnings, size_t* total_errors,
- GlslangInitializer* initializer) const {
+ 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.
@@ -134,7 +183,17 @@
std::vector<uint32_t>& compilation_output_data = std::get<1>(result_tuple);
size_t& compilation_output_data_size_in_bytes = std::get<2>(result_tuple);
- auto token = initializer->Acquire();
+ // 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");
@@ -204,12 +263,37 @@
&string_names, 1);
shader.setPreamble(preamble.c_str());
shader.setEntryPoint(entry_point_name);
+ shader.setAutoMapBindings(auto_bind_uniforms_);
+ shader.setAutoMapLocations(auto_map_locations_);
+ const auto& bases = auto_binding_base_[static_cast<int>(used_shader_stage)];
+ shader.setShiftImageBinding(bases[static_cast<int>(UniformKind::Image)]);
+ shader.setShiftSamplerBinding(bases[static_cast<int>(UniformKind::Sampler)]);
+ shader.setShiftTextureBinding(bases[static_cast<int>(UniformKind::Texture)]);
+ shader.setShiftUboBinding(bases[static_cast<int>(UniformKind::Buffer)]);
+ shader.setShiftSsboBinding(
+ bases[static_cast<int>(UniformKind::StorageBuffer)]);
+ shader.setShiftUavBinding(
+ bases[static_cast<int>(UniformKind::UnorderedAccessView)]);
+ shader.setHlslIoMapping(hlsl_iomap_);
+ shader.setResourceSetBinding(
+ hlsl_explicit_bindings_[static_cast<int>(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();
+ }
+ shader.setInvertY(invert_y_enabled_);
+ shader.setNanMinMaxClamp(nan_clamp_);
- // TODO(dneto): Generate source-level debug info if requested.
- bool success =
- shader.parse(&limits_, default_version_, default_profile_,
- force_version_profile_, kNotForwardCompatible,
- GetMessageRules(target_env_, source_language_), includer);
+ const EShMessages rules =
+ GetMessageRules(target_env_, source_language_, hlsl_offsets_,
+ 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(),
@@ -218,7 +302,7 @@
glslang::TProgram program;
program.addShader(&shader);
- success = program.link(EShMsgDefault);
+ success = program.link(EShMsgDefault) && program.mapIO();
success &= PrintFilteredErrors(error_tag, error_stream, warnings_as_errors_,
suppress_warnings_, program.getInfoLog(),
total_warnings, total_errors);
@@ -227,13 +311,37 @@
// '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<uint32_t>& 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);
+ glslang::GlslangToSpv(*program.getIntermediate(used_shader_stage), spirv,
+ &options);
- if (!enabled_opt_passes_.empty()) {
+ // 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<PassId> 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()) {
std::string opt_errors;
- if (!SpirvToolsOptimize(target_env_, enabled_opt_passes_, &spirv,
- &opt_errors)) {
+ if (!SpirvToolsOptimize(target_env_, target_env_version_,
+ opt_passes, &spirv, &opt_errors)) {
*error_stream << "shaderc: internal error: compilation succeeded but "
"failed to optimize: "
<< opt_errors << "\n";
@@ -243,7 +351,8 @@
if (output_type == OutputType::SpirvAssemblyText) {
std::string text_or_error;
- if (!SpirvToolsDisassemble(target_env_, spirv, &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";
@@ -268,7 +377,16 @@
definition ? std::string(definition, definition_length) : "";
}
-void Compiler::SetTargetEnv(Compiler::TargetEnv env) { target_env_ = env; }
+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;
@@ -300,13 +418,31 @@
if (!generate_debug_info_) {
enabled_opt_passes_.push_back(PassId::kStripDebugInfo);
}
- enabled_opt_passes_.push_back(PassId::kUnifyConstant);
+ 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::EnableInvertY(bool enable) { invert_y_enabled_ = enable; }
+
+void Compiler::SetNanClamp(bool enable) { nan_clamp_ = enable; }
+
void Compiler::SetSuppressWarnings() { suppress_warnings_ = true; }
std::tuple<bool, std::string, std::string> Compiler::PreprocessShader(
@@ -320,12 +456,27 @@
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<EShMessages>(
- EShMsgOnlyPreprocessor | GetMessageRules(target_env_, source_language_));
+ EShMsgOnlyPreprocessor |
+ GetMessageRules(target_env_, source_language_, hlsl_offsets_,
+ false));
std::string preprocessed_shader;
const bool success = shader.preprocess(
@@ -543,4 +694,79 @@
return result_vec;
}
-} // namesapce shaderc_util
+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 {
+ errs << "error:" << error_tag << ": Invalid target client version "
+ << static_cast<uint32_t>(env_version) << " for Vulkan environment "
+ << int(env);
+ }
+ break;
+ case Compiler::TargetEnv::OpenGLCompat: // TODO(dneto): remove this
+ 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<uint32_t>(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;
+ 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
diff --git a/libshaderc_util/src/compiler_test.cc b/libshaderc_util/src/compiler_test.cc
index 9938848..8d2c18d 100644
--- a/libshaderc_util/src/compiler_test.cc
+++ b/libshaderc_util/src/compiler_test.cc
@@ -20,20 +20,24 @@
#include "death_test.h"
#include "libshaderc_util/counting_includer.h"
+#include "libshaderc_util/spirv_tools_wrapper.h"
namespace {
using shaderc_util::Compiler;
-using ::testing::HasSubstr;
+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 compiles under OpenGL compatibility profile rules,
-// but not OpenGL core profile rules.
+// 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;
@@ -41,16 +45,6 @@
gl_FragColor = texture2D(tex, vec2(0.0,0.0));
})";
-// A shader that compiles under OpenGL compatibility profile rules,
-// but not OpenGL core profile rules, even when deducing the stage.
-const char kOpenGLCompatibilityFragShaderDeducibleStage[] =
- R"(#version 140
- #pragma shader_stage(fragment)
- 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
@@ -84,14 +78,105 @@
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 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<float4> 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<uint32_t> binary) {
+ std::string result;
+ shaderc_util::SpirvToolsDisassemble(Compiler::TargetEnv::Vulkan,
+ Compiler::TargetEnvVersion::Vulkan_1_2,
+ 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*, glslang::TShader::Includer::IncludeType, const char*,
- size_t) override {
+ const char*, const char*, IncludeType, size_t) override {
return nullptr;
}
virtual void release_delegate(
@@ -107,16 +192,16 @@
// 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;
- shaderc_util::GlslangInitializer initializer;
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, &initializer);
+ &total_errors);
errors_ = errors.str();
return result;
}
@@ -128,6 +213,25 @@
source, stage, Compiler::OutputType::SpirvBinary);
}
+ // Returns the SPIR-V binary for a successful compilation of a shader.
+ std::vector<uint32_t> 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<uint32_t> 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.
@@ -161,46 +265,6 @@
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
}
-TEST_F(CompilerTest, RespectTargetEnvOnOpenGLCompatibilityShader) {
- const EShLanguage stage = EShLangFragment;
-
- compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat);
- EXPECT_TRUE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader, stage));
- compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
- EXPECT_FALSE(
- SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader, stage));
- compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan);
- EXPECT_FALSE(
- SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader, stage));
- // Default compiler.
- compiler_ = Compiler();
- EXPECT_FALSE(
- SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader, stage));
-}
-
-TEST_F(CompilerTest,
- RespectTargetEnvOnOpenGLCompatibilityShaderWhenDeducingStage) {
- const EShLanguage stage = EShLangCount;
-
- compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat);
- EXPECT_TRUE(SimpleCompilationSucceeds(
- kOpenGLCompatibilityFragShaderDeducibleStage, stage))
- << errors_;
- compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
- EXPECT_FALSE(SimpleCompilationSucceeds(
- kOpenGLCompatibilityFragShaderDeducibleStage, stage))
- << errors_;
- compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan);
- EXPECT_FALSE(SimpleCompilationSucceeds(
- kOpenGLCompatibilityFragShaderDeducibleStage, stage))
- << errors_;
- // Default compiler.
- compiler_ = Compiler();
- EXPECT_FALSE(SimpleCompilationSucceeds(
- kOpenGLCompatibilityFragShaderDeducibleStage, stage))
- << errors_;
-}
-
TEST_F(CompilerTest, RespectTargetEnvOnOpenGLShader) {
const EShLanguage stage = EShLangVertex;
@@ -238,15 +302,16 @@
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
}
-TEST_F(CompilerTest, OpenGLCompatibilitySpecificShaderFailsUnderDefaultRules) {
- EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader,
- EShLangFragment));
-}
-
TEST_F(CompilerTest, OpenGLSpecificShaderFailsUnderDefaultRules) {
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, EShLangVertex));
}
+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,
@@ -258,6 +323,70 @@
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, EShLangVertex));
}
+TEST_F(CompilerTest, BadTargetEnvFails) {
+ compiler_.SetTargetEnv(static_cast<Compiler::TargetEnv>(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<Compiler::TargetEnvVersion>(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<Compiler::TargetEnvVersion>(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, SpirvTargetBadVersionFails) {
+ compiler_.SetTargetSpirv(static_cast<Compiler::SpirvVersion>(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);
@@ -304,7 +433,7 @@
<< "test_case.input_str: " << test_case.input_str << std::endl;
}
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
ConvertStringToVectorTest, ConvertStringToVectorTestFixture,
testing::ValuesIn(std::vector<ConvertStringToVectorTestCase>{
{"", {0x00000000}},
@@ -353,7 +482,7 @@
compiler_.Compile(kHlslVertexShader, EShLangVertex, "shader",
"EntryPoint", dummy_stage_callback_, dummy_includer,
Compiler::OutputType::SpirvAssemblyText, &errors,
- &total_warnings, &total_errors, &initializer);
+ &total_warnings, &total_errors);
EXPECT_TRUE(result);
std::string assembly(reinterpret_cast<char*>(words.data()));
EXPECT_THAT(assembly,
@@ -380,7 +509,7 @@
#define CASE(LIMIT, DEFAULT, NEW) \
{ Compiler::Limit::LIMIT, DEFAULT, NEW }
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
CompilerTest, LimitTest,
// See resources.cc for the defaults.
testing::ValuesIn(std::vector<SetLimitCase>{
@@ -391,15 +520,15 @@
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 150\n"
- "uniform sampler1D tex;\n"
+ oss << "#version 450\n"
+ "layout (binding=0) uniform sampler1D tex;\n"
"void main() { vec4 x = textureOffset(tex, 1.0, "
<< offset << "); }\n";
return oss.str();
@@ -430,4 +559,378 @@
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, 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<GetGlslangClientInfoCase>;
+
+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<Compiler::TargetEnvVersion>(VKVER), \
+ static_cast<Compiler::SpirvVersion>(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<Compiler::TargetEnvVersion>(GLVER), \
+ static_cast<Compiler::SpirvVersion>(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<GetGlslangClientInfoCase>{
+ // 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_GL(4_5, 1_4), false, GCASE_GL("", 450, 1_0)},
+ }));
+
+INSTANTIATE_TEST_SUITE_P(
+ ForcedSpirvSuccess, GetGlslangClientInfoTest,
+ testing::ValuesIn(std::vector<GetGlslangClientInfoCase>{
+ // 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_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<GetGlslangClientInfoCase>{
+ // 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
diff --git a/libshaderc_util/src/counting_includer_test.cc b/libshaderc_util/src/counting_includer_test.cc
index 0400ae3..fbac441 100644
--- a/libshaderc_util/src/counting_includer_test.cc
+++ b/libshaderc_util/src/counting_includer_test.cc
@@ -14,66 +14,75 @@
#include "libshaderc_util/counting_includer.h"
-#include <gmock/gmock.h>
#include <thread>
+#include <vector>
+
+#include <gmock/gmock.h>
namespace {
-const auto kRelative = glslang::TShader::Includer::EIncludeRelative;
-const auto kStandard = glslang::TShader::Includer::EIncludeStandard;
-
// A trivial implementation of CountingIncluder's virtual methods, so tests can
// instantiate.
class ConcreteCountingIncluder : public shaderc_util::CountingIncluder {
public:
- virtual glslang::TShader::Includer::IncludeResult* include_delegate(
- const char* requested, glslang::TShader::Includer::IncludeType,
- const char* requestor,
+ 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";
- return new glslang::TShader::Includer::IncludeResult{
- "", kError, strlen(kError), nullptr};
+ results_.push_back(new IncludeResult{"", kError, strlen(kError), nullptr});
+ return results_.back();
}
- virtual void release_delegate(
- glslang::TShader::Includer::IncludeResult* include_result) override {
+ virtual void release_delegate(IncludeResult* include_result) override {
delete include_result;
}
+
+ private:
+ // All the results we've returned so far.
+ std::vector<IncludeResult*> results_;
};
TEST(CountingIncluderTest, InitialCount) {
EXPECT_EQ(0, ConcreteCountingIncluder().num_include_directives());
}
-TEST(CountingIncluderTest, OneInclude) {
+TEST(CountingIncluderTest, OneIncludeLocal) {
ConcreteCountingIncluder includer;
- includer.include("random file name", kRelative, "from me", 0);
+ includer.includeLocal("random file name", "from me", 0);
EXPECT_EQ(1, includer.num_include_directives());
}
TEST(CountingIncluderTest, TwoIncludesAnyIncludeType) {
ConcreteCountingIncluder includer;
- includer.include("name1", kRelative, "from me", 0);
- includer.include("name2", kStandard, "me", 0);
+ 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.include("filename", kRelative, "from me", i);
+ includer.includeLocal("filename", "from me", i);
+ includer.includeSystem("filename", "from me", i);
}
- EXPECT_EQ(100, includer.num_include_directives());
+ EXPECT_EQ(200, includer.num_include_directives());
}
#ifndef SHADERC_DISABLE_THREADED_TESTS
TEST(CountingIncluderTest, ThreadedIncludes) {
ConcreteCountingIncluder includer;
std::thread t1(
- [&includer]() { includer.include("name1", kRelative, "me", 0); });
+ [&includer]() { includer.includeLocal("name1", "me", 0); });
std::thread t2(
- [&includer]() { includer.include("name2", kRelative, "me", 1); });
+ [&includer]() { includer.includeSystem("name2", "me", 1); });
std::thread t3(
- [&includer]() { includer.include("name3", kRelative, "me", 2); });
+ [&includer]() { includer.includeLocal("name3", "me", 2); });
t1.join();
t2.join();
t3.join();
diff --git a/libshaderc_util/src/io.cc b/libshaderc_util/src/io.cc
index 4692b14..42ae89d 100644
--- a/libshaderc_util/src/io.cc
+++ b/libshaderc_util/src/io.cc
@@ -16,7 +16,15 @@
#include "libshaderc_util/universal_unistd.h"
+#if _WIN32
+// Need _fileno from stdio.h
+// Need _O_BINARY and _O_TEXT from fcntl.h
+#include <fcntl.h>
+#include <stdio.h>
+#endif
+
#include <errno.h>
+#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
@@ -90,13 +98,13 @@
}
std::ostream* GetOutputStream(const string_piece& output_filename,
- std::ofstream* file_stream) {
+ 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()) {
- std::cerr << "glslc: error: cannot open output file: '" << output_filename
+ *err << "glslc: error: cannot open output file: '" << output_filename
<< "'";
if (access(output_filename.str().c_str(), W_OK) != 0) {
OutputFileErrorMessage(errno);
@@ -120,4 +128,18 @@
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
diff --git a/libshaderc_util/src/io_test.cc b/libshaderc_util/src/io_test.cc
index bb0d916..0f605dc 100644
--- a/libshaderc_util/src/io_test.cc
+++ b/libshaderc_util/src/io_test.cc
@@ -25,6 +25,8 @@
using shaderc_util::WriteFile;
using shaderc_util::GetOutputStream;
using shaderc_util::GetBaseFileName;
+using testing::Eq;
+using testing::HasSubstr;
std::string ToString(const std::vector<char>& v) {
return std::string(v.data(), v.size());
@@ -105,18 +107,23 @@
TEST(WriteFiletest, BadStream) {
std::ofstream fstream;
+ std::ostringstream err;
std::ostream* output_stream = GetOutputStream(
- "/this/should/not/be/writable/asdfasdfasdfasdf", &fstream);
+ "/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::ostream* output_stream = GetOutputStream(filename, &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<char> read_data;
ASSERT_TRUE(ReadFile(filename, &read_data));
@@ -125,7 +132,9 @@
TEST(OutputStreamTest, Stdout) {
std::ofstream fstream;
- std::ostream* output_stream = GetOutputStream("-", &fstream);
+ std::ostringstream err;
+ std::ostream* output_stream = GetOutputStream("-", &fstream, &err);
EXPECT_EQ(&std::cout, output_stream);
+ EXPECT_THAT(err.str(), Eq(""));
}
} // anonymous namespace
diff --git a/libshaderc_util/src/message.cc b/libshaderc_util/src/message.cc
index 11fd10a..3604b1e 100644
--- a/libshaderc_util/src/message.cc
+++ b/libshaderc_util/src/message.cc
@@ -45,41 +45,72 @@
}
// Deduces a location specification from the given message. A location
-// specification is of the form "<source-name>:<line-number>:". 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.
+// specification is of the form "<source-name>:<line-number>:" 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) {
- // TODO(antiagainst): we use ':' as a delimiter here. It may be a valid
- // character in the filename. Also be aware of other special characters,
- // for example, ' '.
- string_piece rest(*message);
- size_t colon_after_source = rest.find_first_of(':');
- if (colon_after_source == string_piece::npos) return false;
-
- string_piece source = rest.substr(0, colon_after_source);
- rest = rest.substr(colon_after_source + 1);
- size_t colon_after_line = rest.find_first_of(':');
- if (source.size() == 1 && ::isalpha(source.front()) && rest.size() > 0 &&
- rest.front() == '\\') {
- // Handle Windows path.
- colon_after_source += colon_after_line + 1;
- source = message->substr(0, colon_after_source);
- rest = rest.substr(colon_after_line + 1);
- colon_after_line = rest.find_first_of(':');
+ if (!message || message->empty()) {
+ return false;
}
- if (colon_after_line == string_piece::npos) return false;
- const string_piece line = rest.substr(0, colon_after_line);
+ // 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.
- if (!std::all_of(line.begin(), line.end(), ::isdigit)) return false;
+ 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;
- *source_name = source;
- *line_number = line;
- *message = rest.substr(colon_after_line + 1).strip_whitespace();
- return true;
+ 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.
@@ -114,6 +145,8 @@
// <location-specification> is of the form:
// <filename-or-string-number>:<line-number>:
// 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;
diff --git a/libshaderc_util/src/message_test.cc b/libshaderc_util/src/message_test.cc
index 5d65023..26dc26b 100644
--- a/libshaderc_util/src/message_test.cc
+++ b/libshaderc_util/src/message_test.cc
@@ -135,6 +135,8 @@
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,
@@ -154,7 +156,7 @@
rest.str());
}
-TEST(ParseGlslangOutputTest, FileName) {
+TEST(ParseGlslangOutputTest, FileName_BaseAndExtension) {
string_piece source_name;
string_piece line_number;
string_piece rest;
@@ -165,6 +167,12 @@
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,
@@ -172,6 +180,12 @@
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,
@@ -181,6 +195,60 @@
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;
diff --git a/libshaderc_util/src/resources.cc b/libshaderc_util/src/resources.cc
index e7dc069..d64e47f 100644
--- a/libshaderc_util/src/resources.cc
+++ b/libshaderc_util/src/resources.cc
@@ -32,7 +32,12 @@
/*.maxCombinedTextureImageUnits = */ 80,
/*.maxTextureImageUnits = */ 16,
/*.maxFragmentUniformComponents = */ 1024,
- /*.maxDrawBuffers = */ 2,
+
+ // 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,
@@ -111,6 +116,16 @@
/*.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,
+ /* .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.
diff --git a/libshaderc_util/src/shader_stage.cc b/libshaderc_util/src/shader_stage.cc
index 9b693c3..3122a3d 100644
--- a/libshaderc_util/src/shader_stage.cc
+++ b/libshaderc_util/src/shader_stage.cc
@@ -33,7 +33,16 @@
{"tesscontrol", EShLangTessControl},
{"tesseval", EShLangTessEvaluation},
{"geometry", EShLangGeometry},
- {"compute", EShLangCompute}};
+ {"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;
diff --git a/libshaderc_util/src/spirv_tools_wrapper.cc b/libshaderc_util/src/spirv_tools_wrapper.cc
index 273d1ba..4ed2bac 100644
--- a/libshaderc_util/src/spirv_tools_wrapper.cc
+++ b/libshaderc_util/src/spirv_tools_wrapper.cc
@@ -24,40 +24,61 @@
namespace {
// Gets the corresponding target environment used in SPIRV-Tools.
-spv_target_env GetSpirvToolsTargetEnv(Compiler::TargetEnv env) {
+spv_target_env GetSpirvToolsTargetEnv(Compiler::TargetEnv env,
+ Compiler::TargetEnvVersion version) {
switch (env) {
case Compiler::TargetEnv::Vulkan:
- return SPV_ENV_VULKAN_1_0;
+ 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;
+ default:
+ break;
+ }
+ break;
case Compiler::TargetEnv::OpenGL:
return SPV_ENV_OPENGL_4_5;
- case Compiler::TargetEnv::OpenGLCompat:
- return SPV_ENV_OPENGL_4_5; // TODO(antiagainst): is this correct?
+ case Compiler::TargetEnv::OpenGLCompat: // Deprecated
+ 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<uint32_t>& binary,
std::string* text_or_error) {
- spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
+ 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);
+ 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, const string_piece assembly,
- spv_binary* binary, std::string* errors) {
- auto spvtools_context = spvContextCreate(GetSpirvToolsTargetEnv(env));
+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;
@@ -81,6 +102,7 @@
}
bool SpirvToolsOptimize(Compiler::TargetEnv env,
+ Compiler::TargetEnvVersion version,
const std::vector<PassId>& enabled_passes,
std::vector<uint32_t>* binary, std::string* errors) {
errors->clear();
@@ -91,7 +113,20 @@
return true;
}
- spvtools::Optimizer optimizer(GetSpirvToolsTargetEnv(env));
+ 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);
+
+ spvtools::OptimizerOptions opt_opts;
+ opt_opts.set_validator_options(val_opts);
+ opt_opts.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&,
@@ -99,19 +134,28 @@
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::kUnifyConstant:
- optimizer.RegisterPass(spvtools::CreateUnifyConstantPass());
+ case PassId::kCompactIds:
+ optimizer.RegisterPass(spvtools::CreateCompactIdsPass());
break;
}
}
- if (!optimizer.Run(binary->data(), binary->size(), binary)) {
+ if (!optimizer.Run(binary->data(), binary->size(), binary, opt_opts)) {
*errors = oss.str();
return false;
}
diff --git a/libshaderc_util/src/version_profile_test.cc b/libshaderc_util/src/version_profile_test.cc
new file mode 100644
index 0000000..9adb294
--- /dev/null
+++ b/libshaderc_util/src/version_profile_test.cc
@@ -0,0 +1,133 @@
+// 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<ParseVersionProfileCase>;
+
+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<ParseVersionProfileCase>{
+ {"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<ParseVersionProfileCase>{
+ {"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<ParseVersionProfileCase>{
+ {"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<ParseVersionProfileCase>{
+ {"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
diff --git a/libshaderc_util/testdata/copy-to-build.cmake b/libshaderc_util/testdata/copy-to-build.cmake
index bf50a72..7b41b61 100644
--- a/libshaderc_util/testdata/copy-to-build.cmake
+++ b/libshaderc_util/testdata/copy-to-build.cmake
@@ -1,2 +1,16 @@
+# 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 .)
\ No newline at end of file
diff --git a/license-checker.cfg b/license-checker.cfg
new file mode 100644
index 0000000..0e00206
--- /dev/null
+++ b/license-checker.cfg
@@ -0,0 +1,36 @@
+[
+ {
+ "licenses": [ "Apache-2.0-Header" ],
+ "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" ] }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/third_party/Android.mk b/third_party/Android.mk
index 40395ad..16ea3a1 100644
--- a/third_party/Android.mk
+++ b/third_party/Android.mk
@@ -1,231 +1,35 @@
THIRD_PARTY_PATH := $(call my-dir)
-GLSLANG_LOCAL_PATH := $(THIRD_PARTY_PATH)/glslang
-LOCAL_PATH := $(GLSLANG_LOCAL_PATH)
+# Set the location of glslang
+ifeq ($(GLSLANG_LOCAL_PATH),)
+ GLSLANG_LOCAL_PATH:=$(THIRD_PARTY_PATH)/glslang
+endif
+include $(GLSLANG_LOCAL_PATH)/Android.mk
-GLSLANG_OS_FLAGS := -DGLSLANG_OSINCLUDE_UNIX
-# AMD extensions are turned on by default in upstream Glslang.
-GLSLANG_DEFINES:= -DAMD_EXTENSIONS $(GLSLANG_OS_FLAGS)
+# 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
-include $(CLEAR_VARS)
-LOCAL_MODULE:=SPIRV
-LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES)
-LOCAL_EXPORT_C_INCLUDES:=$(GLSLANG_LOCAL_PATH)
-LOCAL_SRC_FILES:= \
- SPIRV/GlslangToSpv.cpp \
- SPIRV/InReadableOrder.cpp \
- SPIRV/Logger.cpp \
- SPIRV/SPVRemapper.cpp \
- SPIRV/SpvBuilder.cpp \
- SPIRV/disassemble.cpp \
- SPIRV/doc.cpp
+# Now include the SPIRV-Tools dependency
+include $(SPVTOOLS_LOCAL_PATH)/Android.mk
-LOCAL_C_INCLUDES:=$(GLSLANG_LOCAL_PATH) $(GLSLANG_LOCAL_PATH)/glslang/SPIRV
-LOCAL_EXPORT_C_INCLUDES:=$(GLSLANG_LOCAL_PATH)/glslang/SPIRV
-include $(BUILD_STATIC_LIBRARY)
+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
-include $(CLEAR_VARS)
-LOCAL_MODULE:=OSDependent
-LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES)
-LOCAL_EXPORT_C_INCLUDES:=$(GLSLANG_LOCAL_PATH)
-LOCAL_SRC_FILES:=glslang/OSDependent/Unix/ossource.cpp
-LOCAL_C_INCLUDES:=$(GLSLANG_LOCAL_PATH) $(GLSLANG_LOCAL_PATH)/glslang/OSDependent/Unix/
-LOCAL_EXPORT_C_INCLUDES:=$(GLSLANG_LOCAL_PATH)/glslang/OSDependent/Unix/
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE:=OGLCompiler
-LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES)
-LOCAL_EXPORT_C_INCLUDES:=$(GLSLANG_LOCAL_PATH)
-LOCAL_SRC_FILES:=OGLCompilersDLL/InitializeDll.cpp
-LOCAL_C_INCLUDES:=$(GLSLANG_LOCAL_PATH)/OGLCompiler
-LOCAL_STATIC_LIBRARIES:=OSDependent
-include $(BUILD_STATIC_LIBRARY)
-
-
-# Build Glslang's HLSL parser library.
-include $(CLEAR_VARS)
-LOCAL_MODULE:=HLSL
-LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti
-LOCAL_SRC_FILES:= \
- hlsl/hlslAttributes.cpp \
- hlsl/hlslGrammar.cpp \
- hlsl/hlslOpMap.cpp \
- hlsl/hlslParseables.cpp \
- hlsl/hlslParseHelper.cpp \
- hlsl/hlslScanContext.cpp \
- hlsl/hlslTokenStream.cpp
-LOCAL_C_INCLUDES:=$(GLSLANG_LOCAL_PATH) \
- $(GLSLANG_LOCAL_PATH)/hlsl
-include $(BUILD_STATIC_LIBRARY)
-
-
-include $(CLEAR_VARS)
-
-GLSLANG_OUT_PATH=$(if $(call host-path-is-absolute,$(TARGET_OUT)),$(TARGET_OUT),$(abspath $(TARGET_OUT)))
-
-LOCAL_MODULE:=glslang
-LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES)
-LOCAL_EXPORT_C_INCLUDES:=$(GLSLANG_LOCAL_PATH)
-
-LOCAL_SRC_FILES:= \
- glslang/GenericCodeGen/CodeGen.cpp \
- glslang/GenericCodeGen/Link.cpp \
- glslang/MachineIndependent/Constant.cpp \
- glslang/MachineIndependent/glslang_tab.cpp \
- glslang/MachineIndependent/InfoSink.cpp \
- glslang/MachineIndependent/Initialize.cpp \
- glslang/MachineIndependent/Intermediate.cpp \
- glslang/MachineIndependent/intermOut.cpp \
- glslang/MachineIndependent/IntermTraverse.cpp \
- glslang/MachineIndependent/iomapper.cpp \
- glslang/MachineIndependent/limits.cpp \
- glslang/MachineIndependent/linkValidate.cpp \
- glslang/MachineIndependent/parseConst.cpp \
- glslang/MachineIndependent/ParseContextBase.cpp \
- glslang/MachineIndependent/ParseHelper.cpp \
- glslang/MachineIndependent/PoolAlloc.cpp \
- glslang/MachineIndependent/propagateNoContraction.cpp \
- glslang/MachineIndependent/reflection.cpp \
- glslang/MachineIndependent/RemoveTree.cpp \
- glslang/MachineIndependent/Scan.cpp \
- glslang/MachineIndependent/ShaderLang.cpp \
- glslang/MachineIndependent/SymbolTable.cpp \
- glslang/MachineIndependent/Versions.cpp \
- glslang/MachineIndependent/preprocessor/PpAtom.cpp \
- glslang/MachineIndependent/preprocessor/PpContext.cpp \
- glslang/MachineIndependent/preprocessor/Pp.cpp \
- glslang/MachineIndependent/preprocessor/PpMemory.cpp \
- glslang/MachineIndependent/preprocessor/PpScanner.cpp \
- glslang/MachineIndependent/preprocessor/PpSymbols.cpp \
- glslang/MachineIndependent/preprocessor/PpTokens.cpp
-
-LOCAL_C_INCLUDES:=$(GLSLANG_LOCAL_PATH) \
- $(GLSLANG_LOCAL_PATH)/glslang/MachineIndependent \
- $(GLSLANG_OUT_PATH)
-LOCAL_STATIC_LIBRARIES:=OSDependent OGLCompiler SPIRV HLSL
-include $(BUILD_STATIC_LIBRARY)
-
-
-SPVTOOLS_LOCAL_PATH := $(THIRD_PARTY_PATH)/spirv-tools
-LOCAL_PATH := $(SPVTOOLS_LOCAL_PATH)
-SPVTOOLS_OUT_PATH=$(if $(call host-path-is-absolute,$(TARGET_OUT)),$(TARGET_OUT),$(abspath $(TARGET_OUT)))
-SPVHEADERS_LOCAL_PATH := $(THIRD_PARTY_PATH)/spirv-tools/external/spirv-headers
-
-# Locations of grammar files.
-SPV_CORE10_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.0/spirv.core.grammar.json
-SPV_CORE11_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.1/spirv.core.grammar.json
-SPV_GLSL_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.0/extinst.glsl.std.450.grammar.json
-# OpenCL grammar has not yet been published to SPIRV-Headers
-SPV_OPENCL_GRAMMAR=$(SPVTOOLS_LOCAL_PATH)/source/extinst-1.0.opencl.std.grammar.json
-
-define gen_spvtools_grammar_tables
-$(call generate-file-dir,$(1)/core.insts-1.0.inc)
-$(1)/core.insts-1.0.inc $(1)/operand.kinds-1.0.inc $(1)/glsl.std.450.insts-1.0.inc $(1)/opencl.std.insts-1.0.inc: \
- $(SPVTOOLS_LOCAL_PATH)/utils/generate_grammar_tables.py \
- $(SPV_CORE10_GRAMMAR) \
- $(SPV_GLSL_GRAMMAR) \
- $(SPV_OPENCL_GRAMMAR)
- @$(HOST_PYTHON) $(SPVTOOLS_LOCAL_PATH)/utils/generate_grammar_tables.py \
- --spirv-core-grammar=$(SPV_CORE10_GRAMMAR) \
- --extinst-glsl-grammar=$(SPV_GLSL_GRAMMAR) \
- --extinst-opencl-grammar=$(SPV_OPENCL_GRAMMAR) \
- --core-insts-output=$(1)/core.insts-1.0.inc \
- --glsl-insts-output=$(1)/glsl.std.450.insts-1.0.inc \
- --opencl-insts-output=$(1)/opencl.std.insts-1.0.inc \
- --operand-kinds-output=$(1)/operand.kinds-1.0.inc
- @echo "[$(TARGET_ARCH_ABI)] Grammar v1.0 : instructions & operands <= grammar JSON files"
-$(1)/core.insts-1.1.inc $(1)/operand.kinds-1.1.inc: \
- $(SPVTOOLS_LOCAL_PATH)/utils/generate_grammar_tables.py \
- $(SPV_CORE11_GRAMMAR)
- @$(HOST_PYTHON) $(SPVTOOLS_LOCAL_PATH)/utils/generate_grammar_tables.py \
- --spirv-core-grammar=$(SPV_CORE11_GRAMMAR) \
- --core-insts-output=$(1)/core.insts-1.1.inc \
- --operand-kinds-output=$(1)/operand.kinds-1.1.inc
- @echo "[$(TARGET_ARCH_ABI)] Grammar v1.1 : instructions & operands <= grammar JSON files"
-$(SPVTOOLS_LOCAL_PATH)/source/opcode.cpp: $(1)/core.insts-1.0.inc $(1)/core.insts-1.1.inc
-$(SPVTOOLS_LOCAL_PATH)/source/operand.cpp: $(1)/operand.kinds-1.0.inc $(1)/operand.kinds-1.1.inc
-$(SPVTOOLS_LOCAL_PATH)/source/ext_inst.cpp: $(1)/glsl.std.450.insts-1.0.inc $(1)/opencl.std.insts-1.0.inc
-endef
-$(eval $(call gen_spvtools_grammar_tables,$(SPVTOOLS_OUT_PATH)))
-
-define gen_spvtools_build_version_inc
-$(call generate-file-dir,$(1)/dummy_filename)
-$(1)/build-version.inc: \
- $(SPVTOOLS_LOCAL_PATH)/utils/update_build_version.py \
- $(SPVTOOLS_LOCAL_PATH)/CHANGES
- @$(HOST_PYTHON) $(SPVTOOLS_LOCAL_PATH)/utils/update_build_version.py \
- $(SPVTOOLS_LOCAL_PATH) $(1)/build-version.inc
- @echo "[$(TARGET_ARCH_ABI)] Generate : build-version.inc <= CHANGES"
-$(SPVTOOLS_LOCAL_PATH)/source/software_version.cpp: $(1)/build-version.inc
-endef
-$(eval $(call gen_spvtools_build_version_inc,$(SPVTOOLS_OUT_PATH)))
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := SPIRV-Tools
-LOCAL_C_INCLUDES := \
- $(SPVTOOLS_LOCAL_PATH)/include \
- $(SPVTOOLS_LOCAL_PATH)/source \
- $(SPVTOOLS_LOCAL_PATH)/external/spirv-headers/include \
- $(SPVTOOLS_OUT_PATH)
-LOCAL_EXPORT_C_INCLUDES := \
- $(SPVTOOLS_LOCAL_PATH)/include
-LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti
-LOCAL_SRC_FILES:= \
- source/assembly_grammar.cpp \
- source/binary.cpp \
- source/diagnostic.cpp \
- source/disassemble.cpp \
- source/ext_inst.cpp \
- source/libspirv.cpp \
- source/name_mapper.cpp \
- source/opcode.cpp \
- source/operand.cpp \
- source/parsed_operand.cpp \
- source/print.cpp \
- source/software_version.cpp \
- source/spirv_endian.cpp \
- source/spirv_target_env.cpp \
- source/table.cpp \
- source/text.cpp \
- source/text_handler.cpp \
- source/util/parse_number.cpp \
- source/val/basic_block.cpp \
- source/val/construct.cpp \
- source/val/function.cpp \
- source/val/instruction.cpp \
- source/val/validation_state.cpp \
- source/validate.cpp \
- source/validate_cfg.cpp \
- source/validate_datarules.cpp \
- source/validate_id.cpp \
- source/validate_instruction.cpp \
- source/validate_layout.cpp
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := SPIRV-Tools-opt
-LOCAL_C_INCLUDES := \
- $(SPVTOOLS_LOCAL_PATH)/include \
- $(SPVTOOLS_LOCAL_PATH)/source \
- $(SPVTOOLS_LOCAL_PATH)/external/spirv-headers/include
-LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti
-LOCAL_STATIC_LIBRARIES:=SPIRV-Tools
-LOCAL_SRC_FILES:= \
- source/opt/build_module.cpp \
- source/opt/def_use_manager.cpp \
- source/opt/eliminate_dead_constant_pass.cpp \
- source/opt/fold_spec_constant_op_and_composite_pass.cpp \
- source/opt/freeze_spec_constant_value_pass.cpp \
- source/opt/function.cpp \
- source/opt/instruction.cpp \
- source/opt/ir_loader.cpp \
- source/opt/module.cpp \
- source/opt/optimizer.cpp \
- source/opt/pass_manager.cpp \
- source/opt/set_spec_constant_default_value_pass.cpp \
- source/opt/strip_debug_info_pass.cpp \
- source/opt/type_manager.cpp \
- source/opt/types.cpp \
- source/opt/unify_const_pass.cpp
-include $(BUILD_STATIC_LIBRARY)
+ # Now include the SPIRV-Cross dependency
+ include $(SPVCROSS_LOCAL_PATH)/jni/Android.mk
+endif
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index 0b50b96..7bd9617 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -7,8 +7,20 @@
"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( 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})
@@ -21,65 +33,68 @@
endif()
set(OLD_PLATFORM_TOOLSET ${CMAKE_GENERATOR_TOOLSET})
+check_cxx_compiler_flag(-fPIC COMPILER_SUPPORTS_PIC)
-if (IS_DIRECTORY ${SHADERC_GLSLANG_DIR})
- 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)
+
+if (IS_DIRECTORY ${SHADERC_SPIRV_HEADERS_DIR})
+ set(SPIRV_HEADERS_SKIP_EXAMPLES ON)
+ add_subdirectory(${SHADERC_SPIRV_HEADERS_DIR} spirv-headers)
endif()
-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")
- endif()
- add_subdirectory(${SHADERC_SPIRV_TOOLS_DIR} spirv-tools)
-endif()
if (NOT TARGET SPIRV-Tools)
- message(FATAL_ERROR "SPIRV-Tools was not found - required for compilation")
-endif()
-
-if(${SHADERC_ENABLE_TESTS})
- # Configure out-of-source-directory tests for glslang.
- # The glslang project uses a bash script called "runtests" to run tests.
- # The runtests script assumes the glslangValidator executable exists in
- # a location inside the source tree, but we build it elsewhere.
- # We need to copy the test files, fix the path references, and then run tests.
- set(GLSLANG_TEST_SRC_DIR ${SHADERC_GLSLANG_DIR}/Test)
- set(GLSLANG_TEST_BIN_DIR
- ${CMAKE_CURRENT_BINARY_DIR}/test-glslang/${CMAKE_CFG_INTDIR})
-
- # If we are building in a multi-configuration setting we have
- # to put the glslang tests into their respective subdirectories.
- if (CMAKE_CONFIGURATION_TYPES)
- set(GLSLANG_CONFIGURATION_DIR ${CMAKE_CFG_INTDIR})
+ # 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 and re2 to build tests.
+ # 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)
endif()
-
- add_custom_target(copy-tests-if-necessary ALL
- COMMAND ${PYTHON_EXE}
- ${shaderc_SOURCE_DIR}/utils/copy-tests-if-necessary.py
- ${GLSLANG_TEST_SRC_DIR} ${GLSLANG_TEST_BIN_DIR} ${GLSLANG_CONFIGURATION_DIR}
- COMMENT "Copying and patching glslang tests if needed")
-
- if (CMAKE_CONFIGURATION_TYPES)
- # If we are running a multi-configuration project,
- # the tests will be in test-glslang/${Configuration}
- add_test(NAME glslang-testsuite
- COMMAND bash runtests
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test-glslang/$<CONFIGURATION>
- )
- else()
- add_test(NAME glslang-testsuite
- COMMAND bash runtests
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test-glslang/
- )
+ 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})
+ 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)
diff --git a/utils/add_copyright.py b/utils/add_copyright.py
index 2d3f734..37505bc 100755
--- a/utils/add_copyright.py
+++ b/utils/add_copyright.py
@@ -12,8 +12,8 @@
# 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.
+"""Adds copyright notices to all the files that need them under the current
+directory.
usage: add_copyright.py [--check]
@@ -21,8 +21,6 @@
with status 1 if any such files are found, 0 if none.
"""
-from __future__ import print_function
-
import fileinput
import fnmatch
import os
@@ -63,7 +61,8 @@
def filtered_descendants(glob):
"""Returns glob-matching filenames under the current directory, but skips
some irrelevant paths."""
- return find('.', glob, ['third_party', 'ext', 'build*', 'out*'])
+ return find('.', glob, ['third_party', 'external', 'build*', 'out*',
+ 'CompilerIdCXX', '.venv'])
def skip(line):
@@ -75,8 +74,8 @@
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.
+ 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'):
@@ -85,11 +84,12 @@
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.
+ """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.
+ 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'
diff --git a/utils/build.py b/utils/build.py
deleted file mode 100755
index 733e958..0000000
--- a/utils/build.py
+++ /dev/null
@@ -1,166 +0,0 @@
-#!/usr/bin/env python
-
-# 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.
-
-"""Builds the Shaderc project, on Linux, Mac, or Windows.
-"""
-
-from __future__ import print_function
-import argparse
-import os
-import platform
-import subprocess
-import sys
-
-
-OS = platform.system()
-
-
-def run(cmd, cwd, env, justprint):
- """Prints a command to run, and optionally runs it.
-
- Raises a RuntimeError if the command does not launch or otherwise fails.
-
- Args:
- justprint: If true, then only print the command. Otherwise run the
- command after printing it.
- cmd: List of words in the command.
- cwd: Working directory for the command.
- env: Environment to pass to subprocess.
- """
- print(cmd)
- if justprint:
- return
-
- p = subprocess.Popen(cmd, cwd=cwd, env=env)
- (_, _) = p.communicate()
- if p.returncode != 0:
- raise RuntimeError('Failed to run %s in %s' % (cmd, cwd))
-
-
-def build(args):
- """ Builds Shaderc under specified conditions.
-
- Args:
- args: An object with attributes:
- srcdir: where Shaderc source can be found
- builddir: build working directory
- installdir: install directory
- """
-
- if not os.path.isdir(args.srcdir):
- raise RuntimeError('Soure directory %s does not exist' % (args.srcdir))
-
- # Make paths absolute, and ensure directories exist.
- for d in [args.builddir, args.installdir]:
- if not os.path.isdir(d):
- os.makedirs(d)
- args.srcdir = os.path.abspath(args.srcdir)
- args.builddir = os.path.abspath(args.builddir)
- args.installdir = os.path.abspath(args.installdir)
-
- print('Building Shaderc:')
- print(' Source : ', args.srcdir)
- print(' Build dir : ', args.builddir)
- print(' Install dir: ', args.installdir)
- cmake_command = ['cmake', args.srcdir, '-GNinja',
- '-DCMAKE_BUILD_TYPE=%s' % args.buildtype,
- '-DCMAKE_INSTALL_PREFIX=%s' % args.installdir]
-
- env = None
- if OS == 'Windows':
- p = subprocess.Popen(
- '"%VS140COMNTOOLS%..\\..\\VC\\vcvarsall.bat" & set',
- stdout=subprocess.PIPE, cwd=args.builddir, shell=True)
- env = dict([tuple(line.split('=', 1))
- for line in p.communicate()[0].splitlines()])
- run(cmake_command, args.builddir, env, args.dry_run)
- run(['ninja', 'install'], args.builddir, env, args.dry_run)
- run(['ctest', '--output-on-failure'], args.builddir, env, args.dry_run)
-
-
-def cygpath(f):
- p = subprocess.Popen(['cygpath', '-w', f], stdout=subprocess.PIPE)
- return p.communicate()[0].rstrip()
-
-def main():
- """Builds Shaderc after parsing argument specifying locations of
- files, level of parallelism, and whether it's a dry run that should
- skip actual compilation and installation."""
-
- parser = argparse.ArgumentParser(description='Build Shaderc simply')
- parser.add_argument('-n', '--dry_run', dest='dry_run', default=False,
- action='store_true',
- help='Dry run: Make dirs and only print commands '
- 'to be run')
- parser.add_argument('--srcdir', dest='srcdir', default='src/shaderc',
- help='Shaderc source directory. Default "src/shaderc".')
- parser.add_argument('--builddir', dest='builddir', default='out',
- help='Build directory. Default is "out".')
- parser.add_argument('--installdir', dest='installdir', required=True,
- help='Installation directory. Required.')
- parser.add_argument('--type', dest='buildtype', default='RelWithDebInfo',
- help='Build type. Default is RelWithDebInfo')
-
- arch = None
- if (OS == 'Windows' or OS.startswith('CYGWIN')):
- arch = 'windows-x86'
- if OS == 'Linux':
- arch = 'linux-x86'
- if OS == 'Darwin':
- arch = 'darwin-x86'
- if arch is None:
- raise RuntimeError('Unknown OS: %s' % OS)
-
- path_default = os.pathsep.join([
- os.path.join(os.getcwd(), 'prebuilts', 'cmake', arch, 'bin'),
- os.path.join(os.getcwd(), 'prebuilts', 'ninja', arch),
- os.path.join(os.getcwd(), 'prebuilts', 'python', arch, 'x64')])
-
- parser.add_argument('--path', dest='path',
- default=path_default,
- help='Extra directories to prepend to the system path, '
- 'separated by your system\'s path delimiter (typically '
- '":" or ";"). After prepending, path must contain '
- 'cmake, ninja, and python. On Cygwin, the native '
- 'Windows Python must come first. Default is %s.'
- % path_default)
-
- args = parser.parse_args()
-
- if args.path:
- os.environ['PATH'] = os.pathsep.join([args.path, os.getenv('PATH')])
-
- if OS.startswith('CYGWIN'):
- # Escape to Windows.
- winargv = []
- args_dict = vars(args)
- for k in args_dict:
- if k=='path' or k.endswith('dir'):
- winargv.extend(['--%s' % k, cygpath(args_dict[k])])
- elif k=='buildtype':
- winargv.extend(['--type', args.buildtype])
- elif k=='dry_run':
- if args.dry_run:
- winargv.append('-n')
- else:
- winargv.extend(['--%s' % k, args_dict[k]])
- os.execlp('python', 'python', sys.argv[0], *winargv)
-
- build(args)
-
-
-if __name__ == '__main__':
- main()
diff --git a/utils/copy-tests-if-necessary.py b/utils/copy-tests-if-necessary.py
deleted file mode 100755
index f47e816..0000000
--- a/utils/copy-tests-if-necessary.py
+++ /dev/null
@@ -1,120 +0,0 @@
-#!/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.
-
-"""Copies tests from the source directory to the binary directory if something
-in the source directory has changed. It also updates the path in runtests
-to point to the correct binary directory.
-
-Arguments: glslang_test_source_dir glslang_test_bin_dir [intermediate-dir]
-
-intermediate-dir is optional, it specifies that there the additional directory
-between the root, and the tests/binary.
-"""
-
-import errno
-import os
-import shutil
-import sys
-
-
-def get_modified_times(path):
- """Returns a string containing a newline-separated set of
- filename:last_modified_time pairs for all files rooted at path.
- """
- output = []
- for root, _, filenames in os.walk(path):
- for filename in filenames:
- fullpath = os.path.join(root, filename)
- output.append(
- filename + ":" +
- str(os.path.getmtime(fullpath)) + "\n")
- return "".join(sorted(output))
-
-
-def read_file(path):
- """Reads a file and returns the data as a string."""
- output = ""
- try:
- # If we could not open then we simply return "" as the output
- with open(path, "r") as content:
- output = content.read()
- except:
- pass
- return output
-
-
-def write_file(path, output):
- """Writes an output string to the file located at path."""
- with open(path, "w") as content:
- content.write(output)
-
-
-def substitute_file(path, substitution):
- """Substitutes all instances of substitution[0] with substitution[1] for the
- file located at path."""
- with open(path, "r") as content:
- f_input = content.read()
- if f_input:
- f_input = f_input.replace(substitution[0], substitution[1])
- with open(path, "w") as content:
- content.write(f_input)
-
-
-def substitute_files(path, substitution):
- """Runs substitute_file() on all files rooted at path."""
- for root, _, filenames in os.walk(path):
- for filename in filenames:
- substitute_file(os.path.join(root, filename), substitution)
-
-
-def setup_directory(source, dest):
- """Removes the destination directory if it exists and copies the source
- directory over the destination if it exists.
- """
- try:
- shutil.rmtree(dest)
- except OSError as e:
- # shutil will throw if it could not find the directory.
- if e.errno == errno.ENOENT:
- pass
- else:
- raise
- shutil.copytree(source, dest)
-
-
-def main():
- glsl_src_dir = os.path.normpath(sys.argv[1])
- glsl_bin_dir = os.path.normpath(sys.argv[2])
- intermediate_directory = None
- if (len(sys.argv) > 3):
- intermediate_directory = sys.argv[3]
- glsl_list_file = os.path.join(glsl_bin_dir, "glsl_test_list")
-
- src_glsl_stamp = get_modified_times(glsl_src_dir)
- old_glsl_stamp = read_file(glsl_list_file)
-
- target_location = "../glslang/StandAlone/"
- if intermediate_directory:
- target_location = "../" + target_location + intermediate_directory + "/"
- target_location = "EXE=" + target_location
- if src_glsl_stamp != old_glsl_stamp:
- setup_directory(glsl_src_dir, glsl_bin_dir)
- substitute_file(os.path.join(glsl_bin_dir, "runtests"),
- ("EXE=../build/install/bin/", target_location))
- write_file(glsl_list_file, src_glsl_stamp)
-
-
-if __name__ == "__main__":
- main()
diff --git a/utils/git-sync-deps b/utils/git-sync-deps
new file mode 100755
index 0000000..eecfbe9
--- /dev/null
+++ b/utils/git-sync-deps
@@ -0,0 +1,282 @@
+#!/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:]))
diff --git a/utils/roll-deps b/utils/roll-deps
new file mode 100755
index 0000000..4962fd6
--- /dev/null
+++ b/utils/roll-deps
@@ -0,0 +1,53 @@
+#!/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.
+
+effcee_dir="third_party/effcee/"
+effcee_trunk="origin/main"
+glslang_dir="third_party/glslang/"
+glslang_trunk="origin/master"
+googletest_dir="third_party/googletest/"
+googletest_trunk="origin/master"
+re2_dir="third_party/re2/"
+re2_trunk="origin/master"
+spirv_headers_dir="third_party/spirv-headers/"
+spirv_headers_trunk="origin/master"
+spirv_tools_dir="third_party/spirv-tools/"
+spirv_tools_trunk="origin/master"
+
+# 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
+
+old_head=$(git rev-parse HEAD)
+
+roll-dep --ignore-dirty-tree --roll-to="${effcee_trunk}" "${effcee_dir}"
+roll-dep --ignore-dirty-tree --roll-to="${glslang_trunk}" "${glslang_dir}"
+roll-dep --ignore-dirty-tree --roll-to="${googletest_trunk}" "${googletest_dir}"
+roll-dep --ignore-dirty-tree --roll-to="${re2_trunk}" "${re2_dir}"
+roll-dep --ignore-dirty-tree --roll-to="${spirv_headers_trunk}" "${spirv_headers_dir}"
+roll-dep --ignore-dirty-tree --roll-to="${spirv_tools_trunk}" "${spirv_tools_dir}"
+
+git rebase --interactive "${old_head}"
diff --git a/utils/update_build_version.py b/utils/update_build_version.py
index b1a4b0b..5785390 100755
--- a/utils/update_build_version.py
+++ b/utils/update_build_version.py
@@ -23,16 +23,29 @@
# directory's "git describe" output enclosed in double quotes and appropriately
# escaped.
-from __future__ import print_function
-
import datetime
+import errno
import os.path
import re
import subprocess
import sys
+import time
-OUTFILE = 'build-version.inc'
+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.
@@ -52,15 +65,19 @@
def deduce_software_version(directory):
- """Returns a software version number parsed from the CHANGES file
- in the given directory.
+ """Returns a software version number parsed from the CHANGES file in the
+ given directory.
The CHANGES file describes most recent versions first.
"""
- pattern = re.compile(r'(v\d+\.\d+(-dev)?) \d\d\d\d-\d\d-\d\d$')
+ # 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)?) \d\d\d\d-\d\d-\d\d\s*$')
changes_file = os.path.join(directory, 'CHANGES')
- with open(changes_file) as f:
+ with open(changes_file, errors='replace') as f:
for line in f.readlines():
match = pattern.match(line)
if match:
@@ -69,11 +86,13 @@
def describe(directory):
- """Returns a string describing the current Git HEAD version as descriptively
- as possible.
+ """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, <date>'."""
+ Runs 'git describe', or alternately 'git rev-parse HEAD', in
+ directory. If successful, returns the output; otherwise returns
+ 'unknown hash, <date>'.
+ """
try:
# decode() is needed here for Python3 compatibility. In Python2,
# str and bytes are the same type, but not in Python3.
@@ -86,12 +105,21 @@
return command_output(
['git', 'rev-parse', 'HEAD'], directory).rstrip().decode()
except:
- return 'unknown hash, ' + datetime.date.today().isoformat()
+ # 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."""
+ """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))
@@ -100,9 +128,9 @@
def main():
- if len(sys.argv) != 4:
- print('usage: {} <shaderc-dir> <spirv-tools-dir> <glslang-dir>'.format(
- sys.argv[0]))
+ if len(sys.argv) != 5:
+ print(('usage: {} <shaderc-dir> <spirv-tools-dir> <glslang-dir> <output-file>'.format(
+ sys.argv[0])))
sys.exit(1)
projects = ['shaderc', 'spirv-tools', 'glslang']
@@ -111,11 +139,14 @@
for (p, d) in zip(projects, sys.argv[1:])
])
- if os.path.isfile(OUTFILE):
- with open(OUTFILE, 'r') as f:
+ 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(OUTFILE, 'w') as f:
+ with open(output_file, 'w') as f:
f.write(new_content)