First Commit

This commit is contained in:
2025-11-18 14:18:26 -07:00
parent 33eb6e3707
commit 27277ec342
6106 changed files with 3571167 additions and 0 deletions

5
3rdparty/shaderc/.clang-format vendored Normal file
View File

@@ -0,0 +1,5 @@
---
# Use Google code formatting rules.
Language: Cpp
BasedOnStyle: Google
...

View File

@@ -0,0 +1,66 @@
# Copyright 2023 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,s either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: Update dependencies
permissions:
contents: read
on:
schedule:
- cron: '0 2 * * *'
workflow_dispatch:
jobs:
update-dependencies:
permissions:
contents: write
pull-requests: write
name: Update dependencies
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# Checkout the depot tools they are needed by roll_deps.sh
- name: Checkout depot tools
run: git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
- name: Update PATH
run: echo "$(pwd)/depot_tools" >> $GITHUB_PATH
- name: Download dependencies
run: python3 utils/git-sync-deps
- name: Setup git user information
run: |
git config user.name "GitHub Actions[bot]"
git config user.email "<>"
git checkout -b roll_deps
- name: Update dependencies
run: |
utils/roll-deps
if [[ `git diff HEAD..origin/main --name-only | wc -l` == 0 ]]; then
echo "changed=false" >> $GITHUB_OUTPUT
else
echo "changed=true" >> $GITHUB_OUTPUT
fi
id: update_dependencies
- name: Push changes and create PR
if: steps.update_dependencies.outputs.changed == 'true'
run: |
git push --force --set-upstream origin roll_deps
gh pr create --label 'kokoro:run' --base main -f || true
env:
GITHUB_TOKEN: ${{ github.token }}

21
3rdparty/shaderc/.gitignore vendored Normal file
View File

@@ -0,0 +1,21 @@
build/
build-*/
out/
*.pyc
*.swp
compile_commands.json
.ycm_extra_conf.py
cscope.*
third_party/abseil_cpp
third_party/effcee
third_party/glslang
third_party/googletest
third_party/re2
third_party/spirv-tools
third_party/spirv-headers
third_party/spirv-cross
third_party/tint
android_test/libs
android_test/include
.DS_Store
.vscode/

9
3rdparty/shaderc/AUTHORS vendored Normal file
View File

@@ -0,0 +1,9 @@
# This is the official list of shaderc authors for copyright purposes.
# This file is distinct from the CONTRIBUTORS files.
# See the latter for an explanation.
# Names should be added to this file as:
# Name or Organization <email address>
# The email address is not required for organizations.
Google Inc.

67
3rdparty/shaderc/Android.mk vendored Normal file
View File

@@ -0,0 +1,67 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
ROOT_SHADERC_PATH := $(call my-dir)
include $(ROOT_SHADERC_PATH)/third_party/Android.mk
include $(ROOT_SHADERC_PATH)/libshaderc_util/Android.mk
include $(ROOT_SHADERC_PATH)/libshaderc/Android.mk
ALL_LIBS:=libglslang.a \
libOSDependent.a \
libshaderc.a \
libshaderc_util.a \
libSPIRV.a \
libSPIRV-Tools.a \
libSPIRV-Tools-opt.a
SHADERC_HEADERS=shaderc.hpp shaderc.h env.h status.h visibility.h
SHADERC_HEADERS_IN_OUT_DIR=$(foreach H,$(SHADERC_HEADERS),$(NDK_APP_LIBS_OUT)/../include/shaderc/$(H))
define gen_libshaderc_header
$(call generate-file-dir,$(NDK_APP_LIBS_OUT)/../include/shaderc/$(1))
$(NDK_APP_LIBS_OUT)/../include/shaderc/$(1) : \
$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/$(1)
$(call host-cp,$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/$(1) \
,$(NDK_APP_LIBS_OUT)/../include/shaderc/$(1))
endef
# Generate headers
$(eval $(foreach H,$(SHADERC_HEADERS),$(call gen_libshaderc_header,$(H))))
libshaderc_headers: $(SHADERC_HEADERS_IN_OUT_DIR)
.PHONY: libshaderc_headers
# Rules for combining library files to form a single libshader_combined.a.
# It always goes into $(TARGET_OUT)
$(call generate-file-dir,$(TARGET_OUT)/combine.ar)
$(TARGET_OUT)/combine.ar: $(TARGET_OUT) $(addprefix $(TARGET_OUT)/, $(ALL_LIBS))
$(file >$(TARGET_OUT)/combine.ar,create libshaderc_combined.a)
$(foreach lib,$(ALL_LIBS),$(file >>$(TARGET_OUT)/combine.ar,addlib $(lib)))
$(file >>$(TARGET_OUT)/combine.ar,save)
$(file >>$(TARGET_OUT)/combine.ar,end)
$(TARGET_OUT)/libshaderc_combined.a: $(addprefix $(TARGET_OUT)/, $(ALL_LIBS)) $(TARGET_OUT)/combine.ar
@echo "[$(TARGET_ARCH_ABI)] Combine: libshaderc_combined.a <= $(ALL_LIBS)"
@cd $(TARGET_OUT) && $(TARGET_AR) -M < combine.ar && cd $(ROOT_SHADERC_PATH)
@$(TARGET_STRIP) --strip-debug $(TARGET_OUT)/libshaderc_combined.a
$(call generate-file-dir,$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a)
$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a: \
$(TARGET_OUT)/libshaderc_combined.a
$(call host-cp,$(TARGET_OUT)/libshaderc_combined.a \
,$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a)
libshaderc_combined: libshaderc_headers \
$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a

101
3rdparty/shaderc/BUILD.gn vendored Normal file
View File

@@ -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_shaderc.h",
"libshaderc_util/include/libshaderc_util/message.h",
"libshaderc_util/include/libshaderc_util/mutex.h",
"libshaderc_util/include/libshaderc_util/resources.h",
"libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h",
"libshaderc_util/include/libshaderc_util/string_piece.h",
"libshaderc_util/include/libshaderc_util/universal_unistd.h",
"libshaderc_util/include/libshaderc_util/version_profile.h",
"libshaderc_util/src/compiler.cc",
"libshaderc_util/src/file_finder.cc",
"libshaderc_util/src/io_shaderc.cc",
"libshaderc_util/src/message.cc",
"libshaderc_util/src/resources.cc",
"libshaderc_util/src/shader_stage.cc",
"libshaderc_util/src/spirv_tools_wrapper.cc",
"libshaderc_util/src/version_profile.cc",
]
# Configure Glslang's interface to include HLSL-related entry points.
defines = [ "ENABLE_HLSL=1" ]
public_configs = [ ":shaderc_util_public" ]
deps = [
"${glslang_dir}:glslang_sources",
"${spirv_tools_dir}:spvtools",
]
if (build_with_chromium) {
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
}
}
config("shaderc_public") {
include_dirs = [ "libshaderc/include" ]
if (is_component_build) {
defines = [ "SHADERC_SHAREDLIB" ]
}
}
component("libshaderc") {
public_configs = [
":shaderc_public",
":shaderc_util_public",
]
defines = [ "SHADERC_IMPLEMENTATION" ]
sources = [
"libshaderc/include/shaderc/env.h",
"libshaderc/include/shaderc/shaderc.h",
"libshaderc/include/shaderc/shaderc.hpp",
"libshaderc/include/shaderc/status.h",
"libshaderc/include/shaderc/visibility.h",
"libshaderc/src/shaderc.cc",
"libshaderc/src/shaderc_private.h",
]
deps = [
":shaderc_util_sources",
"${spirv_tools_dir}:spvtools",
"${spirv_tools_dir}:spvtools_val",
"${glslang_dir}:glslang_sources",
]
if (build_with_chromium) {
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
}
}

378
3rdparty/shaderc/CHANGES vendored Normal file
View File

@@ -0,0 +1,378 @@
Revision history for Shaderc
v2024.1
- Update dependencies
- Propagate test/install options to Glslang
v2024.0 2024-03-09
- Update dependencies
- Utilities:
- Use Python3 explicitly in utility scripts
v2023.8 2024-01-03
- API: Expose rlaxed Vulkan rules from glslang
- Update to Glslang 14.0.0
- CMake:
- Comply with CMP0148: Use PythonInterp
- Use TARGET_OBJECTS to simplify creating the shaderc_shared library.
v2023.7 2023-10-12
- Update dependencies
- Finish converting build instructions and flags to always use C++17
- Add GitHub CI to test more flows
v2023.6 2023-08-09
- Update dependencies, including SPIRV-Tools v2023.4.rc2
v2023.5 2023-07-19
- Update dependencies
- Update to Android NDK r25c
- Update Android API level for test project (#1333)
- For testing, add a dependency on Abseil's C++ library
- Fix MSVC runtime library linking in CMake (#1339)
v2023.4 2023-05-24
- Refresh Glslang, SPIRV-Tools, SPIRV-Headers
- Android.mk:
- Require NDK 21d or later
- Update scripts for generating the shared library, which
should fix Windows
- glslc and APIs:
- Add options to control mesh shading limits
v2023.3 2023-03-17
- Shaderc now requires C++17
- Drop support for VS 2015
- Add glslc option -fpreserve-bindings
- Refresh Glslang, SPIRV-Tools
v2023.2 2023-01-18
- Update DEPS to pull in SPIRV-Tools bugfix #5049
v2023.1 2023-01-13
- General/Build
- Removed support for GCC-based code coverage builds
- Update minimum CMake to 3.17.2
- Fix C++20 compatibility: explicitly construct string_piece when
comparing to `char*`
v2022.4 2022-11-30
- Update to Glslang 11
- Update SPIRV-Tools, SPIRV-Headers dependencies
- Add Cmake BUNDLE DESTINATION option for target install
- The code coverage build is no longer being tested
v2022.3 2022-10-12
- #1264: Implement defaults for SPV_EXT_mesh_shader builtins
- Update SPIRV-Tools to v2022.4
v2022.2 2022-08-11
- Require CMake 3.14 or later
- Support 16bit types in HLSL, via glslc option -fhlsl-16bit-types
and associated library API methods. PR #1251
- Update glslc tests for newer Glslang debug output
- Update SPIRV-Tools v2022.3 plus one patch
- Update SPIRV-Headers
v2022.1 2022-02-03
- Update DEPS to include two fixes on top of SPIRV-Tools v2022.1:
- Validator handles Nontemporal image operand
- Optimizer handles RayQueryKHR type
v2022.0 2022-01-27
- Update to Glslang 11.8.0
v2021.4 2022-01-27
- Support Vulkan 1.3
- Support targeting SPIR-V 1.6, which is the default for Vulkan 1.3
- Updated copyright check: Excludes Glslang generated files when
building in source tree
- Fix Android.mk rules for building libshaderc_combined, to adapt to more
recent NDKs that have removed the GNU binutils.
v2021.3 2021-11-11
- Add build switch to disable copyright check
- Update DEPS:
- SPIRV-Tools v2021.4
- SPIRV-Headers GitHub master 2021-11-11
- Glslang GitHub master 2021-11-11
v2021.2 2021-08-25
- README: Mention Common Lisp bindings (external)
- Update DEPS:
- SPIRV-Tools v2021.3
- SPIRV-Headers master 2021-08-25
- Glslang GitHub master 2021-08-25
v2021.1 2021-06-21
- Disable --target-env=opengl_compat with an explicit error message
- It has been deprecated for a long time.
v2021.0 2021-04-21
- Refresh dependencies (in DEPS):
- SPIRV-Tools v2021.1
- SPIRV-Headers snapshot 2021-04-21
- Glslang 11.2.0, snapshot 2021-04-21
- Fixes:
#1174: Windows Bazel support: rename internal headers io.* to io_shaderc.*
v2020.5 2021-02-19
- Refresh dependencies (in DEPS):
- SPIRV-Tools v2020.7 + 1 patch
- Glslang 11.1.0
- Add option to skip building examples
- Fixes:
#1153: Improve file+line parsing from Glslang messages
v2020.4 2020-12-09
- Removed svpc
- Fixed issues with embedders getting duplicate symbols
- Converted C-style casts to static_cast
- Rolled ahead to fix/pickup Vulkan Raytracing support
v2020.3 2020-09-02
- General:
- Last release with spvc
- Cleaned up issues discovered by Infer
- spvc:
- Added support for Dawn using deprecated Options constructor
- Adding support for the additional fixed sample mask in MSL
v2020.2 2020-07-23
- General:
- Remove VS2013 support
- Support both posix and non-posix MinGW toolchains
- Support optionally building Tint tooling for WGSL
- Add -h option to glslc, spvc; same as --help
- Add source file license checker
- BUILD.gn improvements
- glslc, libshaderc:
- Update to Glslang generator 9
- Add interface to support 16bit types in HLSL
- Add glslc hidden experimental option -mfmt=wgsl; requires Tint
- spvc:
- Add minimum buffer size for Dawn reflection
v2020.1 2020-06-09
This is the last version that officially supports VS2013.
- General:
- Added warning signs about unsupported downloads (#1041)
- Added .NET bindings to README.md (#1060)
- Only add -fPIC if supported by the compiler. (#1061)
- glslc, libshaderc:
- Removed Singleton pattern around access to glslang (#1059)
- spvc:
- Added concept of comparison sampler to API (#1036)
- Added support for options.hlsl.nonwritable_uav_texture_as_srv (#1048)
- Support forcing storage buffers to be always declared as UAV. (#1076)
v2020.0 2020-03-06
- General:
- Getting spirv.hpp from SPIRV-Headers instead of not glslang (#992)
- Added clarification about status of artifacts in downloads.md (#1012)
- glslc, libshaderc:
- Added support for new Glslang profile enum, EProfileCount (#973)
- Updated user documentation for -S in glslc (#978)
- Add documentation for Vulkan 1.2 and SPIR-V 1.5 (#980)
- Removed NV_EXTENSIONS conditionals (#1003)
- Added support for generating WebGPU SPIR-V to libshaderc (#1021)
- Rolled in all DEPS for provisional SPIR-V extensions for raytracing
- spvc:
- Normalized API behaviour (#967)
- Added source_set target for libshaderc_spvc (#976)
- Added in support for spvc logging to the terminal (#981)
- Internal refactoring to reduce boiler plate in API implementations (#984)
- Added newline to logging messages to make them readable (#985)
- Added reflection support for Dawn:
- storage textures (#1001)
- storage texture format (#1005)
- texture dimension for storage textures (#1008)
- is storage texture declared as multisampled texture (#1011)
- Converted compile options to require explicit environments (#1019)
- Added knob to control force_zero_initialized_variables in SPIRV-Cross (#1028)
v2019.1 2020-01-22
- glslc, libshaderc:
- Add -fnan-clamp: Generate code for max and min builtins so that,
given a NaN operand, will return the other operand. Similarly, the
clamp builtin favours non-NaN operands, as if clamp was implemented
as the composition of max and min.
- Add -finvert-y
- Using SetBeforeHlslLegalization for more relaxed validation rules
- Added support for SPIR-V 1.5
- Add --emit-line-directive option
- Added support for Vulkan 1.2
- spvc:
- Add many options:
--flatten-multidimensional-arrays
--es
--no-es
--glsl-emit-push-constant-as-ubo
--msl-swizzle-texture-samples
--msl-platform=ios|macos
--msl-pad-fragment-output
--msl-capture-output
--msl-domain-lower-left
--msl-argument-buffers
--msl-discrete-descriptor-set=<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
- Support compilation options to optimize for size.
- Maintain compatibility with recent SPIRV-Tools and Glslang versions.
- Update examples.
- Build cleanups.
- Fixes issues:
#238: Fix invocation of python scripts during build
v2016.0 2016-07-07
- Adds v<year>.<index> versioning, with "-dev" suffix to indicate work in
progress. The intent is to summarize and report functionalities more easily
for incorporating into downstream projects.
- Summary of functionalities (See the README.md for more details):
- Provides libraries and command line tools for generating SPIR-V modules
- Supports GLSL source code or SPIR-V assembly as input
- Supports SPIR-V binary or assembly text as output
- Command line options follow GCC/Clang conventions
- Supports various semantics (OpenGL, OpenGL Compatible and Vulkan)
- Supports #include
- Supports user-defined macros
- Supports dependency information dumping

162
3rdparty/shaderc/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,162 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.17.2)
project(shaderc)
enable_testing()
if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
message(STATUS "No build type selected, default to Debug")
set(CMAKE_BUILD_TYPE "Debug")
endif()
message(STATUS "Shaderc: build type is \"${CMAKE_BUILD_TYPE}\".")
option(SHADERC_ENABLE_WGSL_OUTPUT "Enable WGSL output" OFF)
option(SHADERC_SKIP_INSTALL "Skip installation" ${SHADERC_SKIP_INSTALL})
if(NOT ${SHADERC_SKIP_INSTALL})
set(SHADERC_ENABLE_INSTALL ON)
endif()
option(SHADERC_SKIP_TESTS "Skip building tests" ${SHADERC_SKIP_TESTS})
if(NOT ${SHADERC_SKIP_TESTS})
set(SHADERC_ENABLE_TESTS ON)
endif()
if(${SHADERC_ENABLE_TESTS})
message(STATUS "Configuring Shaderc to build tests.")
else()
message(STATUS "Configuring Shaderc to avoid building tests.")
endif()
option(SHADERC_SKIP_EXAMPLES "Skip building examples" ${SHADERC_SKIP_EXAMPLES})
if(NOT ${SHADERC_SKIP_EXAMPLES})
set(SHADERC_ENABLE_EXAMPLES ON)
endif()
if(${SHADERC_ENABLE_EXAMPLES})
message(STATUS "Configuring Shaderc to build examples.")
else()
message(STATUS "Configuring Shaderc to avoid building examples.")
endif()
option(SHADERC_SKIP_COPYRIGHT_CHECK "Skip copyright check" ${SHADERC_SKIP_COPYRIGHT_CHECK})
if(NOT ${SHADERC_SKIP_COPYRIGHT_CHECK})
set(SHADERC_ENABLE_COPYRIGHT_CHECK ON)
endif()
if(${SHADERC_ENABLE_COPYRIGHT_CHECK})
message(STATUS "Configuring Shaderc to check copyrights.")
else()
message(STATUS "Configuring Shaderc to avoid checking copyrights.")
endif()
option(SHADERC_ENABLE_WERROR_COMPILE "Enable passing -Werror to compiler, if available" ON)
set (CMAKE_CXX_STANDARD 17)
include(GNUInstallDirs)
include(cmake/setup_build.cmake)
include(cmake/utils.cmake)
include(CheckCXXCompilerFlag)
set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS ${DISABLE_EXCEPTIONS} CACHE BOOL "Coupling SPIRV-Cross exception conversion to DISABLE_EXCEPTIONS" FORCE)
if(DISABLE_EXCEPTIONS)
# Need to set additional values here, since some of the wrapped code occurs in
# .h/.hpp files, so maybe included outside of the library.
add_definitions(-DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS)
endif()
# These flags are not supported on Windows and some older version of GCC
# that our bots use.
# Warning about implicit fallthrough in switch blocks
check_cxx_compiler_flag(-Wimplicit-fallthrough COMPILER_SUPPORTS_FALLTHROUGH_WARNING)
if (COMPILER_SUPPORTS_FALLTHROUGH_WARNING)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wimplicit-fallthrough")
endif()
# Warning about extra semi-colons
check_cxx_compiler_flag(-Wextra-semi COMPILER_SUPPORTS_EXTRA_SEMI_WARNING)
if (COMPILER_SUPPORTS_EXTRA_SEMI_WARNING)
add_compile_options("-Wextra-semi")
endif()
find_package(Python COMPONENTS Interpreter REQUIRED)
if (SHADERC_ENABLE_COPYRIGHT_CHECK)
add_custom_target(check-copyright ALL
${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/utils/add_copyright.py
--check
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Check copyright")
endif()
add_custom_target(add-copyright
${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/utils/add_copyright.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Add copyright")
if(MSVC)
option(SHADERC_ENABLE_SHARED_CRT
"Use the shared CRT instead of the static CRT"
OFF)
if (SHADERC_ENABLE_SHARED_CRT)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
else()
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
endif(MSVC)
if(NOT WIN32)
add_definitions("-fvisibility=hidden")
endif()
# Configure subdirectories.
# We depend on these for later projects, so they should come first.
add_subdirectory(third_party)
add_subdirectory(libshaderc_util)
add_subdirectory(libshaderc)
if(${SHADERC_ENABLE_EXAMPLES})
add_subdirectory(examples)
endif()
add_custom_target(build-version
${Python_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/utils/update_build_version.py
${shaderc_SOURCE_DIR} ${spirv-tools_SOURCE_DIR} ${glslang_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/build-version.inc
COMMENT "Update build-version.inc in the Shaderc build directory (if necessary).")
function(define_pkg_config_file NAME LIBS)
add_custom_target(${NAME}-pkg-config ALL
COMMAND ${CMAKE_COMMAND}
-DCHANGES_FILE=${CMAKE_CURRENT_SOURCE_DIR}/CHANGES
-DTEMPLATE_FILE=${CMAKE_CURRENT_SOURCE_DIR}/cmake/${NAME}.pc.in
-DOUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/${NAME}.pc
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR}
-DCMAKE_INSTALL_INCLUDEDIR=${CMAKE_INSTALL_INCLUDEDIR}
-DLIBS=${LIBS}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/write_pkg_config.cmake
DEPENDS "CHANGES" "cmake/${NAME}.pc.in" "cmake/write_pkg_config.cmake")
if (SHADERC_ENABLE_INSTALL)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/${NAME}.pc
DESTINATION
${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif()
endfunction()
define_pkg_config_file(shaderc -lshaderc_shared)

25
3rdparty/shaderc/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,25 @@
Want to contribute? Great! First, read this page (including the small print at
the end). Then, have a look at [`DEVELOPMENT.howto.md`](DEVELOPMENT.howto.md),
which contains useful info to guide you along the way.
## Before you contribute
Before we can use your code, you must sign the
[Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1)
(CLA), which you can do online. The CLA is necessary mainly because you own the
copyright to your changes, even after your contribution becomes part of our
codebase, so we need your permission to use and distribute your code. We also
need to be sure of various other things -- for instance that you'll tell us if
you know that your code infringes on other people's patents. You don't have to
sign the CLA until after you've submitted your code for review and a member has
approved it, but you must do it before we can put your code into our codebase.
Before you start working on a larger contribution, you should get in touch with
us first through the issue tracker with your idea so that we can help out and
possibly guide you. Coordinating up front makes it much easier to avoid
frustration later on.
## The small print
Contributions made by corporations are covered by a different agreement than
the one above, the Software Grant and Corporate Contributor License Agreement.

24
3rdparty/shaderc/CONTRIBUTORS vendored Normal file
View File

@@ -0,0 +1,24 @@
# People who have agreed to one of the CLAs and can contribute patches.
# The AUTHORS file lists the copyright holders; this file
# lists people. For example, Google employees are listed here
# but not in AUTHORS, because Google holds the copyright.
#
# https://developers.google.com/open-source/cla/individual
# https://developers.google.com/open-source/cla/corporate
#
# Names should be added to this file as:
# Name <email address>
Lei Zhang <antiagainst@google.com>
David Neto <dneto@google.com>
Andrew Woloszyn <awoloszyn@google.com>
Stefanus Du Toit <sdt@google.com>
Dejan Mircevski <deki@google.com>
Mark Adams <marka@nvidia.com>
Jason Ekstrand <jason.ekstrand@intel.com>
Damien Mabin <dmabin@google.com>
Qining Lu <qining@google.com>
Jakob Vogel <JakobpunktVogel@gmail.com>
David Yen <dyen@google.com>
Adam Chainz <adam@adamj.eu>
Robin Quint <robin.quint@outlook.com>

38
3rdparty/shaderc/DEPS vendored Normal file
View File

@@ -0,0 +1,38 @@
use_relative_paths = True
vars = {
'abseil_git': 'https://github.com/abseil',
'google_git': 'https://github.com/google',
'khronos_git': 'https://github.com/KhronosGroup',
'abseil_revision': '5be22f98733c674d532598454ae729253bc53e82',
'effcee_revision' : 'aea1f4d62ca9ee2f44b5393e98e175e200a22e8e',
'glslang_revision': '142052fa30f9eca191aa9dcf65359fcaed09eeec',
'googletest_revision': 'e47544ad31cb3ceecd04cc13e8fe556f8df9fe0b',
're2_revision': 'c9cba76063cf4235c1a15dd14a24a4ef8d623761',
'spirv_headers_revision': '5e3ad389ee56fca27c9705d093ae5387ce404df4',
'spirv_tools_revision': 'dd4b663e13c07fea4fbb3f70c1c91c86731099f7',
}
deps = {
'third_party/abseil_cpp':
Var('abseil_git') + '/abseil-cpp.git@' + Var('abseil_revision'),
'third_party/effcee': Var('google_git') + '/effcee.git@' +
Var('effcee_revision'),
'third_party/googletest': Var('google_git') + '/googletest.git@' +
Var('googletest_revision'),
'third_party/glslang': Var('khronos_git') + '/glslang.git@' +
Var('glslang_revision'),
'third_party/re2': Var('google_git') + '/re2.git@' +
Var('re2_revision'),
'third_party/spirv-headers': Var('khronos_git') + '/SPIRV-Headers.git@' +
Var('spirv_headers_revision'),
'third_party/spirv-tools': Var('khronos_git') + '/SPIRV-Tools.git@' +
Var('spirv_tools_revision'),
}

52
3rdparty/shaderc/DEVELOPMENT.howto.md vendored Normal file
View File

@@ -0,0 +1,52 @@
Thank you for considering Shaderc development! Please make sure you review
[`CONTRIBUTING.md`](CONTRIBUTING.md) for important preliminary info.
## Building
Instructions for first-time building can be found in [`README.md`](README.md).
Incremental build after a source change can be done using `ninja` (or
`cmake --build`) and `ctest` exactly as in the first-time procedure.
## Code reviews
(Terminology: we consider everyone with write access to our GitHub repo a
project _member_.)
All submissions, including submissions by project members, require review. We
use GitHub pull requests to facilitate the review process. A submission may be
accepted by any project member (other than the submitter), who will then squash
the changes into a single commit and cherry-pick them into the repository.
Before accepting, there may be some review feedback prompting changes in the
submission. You should expect reviewers to strictly insist on the
[commenting](https://google.github.io/styleguide/cppguide.html#Comments)
guidelines -- in particular, every file, class, method, data member, and global
will require a comment. Reviewers will also expect to see test coverage for
every code change. _How much_ coverage will be a judgment call on a
case-by-case basis, balancing the required effort against the incremental
benefit. Coverage will be expected. As a matter of development philosophy,
we will strive to engineer the code to make writing tests easy.
## Coding style
For our C++ files, we use the
[Google C++ style guide](https://google.github.io/styleguide/cppguide.html).
(Conveniently, the formatting rules it specifies can be achieved using
`clang-format -style=google`.)
For our Python files, we use the
[Google Python style guide](https://google.github.io/styleguide/pyguide.html).
## Supported platforms
We expect Shaderc to always build and test successfully on the platforms listed
below. Please keep that in mind when offering contributions. This list will
likely grow over time.
| Platform | Build Status |
|:--------:|:------------:|
| Android (ARMv7) | Not Automated |
| Linux (x86_64) | [![Linux Build Status](https://travis-ci.org/google/shaderc.svg)](https://travis-ci.org/google/shaderc "Linux Build Status") |
| Mac OS X | [![Mac Build Status](https://travis-ci.org/google/shaderc.svg)](https://travis-ci.org/google/shaderc "Mac Build Status") |
| Windows (x86_64) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/g6c372blna7vnk1l?svg=true)](https://ci.appveyor.com/project/dneto0/shaderc "Windows Build Status") |

50
3rdparty/shaderc/Dockerfile vendored Normal file
View File

@@ -0,0 +1,50 @@
# Copyright 2016 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
FROM alpine
MAINTAINER Google Shaderc Team
RUN apk add --update \
build-base \
cmake \
git \
ninja \
python3 \
py-pip \
&& rm -rf /var/cache/apk/*
WORKDIR /root
RUN git clone https://github.com/google/shaderc
WORKDIR shaderc
RUN ./utils/git-sync-deps
WORKDIR build
RUN cmake -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/local \
.. \
&& ninja install
WORKDIR /root
RUN rm -rf shaderc
RUN adduser -s /bin/sh -D shaderc
USER shaderc
VOLUME /code
WORKDIR /code
CMD ["/bin/sh"]

201
3rdparty/shaderc/LICENSE vendored Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

244
3rdparty/shaderc/README.md vendored Normal file
View File

@@ -0,0 +1,244 @@
# Shaderc
A collection of tools, libraries and tests for shader compilation.
At the moment it includes:
- [`glslc`](glslc), a command line compiler for GLSL/HLSL to SPIR-V, and
- [`libshaderc`](libshaderc), a library API for accessing `glslc` functionality.
**Note:** The fact that that `libshaderc` is not named `libshaderc_glslc` is a
quirk of history, and a known inconsistency. Changing it would require a
significant amount of renaming and breaking of downstream projects, so it is
being left as is.
`glslc` wraps around core functionality in [glslang][khr-glslang]
and [SPIRV-Tools][spirv-tools]. `glslc` and its library aims to
to provide:
* a command line compiler with GCC- and Clang-like usage, for better
integration with build systems
* an API where functionality can be added without breaking existing clients
* an API supporting standard concurrency patterns across multiple
operating systems
* increased functionality such as file `#include` support
## Downloads
**Note: These binaries are just the artifacts of the builders and have not
undergone any QA, thus they should be considered unsupported.**
<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 has maintained backward compatibility for quite some time, and we
don't anticipate any breaking changes.
Ongoing enhancements are described in the [CHANGES](CHANGES) file.
Shaderc has been shipping in the
[Android NDK](https://developer.android.com/ndk/index.html) since version r12b.
(The NDK build uses sources from https://android.googlesource.com/platform/external/shaderc/.
Those repos are downstream from GitHub.)
We currently require r25c.
For licensing terms, please see the [`LICENSE`](LICENSE) file. If interested in
contributing to this project, please see [`CONTRIBUTING.md`](CONTRIBUTING.md).
This is not an official Google product (experimental or otherwise), it is just
code that happens to be owned by Google. That may change if Shaderc gains
contributions from others. See the [`CONTRIBUTING.md`](CONTRIBUTING.md) file
for more information. See also the [`AUTHORS`](AUTHORS) and
[`CONTRIBUTORS`](CONTRIBUTORS) files.
## File organization
- `android_test/` : a small Android application to verify compilation
- `cmake/`: CMake utility functions and configuration for Shaderc
- `examples/`: Example programs
- `glslc/`: an executable to compile GLSL to SPIR-V
- `libshaderc/`: a library for compiling shader strings into SPIR-V
- `libshaderc_util/`: a utility library used by multiple shaderc components
- `third_party/`: third party open source packages; see below
- `utils/`: utility scripts for Shaderc
Shaderc depends on glslang, the Khronos reference compiler for GLSL.
Shaderc depends on [SPIRV-Tools][spirv-tools] for assembling, disassembling,
and transforming SPIR-V binaries.
For testing, Shaderc depends on:
| Library | URL | Description |
| -- | -- | -- |
| Googletest | https://github.com/google/googletest | Testing framework |
| Effcee | https://github.com/google/effcee | Stateful pattern matcher inspired by LLVM's FileCheck |
| RE2 | https://github.com/google/re2 | Regular expression matcher |
| Abseil | https://github.com/abseil/abseil-cpp | Common basic utilities in C++ |
In the following sections, `$SOURCE_DIR` is the directory you intend to clone
Shaderc into.
## Getting and building Shaderc
**If you only want prebuilt executables or libraries, see the
[Downloads](#downloads) section.**
The rest of this section describes how to build Shaderc from sources.
Note: Shaderc assumes Glslang supports HLSL compilation. The instructions
below assume you're building Glslang from sources, and in a subtree
of `shaderc/third_party`. In that scenario, Glslang's HLSL support
is automatically enabled. Shaderc also can be built using a Glslang
from outside the `shaderc/third_party` tree. In that case you must
ensure that that external Glslang is built with HLSL functionality.
See Glslang's `ENABLE_HLSL` CMake setting.)
1) Check out the source code:
```sh
git clone https://github.com/google/shaderc $SOURCE_DIR
cd $SOURCE_DIR
./utils/git-sync-deps
```
**Note:** The [known-good](https://github.com/google/shaderc/tree/known-good)
branch of the repository contains a
[known_good.json](https://github.com/google/shaderc/blob/known-good/known_good.json)
file describing a set of repo URLs and specific commits that have been
tested together. This information is updated periodically, and typically
matches the latest update of these sources in the development branch
of the Android NDK.
The `known-good` branch also contains a
[update_shaderc.py](https://github.com/google/shaderc/blob/known-good/update_shaderc_sources.py)
script that will read the JSON file and checkout those specific commits for you.
2) Ensure you have the requisite tools -- see the tools subsection below.
3) Decide where to place the build output. In the following steps, we'll call it
`$BUILD_DIR`. Any new directory should work. We recommend building outside
the source tree, but it is also common to build in a (new) subdirectory of
`$SOURCE_DIR`, such as `$SOURCE_DIR/build`.
4a) Build (and test) with Ninja on Linux or Windows:
```sh
cd $BUILD_DIR
cmake -GNinja -DCMAKE_BUILD_TYPE={Debug|Release|RelWithDebInfo} $SOURCE_DIR
ninja
ctest # optional
```
4b) Or build (and test) with MSVC on Windows:
```sh
cd $BUILD_DIR
cmake $SOURCE_DIR
cmake --build . --config {Release|Debug|MinSizeRel|RelWithDebInfo}
ctest -C {Release|Debug|MinSizeRel|RelWithDebInfo}
```
4c) Or build with MinGW on Linux for Windows:
```sh
cd $BUILD_DIR
cmake -GNinja -DCMAKE_BUILD_TYPE={Debug|Release|RelWithDebInfo} $SOURCE_DIR \
-DCMAKE_TOOLCHAIN_FILE=$SOURCE_DIR/cmake/linux-mingw-toolchain.cmake
ninja
```
After a successful build, you should have a `glslc` executable somewhere under
the `$BUILD_DIR/glslc/` directory, as well as a `libshaderc` library somewhere
under the `$BUILD_DIR/libshaderc/` directory.
The default behavior on MSVC is to link with the static CRT. If you would like
to change this behavior `-DSHADERC_ENABLE_SHARED_CRT` may be passed on the
cmake configure line.
See [the libshaderc README](libshaderc/README.md) for more on using the library
API in your project.
### Tools you'll need
For building, testing, and profiling Shaderc, the following tools should be
installed regardless of your OS:
- A C++17 compiler. Recent versions of Clang, GCC, and MSVC work.
- [CMake](http://www.cmake.org/) 3.14 or later: for generating compilation targets.
- Shaderc is tested with cmake 3.17.2
- [Python 3](http://www.python.org/): for utility scripts and running the test suite.
On Linux, if cross compiling to Windows:
- [`mingw`](http://www.mingw.org): A GCC-based cross compiler targeting Windows
so that generated executables use the Microsoft C runtime libraries.
The MinGW compiler must support C++17.
On Windows, the following tools should be installed and available on your path:
- Visual Studio 2017 or later. Previous versions of Visual Studio may work but
are untested and unsupported.
- Git - including the associated tools, Bash, `diff`.
Optionally, the following tools may be installed on any OS:
- [`asciidoctor`](http://asciidoctor.org/): for generating documentation.
- [`pygments.rb`](https://rubygems.org/gems/pygments.rb) required by
`asciidoctor` for syntax highlighting.
### Building and running Shaderc using Docker
Please make sure you have the Docker engine
[installed](https://docs.docker.com/engine/installation/) on your machine.
To create a Docker image containing Shaderc command line tools, issue the
following command in `${SOURCE_DIR}`: `docker build -t <IMAGE-NAME> .`.
The created image will have all the command line tools installed at
`/usr/local` internally, and a data volume mounted at `/code`.
Assume `<IMAGE-NAME>` is `shaderc/shaderc` from now on.
To invoke a tool from the above created image in a Docker container:
```bash
docker run shaderc/shaderc glslc --version
```
Alternatively, you can mount a host directory (e.g., `example`) containing
the shaders you want to manipulate and run different kinds of tools via
an interactive shell in the container:
```bash
$ docker run -i -t -v `pwd`/example:/code shaderc/shaderc
/code $ ls
test.vert
/code $ glslc -c -o - test.vert | spirv-dis
```
## Bug tracking
We track bugs using GitHub -- click on the "Issues" button on
[the project's GitHub page](https://github.com/google/shaderc).
## Bindings
Bindings are maintained by third parties, may contain content
offered under a different license, and may reference or contain
older versions of Shaderc and its dependencies.
* **Python:** [pyshaderc][pyshaderc]
* **Rust:** [shaderc-rs][shaderc-rs]
* **Go:** [gshaderc][gshaderc]
* **.NET:** [shaderc.net][shadercdotnet]
* **Common Lisp:** [shadercl][shaderccommonlisp]
[khr-glslang]: https://github.com/KhronosGroup/glslang
[spirv-tools]: https://github.com/KhronosGroup/SPIRV-Tools
[spirv-cross]: https://github.com/KhronosGroup/SPIRV-Cross
[pyshaderc]: https://github.com/realitix/pyshaderc
[shaderc-rs]: https://github.com/google/shaderc-rs
[appveyor]: https://ci.appveyor.com/project/dneto0/shaderc
[dawn]: https://dawn.googlesource.com/dawn
[gshaderc]: https://github.com/celer/gshaderc
[shadercdotnet]: https://github.com/jpbruyere/shaderc.net
[shaderccommonlisp]: https://github.com/JolifantoBambla/shadercl

View File

@@ -0,0 +1,26 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cc .cpp .cxx
LOCAL_SRC_FILES:=test.cpp
LOCAL_MODULE:=shaderc_test
LOCAL_LDLIBS:=-landroid
LOCAL_STATIC_LIBRARIES=shaderc android_native_app_glue
include $(BUILD_SHARED_LIBRARY)
include $(LOCAL_PATH)/../Android.mk
$(call import-module,android/native_app_glue)

View File

@@ -0,0 +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

View File

@@ -0,0 +1,20 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
APP_ABI := all
APP_BUILD_SCRIPT := Android.mk
APP_STL := c++_static
# Vulkan was added at API level 24.
# Android NDK 26 will drop support for APIs before 21.
APP_PLATFORM := android-24

23
3rdparty/shaderc/android_test/test.cpp vendored Normal file
View File

@@ -0,0 +1,23 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "shaderc/shaderc.hpp"
#include <android_native_app_glue.h>
void android_main(struct android_app* state) {
shaderc::Compiler compiler;
const char* test_program = "void main() {}";
compiler.CompileGlslToSpv(test_program, strlen(test_program),
shaderc_glsl_vertex_shader, "shader");
}

View File

@@ -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

View File

@@ -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"

View File

@@ -0,0 +1,39 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
SET(CMAKE_SYSTEM_NAME Windows)
set(MINGW_COMPILER_PREFIX "i686-w64-mingw32" CACHE STRING
"What compiler prefix to use for mingw")
set(MINGW_SYSROOT "/usr/${MINGW_COMPILER_PREFIX}" CACHE STRING
"What sysroot to use for mingw")
# Which compilers to use for C and C++
find_program(CMAKE_RC_COMPILER NAMES ${MINGW_COMPILER_PREFIX}-windres)
find_program(CMAKE_C_COMPILER NAMES
${MINGW_COMPILER_PREFIX}-gcc-posix
${MINGW_COMPILER_PREFIX}-gcc)
find_program(CMAKE_CXX_COMPILER NAMES
${MINGW_COMPILER_PREFIX}-g++-posix
${MINGW_COMPILER_PREFIX}-g++)
SET(CMAKE_FIND_ROOT_PATH ${MINGW_SYSROOT})
# Adjust the default behaviour of the FIND_XXX() commands:
# Search headers and libraries in the target environment; search
# programs in the host environment.
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

@@ -0,0 +1,67 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if(NOT COMMAND find_host_package)
macro(find_host_package)
find_package(${ARGN})
endmacro()
endif()
if(NOT COMMAND find_host_program)
macro(find_host_program)
find_program(${ARGN})
endmacro()
endif()
# Find asciidoctor; see shaderc_add_asciidoc() from utils.cmake for
# adding documents.
find_program(ASCIIDOCTOR_EXE NAMES asciidoctor)
if (NOT ASCIIDOCTOR_EXE)
message(STATUS "asciidoctor was not found - no documentation will be"
" generated")
endif()
# On Windows, CMake by default compiles with the shared CRT.
# Ensure that gmock compiles the same, otherwise failures will occur.
if(WIN32)
# TODO(awoloszyn): Once we support selecting CRT versions,
# make sure this matches correctly.
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
endif(WIN32)
if (ANDROID)
# For android let's preemptively find the correct packages so that
# child projects (glslang, googletest) do not fail to find them.
# Tests in glslc and SPIRV-Tools tests require Python 3, or a Python 2
# with the "future" package. Require Python 3 because we can't force
# developers to manually install the "future" package.
find_host_package(PythonInterp 3 REQUIRED)
find_host_package(BISON)
else()
find_package(Python COMPONENTS Interpreter REQUIRED)
endif()
option(DISABLE_RTTI "Disable RTTI in builds")
if(DISABLE_RTTI)
if(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
endif(UNIX)
endif(DISABLE_RTTI)
option(DISABLE_EXCEPTIONS "Disables exceptions in builds")
if(DISABLE_EXCEPTIONS)
if(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
endif(UNIX)
endif(DISABLE_EXCEPTIONS)

12
3rdparty/shaderc/cmake/shaderc.pc.in vendored Normal file
View File

@@ -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}

View File

@@ -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}

View File

@@ -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}

182
3rdparty/shaderc/cmake/utils.cmake vendored Normal file
View File

@@ -0,0 +1,182 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# utility functions
function (shaderc_use_gmock TARGET)
target_include_directories(${TARGET} PRIVATE
${gmock_SOURCE_DIR}/include
${gtest_SOURCE_DIR}/include)
target_link_libraries(${TARGET} PRIVATE gmock gtest_main)
endfunction(shaderc_use_gmock)
function(shaderc_default_c_compile_options TARGET)
if (NOT "${MSVC}")
if (SHADERC_ENABLE_WERROR_COMPILE)
target_compile_options(${TARGET} PRIVATE -Wall -Werror -fvisibility=hidden)
else()
target_compile_options(${TARGET} PRIVATE -Wall -fvisibility=hidden)
endif()
check_cxx_compiler_flag(-fPIC COMPILER_SUPPORTS_PIC)
if (NOT "${MINGW}" AND COMPILER_SUPPORTS_PIC)
target_compile_options(${TARGET} PRIVATE -fPIC)
endif()
if (ENABLE_CODE_COVERAGE)
# The --coverage option is a synonym for -fprofile-arcs -ftest-coverage
# when compiling.
target_compile_options(${TARGET} PRIVATE -g -O0 --coverage)
# The --coverage option is a synonym for -lgcov when linking for gcc.
# For clang, it links in a different library, libclang_rt.profile, which
# requires clang to be built with compiler-rt.
target_link_libraries(${TARGET} PRIVATE --coverage)
endif()
if (NOT SHADERC_ENABLE_SHARED_CRT)
if (WIN32)
# For MinGW cross compile, statically link to the libgcc runtime.
# But it still depends on MSVCRT.dll.
set_target_properties(${TARGET} PROPERTIES
LINK_FLAGS "-static -static-libgcc")
endif(WIN32)
endif(NOT SHADERC_ENABLE_SHARED_CRT)
else()
# disable warning C4800: 'int' : forcing value to bool 'true' or 'false'
# (performance warning)
target_compile_options(${TARGET} PRIVATE /wd4800)
endif()
endfunction(shaderc_default_c_compile_options)
function(shaderc_default_compile_options TARGET)
shaderc_default_c_compile_options(${TARGET})
if (NOT "${MSVC}")
if (NOT SHADERC_ENABLE_SHARED_CRT)
if (WIN32)
# For MinGW cross compile, statically link to the C++ runtime.
# But it still depends on MSVCRT.dll.
set_target_properties(${TARGET} PROPERTIES
LINK_FLAGS "-static -static-libgcc -static-libstdc++")
endif(WIN32)
endif(NOT SHADERC_ENABLE_SHARED_CRT)
endif()
endfunction(shaderc_default_compile_options)
# Build an asciidoc file; additional arguments past the base filename specify
# additional dependencies for the file.
function(shaderc_add_asciidoc TARGET FILE)
if (ASCIIDOCTOR_EXE)
set(DEST ${CMAKE_CURRENT_BINARY_DIR}/${FILE}.html)
add_custom_command(
COMMAND ${ASCIIDOCTOR_EXE} -a toc -o ${DEST}
${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.asciidoc
DEPENDS ${FILE}.asciidoc ${ARGN}
OUTPUT ${DEST})
# Create the target, but the default build target does not depend on it.
# Some Asciidoctor installations are mysteriously broken, and it's hard
# to detect those cases. Generating HTML is not critical by default.
add_custom_target(${TARGET} DEPENDS ${DEST})
endif(ASCIIDOCTOR_EXE)
endfunction()
# Adds a set of tests.
# This function accepts the following parameters:
# TEST_PREFIX: a prefix for each test target name
# TEST_NAMES: a list of test names where each TEST_NAME has a corresponding
# file residing at src/${TEST_NAME}_test.cc
# LINK_LIBS: (optional) a list of libraries to be linked to the test target
# INCLUDE_DIRS: (optional) a list of include directories to be searched
# for header files.
function(shaderc_add_tests)
if(${SHADERC_ENABLE_TESTS})
cmake_parse_arguments(PARSED_ARGS
""
"TEST_PREFIX"
"TEST_NAMES;LINK_LIBS;INCLUDE_DIRS"
${ARGN})
if (NOT PARSED_ARGS_TEST_NAMES)
message(FATAL_ERROR "Tests must have a target")
endif()
if (NOT PARSED_ARGS_TEST_PREFIX)
message(FATAL_ERROR "Tests must have a prefix")
endif()
foreach(TARGET ${PARSED_ARGS_TEST_NAMES})
set(TEST_NAME ${PARSED_ARGS_TEST_PREFIX}_${TARGET}_test)
add_executable(${TEST_NAME} src/${TARGET}_test.cc)
shaderc_default_compile_options(${TEST_NAME})
if (MINGW)
target_compile_options(${TEST_NAME} PRIVATE -DSHADERC_DISABLE_THREADED_TESTS)
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
# Disable this warning, which is useless in test code.
# Fixes https://github.com/google/shaderc/issues/334
target_compile_options(${TEST_NAME} PRIVATE -Wno-noexcept-type)
endif()
if (PARSED_ARGS_LINK_LIBS)
target_link_libraries(${TEST_NAME} PRIVATE
${PARSED_ARGS_LINK_LIBS})
endif()
if (PARSED_ARGS_INCLUDE_DIRS)
target_include_directories(${TEST_NAME} PRIVATE
${PARSED_ARGS_INCLUDE_DIRS})
endif()
shaderc_use_gmock(${TEST_NAME})
add_test(
NAME ${PARSED_ARGS_TEST_PREFIX}_${TARGET}
COMMAND ${TEST_NAME})
endforeach()
endif(${SHADERC_ENABLE_TESTS})
endfunction(shaderc_add_tests)
# Finds all transitive static library dependencies of a given target
# including possibly the target itself.
# This will skip libraries that were statically linked that were not
# built by CMake, for example -lpthread.
macro(shaderc_get_transitive_libs target out_list)
if (TARGET ${target})
get_target_property(libtype ${target} TYPE)
# If this target is a static library, get anything it depends on.
if ("${libtype}" STREQUAL "STATIC_LIBRARY")
# Get the original library if this is an alias library. This is
# to avoid putting both the original library and the alias library
# in the list (given we are deduplicating according to target names).
# Otherwise, we may pack the same library twice, resulting in
# duplicated symbols.
get_target_property(aliased_target ${target} ALIASED_TARGET)
if (aliased_target)
list(INSERT ${out_list} 0 "${aliased_target}")
else()
list(INSERT ${out_list} 0 "${target}")
endif()
get_target_property(libs ${target} LINK_LIBRARIES)
if (libs)
foreach(lib ${libs})
shaderc_get_transitive_libs(${lib} ${out_list})
endforeach()
endif()
endif()
endif()
# If we know the location (i.e. if it was made with CMake) then we
# can add it to our list.
LIST(REMOVE_DUPLICATES ${out_list})
endmacro()
# Combines the static library "target" with all of its transitive static
# library dependencies into a single static library "new_target".
function(shaderc_combine_static_lib new_target target)
set(all_libs "")
shaderc_get_transitive_libs(${target} all_libs)
add_library(${new_target} STATIC)
foreach(lib IN LISTS all_libs)
target_sources(${new_target} PRIVATE $<TARGET_OBJECTS:${lib}>)
endforeach()
endfunction()

View File

@@ -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)

17
3rdparty/shaderc/downloads.md vendored Normal file
View File

@@ -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 2019](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2019_release.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_linux_clang_release.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_macos_clang_release.html) |
| [MSVC 2017](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2017_release.html) | [gcc](https://storage.googleapis.com/shaderc/badges/build_link_linux_gcc_release.html) | |
## Debug
| Windows | Linux | MacOS |
| --- | --- | --- |
| [MSVC 2019](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2019_debug.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_linux_clang_debug.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_macos_clang_debug.html) |
| [MSVC 2017](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2017_debug.html) | [gcc](https://storage.googleapis.com/shaderc/badges/build_link_linux_gcc_debug.html) | |

View File

@@ -0,0 +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)

View File

@@ -0,0 +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)

View File

@@ -0,0 +1,171 @@
// Copyright 2016 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// The program demonstrates basic shader compilation using the Shaderc C++ API.
// For clarity, each method is deliberately self-contained.
//
// Techniques demonstrated:
// - Preprocessing GLSL source text
// - Compiling a shader to SPIR-V assembly text
// - Compliing a shader to a SPIR-V binary module
// - Performing optimization with compilation
// - Setting basic options: setting a preprocessor symbol.
// - Checking compilation status and extracting an error message.
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <shaderc/shaderc.hpp>
// Returns GLSL shader source text after preprocessing.
std::string preprocess_shader(const std::string& source_name,
shaderc_shader_kind kind,
const std::string& source) {
shaderc::Compiler compiler;
shaderc::CompileOptions options;
// Like -DMY_DEFINE=1
options.AddMacroDefinition("MY_DEFINE", "1");
shaderc::PreprocessedSourceCompilationResult result =
compiler.PreprocessGlsl(source, kind, source_name.c_str(), options);
if (result.GetCompilationStatus() != shaderc_compilation_status_success) {
std::cerr << result.GetErrorMessage();
return "";
}
return {result.cbegin(), result.cend()};
}
// Compiles a shader to SPIR-V assembly. Returns the assembly text
// as a string.
std::string compile_file_to_assembly(const std::string& source_name,
shaderc_shader_kind kind,
const std::string& source,
bool optimize = false) {
shaderc::Compiler compiler;
shaderc::CompileOptions options;
// Like -DMY_DEFINE=1
options.AddMacroDefinition("MY_DEFINE", "1");
if (optimize) options.SetOptimizationLevel(shaderc_optimization_level_size);
shaderc::AssemblyCompilationResult result = compiler.CompileGlslToSpvAssembly(
source, kind, source_name.c_str(), options);
if (result.GetCompilationStatus() != shaderc_compilation_status_success) {
std::cerr << result.GetErrorMessage();
return "";
}
return {result.cbegin(), result.cend()};
}
// Compiles a shader to a SPIR-V binary. Returns the binary as
// a vector of 32-bit words.
std::vector<uint32_t> compile_file(const std::string& source_name,
shaderc_shader_kind kind,
const std::string& source,
bool optimize = false) {
shaderc::Compiler compiler;
shaderc::CompileOptions options;
// Like -DMY_DEFINE=1
options.AddMacroDefinition("MY_DEFINE", "1");
if (optimize) options.SetOptimizationLevel(shaderc_optimization_level_size);
shaderc::SpvCompilationResult module =
compiler.CompileGlslToSpv(source, kind, source_name.c_str(), options);
if (module.GetCompilationStatus() != shaderc_compilation_status_success) {
std::cerr << module.GetErrorMessage();
return std::vector<uint32_t>();
}
return {module.cbegin(), module.cend()};
}
int main() {
const char kShaderSource[] =
"#version 310 es\n"
"void main() { int x = MY_DEFINE; }\n";
{ // Preprocessing
auto preprocessed = preprocess_shader(
"shader_src", shaderc_glsl_vertex_shader, kShaderSource);
std::cout << "Compiled a vertex shader resulting in preprocessed text:"
<< std::endl
<< preprocessed << std::endl;
}
{ // Compiling
auto assembly = compile_file_to_assembly(
"shader_src", shaderc_glsl_vertex_shader, kShaderSource);
std::cout << "SPIR-V assembly:" << std::endl << assembly << std::endl;
auto spirv =
compile_file("shader_src", shaderc_glsl_vertex_shader, kShaderSource);
std::cout << "Compiled to a binary module with " << spirv.size()
<< " words." << std::endl;
}
{ // Compiling with optimizing
auto assembly =
compile_file_to_assembly("shader_src", shaderc_glsl_vertex_shader,
kShaderSource, /* optimize = */ true);
std::cout << "Optimized SPIR-V assembly:" << std::endl
<< assembly << std::endl;
auto spirv = compile_file("shader_src", shaderc_glsl_vertex_shader,
kShaderSource, /* optimize = */ true);
std::cout << "Compiled to an optimized binary module with " << spirv.size()
<< " words." << std::endl;
}
{ // Error case
const char kBadShaderSource[] =
"#version 310 es\nint main() { int main_should_be_void; }\n";
std::cout << std::endl << "Compiling a bad shader:" << std::endl;
compile_file("bad_src", shaderc_glsl_vertex_shader, kBadShaderSource);
}
{ // Compile using the C API.
std::cout << "\n\nCompiling with the C API" << std::endl;
// The first example has a compilation problem. The second does not.
const char source[2][80] = {"void main() {}", "#version 450\nvoid main() {}"};
shaderc_compiler_t compiler = shaderc_compiler_initialize();
for (int i = 0; i < 2; ++i) {
std::cout << " Source is:\n---\n" << source[i] << "\n---\n";
shaderc_compilation_result_t result = shaderc_compile_into_spv(
compiler, source[i], std::strlen(source[i]), shaderc_glsl_vertex_shader,
"main.vert", "main", nullptr);
auto status = shaderc_result_get_compilation_status(result);
std::cout << " Result code " << int(status) << std::endl;
if (status != shaderc_compilation_status_success) {
std::cout << "error: " << shaderc_result_get_error_message(result)
<< std::endl;
}
shaderc_result_release(result);
}
shaderc_compiler_release(compiler);
}
return 0;
}

74
3rdparty/shaderc/glslc/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,74 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
find_package(Threads)
add_library(glslc STATIC
src/file_compiler.cc
src/file_compiler.h
src/file.cc
src/file.h
src/file_includer.cc
src/file_includer.h
src/resource_parse.h
src/resource_parse.cc
src/shader_stage.cc
src/shader_stage.h
src/dependency_info.cc
src/dependency_info.h
)
shaderc_default_compile_options(glslc)
target_include_directories(glslc PUBLIC ${glslang_SOURCE_DIR})
if (SHADERC_ENABLE_WGSL_OUTPUT)
if (IS_DIRECTORY "${tint_SOURCE_DIR}/include")
target_include_directories(glslc PRIVATE "${tint_SOURCE_DIR}/include")
target_include_directories(glslc PRIVATE "${tint_SOURCE_DIR}")
endif()
# Turn on features in the tint/tint.h header
add_definitions(-DTINT_BUILD_SPV_READER=1 -DTINT_BUILD_WGSL_WRITER=1)
add_definitions(-DSHADERC_ENABLE_WGSL_OUTPUT=1)
endif(SHADERC_ENABLE_WGSL_OUTPUT)
target_link_libraries(glslc PRIVATE
glslang SPIRV # Glslang libraries
$<$<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)
target_include_directories(glslc_exe PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/.. ${spirv-tools_SOURCE_DIR}/include)
set_target_properties(glslc_exe PROPERTIES OUTPUT_NAME glslc)
target_link_libraries(glslc_exe PRIVATE glslc shaderc_util shaderc)
add_dependencies(glslc_exe build-version)
shaderc_add_tests(
TEST_PREFIX glslc
LINK_LIBS glslc shaderc_util shaderc
TEST_NAMES
file
resource_parse
stage)
shaderc_add_asciidoc(glslc_doc_README README)
if(SHADERC_ENABLE_INSTALL)
install(TARGETS glslc_exe
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR})
endif(SHADERC_ENABLE_INSTALL)
add_subdirectory(test)

732
3rdparty/shaderc/glslc/README.asciidoc vendored Normal file
View File

@@ -0,0 +1,732 @@
= glslc Manual
:toc:
:toclevels: 3
:numbered:
:source-highlighter: pygments
== Name
`glslc` - A command-line GLSL/HLSL to SPIR-V compiler with
Clang-compatible arguments.
== Synopsis
----
glslc [--help]
glslc [-h]
glslc [--show-limits]
glslc [-c|-S|-E]
[-x ...] [-std=standard]
[ ... options for resource bindings ... ]
[-fhlsl-16bit-types]
[-fhlsl-offsets]
[-fhlsl-functionality1]
[-fentry-point=<name>]
[-fauto-map-locations]
[-finvert-y]
[-flimit=...]
[-flimit-file <resource-limits-file>]
[-fshader-stage=...]
[--target-env=...]
[--target-spv=...]
[-g]
[-O0|-Os]
[-Idirectory...]
[-Dmacroname[=value]...]
[-w] [-Werror]
[-o outfile]
shader...
----
== Description
=== Input file languages
glslc accepts both GLSL/HLSL source and SPIR-V assembly files as inputs.
==== Shader stage specification
glslc provides three ways to specify the shader stage of a GLSL source file:
`-fshader-stage=<stage>`, `#pragma shader_stage(<stage>)`, and file extension.
The `-fshader-stage=` option overrides `#pragma shader_stage()`, which overrides
the file extension.
Shader stages can be specified by naming a file with an appropriate extension
as shown in the following table. `-fshader-stage=` and `#pragma shader_stage()`,
on the other hand, enable you to specify shader stages from the command line
and within the source file. Possible ``stage``s for them are also listed in
the following table. Details about `-fshader-stage=` can be found in
<<option-fshader-stage,its own section>>.
[[shader-stage-selection]]
.Shader Stage Selection
|===
|Shader Stage |Shader File Extension |`<stage>`
|vertex |`.vert` |`vertex`
|fragment |`.frag` |`fragment`
|tesselation control |`.tesc` |`tesscontrol`
|tesselation evaluation |`.tese` |`tesseval`
|geometry |`.geom` |`geometry`
|compute |`.comp` |`compute`
|===
`#pragma shader_stage()` relies on the `#pragma` preprocessor directive; thus,
the token inside `shader_stage()` is not subject to preprocessor macro
expansion. It must be exactly one of the ``stage``s in the above table.
`#pragma shader_stage()` behaves as follows:
* The first `#pragma shader_stage()` directive in a translation unit must
precede any non-preprocessor tokens.
* If there is more than one `#pragma shader_stage()` directive in the same
translation unit, all the ``stage``s specified must be the same. Otherwise,
glslc will issue an error.
==== SPIR-V assembly files
SPIR-V assembly input files should follow the
https://github.com/KhronosGroup/SPIRV-Tools/blob/master/syntax.md[syntax]
defined in the https://github.com/KhronosGroup/SPIRV-Tools[SPIRV-Tools]
project and have the `.spvasm` extension. Command line options treat SPIR-V
assembly files differently; some may ignore them, e.g., `<<option-cap-e,-E>>`,
`<<option-cap-s,-S>>`, and some may even treat them not as SPIR-V assembly
files, e.g., `<<shader-stage-with-spirv-assembly,-fshader-stage\=>>`.
[[output-file-naming]]
=== Output file naming
If a name is specified via `-o`, the output file will be given that name.
Otherwise,
* If a compilation stage selection option is given (`-S` or `-c`), there will
be one output file generated per input shader file. The generated output file
will end with a file extension that matches the compilation stage, which is
`.spvasm` for `-S` and `.spv` for `-c`. The name will depend on the original
file's name and extension.
** If the input file has a <<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
`bar.frag.spvasm`.
** Otherwise, the output file will be named as by replacing the input file's
file extension, if any, with the file extension for the compilation stage.
E.g., `glslc -c foo` will generate `foo.spv`, and `glslc -S bar.glsl` will
generate `bar.spvasm`.
* If no compilation stage is selected, the output file will be named `a.spv`.
== Command Line Options
=== Overall Options
==== `--help`, `-h`
Option `--help` or `-h` tells the glslc compiler to display all available options and exit.
==== `--show-limits`
`--show-limits` shows default resource limits for shader compilation. The syntax
is the same as accepted by `-flimit=` and for the contents of the file specified
by `-flimit-file`.
==== `-o`
`-o` lets you specify the output file's name. It cannot be used when there are
multiple files generated. A filename of `-` represents standard output.
=== Language and Mode Selection Options
[[option-finvert-y]]
==== `-finvert-y`
Inverts position.Y output in a vertex shader.
[[option-flimit]]
==== `-flimit=`
`-flimit=<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
inputs from the command line.
Possible values for ``<stage>`` are listed in the <<shader-stage-selection,
Shader Stage Selection>> table.
`-fshader-stage=` behaves as follows:
* `-fshader-stage=` sets the shader stage for subsequent input files. It does
not affect the stages of any preceding inputs on the command line.
* When supplying more than one `-fshader-stage=` argument, the most recent
argument preceding an input file applies.
* A shader file not ending with <<shader-stage-selection,known shader file
extensions>> must have a `-fshader-stage=` argument ahead of it to specify
its stage.
* If there is a `-fshader-stage=` before a file in which there is a `#pragma
shader_stage()` directive, the directive is ignored and the `-fshader-stage=`
argument is used instead.
* If there is a `-fshader-stage=` before a file with a known shader file
extension, the file extension is ignored and the `-fshader-stage=` argument
is used instead.
[[shader-stage-with-spirv-assembly]]
CAUTION: `-fshader-stage=` overrides file extension; that means it should not
be used together with SPIR-V assembly files because glslc will treat the given
SPIR-V assembly files as GLSL source code of the given shader stage. If you
need to supply both SPIR-V assembly files and `-fshader-stage=` on the same
command line, please put SPIR-V assembly files ahead of the first
`-fshader-stage=`, since `-fshader-stage=` only affects the treatment of
subsequent files.
==== `-std=`
`-std=<value>` lets you specify a shader version and profile on the command
line. ``<value>`` can be any valid concatenation of a GLSL version number and
profile, e.g., `310es`, `450core`, etc. The profile can be omitted as allowed by
GLSL, e.g., `450`.
`-std=` behaves as follows:
* `-std=` affects the version of all GLSL inputs passed to `glslc`.
* `-std=` is ignored for HLSL inputs.
* `-std=` overwrites `#version` directives in all input shaders, including those
preceding the argument.
* If a `-std=` argument specifies a different version from a `#version`
directive in an input file, `glslc` will issue a warning.
* If multiple `-std=` arguments are specified on the command line, only the last
one takes effect.
CAUTION: `-std=` does not affect the `#version` directive in the preprocessed
output. That is, when `-std=` specifies a version different from the shader
source code, the `#version` directive in preprocessed output will still be the
one in the source code. But `-std=` does affect the behavior of `#line`
directives in the preprocessed output. Behavior of `#line` directives will
follow the version specified by `-std=`.
==== `--target-env=`
`--target-env=<value>` lets you specify a target environment on the command line.
This affects the generation of warnings and errors. The ``<value>`` can be one of
the following:
* `vulkan`: create SPIR-V under Vulkan 1.0 semantics.
* `vulkan1.0`: create SPIR-V under Vulkan 1.0 semantics.
* `vulkan1.1`: create SPIR-V under Vulkan 1.1 semantics.
* `vulkan1.2`: create SPIR-V under Vulkan 1.2 semantics.
* `opengl`: create SPIR-V under OpenGL 4.5 semantics.
* `opengl4.5`: create SPIR-V under OpenGL 4.5 semantics.
Generated code uses SPIR-V 1.0, except for code compiled for Vulkan 1.1, which uses
SPIR-V 1.3, and code compiled for Vulkan 1.2, which uses SPIR-V 1.5.
If this option is not specified, a default of `vulkan1.0` is used.
Note: Support for OpenGL compatibility profile, `opengl_compat`, has been removed.
==== `--target-spv=`
`--target-spv=<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`
* `spv1.6`
==== `-x`
`-x` lets you specify the language of the input shader files. Valid languages
are `glsl` and `hlsl`. If the file extension is `hlsl` then the default language
is HLSL. Otherwise the default is 'glsl'.
Note: HLSL compilation will use HLSL packing (offset) rules for variables
that are vertex shader outputs, and inputs and outputs of both geometry
and pixel shaders.
[[compilation-stage-selection-options]]
=== Compilation Stage Selection Options
==== `-c`
`-c` tells the glslc compiler to run the preprocessing and compiling stage.
Each input shader file results in a SPIR-V binary file; these SPIR-V binary
files are named by the rules in the <<output-file-naming,Output File Naming>>
section.
[[option-cap-e]]
==== `-E`
`-E` tells the glslc compiler to run only the preprocessing stage. It overrides
`-c` and `-S`. Preprocessed output is written to standard output, while
preprocessing errors are written to standard error. If multiple input shader
files are given, their preprocessed output are all written to standard output,
in the order specified on the command line.
glslc will do nothing for SPIR-V assembly files with this option.
[[option-cap-s]]
==== `-S`
`-S` tells the glslc compiler to run the preprocessing, compiling, and then
disassembling stage. It overrides `-c`. Each input shader file results in a
SPIR-V assembly file; these SPIR-V assembly files are named by the rules in the
<<output-file-naming,Output File Naming>> section.
glslc will do nothing for SPIR-V assembly files with this option.
==== No Compilation Stage Selection
If none of the above options is given, the glslc compiler will run
preprocessing, compiling, and linking stages.
WARNING: Linking of multiple input shader files are not supported yet.
=== Preprocessor Options
==== `-D`
`-Dmacroname[=[value]]` lets you define a preprocessor macro before input shader
files are preprocessed. If `value` is omitted, the macro is defined with an
empty value.
==== `-I`
`-Idirectory` or `-I directory` adds the specified directory to the search path
for include files. The directory may be an absolute path or a relative path to
the current working directory.
=== Code Generation Options
==== `-g`
Requests that the compiler place source-level debug information into the object
code, such as identifier names and line numbers.
This option restrains `-O` from turning on the strip-debug-info optimization
pass.
NOTE: Currently this option has no effect. Full functionality depends on
glslang support for generating debug info.
==== `-O0`, `-Os`
`-O` specifies which optimization level to use:
* `-O0` means "no optimization". This level generates the most debuggable code.
* `-O` means the default optimization level for better performance.
* `-Os` enables optimizations to reduce code size.
==== `-mfmt=<format>`
`-mfmt=<format>` selects output format for compilation output in SPIR-V binary
code form. Supported options are listed in the
<<binary-output-format-options,binary output format options>> table. This
option is only valid to be used when the compilation output is SPIR-V binary
code. Specifying any options listed below when the output is not SPIR-V binary
code, like disassembly (with `-S` specified), text (with `-M`, `-MM` or `-E`
specified) will trigger an error.
[[binary-output-format-options]]
.Binary Output Format Options
[cols="20%,80%"]
|===
|Format option |Description
|bin |Output SPIR-V binary code as a sequence of binary 32-bitwords
in host native endianness. This is the default format for
SPIR-V binary compilation output.
|num |Output SPIR-V binary code as a text file containing a list of
comma-separated hex numbers. +
Example: `glslc -c -mfmt=num main.vert -o output_file.txt` +
Content of the output_file.txt: +
0x07230203,0x00010000,0x00080001,0x00000006...
|c |Output SPIR-V binary code as a text file containing C-style +
initializer list. +
This is just wrapping the output of `num` option with curly
brackets. +
Example: `glslc -c -mfmt=c main.vert -o output_file.txt` +
Content of output_file.txt: +
{0x07230203, 0x00010000, 0x00080001, 0x00000006...}
|===
[[option-fhlsl-16bit-types]]
==== `-fhlsl-16bit-types`
Enables 16bit types for HLSL compilation.
[[option-fhlsl-offsets]]
==== `-fhlsl-offsets`
Use HLSL packing rules instead of GLSL rules when determining offsets of
members of blocks. This option is always on when compiling for HLSL.
[[option-fhlsl-functionality1]]
==== `-fhlsl-functionality1`
Enable extension `SPV_GOOGLE_hlsl_functionality1`, and instructs the compiler
to:
- Annotate HLSL semantic string decorations on interface objects
- Explicitly record the association of a UAV resource with its companion counter buffer.
This option can also be spelled with an underscore: `-fhlsl_functionality1`.
[[option-fentry-point]]
==== `-fentry-point=<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;
}
----
[[option-fpreserve-bindings
==== `-fpreserve-bindings`
Directs the optimizer to preserve bindings declarations, even when those
bindings are known to be unused.
=== Warning and Error Options
==== `-w`
`-w` suppresses all warning output from `glslc`. Any warning that would have
been generated is silently ignored.
==== `-Werror`
`-Werror` forces any warning to be treated as an error in `glslc`. This means
that all `warning:` messages are shown as `error:` and any warnings will cause
a non-zero exit code from `glslc`. If `-w` is specified the warnings
generated are suppressed before they are converted to errors.
=== Dependency Generation Options
==== `-M` or `-MM`
`-M` generates *make* dependencies. It outputs a rule suitable for *make*
describing the dependencies of the input file. Instead of outputting the result
of preprocessing, the preprocessor outputs one *make* rule containing the
SPIR-V object file name for that source file, a colon, and the names of all the
included files.
Unless specified explicitly (with `-MT`), the SPIR-V object file name in the
generated *make* rules follows the rules of <<output-file-naming,Output File
Naming>> as in `-c` compilation stage.
Specifying `-M` implies `-E`, and suppresses warnings with an implicit `-w`.
By default the output will be written to stdout, unless `-MF` or `-o` is
specified.
The dependency info file name can be specified by `-o` and `-MF` options. When
both are specified, `-o` option is ignored.
Specifying multiple input files is valid when the *make* rules are written to
stdout, which means neither `-MF` nor `-o` is specified. When `-o` or `-MF` is
specified, only one input file is allowed.
`-MM` is an alias for `-M`.
E.g., `glslc -M main.vert` will dump `main.vert.spv: main.vert <other included
files>` to stdout. More examples are listed in
<<dependency-generation-examples,Dependency Generation Examples>>
==== `-MD`
`-MD` tells the glslc compiler to both compile the source and generate *make*
dependencies. Dependencies are written to a file whose name is determined as
follows: If option `-MF` is specified, use its argument. Otherwise, use the
filename formed by appending *.d* to the name of the file containing
compilation results.
Specifying multiple input files is valid when neither `-MF` nor `-o` is
specified. When `-o` or `-MF` is specified, only one input file is allowed.
E.g., `glslc -c -MD main.vert` will generate `main.vert.spv` as the SPIR-V
object file and `main.vert.spv.d` as the dependency info file. More examples
are listed in <<dependency-generation-examples,Dependency Generation Examples>>
==== `-MF`
`-MF` lets you specify the dependency info file name when used with `-M` or
`-MD`. This option is invalid when used with multiple input files.
E.g., `glslc -c -MD main.vert -MF dep_info` will generate `main.vert.spv` as
the SPIR-V object file and `dep_info` as the dependency info file.
==== `-MT`
`-MT` lets you specify the target of the rule emitted by dependency generation
when used with `-M` or `-MD`. This option is invalid when used with multiple
input files.
E.g., `glslc -M main.vert -MT target` will dump following dependency info to
stdout: `target: main.vert <other dependent files>`.
[[dependency-generation-examples]]
.Dependency Generation Examples
|===
|Command Line Input|Compilation Output File|Dependency Output File|Dependency Info
|glslc -M main.vert | <NA> | <Stdout> | main.vert.spv: main.vert
.2+|glslc -M a.vert b.vert | <NA> | <Stdout> | a.vert.spv: a.vert
| <NA> | <Stdout> | b.vert.spv: b.vert
|glslc -M main.vert -o dep_info | <NA> | dep_info | main.vert.spv: main.vert
|glslc -M main.vert -MF dep_info| <NA> | dep_info | main.vert.spv: main.vert
|glslc -M main.vert -MT target | <NA> | <Stdout> | target: main.vert
|glslc -MD main.vert |a.spv |main.vert.spv.d|main.vert.spv: main.vert
|glslc -c -MD main.vert |main.vert.spv|main.vert.spv.d|main.vert.spv: main.vert
.2+|glslc -c -MD a.vert b.vert | a.vert.spv | a.vert.spv.d | a.vert.spv: a.vert
| b.vert.spv | b.vert.spv.d | b.vert.spv: b.vert
|glslc -S -MD main.vert |main.vert.spvasm |main.vert.spvasm.d |main.vert.spvasm: main.vert
|glslc -c -MD main.vert -MF dep_info |main.vert.spv|dep_info|main.vert.spv: main.vert
|glslc -c -MD main.vert -o obj |obj |obj.d |obj: main.vert
|glslc -c -MD main.vert -o obj -MF dep_info -MT target|obj|dep_info|target: main.vert
|===
=== Resource Binding Options
[[option-fauto-bind-uniforms]]
==== `-fauto-bind-uniforms`
Option `-fauto-bind-uniforms` directs the compiler to automatically assign
binding numbers to uniform variables, when an explicit binding is not
specified in the shader source.
An explicit binding number can be specified in the shader source by using
a `binding` layout qualifier. For example:
----
layout(binding = 12) uniform texture2D;
----
[[option-fhlsl-iomap]]
==== `-fhlsl-iomap`
Option `-fhlsl-iomap` directs the compiler to use HLSL register
assignments as binding values.
[[option-fimage-binding-base]]
==== `-fimage-binding-base`
Option `-fimage-binding-base [stage] base` sets the lowest automatically
assigned binding for images. If a stage is specified, only affects the specified
stage.
For HLSL, sets one less than the base.
[[option-fsampler-binding-base]]
==== `-fsampler-binding-base`
Option `-fsampler-binding-base [stage] base` sets the lowest automatically
assigned binding for samplers. If a stage is specified, only affects the specified
stage.
For HLSL, sets one less than the base.
[[option-ftexture-binding-base]]
==== `-ftexture-binding-base`
Option `-ftexture-binding-base [stage] base` sets the lowest automatically
assigned binding for textures. If a stage is specified, only affects the specified
stage.
For HLSL, sets one less than the base.
[[option-fubo-binding-base]]
==== `-fubo-binding-base`
Option `-fubo-binding-base [stage] base` sets the lowest automatically
assigned binding for Uniform Buffer Objects (GLSL) or Cbuffers (HLSL).
If a stage is specified, only affects the specified stage.
For HLSL, sets one less than the base.
[[option-fcbuffer-binding-base]]
==== `-fcbuffer-binding-base`
Option `-fcbuffer-binding-base [stage] base` is the same as
`-fubo-binding-base [stage] base`.
[[option-fssbo-binding-base]]
==== `-fssbo-binding-base`
Option `-fssbo-binding-base [stage] base` sets the lowest automatically
assigned binding for Shader Storage Buffer Objects (GLSL).
If a stage is specified, only affects the specified stage.
This only affects GLSL compilation.
[[option-fuav-binding-base]]
==== `-fuav-binding-base`
Option `-fuav-binding-base [stage] base` sets one less than the lowest
automatically assigned binding for Unordered Access Views (UAV).
If a stage is specified, only affects the specified stage.
This only affects HLSL compilation.
[[option-fregister-set-binding]]
==== `-fresource-set-binding`
Option `-fresource-set-binding [stage] <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__`
This section describes how the glslc compiler extends the syntax for the `#line`
directive and the `\\__FILE__` macro. By default, the glslc compiler enables
the `GL_GOOGLE_cpp_style_line_directive` extension. It will generate this
extended syntax in the preprocessed output (obtained via the `-E` option).
WARNING: This section is still evolving. Expect changes.
GLSL specifications have a notion of source strings.
[quote, Section 3.2 of both version 3.30 and 4.50]
____
The source for a single shader is an array of strings of characters from the
character set. A single shader is made from the concatenation of these strings.
____
With the above notion, the second parameter to the `#line` directive should
be a constant integer expressions representing the source string number. Also
the `\\__FILE__` macro will "substitute a decimal integer constant that says
which source string number is currently being processed."
The glslc compiler implements the standard `#line` and `\\__FILE__` syntax. It
also provides an extension, `GL_GOOGLE_cpp_style_line_directive`, to allow
source filenames to be used instead of integer source string indices.
Specifically, the `#line` directive can have, after macro substitution, one of
the following three forms:
[source,glsl]
----
#line line-number
#line line-number integer-source-string-index
#line line-number "source-filename"
----
where `source-filename` can be any combinations of characters except double
quotation marks. (Note that according to the GLSL specification, "there are
no escape sequences or other uses of the backslash beyond use as the
line-continuation character".)
And if source-filename-based `#line` is used, the `\\__FILE__` macro expands to
a string whose contents are the filename quoted with double quotation marks.
The filename is dertermined as the last of
* The filename given to the glslc compiler,
* The filename argument of the most recent `#line` directive, if any.
[[include-directive]]
=== `#include`
The glslc compiler extends GLSL with the include syntax by turning on the
`GL_GOOGLE_include_directive` extension. It will preprocess and substitute
`#include` directives properly with the following behaviors.
WARNING: This section is still evolving. Expect changes.
If `#include` directives are used in a shader, there will be an `#extension
GL_GOOGLE_include_directive : enable` line generated into the preprocessed
output.
The `GL_GOOGLE_cpp_style_line_directive` extension is implicitly turned on by
the `GL_GOOGLE_include_directive` extension.
The file argument to `#include` must be enclosed in double quotes. It must be a
relative path, using whatever path separator the OS supports. However, the last
path element -- the name of the file itself -- must not contain either '/' or
'\', regardless of which path separator is used. This will not be flagged as an
error but will instead trigger undefined behavior. For example, let's say there
is a file named `f\ilename.vert` on a Unix OS. It is not possible to craft a
`#include` that includes that file.
Furthermore, it is not possible to escape any characters in a `#include`
directive, so the file argument cannot contain any special characters that need
escaping in C.
The file argument is a relative path that is matched first against the including
file's own directory and then against all `-I` arguments in order of their
appearance on the command line. If the file cannot be found, `glslc` aborts
with an error.

View File

@@ -0,0 +1,104 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "dependency_info.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include "file.h"
#include "libshaderc_util/io_shaderc.h"
namespace glslc {
DependencyInfoDumpingHandler::DependencyInfoDumpingHandler() : mode_(not_set) {}
bool DependencyInfoDumpingHandler::DumpDependencyInfo(
std::string compilation_output_file_name, std::string source_file_name,
std::string* compilation_output_ptr,
const std::unordered_set<std::string>& dependent_files) {
std::string dep_target_label = GetTarget(compilation_output_file_name);
std::string dep_file_name =
GetDependencyFileName(compilation_output_file_name);
// Dump everything to a string stream first, then dump its content to either
// a file or compilation output string, depends on current dumping mode.
std::stringstream dep_string_stream;
// dump target label and the source_file_name.
dep_string_stream << dep_target_label << ": " << source_file_name;
// dump the dependent file names.
for (auto& dependent_file_name : dependent_files) {
dep_string_stream << " " << dependent_file_name;
}
dep_string_stream << std::endl;
if (mode_ == dump_as_compilation_output) {
compilation_output_ptr->assign(dep_string_stream.str());
} else if (mode_ == dump_as_extra_file) {
std::ofstream potential_file_stream_for_dep_info_dump;
std::ostream* dep_file_stream = shaderc_util::GetOutputStream(
dep_file_name, &potential_file_stream_for_dep_info_dump, &std::cerr);
*dep_file_stream << dep_string_stream.str();
if (dep_file_stream->fail()) {
std::cerr << "glslc: error: error writing dependent_files info to output "
"file: '"
<< dep_file_name << "'" << std::endl;
return false;
}
} else {
// mode_ should not be 'not_set', we should never be here.
return false;
}
return true;
}
std::string DependencyInfoDumpingHandler::GetTarget(
const std::string& compilation_output_file_name) {
if (!user_specified_dep_target_label_.empty()) {
return user_specified_dep_target_label_;
}
return compilation_output_file_name;
}
std::string DependencyInfoDumpingHandler::GetDependencyFileName(
const std::string& compilation_output_file_name) {
if (!user_specified_dep_file_name_.empty()) {
return user_specified_dep_file_name_;
}
return compilation_output_file_name + ".d";
}
bool DependencyInfoDumpingHandler::IsValid(std::string* error_msg_ptr,
size_t num_files) {
if (DumpingModeNotSet()) {
*error_msg_ptr =
"to generate dependencies you must specify either -M (-MM) or -MD";
return false;
}
if (!user_specified_dep_file_name_.empty() ||
!user_specified_dep_target_label_.empty()) {
if (num_files > 1) {
*error_msg_ptr =
"to specify dependency info file name or dependency info target, "
"only one input file is allowed.";
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,136 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GLSLC_DEPENDENCY_INFO_H
#define GLSLC_DEPENDENCY_INFO_H
#include <unordered_set>
#include <string>
#include <string>
namespace glslc {
// An object to handle everything about dumping dependency info. Internally it
// has two valid dumping mode: 1) Dump to extra dependency info files, such as
// *.d files. This mode is used when we want to generate dependency info and
// also compile. 2) Overwrite the original compilation output and dump
// dependency info as compilation output. This mode is used when we do not want
// to compile the source code and want the dependency info only.
class DependencyInfoDumpingHandler {
public:
DependencyInfoDumpingHandler();
// Sets the dependency target explicitly. It's the same as the argument to
// -MT.
void SetTarget(const std::string& target_label) {
user_specified_dep_target_label_ = target_label;
}
// Sets the name of the file where dependency info will be written.
void SetDependencyFileName(const std::string& dep_file_name) {
user_specified_dep_file_name_ = dep_file_name;
}
// Dump depdendency info to a) an extra dependency info file, b) an string
// which holds the compilation output. The choice depends on the dump
// mode of the handler. Returns true if dumping is succeeded, false otherwise.
//
// The dependency file name and target are deduced based on 1) user
// specified dependency file name and target name, 2) the output filename when
// the compiler is in 'does not need linking' and 'not preprocessing-only'
// mode. It is passed through compilation_output_file_name.
//
// When the handler is set to dump dependency info as extra dependency info
// files, this method will open a file with the dependency file name and write
// the dependency info to it. Error messages caused by writing to the file are
// emitted to stderr.
//
// When the handler is set to dump dependency info as compilation output, the
// compilation output string, which is passed through compilation_output_ptr,
// will be cleared and this method will write dependency info to it. Then the
// dependency info should be emitted as normal compilation output.
//
// If the dump mode is not set when this method is called, return false.
bool DumpDependencyInfo(std::string compilation_output_file_name,
std::string source_file_name,
std::string* compilation_output_ptr,
const std::unordered_set<std::string>& dependent_files);
// Sets to always dump dependency info as an extra file, instead of the normal
// compilation output. This means the output name specified by -o options
// won't be used for the dependency info file.
void SetDumpToExtraDependencyInfoFiles() { mode_ = dump_as_extra_file; }
// Sets to dump dependency info as normal compilation output. The dependency
// info will be either saved in a file with -o option specified file, or, if
// no output file name specified, to stdout.
void SetDumpAsNormalCompilationOutput() {
mode_ = dump_as_compilation_output;
}
// Returns true if the handler's dumping mode is set to dump dependency info
// as extra dependency info files.
bool DumpingToExtraDependencyInfoFiles() {
return mode_ == dump_as_extra_file;
}
// Returns true if the handler's dumping mode is set to dump dependency info
// as normal compilation output.
bool DumpingAsCompilationOutput() {
return mode_ == dump_as_compilation_output;
}
// Returns true if the handler's dumping mode is not set.
bool DumpingModeNotSet() { return mode_ == not_set; }
// Returns true if the handler is at valid state for dumping dependency info.
bool IsValid(std::string* error_msg_ptr, size_t num_files);
private:
typedef enum {
// not_set mode tells that the dumping mode is not set yet, so the handler
// is not ready for dumping dependency info. Calling DumpDependencyInfo when
// the handler is in this mode will cause failure.
not_set = 0,
// Dumping dependency info as normal compilation output mode. In this mode,
// the dependency info will be dumped as compilation output by overwriting
// the string which holds the compilation output.
dump_as_compilation_output,
// Dumping dependency info as extra dependency info files mode. In this
// mode, dependency info will be dumped to a user specified dependency info
// file or a *.d file. Compilation output will still be generated along with
// the dependency info.
dump_as_extra_file,
} dump_mode;
// Returns the target file label to be used in depdendency info file. If -MT
// defined a label, use that string as the label. Otherwise returns the
// compilation output filename deduced in 'doesn't need linking' and 'not
// preprocessing-only' mode.
std::string GetTarget(const std::string& compilation_output_file_name);
// Returns the dependency file name to be used. If -MF defined a file name
// before, use it. Othwise, returns a filename formed by appending .d to the
// output filename deduced in 'doesn't need linking' and 'no
// preprocessing-only' mode.
std::string GetDependencyFileName(
const std::string& compilation_output_file_name);
std::string user_specified_dep_file_name_;
std::string user_specified_dep_target_label_;
dump_mode mode_;
};
}
#endif // GLSLC_DEPENDENCY_INFO_H

26
3rdparty/shaderc/glslc/src/file.cc vendored Normal file
View File

@@ -0,0 +1,26 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "file.h"
namespace glslc {
shaderc_util::string_piece GetFileExtension(
const shaderc_util::string_piece& filename) {
size_t dot_pos = filename.find_last_of(".");
if (dot_pos == shaderc_util::string_piece::npos) return "";
return filename.substr(dot_pos + 1);
}
} // namespace glslc

46
3rdparty/shaderc/glslc/src/file.h vendored Normal file
View File

@@ -0,0 +1,46 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GLSLC_FILE_H_
#define GLSLC_FILE_H_
#include "libshaderc_util/string_piece.h"
namespace glslc {
// Given a file name, returns its extension. If no extension exists,
// returns an empty string_piece.
shaderc_util::string_piece GetFileExtension(
const shaderc_util::string_piece& filename);
// Returns true if the given file name ends with a known shader file extension.
inline bool IsStageFile(const shaderc_util::string_piece& filename) {
const shaderc_util::string_piece extension =
glslc::GetFileExtension(filename);
return extension == "vert" || extension == "frag" || extension == "tesc" ||
extension == "tese" || extension == "geom" || extension == "comp";
}
// Returns the file extension if is either "glsl" or "hlsl", or an empty
// string otherwise.
inline std::string GetGlslOrHlslExtension(
const shaderc_util::string_piece& filename) {
auto extension = glslc::GetFileExtension(filename);
if ((extension == "glsl") || (extension == "hlsl")) return extension.str();
return "";
}
} // namespace glslc
#endif // GLSLC_FILE_H_

View File

@@ -0,0 +1,435 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "file_compiler.h"
#include <cassert>
#include <fstream>
#include <iomanip>
#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"
#include "libshaderc_util/io_shaderc.h"
#include "libshaderc_util/message.h"
namespace {
using shaderc_util::string_piece;
// A helper function to emit SPIR-V binary code as a list of hex numbers in
// text form. Returns true if a non-empty compilation result is emitted
// successfully. Return false if nothing should be emitted, either because the
// compilation result is empty, or the compilation output is not SPIR-V binary
// code.
template <typename CompilationResultType>
bool EmitSpirvBinaryAsCommaSeparatedNumbers(const CompilationResultType& result,
std::ostream* out) {
// Return early if the compilation output is not in SPIR-V binary code form.
if (!std::is_same<CompilationResultType,
shaderc::SpvCompilationResult>::value)
return false;
// Return early if the compilation result is empty.
if (result.cbegin() == result.cend()) return false;
std::ios::fmtflags output_stream_flag_cache(out->flags());
*out << std::hex << std::setfill('0');
auto RI = result.cbegin();
*out << "0x" << std::setw(8) << *RI++;
for (size_t counter = 1; RI != result.cend(); RI++, counter++) {
*out << ",";
// Break line for every four words.
if (counter % 4 == 0) {
*out << std::endl;
}
*out << "0x" << std::setw(8) << *RI;
}
out->flags(output_stream_flag_cache);
return true;
}
} // anonymous namespace
namespace glslc {
bool FileCompiler::CompileShaderFile(const InputFileSpec& input_file) {
std::vector<char> input_data;
std::string path = input_file.name;
if (!shaderc_util::ReadFile(path, &input_data)) {
return false;
}
std::string output_file_name = GetOutputFileName(input_file.name);
string_piece error_file_name = input_file.name;
if (error_file_name == "-") {
// If the input file was stdin, we want to output errors as <stdin>.
error_file_name = "<stdin>";
}
string_piece source_string = "";
if (!input_data.empty()) {
source_string = {&input_data.front(),
&input_data.front() + input_data.size()};
}
std::unique_ptr<FileIncluder> includer(
new FileIncluder(&include_file_finder_));
// Get a reference to the dependency trace before we pass the ownership to
// shaderc::CompileOptions.
const auto& used_source_files = includer->file_path_trace();
options_.SetIncluder(std::move(includer));
if (input_file.stage == shaderc_spirv_assembly) {
// Only act if the requested target is SPIR-V binary.
if (output_type_ == OutputType::SpirvBinary) {
const auto result =
compiler_.AssembleToSpv(source_string.data(), source_string.size());
return EmitCompiledResult(result, input_file.name, output_file_name,
error_file_name, used_source_files);
} else {
return true;
}
}
// Set the language. Since we only use the options object in this
// method, then it's ok to always set it without resetting it after
// compilation. A subsequent compilation will set it again anyway.
options_.SetSourceLanguage(input_file.language);
switch (output_type_) {
case OutputType::SpirvBinary: {
const auto result = compiler_.CompileGlslToSpv(
source_string.data(), source_string.size(), input_file.stage,
error_file_name.data(), input_file.entry_point_name.c_str(),
options_);
return EmitCompiledResult(result, input_file.name, output_file_name,
error_file_name, used_source_files);
}
case OutputType::SpirvAssemblyText: {
const auto result = compiler_.CompileGlslToSpvAssembly(
source_string.data(), source_string.size(), input_file.stage,
error_file_name.data(), input_file.entry_point_name.c_str(),
options_);
return EmitCompiledResult(result, input_file.name, output_file_name,
error_file_name, used_source_files);
}
case OutputType::PreprocessedText: {
const auto result = compiler_.PreprocessGlsl(
source_string.data(), source_string.size(), input_file.stage,
error_file_name.data(), options_);
return EmitCompiledResult(result, input_file.name, output_file_name,
error_file_name, used_source_files);
}
}
return false;
}
template <typename CompilationResultType>
bool FileCompiler::EmitCompiledResult(
const CompilationResultType& result, const std::string& input_file,
const std::string& output_file_name, string_piece error_file_name,
const std::unordered_set<std::string>& used_source_files) {
total_errors_ += result.GetNumErrors();
total_warnings_ += result.GetNumWarnings();
bool compilation_success =
result.GetCompilationStatus() == shaderc_compilation_status_success;
// Handle the error message for failing to deduce the shader kind.
if (result.GetCompilationStatus() ==
shaderc_compilation_status_invalid_stage) {
auto glsl_or_hlsl_extension = GetGlslOrHlslExtension(error_file_name);
if (glsl_or_hlsl_extension != "") {
std::cerr << "glslc: error: "
<< "'" << error_file_name << "': "
<< "." << glsl_or_hlsl_extension
<< " file encountered but no -fshader-stage specified ahead";
} else if (error_file_name == "<stdin>") {
std::cerr
<< "glslc: error: '-': -fshader-stage required when input is from "
"standard "
"input \"-\"";
} else {
std::cerr << "glslc: error: "
<< "'" << error_file_name << "': "
<< "file not recognized: File format not recognized";
}
std::cerr << "\n";
return false;
}
// Get a string_piece which refers to the normal compilation output for now.
// This string_piece might be redirected to the dependency info to be dumped
// later, if the handler is instantiated to dump as normal compilation output,
// and the original compilation output should be blocked. Otherwise it won't
// be touched. The main output stream dumps this string_piece later.
string_piece compilation_output(
reinterpret_cast<const char*>(result.cbegin()),
reinterpret_cast<const char*>(result.cend()));
// If we have dependency info dumping handler instantiated, we should dump
// dependency info first. This may redirect the compilation output
// string_piece to dependency info.
std::string potential_dependency_info_output;
if (dependency_info_dumping_handler_) {
if (!dependency_info_dumping_handler_->DumpDependencyInfo(
GetCandidateOutputFileName(input_file), error_file_name.data(),
&potential_dependency_info_output, used_source_files)) {
return false;
}
if (!potential_dependency_info_output.empty()) {
// If the potential_dependency_info_output string is not empty, it means
// we should dump dependency info as normal compilation output. Redirect
// the compilation output string_piece to the dependency info stored in
// potential_dependency_info_output to make it happen.
compilation_output = potential_dependency_info_output;
}
}
std::ostream* out = nullptr;
std::ofstream potential_file_stream;
if (compilation_success) {
out = shaderc_util::GetOutputStream(output_file_name,
&potential_file_stream, &std::cerr);
if (!out || out->fail()) {
// An error message has already been emitted to the stderr stream.
return false;
}
// Write compilation output to output file. If an output format for SPIR-V
// binary code is specified, it is handled here.
switch (binary_emission_format_) {
case SpirvBinaryEmissionFormat::Unspecified:
case SpirvBinaryEmissionFormat::Binary:
// The output format is unspecified or specified as binary output.
// On Windows, the output stream must be set to binary mode. By
// default the standard output stream is set to text mode, which
// translates newlines (\n) to carriage-return newline pairs
// (\r\n).
if (out == &std::cout) shaderc_util::FlushAndSetBinaryModeOnStdout();
out->write(compilation_output.data(), compilation_output.size());
if (out == &std::cout) shaderc_util::FlushAndSetTextModeOnStdout();
break;
case SpirvBinaryEmissionFormat::Numbers:
// The output format is specified to be a list of hex numbers, the
// compilation output must be in SPIR-V binary code form.
assert(output_type_ == OutputType::SpirvBinary);
if (EmitSpirvBinaryAsCommaSeparatedNumbers(result, out)) {
// Only emits the end-of-line character when the emitted compilation
// result is not empty.
*out << std::endl;
}
break;
case SpirvBinaryEmissionFormat::CInitList:
// The output format is specified to be a C-style initializer list, the
// compilation output must be in SPIR-V binary code form.
assert(output_type_ == OutputType::SpirvBinary);
if (result.begin() != result.end()) {
// Only emits the '{' when the compilation result is not empty.
*out << "{";
}
if (EmitSpirvBinaryAsCommaSeparatedNumbers(result, out)) {
// Only emits the end-of-line character when the emitted compilation
// result is not empty.
*out << "}" << std::endl;
}
break;
case SpirvBinaryEmissionFormat::WGSL: {
#if SHADERC_ENABLE_WGSL_OUTPUT == 1
tint::Context ctx;
tint::reader::spirv::Parser spv_reader(
&ctx, std::vector<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;
}
}
}
// Write error message to std::cerr.
std::cerr << result.GetErrorMessage();
if (out && out->fail()) {
// Something wrong happened on output.
if (out == &std::cout) {
std::cerr << "glslc: error: error writing to standard output"
<< std::endl;
} else {
std::cerr << "glslc: error: error writing to output file: '"
<< output_file_name_ << "'" << std::endl;
}
return false;
}
return compilation_success;
}
void FileCompiler::AddIncludeDirectory(const std::string& path) {
include_file_finder_.search_path().push_back(path);
}
void FileCompiler::SetIndividualCompilationFlag() {
if (output_type_ != OutputType::SpirvAssemblyText) {
needs_linking_ = false;
file_extension_ = ".spv";
}
}
void FileCompiler::SetDisassemblyFlag() {
if (!PreprocessingOnly()) {
output_type_ = OutputType::SpirvAssemblyText;
needs_linking_ = false;
file_extension_ = ".spvasm";
}
}
void FileCompiler::SetPreprocessingOnlyFlag() {
output_type_ = OutputType::PreprocessedText;
needs_linking_ = false;
if (output_file_name_.empty()) {
output_file_name_ = "-";
}
}
bool FileCompiler::ValidateOptions(size_t num_files) {
if (num_files == 0) {
std::cerr << "glslc: error: no input files" << std::endl;
return false;
}
if (num_files > 1 && needs_linking_) {
std::cerr << "glslc: error: linking multiple files is not supported yet. "
"Use -c to compile files individually."
<< std::endl;
return false;
}
// If we are outputting many object files, we cannot specify -o. Also
// if we are preprocessing multiple files they must be to stdout.
if (num_files > 1 && ((!PreprocessingOnly() && !needs_linking_ &&
!output_file_name_.empty()) ||
(PreprocessingOnly() && output_file_name_ != "-"))) {
std::cerr << "glslc: error: cannot specify -o when generating multiple"
" output files"
<< std::endl;
return false;
}
// If we have dependency info dumping handler instantiated, we should check
// its validity.
if (dependency_info_dumping_handler_) {
std::string dependency_info_dumping_hander_error_msg;
if (!dependency_info_dumping_handler_->IsValid(
&dependency_info_dumping_hander_error_msg, num_files)) {
std::cerr << "glslc: error: " << dependency_info_dumping_hander_error_msg
<< std::endl;
return false;
}
}
// If the output format is specified to be a binary, a list of hex numbers or
// a C-style initializer list, the output must be in SPIR-V binary code form.
if (binary_emission_format_ != SpirvBinaryEmissionFormat::Unspecified) {
if (output_type_ != OutputType::SpirvBinary) {
std::cerr << "glslc: error: cannot emit output as a ";
switch (binary_emission_format_) {
case SpirvBinaryEmissionFormat::Binary:
std::cerr << "binary";
break;
case SpirvBinaryEmissionFormat::Numbers:
std::cerr << "list of hex numbers";
break;
case SpirvBinaryEmissionFormat::CInitList:
std::cerr << "C-style initializer list";
break;
case SpirvBinaryEmissionFormat::WGSL:
std::cerr << "WGSL source program";
break;
case SpirvBinaryEmissionFormat::Unspecified:
// The compiler should never be here at runtime. This case is added to
// complete the switch cases.
break;
}
std::cerr << " when only preprocessing the source" << std::endl;
return false;
}
if (dependency_info_dumping_handler_ &&
dependency_info_dumping_handler_->DumpingAsCompilationOutput()) {
std::cerr << "glslc: error: cannot dump dependency info when specifying "
"any binary output format"
<< std::endl;
return false;
}
}
if (binary_emission_format_ == SpirvBinaryEmissionFormat::WGSL) {
#if SHADERC_ENABLE_WGSL_OUTPUT != 1
std::cerr << "glslc: error: can't output WGSL: glslc was built without "
"WGSL output support"
<< std::endl;
return false;
#endif
}
return true;
}
void FileCompiler::OutputMessages() {
shaderc_util::OutputMessages(&std::cerr, total_warnings_, total_errors_);
}
std::string FileCompiler::GetOutputFileName(std::string input_filename) {
if (output_file_name_.empty()) {
return needs_linking_ ? std::string("a.spv")
: GetCandidateOutputFileName(input_filename);
} else {
return output_file_name_.str();
}
}
std::string FileCompiler::GetCandidateOutputFileName(
std::string input_filename) {
if (!output_file_name_.empty() && !PreprocessingOnly()) {
return output_file_name_.str();
}
std::string extension = file_extension_;
if (PreprocessingOnly() || needs_linking_) {
extension = ".spv";
}
std::string candidate_output_file_name =
IsStageFile(input_filename)
? shaderc_util::GetBaseFileName(input_filename) + extension
: shaderc_util::GetBaseFileName(
input_filename.substr(0, input_filename.find_last_of('.')) +
extension);
return candidate_output_file_name;
}
} // namesapce glslc

View File

@@ -0,0 +1,234 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GLSLC_FILE_COMPILER_H
#define GLSLC_FILE_COMPILER_H
#include <string>
#include "libshaderc_util/file_finder.h"
#include "libshaderc_util/string_piece.h"
#include "shaderc/shaderc.hpp"
#include "dependency_info.h"
namespace glslc {
// Describes an input file to be compiled.
struct InputFileSpec {
std::string name;
shaderc_shader_kind stage;
shaderc_source_language language;
std::string entry_point_name;
};
// Context for managing compilation of source GLSL files into destination
// SPIR-V files or preprocessed output.
class FileCompiler {
public:
enum class SpirvBinaryEmissionFormat {
Unspecified, // No binary output format specified, this is the only valid
// option when the compilation output is not in SPIR-V binary
// code form.
Binary, // Emits SPIR-V binary code directly.
Numbers, // Emits SPIR-V binary code as a list of hex numbers.
CInitList, // Emits SPIR-V binary code as a C-style initializer list
// of hex numbers.
WGSL, // Emits SPIR-V module converted to WGSL source text.
// Requires a build with Tint support.
};
FileCompiler()
: output_type_(OutputType::SpirvBinary),
binary_emission_format_(SpirvBinaryEmissionFormat::Unspecified),
needs_linking_(true),
total_warnings_(0),
total_errors_(0) {}
// Compiles a shader received as specified by input_file, returning true
// on success and false otherwise. If force_shader_stage is not
// shaderc_glsl_infer_source or any default shader stage then the given
// shader_stage will be used, otherwise it will be determined from the source
// or the file type.
//
// Places the compilation output into a new file whose name is derived from
// input_file according to the rules from glslc/README.asciidoc.
//
// If version/profile has been forced, the shader's version/profile is set to
// that value regardless of the #version directive in the source code.
//
// Any errors/warnings found in the shader source will be output to std::cerr
// and increment the counts reported by OutputMessages().
bool CompileShaderFile(const InputFileSpec& input_file);
// Adds a directory to be searched when processing #include directives.
//
// Best practice: if you add an empty string before any other path, that will
// correctly resolve both absolute paths and paths relative to the current
// working directory.
void AddIncludeDirectory(const std::string& path);
// Sets the output filename. A name of "-" indicates standard output.
void SetOutputFileName(const shaderc_util::string_piece& file) {
output_file_name_ = file;
}
// Sets the format for SPIR-V binary compilation output.
void SetSpirvBinaryOutputFormat(SpirvBinaryEmissionFormat format) {
binary_emission_format_ = format;
}
// Returns false if any options are incompatible. The num_files parameter
// represents the number of files that will be compiled.
bool ValidateOptions(size_t num_files);
// Outputs to std::cerr the number of warnings and errors if there are any.
void OutputMessages();
// Sets the flag to indicate individual compilation mode. In this mode, all
// files are compiled individually and written to separate output files
// instead of linked together. This method also disables linking and sets the
// output file extension to ".spv". Disassembly mode and preprocessing only
// mode override this mode and flags.
void SetIndividualCompilationFlag();
// Sets the flag to indicate disassembly mode. In this mode, the compiler
// emits disassembled textual output, instead of outputting object files.
// This method also sets the output file extension to ".spvasm" and disables
// linking. This mode overrides individual compilation mode, and preprocessing
// only mode overrides this mode.
void SetDisassemblyFlag();
// Sets the flag to indicate preprocessing only mode. In this mode, instead of
// outputting object files, the compiler emits the preprocessed source files.
// This method disables linking and sets the output file to stdout. This mode
// overrides disassembly mode and individual compilation mode.
void SetPreprocessingOnlyFlag();
// Gets the reference of the compiler options which reflects the command-line
// arguments.
shaderc::CompileOptions& options() { return options_; }
// Gets a pointer which points to the dependency info dumping hander. Creates
// such a handler if such one does not exist.
DependencyInfoDumpingHandler* GetDependencyDumpingHandler() {
if (!dependency_info_dumping_handler_) {
dependency_info_dumping_handler_.reset(
new DependencyInfoDumpingHandler());
}
return dependency_info_dumping_handler_.get();
}
private:
enum class OutputType {
SpirvBinary, // A binary module, as defined by the SPIR-V specification.
SpirvAssemblyText, // Assembly syntax defined by the SPIRV-Tools project.
PreprocessedText, // Preprocessed source code.
};
// Emits the compilation output from the given result to the given output
// file and returns true if the result represents a successful compilation
// step. Otherwise returns false, possibly emits messages to the standard
// error stream, and does not produce an output file. Accumulates error
// and warning counts for use by the OutputMessages() method.
template <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);
// Returns the final file name to be used for the output file.
//
// If an output file name is specified by the SetOutputFileName(), use that
// argument as the final output file name.
//
// If the user did not specify an output filename:
// If linking is not required, and the input filename has a
// standard stage extension (e.g. .vert) then returns the input filename
// without directory names but with the result extenstion (e.g. .spv or
// .spvasm) appended.
//
// If linking is not required, and the input file name does not have a
// standard stage extension, then also returns the directory-stripped input
// filename, but replaces its extension with the result extension. (If the
// resolved input filename does not have an extension, then appends the
// result extension.)
//
// If linking is required and output filename is not specified, returns
// "a.spv".
std::string GetOutputFileName(std::string input_filename);
// Returns the candidate output file name deduced from input file name and
// user specified output file name. It is computed as follows:
//
// If the user did specify an output filename and the compiler is not in
// preprocessing-only mode, then returns that file name.
//
// If the user did not specify an output filename:
// If the input filename has a standard stage extension (e.g. .vert) then
// returns the input filename without directory names but with the result
// extenstion (e.g. .spv or .spvasm) appended.
//
// If the input file name does not have a standard stage extension, then also
// returns the directory-stripped input filename, but replaces its extension
// with the result extension. (If the resolved input filename does not have
// an extension, then appends the result extension.)
//
// When a resolved extension is not available because the compiler is in
// preprocessing-only mode or the compilation requires linking, use .spv as
// the extension.
std::string GetCandidateOutputFileName(std::string input_filename);
// Returns true if the compiler's output is preprocessed text.
bool PreprocessingOnly() {
return output_type_ == OutputType::PreprocessedText;
}
// Performs actual SPIR-V compilation on the contents of input files.
shaderc::Compiler compiler_;
// Reflects the command-line arguments and goes into
// compiler_.CompileGlslToSpv().
shaderc::CompileOptions options_;
// What kind of output will be produced?
OutputType output_type_;
// The Flag to indicate to which format the output SPIR-V binary code should
// be emitted.
SpirvBinaryEmissionFormat binary_emission_format_;
// A FileFinder used to substitute #include directives in the source code.
shaderc_util::FileFinder include_file_finder_;
// Indicates whether linking is needed to generate the final output.
bool needs_linking_;
// The ownership of dependency dumping handler.
std::unique_ptr<DependencyInfoDumpingHandler>
dependency_info_dumping_handler_ = nullptr;
// Reflects the type of file being generated.
std::string file_extension_;
// Name of the file where the compilation output will go.
shaderc_util::string_piece output_file_name_;
// Counts warnings encountered in all compilations via this object.
size_t total_warnings_;
// Counts errors encountered in all compilations via this object.
size_t total_errors_;
};
} // namespace glslc
#endif // GLSLC_FILE_COMPILER_H

View File

@@ -0,0 +1,66 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "file_includer.h"
#include <mutex>
#include <utility>
#include "libshaderc_util/io_shaderc.h"
namespace glslc {
shaderc_include_result* MakeErrorIncludeResult(const char* message) {
return new shaderc_include_result{"", 0, message, strlen(message)};
}
FileIncluder::~FileIncluder() = default;
shaderc_include_result* FileIncluder::GetInclude(
const char* requested_source, shaderc_include_type include_type,
const char* requesting_source, size_t) {
const std::string full_path =
(include_type == shaderc_include_type_relative)
? file_finder_.FindRelativeReadableFilepath(requesting_source,
requested_source)
: file_finder_.FindReadableFilepath(requested_source);
if (full_path.empty())
return MakeErrorIncludeResult("Cannot find or open include file.");
// In principle, several threads could be resolving includes at the same
// time. Protect the included_files.
// Read the file and save its full path and contents into stable addresses.
FileInfo* new_file_info = new FileInfo{full_path, {}};
if (!shaderc_util::ReadFile(full_path, &(new_file_info->contents))) {
return MakeErrorIncludeResult("Cannot read file");
}
included_files_.insert(full_path);
return new shaderc_include_result{
new_file_info->full_path.data(), new_file_info->full_path.length(),
new_file_info->contents.data(), new_file_info->contents.size(),
new_file_info};
}
void FileIncluder::ReleaseInclude(shaderc_include_result* include_result) {
FileInfo* info = static_cast<FileInfo*>(include_result->user_data);
delete info;
delete include_result;
}
} // namespace glslc

View File

@@ -0,0 +1,74 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GLSLC_FILE_INCLUDER_H_
#define GLSLC_FILE_INCLUDER_H_
#include <mutex>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include <unordered_set>
#include "libshaderc_util/file_finder.h"
#include "shaderc/shaderc.hpp"
namespace glslc {
// An includer for files implementing shaderc's includer interface. It responds
// to the file including query from the compiler with the full path and content
// of the file to be included. In the case that the file is not found or cannot
// be opened, the full path field of in the response will point to an empty
// string, and error message will be passed to the content field.
// This class provides the basic thread-safety guarantee.
class FileIncluder : public shaderc::CompileOptions::IncluderInterface {
public:
explicit FileIncluder(const shaderc_util::FileFinder* file_finder)
: file_finder_(*file_finder) {}
~FileIncluder() override;
// Resolves a requested source file of a given type from a requesting
// source into a shaderc_include_result whose contents will remain valid
// until it's released.
shaderc_include_result* GetInclude(const char* requested_source,
shaderc_include_type type,
const char* requesting_source,
size_t include_depth) override;
// Releases an include result.
void ReleaseInclude(shaderc_include_result* include_result) override;
// Returns a reference to the member storing the set of included files.
const std::unordered_set<std::string>& file_path_trace() const {
return included_files_;
}
private:
// Used by GetInclude() to get the full filepath.
const shaderc_util::FileFinder& file_finder_;
// The full path and content of a source file.
struct FileInfo {
const std::string full_path;
std::vector<char> contents;
};
// The set of full paths of included files.
std::unordered_set<std::string> included_files_;
};
} // namespace glslc
#endif // GLSLC_FILE_INCLUDER_H_

96
3rdparty/shaderc/glslc/src/file_test.cc vendored Normal file
View File

@@ -0,0 +1,96 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "file.h"
#include <gmock/gmock.h>
namespace {
using glslc::GetFileExtension;
using glslc::IsStageFile;
using glslc::GetGlslOrHlslExtension;
using shaderc_util::string_piece;
using testing::Eq;
class FileExtensionTest : public testing::Test {
protected:
string_piece empty = "";
string_piece dot = ".";
string_piece no_ext = "shader";
string_piece trailing_dot = "shader.";
string_piece vert_ext = "shader.vert";
string_piece frag_ext = "shader.frag";
string_piece tesc_ext = "shader.tesc";
string_piece tese_ext = "shader.tese";
string_piece geom_ext = "shader.geom";
string_piece comp_ext = "shader.comp";
string_piece glsl_ext = "shader.glsl";
string_piece hlsl_ext = "shader.hlsl";
string_piece multi_dot = "shader.some..ext";
string_piece both_hg_ext = "shader.hlsl.glsl";
string_piece both_gh_ext = "shader.glsl.hlsl";
};
TEST_F(FileExtensionTest, GetFileExtension) {
EXPECT_EQ("", GetFileExtension(empty));
EXPECT_EQ("", GetFileExtension(dot));
EXPECT_EQ("", GetFileExtension(no_ext));
EXPECT_EQ("", GetFileExtension(trailing_dot));
EXPECT_EQ("vert", GetFileExtension(vert_ext));
EXPECT_EQ("frag", GetFileExtension(frag_ext));
EXPECT_EQ("tesc", GetFileExtension(tesc_ext));
EXPECT_EQ("tese", GetFileExtension(tese_ext));
EXPECT_EQ("geom", GetFileExtension(geom_ext));
EXPECT_EQ("comp", GetFileExtension(comp_ext));
EXPECT_EQ("glsl", GetFileExtension(glsl_ext));
EXPECT_EQ("ext", GetFileExtension(multi_dot));
EXPECT_EQ("glsl", GetFileExtension(both_hg_ext));
EXPECT_EQ("hlsl", GetFileExtension(both_gh_ext));
}
TEST_F(FileExtensionTest, GetGlslOrHlslExtension) {
EXPECT_THAT(GetGlslOrHlslExtension(empty), Eq(""));
EXPECT_THAT(GetGlslOrHlslExtension(dot), Eq(""));
EXPECT_THAT(GetGlslOrHlslExtension(no_ext), Eq(""));
EXPECT_THAT(GetGlslOrHlslExtension(trailing_dot), Eq(""));
EXPECT_THAT(GetGlslOrHlslExtension(vert_ext), Eq(""));
EXPECT_THAT(GetGlslOrHlslExtension(frag_ext), Eq(""));
EXPECT_THAT(GetGlslOrHlslExtension(tesc_ext), Eq(""));
EXPECT_THAT(GetGlslOrHlslExtension(tese_ext), Eq(""));
EXPECT_THAT(GetGlslOrHlslExtension(geom_ext), Eq(""));
EXPECT_THAT(GetGlslOrHlslExtension(comp_ext), Eq(""));
EXPECT_THAT(GetGlslOrHlslExtension(glsl_ext), Eq("glsl"));
EXPECT_THAT(GetGlslOrHlslExtension(hlsl_ext), Eq("hlsl"));
EXPECT_THAT(GetGlslOrHlslExtension(multi_dot), Eq(""));
EXPECT_THAT(GetGlslOrHlslExtension(both_hg_ext), Eq("glsl"));
EXPECT_THAT(GetGlslOrHlslExtension(both_gh_ext), Eq("hlsl"));
}
TEST_F(FileExtensionTest, IsStageFile) {
EXPECT_FALSE(IsStageFile(empty));
EXPECT_FALSE(IsStageFile(dot));
EXPECT_FALSE(IsStageFile(no_ext));
EXPECT_FALSE(IsStageFile(trailing_dot));
EXPECT_TRUE(IsStageFile(vert_ext));
EXPECT_TRUE(IsStageFile(frag_ext));
EXPECT_TRUE(IsStageFile(tesc_ext));
EXPECT_TRUE(IsStageFile(tese_ext));
EXPECT_TRUE(IsStageFile(geom_ext));
EXPECT_TRUE(IsStageFile(comp_ext));
EXPECT_FALSE(IsStageFile(glsl_ext));
EXPECT_FALSE(IsStageFile(multi_dot));
}
} // anonymous namespace

695
3rdparty/shaderc/glslc/src/main.cc vendored Normal file
View File

@@ -0,0 +1,695 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cassert>
#include <cctype>
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <list>
#include <sstream>
#include <string>
#include <tuple>
#include <utility>
#include "file.h"
#include "file_compiler.h"
#include "libshaderc_util/args.h"
#include "libshaderc_util/compiler.h"
#include "libshaderc_util/io_shaderc.h"
#include "libshaderc_util/string_piece.h"
#include "resource_parse.h"
#include "shader_stage.h"
#include "shaderc/env.h"
#include "shaderc/shaderc.h"
#include "spirv-tools/libspirv.h"
using shaderc_util::string_piece;
namespace {
// Prints the help message.
void PrintHelp(std::ostream* out) {
*out << R"(glslc - Compile shaders into SPIR-V
Usage: glslc [options] file...
An input file of - represents standard input.
Options:
-c Only run preprocess, compile, and assemble steps.
-Dmacro[=defn] Add an implicit macro definition.
-E Outputs only the results of the preprocessing step.
Output defaults to standard output.
-fauto-bind-uniforms
Automatically assign bindings to uniform variables that
don't have an explicit 'binding' layout in the shader
source.
-fauto-map-locations
Automatically assign locations to uniform variables that
don't have an explicit 'location' layout in the shader
source.
-fauto-combined-image-sampler
Removes sampler variables and converts existing textures
to combined image-samplers.
-fentry-point=<name>
Specify the entry point name for HLSL compilation, for
all subsequent source files. Default is "main".
-fhlsl-16bit-types
Enable 16-bit type support for HLSL.
-fhlsl_functionality1, -fhlsl-functionality1
Enable extension SPV_GOOGLE_hlsl_functionality1 for HLSL
compilation.
-fhlsl-iomap Use HLSL IO mappings for bindings.
-fhlsl-offsets Use HLSL offset rules for packing members of blocks.
Affects only GLSL. HLSL rules are always used for HLSL.
-finvert-y Invert position.Y output in vertex shader.
-flimit=<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.
-fpreserve-bindings
Preserve all binding declarations, even if those bindings
are not used.
-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.
-h Display available options.
--help Display available options.
-I <value> Add directory to include search path.
-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 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.
-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 client environment, and the semantics
of warnings and errors. An optional suffix can specify
the client version. Values are:
vulkan1.0 # The default
vulkan1.1
vulkan1.2
vulkan1.3
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.
the default for vulkan1.3 is spv1.6.
Values are:
spv1.0, spv1.1, spv1.2, spv1.3, spv1.4, spv1.5, spv1.6
--version Display compiler version information.
-w Suppresses all warning messages.
-Werror Treat all warnings as errors.
-x <language> Treat subsequent input files as having type <language>.
Valid languages are: glsl, hlsl.
For files ending in .hlsl the default is hlsl.
Otherwise the default is glsl.
)";
}
// Sets resource limits according to the given string. The string
// should be formated as required for ParseResourceSettings.
// Returns true on success. Otherwise returns false and sets err
// to a descriptive error message.
bool SetResourceLimits(const std::string& str, shaderc::CompileOptions* options,
std::string* err) {
std::vector<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) {
std::vector<glslc::InputFileSpec> input_files;
shaderc_shader_kind current_fshader_stage = shaderc_glsl_infer_from_source;
bool source_language_forced = false;
shaderc_source_language current_source_language =
shaderc_source_language_glsl;
std::string current_entry_point_name("main");
glslc::FileCompiler compiler;
bool success = true;
bool has_stdin_input = false;
// Shader stage for a single option.
shaderc_shader_kind arg_stage = shaderc_glsl_infer_from_source;
// Binding base for a single option.
uint32_t arg_base = 0;
// What kind of uniform variable are we setting the binding base for?
shaderc_uniform_kind u_kind = shaderc_uniform_kind_buffer;
// Sets binding base for the given uniform kind. If stage is
// shader_glsl_infer_from_source then set it for all shader stages.
auto set_binding_base = [&compiler](
shaderc_shader_kind stage, shaderc_uniform_kind kind, uint32_t base) {
if (stage == shaderc_glsl_infer_from_source)
compiler.options().SetBindingBase(kind, base);
else
compiler.options().SetBindingBaseForStage(stage, kind, base);
};
for (int i = 1; i < argc; ++i) {
const string_piece arg = argv[i];
if (arg == "--help" || arg == "-h") {
::PrintHelp(&std::cout);
return 0;
} else if (arg == "--show-limits") {
shaderc_util::Compiler default_compiler;
// The static cast here depends on us keeping the shaderc_limit enum in
// lockstep with the shaderc_util::Compiler::Limit enum. The risk of mismatch
// is low since both are generated from the same resources.inc file.
#define RESOURCE(NAME, FIELD, ENUM) \
std::cout << #NAME << " " \
<< default_compiler.GetLimit( \
static_cast<shaderc_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)
<< std::endl;
return 0;
} else if (arg.starts_with("-o")) {
string_piece file_name;
if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-o", &file_name)) {
std::cerr
<< "glslc: error: argument to '-o' is missing (expected 1 value)"
<< std::endl;
return 1;
}
compiler.SetOutputFileName(file_name);
} else if (arg.starts_with("-fshader-stage=")) {
const string_piece stage = arg.substr(std::strlen("-fshader-stage="));
current_fshader_stage = glslc::GetForcedShaderKindFromCmdLine(arg);
if (current_fshader_stage == shaderc_glsl_infer_from_source) {
std::cerr << "glslc: error: stage not recognized: '" << stage << "'"
<< std::endl;
return 1;
}
} else if (arg == "-fauto-bind-uniforms") {
compiler.options().SetAutoBindUniforms(true);
} else if (arg == "-fauto-combined-image-sampler") {
compiler.options().SetAutoSampledTextures(true);
} else if (arg == "-fauto-map-locations") {
compiler.options().SetAutoMapLocations(true);
} else if (arg == "-fhlsl-iomap") {
compiler.options().SetHlslIoMapping(true);
} else if (arg == "-fhlsl-offsets") {
compiler.options().SetHlslOffsets(true);
} else if (arg == "-fhlsl_functionality1" ||
arg == "-fhlsl-functionality1") {
compiler.options().SetHlslFunctionality1(true);
} else if (arg == "-fhlsl-16bit-types") {
compiler.options().SetHlsl16BitTypes(true);
} else if (arg == "-finvert-y") {
compiler.options().SetInvertY(true);
} else if (arg == "-fnan-clamp") {
compiler.options().SetNanClamp(true);
} else if (arg.starts_with("-fpreserve-bindings")) {
compiler.options().SetPreserveBindings(true);
} else if (((u_kind = shaderc_uniform_kind_image),
(arg == "-fimage-binding-base")) ||
((u_kind = shaderc_uniform_kind_texture),
(arg == "-ftexture-binding-base")) ||
((u_kind = shaderc_uniform_kind_sampler),
(arg == "-fsampler-binding-base")) ||
((u_kind = shaderc_uniform_kind_buffer),
(arg == "-fubo-binding-base")) ||
((u_kind = shaderc_uniform_kind_buffer),
(arg == "-fcbuffer-binding-base")) ||
((u_kind = shaderc_uniform_kind_storage_buffer),
(arg == "-fssbo-binding-base")) ||
((u_kind = shaderc_uniform_kind_unordered_access_view),
(arg == "-fuav-binding-base"))) {
if (!GetOptionalStageThenOffsetArgument(arg, &std::cerr, argc, argv, &i,
&arg_stage, &arg_base))
return 1;
set_binding_base(arg_stage, u_kind, arg_base);
} else if (arg == "-fresource-set-binding") {
auto need_three_args_err = []() {
std::cerr << "glsc: error: Option -fresource-set-binding"
<< " requires at least 3 arguments" << std::endl;
return 1;
};
if (i + 1 >= argc) return need_three_args_err();
auto stage = glslc::MapStageNameToForcedKind(argv[i + 1]);
if (stage != shaderc_glsl_infer_from_source) {
++i;
}
bool seen_triple = false;
while (i + 3 < argc && argv[i + 1][0] != '-' && argv[i + 2][0] != '-' &&
argv[i + 3][0] != '-') {
seen_triple = true;
uint32_t set = 0;
if (!shaderc_util::ParseUint32(argv[i + 2], &set)) {
std::cerr << "glslc: error: Invalid set number: " << argv[i + 2]
<< std::endl;
return 1;
}
uint32_t binding = 0;
if (!shaderc_util::ParseUint32(argv[i + 3], &binding)) {
std::cerr << "glslc: error: Invalid binding number: " << argv[i + 3]
<< std::endl;
return 1;
}
if (stage == shaderc_glsl_infer_from_source) {
compiler.options().SetHlslRegisterSetAndBinding(
argv[i + 1], argv[i + 2], argv[i + 3]);
} else {
compiler.options().SetHlslRegisterSetAndBindingForStage(
stage, argv[i + 1], argv[i + 2], argv[i + 3]);
}
i += 3;
}
if (!seen_triple) return need_three_args_err();
} else if (arg.starts_with("-fentry-point=")) {
current_entry_point_name =
arg.substr(std::strlen("-fentry-point=")).str();
} else if (arg.starts_with("-flimit=")) {
std::string err;
if (!SetResourceLimits(arg.substr(std::strlen("-flimit=")).str(),
&compiler.options(), &err)) {
std::cerr << "glslc: error: -flimit error: " << err << std::endl;
return 1;
}
} else if (arg.starts_with("-flimit-file")) {
std::string err;
string_piece limits_file;
if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-flimit-file",
&limits_file)) {
std::cerr << "glslc: error: argument to '-flimit-file' is missing"
<< std::endl;
return 1;
}
std::vector<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;
shaderc_profile profile;
if (!shaderc_parse_version_profile(standard.begin(), &version,
&profile)) {
std::cerr << "glslc: error: invalid value '" << standard
<< "' in '-std=" << standard << "'" << std::endl;
return 1;
}
compiler.options().SetForcedVersionProfile(version, profile);
} else if (arg.starts_with("--target-env=")) {
shaderc_target_env target_env = shaderc_target_env_default;
const string_piece target_env_str =
arg.substr(std::strlen("--target-env="));
uint32_t version = 0; // Will default appropriately.
if (target_env_str == "vulkan") {
target_env = shaderc_target_env_vulkan;
} else if (target_env_str == "vulkan1.0") {
target_env = shaderc_target_env_vulkan;
version = shaderc_env_version_vulkan_1_0;
} else if (target_env_str == "vulkan1.1") {
target_env = shaderc_target_env_vulkan;
version = shaderc_env_version_vulkan_1_1;
} else if (target_env_str == "vulkan1.2") {
target_env = shaderc_target_env_vulkan;
version = shaderc_env_version_vulkan_1_2;
} else if (target_env_str == "vulkan1.3") {
target_env = shaderc_target_env_vulkan;
version = shaderc_env_version_vulkan_1_3;
} else if (target_env_str == "opengl") {
target_env = shaderc_target_env_opengl;
} else if (target_env_str == "opengl4.5") {
target_env = shaderc_target_env_opengl;
version = shaderc_env_version_opengl_4_5;
} else if (target_env_str == "opengl_compat") {
target_env = shaderc_target_env_opengl_compat;
std::cerr << "glslc: error: opengl_compat is no longer supported"
<< std::endl;
return 1;
} else {
std::cerr << "glslc: error: invalid value '" << target_env_str
<< "' in '--target-env=" << target_env_str << "'"
<< std::endl;
return 1;
}
compiler.options().SetTargetEnvironment(target_env, version);
} else if (arg.starts_with("--target-spv=")) {
shaderc_spirv_version ver = shaderc_spirv_version_1_0;
const string_piece ver_str = arg.substr(std::strlen("--target-spv="));
if (ver_str == "spv1.0") {
ver = shaderc_spirv_version_1_0;
} else if (ver_str == "spv1.1") {
ver = shaderc_spirv_version_1_1;
} else if (ver_str == "spv1.2") {
ver = shaderc_spirv_version_1_2;
} else if (ver_str == "spv1.3") {
ver = shaderc_spirv_version_1_3;
} else if (ver_str == "spv1.4") {
ver = shaderc_spirv_version_1_4;
} else if (ver_str == "spv1.5") {
ver = shaderc_spirv_version_1_5;
} else if (ver_str == "spv1.6") {
ver = shaderc_spirv_version_1_6;
} else {
std::cerr << "glslc: error: invalid value '" << ver_str
<< "' in '--target-spv=" << ver_str << "'" << std::endl;
return 1;
}
compiler.options().SetTargetSpirv(ver);
} else if (arg.starts_with("-mfmt=")) {
const string_piece binary_output_format =
arg.substr(std::strlen("-mfmt="));
if (binary_output_format == "bin") {
compiler.SetSpirvBinaryOutputFormat(
glslc::FileCompiler::SpirvBinaryEmissionFormat::Binary);
} else if (binary_output_format == "num") {
compiler.SetSpirvBinaryOutputFormat(
glslc::FileCompiler::SpirvBinaryEmissionFormat::Numbers);
} else if (binary_output_format == "c") {
compiler.SetSpirvBinaryOutputFormat(
glslc::FileCompiler::SpirvBinaryEmissionFormat::CInitList);
} else if (binary_output_format == "wgsl") {
compiler.SetSpirvBinaryOutputFormat(
glslc::FileCompiler::SpirvBinaryEmissionFormat::WGSL);
} else {
std::cerr << "glslc: error: invalid value '" << binary_output_format
<< "' in '-mfmt=" << binary_output_format << "'" << std::endl;
return 1;
}
} else if (arg.starts_with("-x")) {
string_piece option_arg;
if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-x", &option_arg)) {
std::cerr
<< "glslc: error: argument to '-x' is missing (expected 1 value)"
<< std::endl;
success = false;
} else {
if (option_arg == "glsl") {
current_source_language = shaderc_source_language_glsl;
} else if (option_arg == "hlsl") {
current_source_language = shaderc_source_language_hlsl;
} else {
std::cerr << "glslc: error: language not recognized: '" << option_arg
<< "'" << std::endl;
return 1;
}
source_language_forced = true;
}
} else if (arg == "-c") {
compiler.SetIndividualCompilationFlag();
} else if (arg == "-E") {
compiler.SetPreprocessingOnlyFlag();
} else if (arg == "-M" || arg == "-MM") {
// -M implies -E and -w
compiler.SetPreprocessingOnlyFlag();
compiler.options().SetSuppressWarnings();
if (compiler.GetDependencyDumpingHandler()->DumpingModeNotSet()) {
compiler.GetDependencyDumpingHandler()
->SetDumpAsNormalCompilationOutput();
} else {
std::cerr << "glslc: error: both -M (or -MM) and -MD are specified. "
"Only one should be used at one time."
<< std::endl;
return 1;
}
} else if (arg == "-MD") {
if (compiler.GetDependencyDumpingHandler()->DumpingModeNotSet()) {
compiler.GetDependencyDumpingHandler()
->SetDumpToExtraDependencyInfoFiles();
} else {
std::cerr << "glslc: error: both -M (or -MM) and -MD are specified. "
"Only one should be used at one time."
<< std::endl;
return 1;
}
} else if (arg == "-MF") {
string_piece dep_file_name;
if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-MF",
&dep_file_name)) {
std::cerr
<< "glslc: error: missing dependency info filename after '-MF'"
<< std::endl;
return 1;
}
compiler.GetDependencyDumpingHandler()->SetDependencyFileName(
std::string(dep_file_name.data(), dep_file_name.size()));
} else if (arg == "-MT") {
string_piece dep_file_name;
if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-MT",
&dep_file_name)) {
std::cerr << "glslc: error: missing dependency info target after '-MT'"
<< std::endl;
return 1;
}
compiler.GetDependencyDumpingHandler()->SetTarget(
std::string(dep_file_name.data(), dep_file_name.size()));
} else if (arg == "-S") {
compiler.SetDisassemblyFlag();
} else if (arg.starts_with("-D")) {
const size_t length = arg.size();
if (length <= 2) {
std::cerr << "glslc: error: argument to '-D' is missing" << std::endl;
} else {
const string_piece argument = arg.substr(2);
// Get the exact length of the macro string.
size_t equal_sign_loc = argument.find_first_of('=');
size_t name_length = equal_sign_loc != shaderc_util::string_piece::npos
? equal_sign_loc
: argument.size();
const string_piece name_piece = argument.substr(0, name_length);
if (name_piece.starts_with("GL_")) {
std::cerr
<< "glslc: error: names beginning with 'GL_' cannot be defined: "
<< arg << std::endl;
return 1;
}
if (name_piece.find("__") != string_piece::npos) {
std::cerr
<< "glslc: warning: names containing consecutive underscores "
"are reserved: "
<< arg << std::endl;
}
const string_piece value_piece =
(equal_sign_loc == string_piece::npos ||
equal_sign_loc == argument.size() - 1)
? ""
: argument.substr(name_length + 1);
// TODO(deki): check arg for newlines.
compiler.options().AddMacroDefinition(
name_piece.data(), name_piece.size(), value_piece.data(),
value_piece.size());
}
} else if (arg.starts_with("-I")) {
string_piece option_arg;
if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-I", &option_arg)) {
std::cerr
<< "glslc: error: argument to '-I' is missing (expected 1 value)"
<< std::endl;
success = false;
} else {
compiler.AddIncludeDirectory(option_arg.str());
}
} else if (arg == "-g") {
compiler.options().SetGenerateDebugInfo();
} else if (arg.starts_with("-O")) {
if (arg == "-O") {
compiler.options().SetOptimizationLevel(
shaderc_optimization_level_performance);
} else if (arg == "-Os") {
compiler.options().SetOptimizationLevel(
shaderc_optimization_level_size);
} else if (arg == "-O0") {
compiler.options().SetOptimizationLevel(
shaderc_optimization_level_zero);
} else {
std::cerr << "glslc: error: invalid value '"
<< arg.substr(std::strlen("-O")) << "' in '" << arg << "'"
<< std::endl;
return 1;
}
} else if (arg == "-w") {
compiler.options().SetSuppressWarnings();
} else if (arg == "-Werror") {
compiler.options().SetWarningsAsErrors();
} else if (!(arg == "-") && arg[0] == '-') {
std::cerr << "glslc: error: "
<< (arg[1] == '-' ? "unsupported option" : "unknown argument")
<< ": '" << arg << "'" << std::endl;
return 1;
} else {
if (arg == "-") {
if (has_stdin_input) {
std::cerr << "glslc: error: specifying standard input \"-\" as input "
<< "more than once is not allowed." << std::endl;
return 1;
}
has_stdin_input = true;
}
const auto language = source_language_forced
? current_source_language
: ((glslc::GetFileExtension(arg) == "hlsl")
? shaderc_source_language_hlsl
: shaderc_source_language_glsl);
// If current_fshader_stage is shaderc_glsl_infer_from_source, that means
// we didn't set forced shader kinds (otherwise an error should have
// already been emitted before). So we should deduce the shader kind
// from the file name. If current_fshader_stage is specifed to one of
// the forced shader kinds, use that for the following compilation.
input_files.emplace_back(glslc::InputFileSpec{
arg.str(), (current_fshader_stage == shaderc_glsl_infer_from_source
? glslc::DeduceDefaultShaderKindFromFileName(arg)
: current_fshader_stage),
language, current_entry_point_name});
}
}
if (!compiler.ValidateOptions(input_files.size())) return 1;
if (!success) return 1;
for (const auto& input_file : input_files) {
success &= compiler.CompileShaderFile(input_file);
}
compiler.OutputMessages();
return success ? 0 : 1;
}

View File

@@ -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

View File

@@ -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_

View File

@@ -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

View File

@@ -0,0 +1,100 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "shader_stage.h"
#include "file.h"
using shaderc_util::string_piece;
namespace {
// Maps an identifier to a shader stage.
struct StageMapping {
const char* id;
shaderc_shader_kind stage;
};
} // anonymous namespace
namespace glslc {
shaderc_shader_kind MapStageNameToForcedKind(const string_piece& stage_name) {
const StageMapping string_to_kind[] = {
{"vertex", shaderc_glsl_vertex_shader},
{"vert", shaderc_glsl_vertex_shader},
{"fragment", shaderc_glsl_fragment_shader},
{"frag", shaderc_glsl_fragment_shader},
{"tesscontrol", shaderc_glsl_tess_control_shader},
{"tesc", shaderc_glsl_tess_control_shader},
{"tesseval", shaderc_glsl_tess_evaluation_shader},
{"tese", shaderc_glsl_tess_evaluation_shader},
{"geometry", shaderc_glsl_geometry_shader},
{"geom", shaderc_glsl_geometry_shader},
{"compute", shaderc_glsl_compute_shader},
{"comp", shaderc_glsl_compute_shader},
{"rgen", shaderc_glsl_raygen_shader },
{"rahit", shaderc_glsl_anyhit_shader },
{"rchit", shaderc_glsl_closesthit_shader },
{"rmiss", shaderc_glsl_miss_shader },
{"rint", shaderc_glsl_intersection_shader },
{"rcall", shaderc_glsl_callable_shader },
{"task", shaderc_glsl_task_shader },
{"mesh", shaderc_glsl_mesh_shader },
};
for (const auto& entry : string_to_kind) {
if (stage_name == entry.id) return entry.stage;
}
return shaderc_glsl_infer_from_source;
}
shaderc_shader_kind GetForcedShaderKindFromCmdLine(
const shaderc_util::string_piece& f_shader_stage_str) {
size_t equal_pos = f_shader_stage_str.find_first_of("=");
if (equal_pos == std::string::npos) return shaderc_glsl_infer_from_source;
return MapStageNameToForcedKind(f_shader_stage_str.substr(equal_pos + 1));
}
shaderc_shader_kind DeduceDefaultShaderKindFromFileName(
const string_piece file_name) {
// Add new stage types here.
static const StageMapping kStringToStage[] = {
{"vert", shaderc_glsl_default_vertex_shader},
{"frag", shaderc_glsl_default_fragment_shader},
{"tesc", shaderc_glsl_default_tess_control_shader},
{"tese", shaderc_glsl_default_tess_evaluation_shader},
{"geom", shaderc_glsl_default_geometry_shader},
{"comp", shaderc_glsl_default_compute_shader},
{"spvasm", shaderc_spirv_assembly},
{"rgen", shaderc_glsl_default_raygen_shader },
{"rahit", shaderc_glsl_default_anyhit_shader },
{"rchit", shaderc_glsl_default_closesthit_shader },
{"rmiss", shaderc_glsl_default_miss_shader },
{"rint", shaderc_glsl_default_intersection_shader },
{"rcall", shaderc_glsl_default_callable_shader },
{"task", shaderc_glsl_default_task_shader },
{"mesh", shaderc_glsl_default_mesh_shader },
};
const string_piece extension = glslc::GetFileExtension(file_name);
shaderc_shader_kind stage = shaderc_glsl_infer_from_source;
for (const auto& entry : kStringToStage) {
if (extension == entry.id) stage = entry.stage;
}
return stage;
}
} // namespace glslc

View File

@@ -0,0 +1,42 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GLSLC_SHADER_STAGE_H_
#define GLSLC_SHADER_STAGE_H_
#include <ostream>
#include "libshaderc_util/string_piece.h"
#include "shaderc/shaderc.h"
namespace glslc {
// Maps a shader stage name to a forced shader stage enum value. Returns
// 'shaderc_glsl_infer_from_source' if the stage name is unrecognized.
shaderc_shader_kind MapStageNameToForcedKind(
const shaderc_util::string_piece& f_shader_stage_str);
// Parse the string piece from command line to get the force shader stage.
// If the 'f_shader_stage_str' cannot be parsed to a valid force shader stage,
// returns 'shaderc_glsl_infer_from_source'. Requires the string to begin with
// '='.
shaderc_shader_kind GetForcedShaderKindFromCmdLine(
const shaderc_util::string_piece& f_shader_stage_str);
// Parse the file name extension to get the default shader kind.
shaderc_shader_kind DeduceDefaultShaderKindFromFileName(
shaderc_util::string_piece file_name);
} // namespace glslc
#endif // GLSLC_SHADER_STAGE_H_

View File

@@ -0,0 +1,92 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Some of the tests here check code paths that are not checked by
// integration tests.
// Generally, these would be conditions not generated by the Glslang
// compiler. It's easier to write these unit tests than to inject
// a dependency on a fake compiler.
#include <sstream>
#include <gtest/gtest.h>
#include "shaderc/shaderc.h"
#include "shader_stage.h"
using shaderc_util::string_piece;
namespace {
TEST(DeduceDefaultShaderKindFromFileName, ValidStage) {
std::stringstream error_stream;
EXPECT_EQ(shaderc_glsl_default_vertex_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.vert"));
EXPECT_EQ(shaderc_glsl_default_fragment_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.frag"));
EXPECT_EQ(shaderc_glsl_default_geometry_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.geom"));
EXPECT_EQ(shaderc_glsl_default_tess_control_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.tesc"));
EXPECT_EQ(shaderc_glsl_default_tess_evaluation_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.tese"));
EXPECT_EQ(shaderc_glsl_default_compute_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.comp"));
EXPECT_EQ(shaderc_glsl_default_raygen_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.rgen"));
EXPECT_EQ(shaderc_glsl_default_anyhit_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.rahit"));
EXPECT_EQ(shaderc_glsl_default_closesthit_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.rchit"));
EXPECT_EQ(shaderc_glsl_default_miss_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.rmiss"));
EXPECT_EQ(shaderc_glsl_default_intersection_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.rint"));
EXPECT_EQ(shaderc_glsl_default_callable_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.rcall"));
EXPECT_EQ(shaderc_glsl_default_task_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.task"));
EXPECT_EQ(shaderc_glsl_default_mesh_shader,
glslc::DeduceDefaultShaderKindFromFileName("a.mesh"));
}
TEST(DeduceDefaultShaderKindFromFileName, InvalidStage) {
std::stringstream error_stream;
EXPECT_EQ(shaderc_glsl_infer_from_source,
glslc::DeduceDefaultShaderKindFromFileName("a.glsl"));
EXPECT_EQ(shaderc_glsl_infer_from_source,
glslc::DeduceDefaultShaderKindFromFileName("-"));
EXPECT_EQ(shaderc_glsl_infer_from_source,
glslc::DeduceDefaultShaderKindFromFileName("a.foo"));
EXPECT_EQ(shaderc_glsl_infer_from_source,
glslc::DeduceDefaultShaderKindFromFileName("no-file-extension"));
}
} // anonymous namespace

View File

@@ -0,0 +1,28 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
add_test(NAME shaderc_expect_unittests
COMMAND ${Python_EXECUTABLE} -m unittest expect_unittest.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_test(NAME shaderc_glslc_test_framework_unittests
COMMAND ${Python_EXECUTABLE} -m unittest glslc_test_framework_unittest.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
if(${SHADERC_ENABLE_TESTS})
add_test(NAME glslc_tests
COMMAND ${Python_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/glslc_test_framework.py
$<TARGET_FILE:glslc_exe> $<TARGET_FILE:spirv-dis>
--test-dir ${CMAKE_CURRENT_SOURCE_DIR})
endif()

140
3rdparty/shaderc/glslc/test/assembly.py vendored Normal file
View File

@@ -0,0 +1,140 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
def assembly_comments():
return """
; SPIR-V
; Version: 1.0
; Generator: Google Shaderc over Glslang; 11
; Bound: 6
; Schema: 0"""
def empty_main_assembly():
return assembly_comments() + """
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %4 "main"
OpSource ESSL 310
OpName %4 "main"
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd"""
def empty_main():
return '#version 310 es\nvoid main() {}'
@inside_glslc_testsuite('SpirvAssembly')
class TestAssemblyFileAsOnlyParameter(expect.ValidNamedObjectFile):
"""Tests that glslc accepts a SPIR-V assembly file as the only parameter."""
shader = FileShader(empty_main_assembly(), '.spvasm')
glslc_args = [shader]
expected_object_filenames = ('a.spv',)
@inside_glslc_testsuite('SpirvAssembly')
class TestDashCAssemblyFile(expect.ValidObjectFile):
"""Tests that -c works with SPIR-V assembly file."""
shader = FileShader(empty_main_assembly(), '.spvasm')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('SpirvAssembly')
class TestAssemblyFileWithOnlyComments(expect.ValidObjectFile):
"""Tests that glslc accepts an assembly file with only comments inside."""
shader = FileShader(assembly_comments(), '.spvasm')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('SpirvAssembly')
class TestEmptyAssemblyFile(expect.ValidObjectFile):
"""Tests that glslc accepts an empty assembly file."""
shader = FileShader('', '.spvasm')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('SpirvAssembly')
class TestDashEAssemblyFile(expect.SuccessfulReturn, expect.NoGeneratedFiles):
"""Tests that -E works with SPIR-V assembly file."""
shader = FileShader(empty_main_assembly(), '.spvasm')
glslc_args = ['-E', shader]
@inside_glslc_testsuite('SpirvAssembly')
class TestDashSAssemblyFile(expect.SuccessfulReturn, expect.NoGeneratedFiles):
"""Tests that -S works with SPIR-V assembly file."""
shader = FileShader(empty_main_assembly(), '.spvasm')
glslc_args = ['-S', shader]
@inside_glslc_testsuite('SpirvAssembly')
class TestMultipleAssemblyFiles(expect.ValidObjectFile):
"""Tests that glslc accepts multiple SPIR-V assembly files."""
shader1 = FileShader(empty_main_assembly(), '.spvasm')
shader2 = FileShader(empty_main_assembly(), '.spvasm')
shader3 = FileShader(empty_main_assembly(), '.spvasm')
glslc_args = ['-c', shader1, shader2, shader3]
@inside_glslc_testsuite('SpirvAssembly')
class TestHybridInputFiles(expect.ValidObjectFile):
"""Tests that glslc accepts a mix of SPIR-V assembly files and
GLSL source files."""
shader1 = FileShader(empty_main_assembly(), '.spvasm')
shader2 = FileShader(empty_main(), '.vert')
shader3 = FileShader(empty_main(), '.frag')
glslc_args = ['-c', shader1, shader2, shader3]
@inside_glslc_testsuite('SpirvAssembly')
class TestShaderStageWithAssemblyFile(expect.ErrorMessage):
"""Tests that assembly files don't work with -fshader-stage"""
shader = FileShader(empty_main_assembly(), '.spvasm')
glslc_args = ['-c', '-fshader-stage=vertex', shader]
expected_error = [
shader, ": error: #version: Desktop shaders for Vulkan SPIR-V require "
"version 140 or higher\n",
shader, ":2: error: 'extraneous semicolon' :",
" not supported for this version or the enabled extensions\n",
shader, ":2: error: '' : syntax error, unexpected IDENTIFIER\n",
'3 errors generated.\n']
@inside_glslc_testsuite('SpirvAssembly')
class TestStdWithAssemblyFile(expect.ValidObjectFile):
"""Tests that --std= doesn't affect the processing of assembly files."""
shader = FileShader(empty_main_assembly(), '.spvasm')
glslc_args = ['-c', '-std=310es', shader]

View File

@@ -0,0 +1,72 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Classes for conveniently specifying a test environment.
These classes have write() methods that create objects in a test's environment.
For instance, File creates a file, and Directory creates a directory with some
files or subdirectories in it.
Example:
test.environment = Directory('.', [
File('a.vert', 'void main(){}'),
Directory('subdir', [
File('b', 'b content'),
File('c', 'c content')
])
])
In general, these classes don't clean up the disk content they create. They
were written in a test framework that handles clean-up at a higher level.
"""
import os
class Directory:
"""Specifies a directory or a subdirectory."""
def __init__(self, name, content):
"""content is a list of File or Directory objects."""
self.name = name
self.content = content
@staticmethod
def create(path):
"""Creates a directory path if it doesn't already exist."""
try:
os.makedirs(path)
except OSError: # Handles both pre-existence and a racing creation.
if not os.path.isdir(path):
raise
def write(self, parent):
"""Creates a self.name directory within parent (which is a string path) and
recursively writes the content in it.
"""
full_path = os.path.join(parent, self.name)
Directory.create(full_path)
for c in self.content:
c.write(full_path)
class File:
"""Specifies a file by name and content."""
def __init__(self, name, content):
self.name = name
self.content = content
def write(self, directory):
"""Writes content to directory/name."""
with open(os.path.join(directory, self.name), 'w') as f:
f.write(self.content)

View File

@@ -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']

707
3rdparty/shaderc/glslc/test/expect.py vendored Normal file
View File

@@ -0,0 +1,707 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A number of common glslc result checks coded in mixin classes.
A test case can use these checks by declaring their enclosing mixin classes
as superclass and providing the expected_* variables required by the check_*()
methods in the mixin classes.
"""
import difflib
import functools
import os
import re
import subprocess
import sys
from glslc_test_framework import GlslCTest
from builtins import bytes
GLSLANG_GENERATOR_VERSION=11
SHADERC_GENERATOR_NUMBER=13
SHADERC_GENERATOR_WORD=(SHADERC_GENERATOR_NUMBER << 16) + GLSLANG_GENERATOR_VERSION
ASSEMBLER_GENERATOR_WORD=(7<<16)
def convert_to_string(input):
if type(input) is not str:
if sys.version_info[0] == 2:
return input.decode('utf-8')
elif sys.version_info[0] == 3:
return str(input,
encoding='utf-8',
errors='ignore') if input is not None else input
else:
raise Exception(
'Unable to determine if running Python 2 or 3 from {}'.format(
sys.version_info))
else:
return input
def convert_to_unix_line_endings(source):
"""Converts all line endings in source to be unix line endings."""
return source.replace('\r\n', '\n').replace('\r', '\n')
def substitute_file_extension(filename, extension):
"""Substitutes file extension, respecting known shader extensions.
foo.vert -> foo.vert.[extension] [similarly for .frag, .comp, etc.]
foo.glsl -> foo.[extension]
foo.unknown -> foo.[extension]
foo -> foo.[extension]
"""
if filename[-5:] not in ['.vert', '.frag', '.tesc', '.tese',
'.geom', '.comp', '.spvasm']:
return filename.rsplit('.', 1)[0] + '.' + extension
else:
return filename + '.' + extension
def get_object_filename(source_filename):
"""Gets the object filename for the given source file."""
return substitute_file_extension(source_filename, 'spv')
def get_assembly_filename(source_filename):
"""Gets the assembly filename for the given source file."""
return substitute_file_extension(source_filename, 'spvasm')
def verify_file_non_empty(filename):
"""Checks that a given file exists and is not empty."""
if not os.path.isfile(filename):
return False, 'Cannot find file: ' + filename
if not os.path.getsize(filename):
return False, 'Empty file: ' + filename
return True, ''
class ReturnCodeIsZero(GlslCTest):
"""Mixin class for checking that the return code is zero."""
def check_return_code_is_zero(self, status):
if status.returncode:
return False, 'Non-zero return code: {ret}\n'.format(
ret=status.returncode)
return True, ''
class NoOutputOnStdout(GlslCTest):
"""Mixin class for checking that there is no output on stdout."""
def check_no_output_on_stdout(self, status):
if status.stdout:
return False, 'Non empty stdout: {out}\n'.format(out=status.stdout)
return True, ''
class NoOutputOnStderr(GlslCTest):
"""Mixin class for checking that there is no output on stderr."""
def check_no_output_on_stderr(self, status):
if status.stderr:
return False, 'Non empty stderr: {err}\n'.format(err=status.stderr)
return True, ''
class SuccessfulReturn(ReturnCodeIsZero, NoOutputOnStdout, NoOutputOnStderr):
"""Mixin class for checking that return code is zero and no output on
stdout and stderr."""
pass
class NoGeneratedFiles(GlslCTest):
"""Mixin class for checking that there is no file generated."""
def check_no_generated_files(self, status):
all_files = os.listdir(status.directory)
input_files = status.input_filenames
if all([f.startswith(status.directory) for f in input_files]):
all_files = [os.path.join(status.directory, f) for f in all_files]
generated_files = set(all_files) - set(input_files)
if len(generated_files) == 0:
return True, ''
else:
return False, 'Extra files generated: {}'.format(generated_files)
class CorrectBinaryLengthAndPreamble(GlslCTest):
"""Provides methods for verifying preamble for a SPIR-V binary."""
def verify_binary_length_and_header(self, binary, spv_version = 0x10000):
"""Checks that the given SPIR-V binary has valid length and header.
Returns:
False, error string if anything is invalid
True, '' otherwise
Args:
binary: a bytes object containing the SPIR-V binary
spv_version: target SPIR-V version number, with same encoding
as the version word in a SPIR-V header.
"""
def read_word(binary, index, little_endian):
"""Reads the index-th word from the given binary file."""
word = binary[index * 4:(index + 1) * 4]
if little_endian:
word = reversed(word)
return functools.reduce(lambda w, b: (w << 8) | b, word, 0)
def check_endianness(binary):
"""Checks the endianness of the given SPIR-V binary.
Returns:
True if it's little endian, False if it's big endian.
None if magic number is wrong.
"""
first_word = read_word(binary, 0, True)
if first_word == 0x07230203:
return True
first_word = read_word(binary, 0, False)
if first_word == 0x07230203:
return False
return None
num_bytes = len(binary)
if num_bytes % 4 != 0:
return False, ('Incorrect SPV binary: size should be a multiple'
' of words')
if num_bytes < 20:
return False, 'Incorrect SPV binary: size less than 5 words'
preamble = binary[0:19]
little_endian = check_endianness(preamble)
# SPIR-V module magic number
if little_endian is None:
return False, 'Incorrect SPV binary: wrong magic number'
# SPIR-V version number
version = read_word(preamble, 1, little_endian)
# TODO(dneto): Recent Glslang uses version word 0 for opengl_compat
# profile
if version != spv_version and version != 0:
return False, 'Incorrect SPV binary: wrong version number'
# Shaderc-over-Glslang (0x000d....) or
# SPIRV-Tools (0x0007....) generator number
if read_word(preamble, 2, little_endian) != SHADERC_GENERATOR_WORD and \
read_word(preamble, 2, little_endian) != ASSEMBLER_GENERATOR_WORD:
return False, ('Incorrect SPV binary: wrong generator magic '
'number')
# reserved for instruction schema
if read_word(preamble, 4, little_endian) != 0:
return False, 'Incorrect SPV binary: the 5th byte should be 0'
return True, ''
class CorrectObjectFilePreamble(CorrectBinaryLengthAndPreamble):
"""Provides methods for verifying preamble for a SPV object file."""
def verify_object_file_preamble(self, filename, spv_version = 0x10000):
"""Checks that the given SPIR-V binary file has correct preamble."""
success, message = verify_file_non_empty(filename)
if not success:
return False, message
with open(filename, 'rb') as object_file:
object_file.seek(0, os.SEEK_END)
num_bytes = object_file.tell()
object_file.seek(0)
binary = bytes(object_file.read())
return self.verify_binary_length_and_header(binary, spv_version)
return True, ''
class CorrectAssemblyFilePreamble(GlslCTest):
"""Provides methods for verifying preamble for a SPV assembly file."""
def verify_assembly_file_preamble(self, filename):
success, message = verify_file_non_empty(filename)
if not success:
return False, message
with open(filename) as assembly_file:
line1 = assembly_file.readline()
line2 = assembly_file.readline()
line3 = assembly_file.readline()
if (line1 != '; SPIR-V\n' or
line2 != '; Version: 1.0\n' or
(not line3.startswith('; Generator: Google Shaderc over Glslang;'))):
return False, 'Incorrect SPV assembly'
return True, ''
class ValidObjectFile(SuccessfulReturn, CorrectObjectFilePreamble):
"""Mixin class for checking that every input file generates a valid SPIR-V 1.0
object file following the object file naming rule, and there is no output on
stdout/stderr."""
def check_object_file_preamble(self, status):
for input_filename in status.input_filenames:
object_filename = get_object_filename(input_filename)
success, message = self.verify_object_file_preamble(
os.path.join(status.directory, object_filename))
if not success:
return False, message
return True, ''
class ValidObjectFile1_3(SuccessfulReturn, CorrectObjectFilePreamble):
"""Mixin class for checking that every input file generates a valid SPIR-V 1.3
object file following the object file naming rule, and there is no output on
stdout/stderr."""
def check_object_file_preamble(self, status):
for input_filename in status.input_filenames:
object_filename = get_object_filename(input_filename)
success, message = self.verify_object_file_preamble(
os.path.join(status.directory, object_filename),
0x10300)
if not success:
return False, message
return True, ''
class ValidObjectFile1_4(SuccessfulReturn, CorrectObjectFilePreamble):
"""Mixin class for checking that every input file generates a valid SPIR-V 1.4
object file following the object file naming rule, and there is no output on
stdout/stderr."""
def check_object_file_preamble(self, status):
for input_filename in status.input_filenames:
object_filename = get_object_filename(input_filename)
success, message = self.verify_object_file_preamble(
os.path.join(status.directory, object_filename),
0x10400)
if not success:
return False, message
return True, ''
class ValidObjectFile1_5(SuccessfulReturn, CorrectObjectFilePreamble):
"""Mixin class for checking that every input file generates a valid SPIR-V 1.5
object file following the object file naming rule, and there is no output on
stdout/stderr."""
def check_object_file_preamble(self, status):
for input_filename in status.input_filenames:
object_filename = get_object_filename(input_filename)
success, message = self.verify_object_file_preamble(
os.path.join(status.directory, object_filename),
0x10500)
if not success:
return False, message
return True, ''
class ValidObjectFile1_6(SuccessfulReturn, CorrectObjectFilePreamble):
"""Mixin class for checking that every input file generates a valid SPIR-V 1.6
object file following the object file naming rule, and there is no output on
stdout/stderr."""
def check_object_file_preamble(self, status):
for input_filename in status.input_filenames:
object_filename = get_object_filename(input_filename)
success, message = self.verify_object_file_preamble(
os.path.join(status.directory, object_filename),
0x10600)
if not success:
return False, message
return True, ''
class ValidObjectFileWithAssemblySubstr(SuccessfulReturn, CorrectObjectFilePreamble):
"""Mixin class for checking that every input file generates a valid object
file following the object file naming rule, there is no output on
stdout/stderr, and the disassmbly contains a specified substring per input."""
def check_object_file_disassembly(self, status):
for an_input in status.inputs:
object_filename = get_object_filename(an_input.filename)
obj_file = str(os.path.join(status.directory, object_filename))
success, message = self.verify_object_file_preamble(obj_file)
if not success:
return False, message
cmd = [status.test_manager.disassembler_path, '--no-color', obj_file]
process = subprocess.Popen(
args=cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, cwd=status.directory)
output = process.communicate(None)
disassembly = output[0]
if not isinstance(an_input.assembly_substr, str):
return False, "Missing assembly_substr member"
if bytes(an_input.assembly_substr, 'utf-8') not in disassembly:
return False, ('Incorrect disassembly output:\n{asm}\n'
'Expected substring not found:\n{exp}'.format(
asm=disassembly, exp=an_input.assembly_substr))
return True, ''
class ValidNamedObjectFile(SuccessfulReturn, CorrectObjectFilePreamble):
"""Mixin class for checking that a list of object files with the given
names are correctly generated, and there is no output on stdout/stderr.
To mix in this class, subclasses need to provide expected_object_filenames
as the expected object filenames.
"""
def check_object_file_preamble(self, status):
for object_filename in self.expected_object_filenames:
success, message = self.verify_object_file_preamble(
os.path.join(status.directory, object_filename))
if not success:
return False, message
return True, ''
class ValidFileContents(GlslCTest):
"""Mixin class to test that a specific file contains specific text
To mix in this class, subclasses need to provide expected_file_contents as
the contents of the file and target_filename to determine the location."""
def check_file(self, status):
target_filename = os.path.join(status.directory, self.target_filename)
if not os.path.isfile(target_filename):
return False, 'Cannot find file: ' + target_filename
with open(target_filename, 'r') as target_file:
file_contents = target_file.read()
if isinstance(self.expected_file_contents, str):
if file_contents == self.expected_file_contents:
return True, ''
return False, ('Incorrect file output: \n{act}\n'
'Expected:\n{exp}'
'With diff:\n{diff}'.format(
act=file_contents,
exp=self.expected_file_contents,
diff='\n'.join(list(difflib.unified_diff(
self.expected_file_contents.split('\n'),
file_contents.split('\n'),
fromfile='expected_output',
tofile='actual_output')))))
elif isinstance(self.expected_file_contents, type(re.compile(''))):
if self.expected_file_contents.search(file_contents):
return True, ''
return False, (
'Incorrect file output: \n{act}\n'
'Expected matching regex pattern:\n{exp}'.format(
act=file_contents,
exp=self.expected_file_contents.pattern))
return False, ('Could not open target file ' + target_filename +
' for reading')
class ValidAssemblyFile(SuccessfulReturn, CorrectAssemblyFilePreamble):
"""Mixin class for checking that every input file generates a valid assembly
file following the assembly file naming rule, and there is no output on
stdout/stderr."""
def check_assembly_file_preamble(self, status):
for input_filename in status.input_filenames:
assembly_filename = get_assembly_filename(input_filename)
success, message = self.verify_assembly_file_preamble(
os.path.join(status.directory, assembly_filename))
if not success:
return False, message
return True, ''
class ValidAssemblyFileWithSubstr(ValidAssemblyFile):
"""Mixin class for checking that every input file generates a valid assembly
file following the assembly file naming rule, there is no output on
stdout/stderr, and all assembly files have the given substring specified
by expected_assembly_substr.
To mix in this class, subclasses need to provde expected_assembly_substr
as the expected substring.
"""
def check_assembly_with_substr(self, status):
for input_filename in status.input_filenames:
assembly_filename = get_assembly_filename(input_filename)
success, message = self.verify_assembly_file_preamble(
os.path.join(status.directory, assembly_filename))
if not success:
return False, message
with open(assembly_filename, 'r') as f:
content = f.read()
if self.expected_assembly_substr not in convert_to_unix_line_endings(content):
return False, ('Incorrect assembly output:\n{asm}\n'
'Expected substring not found:\n{exp}'.format(
asm=content, exp=self.expected_assembly_substr))
return True, ''
class ValidAssemblyFileWithoutSubstr(ValidAssemblyFile):
"""Mixin class for checking that every input file generates a valid assembly
file following the assembly file naming rule, there is no output on
stdout/stderr, and no assembly files have the given substring specified
by unexpected_assembly_substr.
To mix in this class, subclasses need to provde unexpected_assembly_substr
as the substring we expect not to see.
"""
def check_assembly_for_substr(self, status):
for input_filename in status.input_filenames:
assembly_filename = get_assembly_filename(input_filename)
success, message = self.verify_assembly_file_preamble(
os.path.join(status.directory, assembly_filename))
if not success:
return False, message
with open(assembly_filename, 'r') as f:
content = f.read()
if self.unexpected_assembly_substr in convert_to_unix_line_endings(content):
return False, ('Incorrect assembly output:\n{asm}\n'
'Unexpected substring found:\n{unexp}'.format(
asm=content, exp=self.unexpected_assembly_substr))
return True, ''
class ValidNamedAssemblyFile(SuccessfulReturn, CorrectAssemblyFilePreamble):
"""Mixin class for checking that a list of assembly files with the given
names are correctly generated, and there is no output on stdout/stderr.
To mix in this class, subclasses need to provide expected_assembly_filenames
as the expected assembly filenames.
"""
def check_object_file_preamble(self, status):
for assembly_filename in self.expected_assembly_filenames:
success, message = self.verify_assembly_file_preamble(
os.path.join(status.directory, assembly_filename))
if not success:
return False, message
return True, ''
class ErrorMessage(GlslCTest):
"""Mixin class for tests that fail with a specific error message.
To mix in this class, subclasses need to provide expected_error as the
expected error message.
The test should fail if the subprocess was terminated by a signal.
"""
def check_has_error_message(self, status):
if not status.returncode:
return False, ('Expected error message, but returned success from '
'glslc')
if status.returncode < 0:
# On Unix, a negative value -N for Popen.returncode indicates
# termination by signal N.
# https://docs.python.org/2/library/subprocess.html
return False, ('Expected error message, but glslc was terminated by '
'signal ' + str(status.returncode))
if not status.stderr:
return False, 'Expected error message, but no output on stderr'
if self.expected_error != convert_to_unix_line_endings(convert_to_string(status.stderr)):
return False, ('Incorrect stderr output:\n{act}\n'
'Expected:\n{exp}'.format(
act=status.stderr, exp=self.expected_error))
return True, ''
class ErrorMessageSubstr(GlslCTest):
"""Mixin class for tests that fail with a specific substring in the error
message.
To mix in this class, subclasses need to provide expected_error_substr as
the expected error message substring.
The test should fail if the subprocess was terminated by a signal.
"""
def check_has_error_message_as_substring(self, status):
if not status.returncode:
return False, ('Expected error message, but returned success from '
'glslc')
if status.returncode < 0:
# On Unix, a negative value -N for Popen.returncode indicates
# termination by signal N.
# https://docs.python.org/2/library/subprocess.html
return False, ('Expected error message, but glslc was terminated by '
'signal ' + str(status.returncode))
if not status.stderr:
return False, 'Expected error message, but no output on stderr'
if self.expected_error_substr not in convert_to_unix_line_endings(convert_to_string(status.stderr)):
return False, ('Incorrect stderr output:\n{act}\n'
'Expected substring not found in stderr:\n{exp}'.format(
act=status.stderr, exp=self.expected_error_substr))
return True, ''
class WarningMessage(GlslCTest):
"""Mixin class for tests that succeed but have a specific warning message.
To mix in this class, subclasses need to provide expected_warning as the
expected warning message.
"""
def check_has_warning_message(self, status):
if status.returncode:
return False, ('Expected warning message, but returned failure from'
' glslc')
if not status.stderr:
return False, 'Expected warning message, but no output on stderr'
if self.expected_warning != convert_to_unix_line_endings(convert_to_string(status.stderr)):
return False, ('Incorrect stderr output:\n{act}\n'
'Expected:\n{exp}'.format(
act=status.stderr, exp=self.expected_warning))
return True, ''
class ValidObjectFileWithWarning(
NoOutputOnStdout, CorrectObjectFilePreamble, WarningMessage):
"""Mixin class for checking that every input file generates a valid object
file following the object file naming rule, with a specific warning message.
"""
def check_object_file_preamble(self, status):
for input_filename in status.input_filenames:
object_filename = get_object_filename(input_filename)
success, message = self.verify_object_file_preamble(
os.path.join(status.directory, object_filename))
if not success:
return False, message
return True, ''
class ValidAssemblyFileWithWarning(
NoOutputOnStdout, CorrectAssemblyFilePreamble, WarningMessage):
"""Mixin class for checking that every input file generates a valid assembly
file following the assembly file naming rule, with a specific warning
message."""
def check_assembly_file_preamble(self, status):
for input_filename in status.input_filenames:
assembly_filename = get_assembly_filename(input_filename)
success, message = self.verify_assembly_file_preamble(
os.path.join(status.directory, assembly_filename))
if not success:
return False, message
return True, ''
class StdoutMatch(GlslCTest):
"""Mixin class for tests that can expect output on stdout.
To mix in this class, subclasses need to provide expected_stdout as the
expected stdout output.
For expected_stdout, if it's True, then they expect something on stdout but
will not check what it is. If it's a string, expect an exact match. If it's
anything else, expect expected_stdout.search(stdout) to be true.
"""
def check_stdout_match(self, status):
# "True" in this case means we expect something on stdout, but we do not
# care what it is, we want to distinguish this from "blah" which means we
# expect exactly the string "blah".
if self.expected_stdout is True:
if not status.stdout:
return False, 'Expected something on stdout'
elif type(self.expected_stdout) == str:
if self.expected_stdout != convert_to_unix_line_endings(
convert_to_string(status.stdout)):
return False, ('Incorrect stdout output:\n{ac}\n'
'Expected:\n{ex}'.format(
ac=status.stdout, ex=self.expected_stdout))
else:
if not self.expected_stdout.search(convert_to_unix_line_endings(
convert_to_string(status.stdout))):
return False, ('Incorrect stdout output:\n{ac}\n'
'Expected to match regex:\n{ex}'.format(
ac=convert_to_string(status.stdout),
ex=self.expected_stdout.pattern))
return True, ''
class StderrMatch(GlslCTest):
"""Mixin class for tests that can expect output on stderr.
To mix in this class, subclasses need to provide expected_stderr as the
expected stderr output.
For expected_stderr, if it's True, then they expect something on stderr,
but will not check what it is. If it's a string, expect an exact match.
"""
def check_stderr_match(self, status):
# "True" in this case means we expect something on stderr, but we do not
# care what it is, we want to distinguish this from "blah" which means we
# expect exactly the string "blah".
if self.expected_stderr is True:
if not status.stderr:
return False, 'Expected something on stderr'
else:
if self.expected_stderr != convert_to_unix_line_endings(
convert_to_string(status.stderr)):
return False, ('Incorrect stderr output:\n{ac}\n'
'Expected:\n{ex}'.format(
ac=status.stderr, ex=self.expected_stderr))
return True, ''
class StdoutNoWiderThan80Columns(GlslCTest):
"""Mixin class for tests that require stdout to 80 characters or narrower.
To mix in this class, subclasses need to provide expected_stdout as the
expected stdout output.
"""
def check_stdout_not_too_wide(self, status):
if not status.stdout:
return True, ''
else:
for line in status.stdout.splitlines():
if len(line) > 80:
return False, ('Stdout line longer than 80 columns: %s'
% line)
return True, ''
class NoObjectFile(GlslCTest):
"""Mixin class for checking that no input file has a corresponding object
file."""
def check_no_object_file(self, status):
for input_filename in status.input_filenames:
object_filename = get_object_filename(input_filename)
full_object_file = os.path.join(status.directory, object_filename)
print("checking %s" % full_object_file)
if os.path.isfile(full_object_file):
return False, ('Expected no object file, but found: %s'
% full_object_file)
return True, ''
class NoNamedOutputFiles(GlslCTest):
"""Mixin class for checking that no specified output files exist.
The expected_output_filenames member should be full pathnames."""
def check_no_named_output_files(self, status):
for object_filename in self.expected_output_filenames:
if os.path.isfile(object_filename):
return False, ('Expected no output file, but found: %s'
% object_filename)
return True, ''

View File

@@ -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])

View File

@@ -0,0 +1,86 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import GlslCTest, inside_glslc_testsuite
from placeholder import FileShader
def empty_es_310_shader():
return '#version 310 es\n void main() {}\n'
@inside_glslc_testsuite('FileExtension')
class VerifyVertExtension(expect.ValidObjectFile):
"""Tests glslc accepts vertex shader extension (.vert)."""
shader = FileShader(empty_es_310_shader(), '.vert')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('FileExtension')
class VerifyFragExtension(expect.ValidObjectFile):
"""Tests glslc accepts fragment shader extension (.frag)."""
shader = FileShader(empty_es_310_shader(), '.frag')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('FileExtension')
class VerifyTescExtension(expect.ValidObjectFile):
"""Tests glslc accepts tessellation control shader extension (.tesc)."""
shader = FileShader(
'#version 440 core\n layout(vertices = 3) out;\n void main() {}',
'.tesc')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('FileExtension')
class VerifyTeseExtension(expect.ValidObjectFile):
"""Tests glslc accepts tessellation evaluation shader extension (.tese)."""
shader = FileShader(
'#version 440 core\n layout(triangles) in;\n void main() {}', '.tese')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('FileExtension')
class VerifyGeomExtension(expect.ValidObjectFile):
"""Tests glslc accepts geomtry shader extension (.geom)."""
shader = FileShader(
'#version 150 core\n layout (triangles) in;\n'
'layout (line_strip, max_vertices = 4) out;\n void main() {}',
'.geom')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('FileExtension')
class VerifyCompExtension(expect.ValidObjectFile):
"""Tests glslc accepts compute shader extension (.comp)."""
shader = FileShader(empty_es_310_shader(), '.comp')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('FileExtension')
class InvalidExtension(expect.ErrorMessage):
"""Tests the error message if a file extension cannot be determined."""
shader = FileShader('#version 150\n', '.fraga')
glslc_args = ['-c', shader]
expected_error = [
"glslc: error: '", shader,
"': file not recognized: File format not recognized\n"]

View File

@@ -0,0 +1,355 @@
#!/usr/bin/env python
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Manages and runs tests from the current working directory.
This will traverse the current working directory and look for python files that
contain subclasses of GlslCTest.
If a class has an @inside_glslc_testsuite decorator, an instance of that
class will be created and serve as a test case in that testsuite. The test
case is then run by the following steps:
1. A temporary directory will be created.
2. The glslc_args member variable will be inspected and all placeholders in it
will be expanded by calling instantiate_for_glslc_args() on placeholders.
The transformed list elements are then supplied as glslc arguments.
3. If the environment member variable exists, its write() method will be
invoked.
4. All expected_* member variables will be inspected and all placeholders in
them will be expanded by calling instantiate_for_expectation() on those
placeholders. After placeholder expansion, if the expected_* variable is
a list, its element will be joined together with '' to form a single
string. These expected_* variables are to be used by the check_*() methods.
5. glslc will be run with the arguments supplied in glslc_args.
6. All check_*() member methods will be called by supplying a TestStatus as
argument. Each check_*() method is expected to return a (Success, Message)
pair where Success is a boolean indicating success and Message is an error
message.
7. If any check_*() method fails, the error message is outputted and the
current test case fails.
If --leave-output was not specified, all temporary files and directories will
be deleted.
"""
import argparse
import fnmatch
import inspect
import os
import shutil
import subprocess
import sys
import tempfile
from collections import defaultdict
from placeholder import PlaceHolder
EXPECTED_BEHAVIOR_PREFIX = 'expected_'
VALIDATE_METHOD_PREFIX = 'check_'
def get_all_variables(instance):
"""Returns the names of all the variables in instance."""
return [v for v in dir(instance) if not callable(getattr(instance, v))]
def get_all_methods(instance):
"""Returns the names of all methods in instance."""
return [m for m in dir(instance) if callable(getattr(instance, m))]
def get_all_superclasses(cls):
"""Returns all superclasses of a given class. Omits root 'object' superclass.
Returns:
A list of superclasses of the given class. The order guarantees that
* A Base class precedes its derived classes, e.g., for "class B(A)", it
will be [..., A, B, ...].
* When there are multiple base classes, base classes declared first
precede those declared later, e.g., for "class C(A, B), it will be
[..., A, B, C, ...]
"""
classes = []
for superclass in cls.__bases__:
for c in get_all_superclasses(superclass):
if c is not object and c not in classes:
classes.append(c)
for superclass in cls.__bases__:
if superclass is not object and superclass not in classes:
classes.append(superclass)
return classes
def get_all_test_methods(test_class):
"""Gets all validation methods.
Returns:
A list of validation methods. The order guarantees that
* A method defined in superclass precedes one defined in subclass,
e.g., for "class A(B)", methods defined in B precedes those defined
in A.
* If a subclass has more than one superclass, e.g., "class C(A, B)",
then methods defined in A precedes those defined in B.
"""
classes = get_all_superclasses(test_class)
classes.append(test_class)
all_tests = [m for c in classes
for m in get_all_methods(c)
if m.startswith(VALIDATE_METHOD_PREFIX)]
unique_tests = []
for t in all_tests:
if t not in unique_tests:
unique_tests.append(t)
return unique_tests
class GlslCTest:
"""Base class for glslc test cases.
Subclasses define test cases' facts (shader source code, glslc command,
result validation), which will be used by the TestCase class for running
tests. Subclasses should define glslc_args (specifying glslc command
arguments), and at least one check_*() method (for result validation) for
a full-fledged test case. All check_*() methods should take a TestStatus
parameter and return a (Success, Message) pair, in which Success is a
boolean indicating success and Message is an error message. The test passes
iff all check_*() methods returns true.
Often, a test case class will delegate the check_* behaviors by inheriting
from other classes.
"""
def name(self):
return self.__class__.__name__
class TestStatus:
"""A struct for holding run status of a test case."""
def __init__(self, test_manager, returncode, stdout, stderr, directory, inputs, input_filenames):
self.test_manager = test_manager
self.returncode = returncode
self.stdout = stdout
self.stderr = stderr
# temporary directory where the test runs
self.directory = directory
# List of inputs, as PlaceHolder objects.
self.inputs = inputs
# the names of input shader files (potentially including paths)
self.input_filenames = input_filenames
class GlslCTestException(Exception):
"""GlslCTest exception class."""
pass
def inside_glslc_testsuite(testsuite_name):
"""Decorator for subclasses of GlslCTest.
This decorator checks that a class meets the requirements (see below)
for a test case class, and then puts the class in a certain testsuite.
* The class needs to be a subclass of GlslCTest.
* The class needs to have glslc_args defined as a list.
* The class needs to define at least one check_*() methods.
* All expected_* variables required by check_*() methods can only be
of bool, str, or list type.
* Python runtime will throw an exception if the expected_* member
attributes required by check_*() methods are missing.
"""
def actual_decorator(cls):
if not inspect.isclass(cls):
raise GlslCTestException('Test case should be a class')
if not issubclass(cls, GlslCTest):
raise GlslCTestException(
'All test cases should be subclasses of GlslCTest')
if 'glslc_args' not in get_all_variables(cls):
raise GlslCTestException('No glslc_args found in the test case')
if not isinstance(cls.glslc_args, list):
raise GlslCTestException('glslc_args needs to be a list')
if not any([
m.startswith(VALIDATE_METHOD_PREFIX)
for m in get_all_methods(cls)]):
raise GlslCTestException(
'No check_*() methods found in the test case')
if not all([
isinstance(v, (bool, str, list))
for v in get_all_variables(cls)]):
raise GlslCTestException(
'expected_* variables are only allowed to be bool, str, or '
'list type.')
cls.parent_testsuite = testsuite_name
return cls
return actual_decorator
class TestManager:
"""Manages and runs a set of tests."""
def __init__(self, executable_path, disassembler_path):
self.executable_path = executable_path
self.disassembler_path = disassembler_path
self.num_successes = 0
self.num_failures = 0
self.num_tests = 0
self.leave_output = False
self.tests = defaultdict(list)
def notify_result(self, test_case, success, message):
"""Call this to notify the manager of the results of a test run."""
self.num_successes += 1 if success else 0
self.num_failures += 0 if success else 1
counter_string = str(
self.num_successes + self.num_failures) + '/' + str(self.num_tests)
print('%-10s %-40s ' % (counter_string, test_case.test.name()) +
('Passed' if success else '-Failed-'))
if not success:
print(' '.join(test_case.command))
print(message)
def add_test(self, testsuite, test):
"""Add this to the current list of test cases."""
self.tests[testsuite].append(TestCase(test, self))
self.num_tests += 1
def run_tests(self):
for suite in self.tests:
print('Glslc test suite: "{suite}"'.format(suite=suite))
for x in self.tests[suite]:
x.runTest()
class TestCase:
"""A single test case that runs in its own directory."""
def __init__(self, test, test_manager):
self.test = test
self.test_manager = test_manager
self.inputs = [] # inputs, as PlaceHolder objects.
self.file_shaders = [] # filenames of shader files.
self.stdin_shader = None # text to be passed to glslc as stdin
def setUp(self):
"""Creates environment and instantiates placeholders for the test case."""
self.directory = tempfile.mkdtemp(dir=os.getcwd())
glslc_args = self.test.glslc_args
# Instantiate placeholders in glslc_args
self.test.glslc_args = [
arg.instantiate_for_glslc_args(self)
if isinstance(arg, PlaceHolder) else arg
for arg in self.test.glslc_args]
# Get all shader files' names
self.inputs = [arg for arg in glslc_args if isinstance(arg, PlaceHolder)]
self.file_shaders = [arg.filename for arg in self.inputs]
if 'environment' in get_all_variables(self.test):
self.test.environment.write(self.directory)
expectations = [v for v in get_all_variables(self.test)
if v.startswith(EXPECTED_BEHAVIOR_PREFIX)]
# Instantiate placeholders in expectations
for expectation_name in expectations:
expectation = getattr(self.test, expectation_name)
if isinstance(expectation, list):
expanded_expections = [
element.instantiate_for_expectation(self)
if isinstance(element, PlaceHolder) else element
for element in expectation]
setattr(
self.test, expectation_name,
''.join(expanded_expections))
elif isinstance(expectation, PlaceHolder):
setattr(self.test, expectation_name,
expectation.instantiate_for_expectation(self))
def tearDown(self):
"""Removes the directory if we were not instructed to do otherwise."""
if not self.test_manager.leave_output:
shutil.rmtree(self.directory)
def runTest(self):
"""Sets up and runs a test, reports any failures and then cleans up."""
self.setUp()
success = False
message = ''
try:
self.command = [self.test_manager.executable_path]
self.command.extend(self.test.glslc_args)
process = subprocess.Popen(
args=self.command, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
cwd=self.directory)
output = process.communicate(self.stdin_shader)
test_status = TestStatus(
self.test_manager,
process.returncode, output[0], output[1],
self.directory, self.inputs, self.file_shaders)
run_results = [getattr(self.test, test_method)(test_status)
for test_method in get_all_test_methods(
self.test.__class__)]
success, message = list(zip(*run_results))
success = all(success)
message = '\n'.join(message)
except Exception as e:
success = False
message = str(e)
self.test_manager.notify_result(self, success, message)
self.tearDown()
def main():
parser = argparse.ArgumentParser()
parser.add_argument('glslc', metavar='path/to/glslc', type=str, nargs=1,
help='Path to glslc')
parser.add_argument('spirvdis', metavar='path/to/glslc', type=str, nargs=1,
help='Path to spirv-dis')
parser.add_argument('--leave-output', action='store_const', const=1,
help='Do not clean up temporary directories')
parser.add_argument('--test-dir', nargs=1,
help='Directory to gather the tests from')
args = parser.parse_args()
default_path = sys.path
root_dir = os.getcwd()
if args.test_dir:
root_dir = args.test_dir[0]
manager = TestManager(args.glslc[0], args.spirvdis[0])
if args.leave_output:
manager.leave_output = True
for root, _, filenames in os.walk(root_dir):
for filename in fnmatch.filter(filenames, '*.py'):
if filename.endswith('unittest.py'):
# Skip unit tests, which are for testing functions of
# the test framework.
continue
sys.path = default_path
sys.path.append(root)
try:
mod = __import__(os.path.splitext(filename)[0])
for _, obj, in inspect.getmembers(mod):
if inspect.isclass(obj) and hasattr(obj, 'parent_testsuite'):
manager.add_test(obj.parent_testsuite, obj())
except:
print("Failed to load " + filename)
raise
manager.run_tests()
if manager.num_failures > 0:
sys.exit(-1)
if __name__ == '__main__':
main()

View File

@@ -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'])

555
3rdparty/shaderc/glslc/test/include.py vendored Normal file
View File

@@ -0,0 +1,555 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import SpecializedString
from environment import File, Directory
@inside_glslc_testsuite('Include')
class VerifyIncludeOneSibling(expect.StdoutMatch):
"""Tests #including a sibling file."""
environment = Directory('.', [
File('a.vert', '#version 140\ncontent a\n#include "b"\n'),
File('b', 'content b\n')])
glslc_args = ['-E', 'a.vert']
expected_stdout = \
"""#version 140
#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
content a
#line 0 "b"
content b
#line 3 "a.vert"
"""
@inside_glslc_testsuite('Include')
class VerifyIncludeNotFound(expect.ErrorMessage):
"""Tests #including a not existing sibling file."""
environment = Directory('.', [
File('a.vert', '#version 140\ncontent a\n#include "b"\n')])
glslc_args = ['-E', 'a.vert']
expected_error = [
"a.vert:3: error: '#include' : Cannot find or open include file. for header name: b\n",
'1 error generated.\n'
]
@inside_glslc_testsuite('Include')
class VerifyCompileIncludeOneSibling(expect.ValidObjectFile):
"""Tests #including a sibling file via full compilation."""
environment = Directory('.', [
File('a.vert', '#version 140\nvoid foo(){}\n#include "b"\n'),
File('b', 'void main(){foo();}\n')])
glslc_args = ['a.vert']
@inside_glslc_testsuite('Include')
class VerifyIncludeWithoutNewline(expect.ErrorMessageSubstr):
"""Tests a #include without a newline."""
environment = Directory('.', [
File('a.vert', '#version 140\n#include "b"'),
File('b', 'content b\n')])
glslc_args = ['-E', 'a.vert']
expected_error_substr = 'expected newline after header name: b'
@inside_glslc_testsuite('Include')
class VerifyCompileIncludeWithoutNewline(expect.ValidObjectFile):
"""Tests a #include without a newline via full compilation."""
environment = Directory('.', [
File('a.vert',
"""#version 140
void main
#include "b"
"""),
File('b',
"""#define PAR ()
PAR{}
""")])
glslc_args = ['a.vert']
@inside_glslc_testsuite('Include')
class VerifyIncludeTwoSiblings(expect.StdoutMatch):
"""Tests #including two sibling files."""
environment = Directory('.', [
File('b.vert', '#version 140\n#include "a"\ncontent b\n#include "c"\n'),
File('a', 'content a\n'),
File('c', 'content c\n')])
glslc_args = ['-E', 'b.vert']
expected_stdout = \
"""#version 140
#extension GL_GOOGLE_include_directive : enable
#line 0 "b.vert"
#line 0 "a"
content a
#line 2 "b.vert"
content b
#line 0 "c"
content c
#line 4 "b.vert"
"""
@inside_glslc_testsuite('Include')
class VerifyCompileIncludeTwoSiblings(expect.ValidObjectFile):
"""Tests #including two sibling files via full compilation."""
environment = Directory('.', [
File('b.vert',
"""#version 140
#include "a"
void bfun(){afun();}
#include "c"
"""),
File('a',
"""void afun(){}
#define BODY {}
"""),
File('c', 'void main() BODY\n')])
glslc_args = ['b.vert']
@inside_glslc_testsuite('Include')
class VerifyNestedIncludeAmongSiblings(expect.StdoutMatch):
"""Tests #include inside #included sibling files."""
environment = Directory('.', [
File('a.vert', '#version 140\n#include "b"\ncontent a\n'),
File('b', 'content b\n#include "c"\n'),
File('c', 'content c\n')])
glslc_args = ['-E', 'a.vert']
expected_stdout = \
"""#version 140
#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
#line 0 "b"
content b
#line 0 "c"
content c
#line 2 "b"
#line 2 "a.vert"
content a
"""
@inside_glslc_testsuite('Include')
class VerifyCompileNestedIncludeAmongSiblings(expect.ValidObjectFile):
"""Tests #include inside #included sibling files via full compilation."""
environment = Directory('.', [
File('a.vert',
"""#version 140
#define BODY {}
#include "b"
void main(){cfun();}
"""),
File('b',
"""void bfun() BODY
#include "c"
"""),
File('c',
"""#define BF bfun()
void cfun(){BF;}
""")])
glslc_args = ['a.vert']
@inside_glslc_testsuite('Include')
class VerifyIncludeSubdir(expect.StdoutMatch):
"""Tests #including a file from a subdirectory."""
environment = Directory('.', [
File('a.vert', '#version 140\ncontent a1\n#include "subdir/a"\ncontent a2\n'),
Directory('subdir', [File('a', 'content suba\n')])])
glslc_args = ['-E', 'a.vert']
expected_stdout = \
"""#version 140
#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
content a1
#line 0 "subdir/a"
content suba
#line 3 "a.vert"
content a2
"""
@inside_glslc_testsuite('Include')
class VerifyCompileIncludeSubdir(expect.ValidObjectFile):
"""Tests #including a file from a subdirectory via full compilation."""
environment = Directory('.', [
File('a.vert',
"""#version 140
#define BODY {}
#include "subdir/a"
void afun()BODY
"""),
Directory('subdir', [File('a', 'void main() BODY\n')])])
glslc_args = ['a.vert']
@inside_glslc_testsuite('Include')
class VerifyIncludeDeepSubdir(expect.StdoutMatch):
"""Tests #including a file from a subdirectory nested a few levels down."""
environment = Directory('.', [
File('a.vert',
'#version 140\ncontent a1\n#include "dir/subdir/subsubdir/a"\ncontent a2\n'),
Directory('dir', [
Directory('subdir', [
Directory('subsubdir', [File('a', 'content incl\n')])])])])
glslc_args = ['-E', 'a.vert']
expected_stdout = \
"""#version 140
#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
content a1
#line 0 "dir/subdir/subsubdir/a"
content incl
#line 3 "a.vert"
content a2
"""
@inside_glslc_testsuite('Include')
class VerifyCompileIncludeDeepSubdir(expect.ValidObjectFile):
"""Tests #including a file from a subdirectory nested a few levels down
via full compilation."""
environment = Directory('.', [
File('a.vert',
"""#version 140
#define BODY {}
#include "dir/subdir/subsubdir/a"
void afun()BODY
"""),
Directory('dir', [
Directory('subdir', [
Directory('subsubdir', [File('a', 'void main() BODY\n')])])])])
glslc_args = ['a.vert']
@inside_glslc_testsuite('Include')
class TestWrongPoundVersionInIncludingFile(expect.ValidObjectFileWithWarning):
"""Tests that warning message for #version directive in the including file
has the correct filename."""
environment = Directory('.', [
File('a.vert', '#version 100000000\n#include "b.glsl"\n'),
File('b.glsl', 'void main() {}\n')])
glslc_args = ['-c', '-std=400', 'a.vert']
expected_warning = [
'a.vert: warning: (version, profile) forced to be (400, none),'
' while in source code it is (100000000, none)\n'
'1 warning generated.\n'
]
# TODO(antiagainst): now #version in included files results in an error.
# Fix this after #version in included files are supported.
# TODO(dneto): I'm not sure what the expected result should be.
@inside_glslc_testsuite('Include')
class TestWrongPoundVersionInIncludedFile(expect.ErrorMessage):
"""Tests that warning message for #version directive in the included file
has the correct filename."""
environment = Directory('.', [
File('a.vert', '#version 140\n#include "b.glsl"\nvoid main() {}'),
File('b.glsl', '#version 10000000\n')])
glslc_args = ['-E', 'a.vert']
expected_error = [
"b.glsl:1: error: '#version' : must occur first in shader\n",
'1 error generated.\n'
]
@inside_glslc_testsuite('Include')
class VerifyRelativeInclude(expect.StdoutMatch):
"""Tests #including a relative sibling."""
environment = Directory('.', [
File('a.vert', '#version 140\ncontent a\n#include "foo/b.glsl"\n'),
Directory('foo', [
File('b.glsl', '#include "c.glsl"\ncontent b\n'),
File('c.glsl', 'content c\n')
])])
glslc_args = ['-E', 'a.vert']
expected_stdout = \
"""#version 140
#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
content a
#line 0 "foo/b.glsl"
#line 0 "foo/c.glsl"
content c
#line 1 "foo/b.glsl"
content b
#line 3 "a.vert"
"""
@inside_glslc_testsuite('Include')
class VerifyNestedRelativeInclude(expect.StdoutMatch):
"""Tests #including a relative child file."""
environment = Directory('.', [
File('a.vert', '#version 140\ncontent a\n#include "foo/b.glsl"\n'),
Directory('foo', [
File('b.glsl', '#include "bar/c.glsl"\ncontent b\n'),
Directory('bar', [
File('c.glsl', 'content c\n')
])
])
])
glslc_args = ['-E', 'a.vert']
expected_stdout = \
"""#version 140
#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
content a
#line 0 "foo/b.glsl"
#line 0 "foo/bar/c.glsl"
content c
#line 1 "foo/b.glsl"
content b
#line 3 "a.vert"
"""
@inside_glslc_testsuite('Include')
class VerifyRelativeIncludeWithDashI(expect.StdoutMatch):
"""Tests #including a relative file from a -I directory."""
environment = Directory('.', [
File('a.vert', '#version 140\ncontent a\n#include "bar/b.glsl"\n'),
Directory('foo', [
Directory('bar', [
File('b.glsl', '#include "c.glsl"\ncontent b\n'),
]),
File('c.glsl', 'content c\n')
])
])
glslc_args = ['-E', 'a.vert', '-Ifoo']
expected_stdout = \
"""#version 140
#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
content a
#line 0 "foo/bar/b.glsl"
#line 0 "foo/c.glsl"
content c
#line 1 "foo/bar/b.glsl"
content b
#line 3 "a.vert"
"""
@inside_glslc_testsuite('Include')
class VerifyRelativeOverridesDashI(expect.StdoutMatch):
"""Tests that relative includes override -I parameters."""
environment = Directory('.', [
File('a.vert', '#version 140\ncontent a\n#include "b.glsl"\n'),
File('b.glsl', 'content base_b\n'),
Directory('foo', [
File('b.glsl', '#include "c.glsl"\ncontent b\n'),
File('c.glsl', 'content c\n')
])
])
glslc_args = ['-E', 'a.vert', '-Ifoo']
expected_stdout = \
"""#version 140
#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
content a
#line 0 "b.glsl"
content base_b
#line 3 "a.vert"
"""
@inside_glslc_testsuite('Include')
class VerifyRelativeParent(expect.StdoutMatch):
"""Tests #including a parent file."""
environment = Directory('.', [
File('a.vert', '#version 140\ncontent a\n#include "b.glsl"\n'),
File('c.glsl', 'content c\n'),
Directory('foo', [
File('b.glsl', '#include "../c.glsl"\ncontent b\n')
])
])
glslc_args = ['-E', 'a.vert', '-Ifoo']
expected_stdout = \
"""#version 140
#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
content a
#line 0 "foo/b.glsl"
#line 0 "foo/../c.glsl"
content c
#line 1 "foo/b.glsl"
content b
#line 3 "a.vert"
"""
@inside_glslc_testsuite('Include')
class VerifyRelativeNeighbourDirectory(expect.StdoutMatch):
"""Tests #including a relative file in a neighbour directory."""
environment = Directory('.', [
File('a.vert', '#version 140\ncontent a\n#include "foo/b.glsl"\n'),
Directory('foo', [
File('b.glsl', '#include "../bar/c.glsl"\ncontent b\n')
]),
Directory('bar', [
File('c.glsl', 'content c\n')
])
])
glslc_args = ['-E', 'a.vert']
expected_stdout = \
"""#version 140
#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
content a
#line 0 "foo/b.glsl"
#line 0 "foo/../bar/c.glsl"
content c
#line 1 "foo/b.glsl"
content b
#line 3 "a.vert"
"""
@inside_glslc_testsuite('Include')
class VerifyRelativeOnlyToSelf(expect.ErrorMessage):
"""Tests that a relative includes are only relative to yourself."""
environment = Directory('.', [
File('a.vert', '#version 140\ncontent a\n#include "foo/b.glsl"\n'),
File('c.glsl', 'content c\n'),
Directory('foo', [
File('b.glsl', '#include "c.glsl"\ncontent b\n')
]),
])
glslc_args = ['-E', 'a.vert']
expected_error = [
"foo/b.glsl:1: error: '#include' : "
'Cannot find or open include file. for header name: c.glsl\n',
'1 error generated.\n'
]
@inside_glslc_testsuite('Include')
class VerifyRelativeFromAbsolutePath(expect.StdoutMatch):
"""Tests that absolute files can relatively include."""
environment = Directory('.', [
File('a.vert', '#version 140\ncontent a\n#include "b.glsl"\n'),
File('b.glsl', 'content b\n')
])
glslc_args = ['-E', SpecializedString('$directory/a.vert')]
expected_stdout = SpecializedString(
"""#version 140
#extension GL_GOOGLE_include_directive : enable
#line 0 "$directory/a.vert"
content a
#line 0 "$directory/b.glsl"
content b
#line 3 "$directory/a.vert"
""")
@inside_glslc_testsuite('Include')
class VerifyDashIAbsolutePath(expect.StdoutMatch):
"""Tests that -I parameters can be absolute paths."""
environment = Directory('.', [
File('a.vert', '#version 140\ncontent a\n#include "b.glsl"\n'),
Directory('foo', {
File('b.glsl', 'content b\n')
})
])
glslc_args = ['-E', 'a.vert', '-I', SpecializedString('$directory/foo')]
expected_stdout = SpecializedString(
"""#version 140
#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
content a
#line 0 "$directory/foo/b.glsl"
content b
#line 3 "a.vert"
""")

303
3rdparty/shaderc/glslc/test/line.py vendored Normal file
View File

@@ -0,0 +1,303 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from environment import Directory, File
from glslc_test_framework import inside_glslc_testsuite
@inside_glslc_testsuite('#line')
class TestPoundVersion310InIncludingFile(
expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch):
"""Tests that #line directives follows the behavior of version 310
(specifying the line number for the next line) when we find a
#version 310 directive in the including file."""
environment = Directory('.', [
File('a.vert', '#version 310 es\n#include "b.glsl"\n'),
File('b.glsl', 'void main() {}\n')])
glslc_args = ['-E', 'a.vert']
expected_stderr = ''
expected_stdout = \
"""#version 310 es
#extension GL_GOOGLE_include_directive : enable
#line 1 "a.vert"
#line 1 "b.glsl"
void main() { }
#line 3 "a.vert"
"""
@inside_glslc_testsuite('#line')
class TestPoundVersion150InIncludingFile(
expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch):
"""Tests that #line directives follows the behavior of version 150
(specifying the line number for itself) when we find a #version 150
directive in the including file."""
environment = Directory('.', [
File('a.vert', '#version 150\n#include "b.glsl"\n'),
File('b.glsl', 'void main() {}\n')])
glslc_args = ['-E', 'a.vert']
expected_stderr = ''
expected_stdout = \
"""#version 150
#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
#line 0 "b.glsl"
void main() { }
#line 2 "a.vert"
"""
@inside_glslc_testsuite('#line')
class TestPoundVersionSyntaxErrorInIncludingFile(expect.ErrorMessageSubstr):
"""Tests that error message for #version directive has the correct
filename and line number."""
environment = Directory('.', [
File('a.vert', '#version abc def\n#include "b.glsl"\n'),
File('b.glsl', 'void main() {}\n')])
glslc_args = ['-E', 'a.vert']
expected_error_substr = [
"a.vert:1: error: '#version' : must occur first in shader\n",
"a.vert:1: error: '#version' : must be followed by version number\n",
"a.vert:1: error: '#version' : bad profile name; use es, core, or "
"compatibility\n",
]
# TODO(antiagainst): now #version in included files results in an error.
# Fix this after #version in included files are supported.
@inside_glslc_testsuite('#line')
class TestPoundVersion310InIncludedFile(expect.ErrorMessageSubstr):
"""Tests that #line directives follows the behavior of version 310
(specifying the line number for the next line) when we find a
#version 310 directive in the included file."""
environment = Directory('.', [
File('a.vert', '#include "b.glsl"\nvoid main() {}'),
File('b.glsl', '#version 310 es\n')])
glslc_args = ['-E', 'a.vert']
expected_error_substr = [
"b.glsl:1: error: '#version' : must occur first in shader\n"
]
# TODO(antiagainst): now #version in included files results in an error.
# Fix this after #version in included files are supported.
@inside_glslc_testsuite('#line')
class TestPoundVersion150InIncludedFile(expect.ErrorMessageSubstr):
"""Tests that #line directives follows the behavior of version 150
(specifying the line number for itself) when we find a #version 150
directive in the included file."""
environment = Directory('.', [
File('a.vert', '#include "b.glsl"\nvoid main() {}'),
File('b.glsl', '#version 150\n')])
glslc_args = ['-E', 'a.vert']
expected_error_substr = [
"b.glsl:1: error: '#version' : must occur first in shader\n"
]
@inside_glslc_testsuite('#line')
class TestSpaceAroundPoundVersion310InIncludingFile(
expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch):
"""Tests that spaces around #version & #include directive doesn't matter."""
environment = Directory('.', [
File('a.vert', '\t # \t version 310 \t es\n#\tinclude "b.glsl"\n'),
File('b.glsl', 'void main() {}\n')])
glslc_args = ['-E', 'a.vert']
expected_stderr = ''
expected_stdout = \
"""#version 310 es
#extension GL_GOOGLE_include_directive : enable
#line 1 "a.vert"
#line 1 "b.glsl"
void main() { }
#line 3 "a.vert"
"""
@inside_glslc_testsuite('#line')
class TestSpaceAroundPoundVersion150InIncludingFile(
expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch):
"""Tests that spaces around #version & #include directive doesn't matter."""
environment = Directory('.', [
File('a.vert', ' \t #\t\tversion\t 150\t \n# include \t "b.glsl"\n'),
File('b.glsl', 'void main() {}\n')])
glslc_args = ['-E', 'a.vert']
expected_stderr = ''
expected_stdout = \
"""#version 150
#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
#line 0 "b.glsl"
void main() { }
#line 2 "a.vert"
"""
@inside_glslc_testsuite('#line')
class TestPoundLineWithForcedVersion310(
expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch):
"""Tests that #line directives follows the behavior for the version
specified via command-line."""
environment = Directory('.', [
File('a.vert', '#include "b.glsl"\n'),
File('b.glsl', 'void main() {}\n')])
glslc_args = ['-E', '-std=310es', 'a.vert']
expected_stderr = ''
expected_stdout = \
"""#extension GL_GOOGLE_include_directive : enable
#line 1 "a.vert"
#line 1 "b.glsl"
void main() { }
#line 2 "a.vert"
"""
@inside_glslc_testsuite('#line')
class TestPoundLineWithForcedVersion150(
expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch):
"""Tests that #line directives follows the behavior for the version
specified via command-line."""
environment = Directory('.', [
File('a.vert', '#include "b.glsl"\n'),
File('b.glsl', 'void main() {}\n')])
glslc_args = ['-E', '-std=150', 'a.vert']
expected_stderr = ''
expected_stdout = \
"""#extension GL_GOOGLE_include_directive : enable
#line 0 "a.vert"
#line 0 "b.glsl"
void main() { }
#line 1 "a.vert"
"""
@inside_glslc_testsuite('#line')
class TestPoundLineWithForcedDifferentVersion(
expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch):
"""Tests that #line directives follows the behavior for the version
specified via command-line, even if there is a version specification
in the source code."""
environment = Directory('.', [
File('a.vert', '#version 150\n#include "b.glsl"\n'),
File('b.glsl', 'void main() {}\n')])
glslc_args = ['-E', '-std=310es', 'a.vert']
expected_stderr = ''
expected_stdout = \
"""#version 150
#extension GL_GOOGLE_include_directive : enable
#line 1 "a.vert"
#line 1 "b.glsl"
void main() { }
#line 3 "a.vert"
"""
@inside_glslc_testsuite('#line')
class TestErrorsFromMultipleFiles(expect.ErrorMessage):
"""Tests that errors from different files have the correct error message
filename specification."""
including_file = '''#version 310 es
#include "error.glsl"
int no_return() {}
#include "main.glsl"
'''
environment = Directory('.', [
File('a.vert', including_file),
File('error.glsl', 'int unknown_identifier(int) { return a; }'),
File('main.glsl', 'void main() {\n int b = 1.5;\n}')])
glslc_args = ['-c', 'a.vert']
expected_error = [
"error.glsl:1: error: 'a' : undeclared identifier\n",
"error.glsl:1: error: 'return' : type does not match, or is not "
"convertible to, the function's return type\n",
"a.vert:3: error: '' : function does not return a value: no_return\n",
"main.glsl:2: error: '=' : cannot convert from ' const float' to "
"' temp highp int'\n",
"4 errors generated.\n"]
@inside_glslc_testsuite('#line')
class TestExplicitPoundLineWithPoundInclude(
expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch):
"""Tests that #line works correctly in the presence of #include (which
itself will generate some #line directives."""
including_file = '''#version 310 es
#line 10000 "injected.glsl"
int plus1(int a) { return a + 1; }
#include "inc.glsl"
int plus2(int a) { return a + 2; }
#line 55555
#include "main.glsl"
'''
environment = Directory('.', [
File('a.vert', including_file),
File('inc.glsl', 'int inc(int a) { return a + 1; }'),
File('main.glsl', 'void main() {\n gl_Position = vec4(1.);\n}')])
glslc_args = ['-E', 'a.vert']
expected_stderr = ''
expected_stdout = '''#version 310 es
#extension GL_GOOGLE_include_directive : enable
#line 1 "a.vert"
#line 10000 "injected.glsl"
int plus1(int a) { return a + 1; }
#line 1 "inc.glsl"
int inc(int a) { return a + 1; }
#line 10002 "injected.glsl"
int plus2(int a) { return a + 2; }
#line 55555
#line 1 "main.glsl"
void main() {
gl_Position = vec4(1.);
}
#line 55556 "injected.glsl"
'''

View File

@@ -0,0 +1,311 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader, StdinShader
@inside_glslc_testsuite('ErrorMessages')
class MultipleErrors(expect.ErrorMessage):
"""Test Multiple error messages generated."""
shader = FileShader('#version 140\nint main() {}', '.vert')
glslc_args = ['-c', shader]
expected_error = [
shader, ":2: error: 'int' : entry point cannot return a value\n",
shader, ":2: error: '' : function does not return a value: main\n",
'2 errors generated.\n']
@inside_glslc_testsuite('ErrorMessages')
class OneError(expect.ErrorMessage):
"""Tests that only one error message is generated correctly."""
shader = FileShader(
"""#version 140
int a() {
}
void main() {
int x = a();
}
""", '.vert')
glslc_args = ['-c', shader]
expected_error = [
shader, ":2: error: '' : function does not return a value: a\n",
'1 error generated.\n']
@inside_glslc_testsuite('ErrorMessages')
class ManyLineError(expect.ErrorMessage):
"""Tests that only one error message is generated correctly."""
shader = FileShader(
"""#version 140
int a() {
}
void main() {
int x = a();
}
""", '.vert')
glslc_args = ['-c', shader]
expected_error = [
shader, ":12: error: '' : function does not return a value: a\n",
'1 error generated.\n']
@inside_glslc_testsuite('ErrorMessages')
class GlobalWarning(expect.WarningMessage):
"""Tests that a warning message without file/line number is emitted."""
shader = FileShader(
"""#version 550
void main() {
}
""", '.vert')
glslc_args = ['-c', '-std=400', shader]
expected_warning = [
shader, ': warning: (version, profile) forced to be (400, none),'
' while in source code it is (550, none)\n1 warning generated.\n']
@inside_glslc_testsuite('ErrorMessages')
class SuppressedGlobalWarning(expect.SuccessfulReturn):
"""Tests that warning messages without file/line numbers are suppressed
with -w."""
shader = FileShader(
"""#version 550
void main() {
}
""", '.vert')
glslc_args = ['-c', '-std=400', shader, '-w']
@inside_glslc_testsuite('ErrorMessages')
class GlobalWarningAsError(expect.ErrorMessage):
"""Tests that with -Werror an error warning message without file/line
number is emitted instead of a warning."""
shader = FileShader(
"""#version 550
void main() {
}
""", '.vert')
glslc_args = ['-c', '-std=400', shader, '-Werror']
expected_error= [
shader, ': error: (version, profile) forced to be (400, none),'
' while in source code it is (550, none)\n1 error generated.\n']
@inside_glslc_testsuite('ErrorMessages')
class WarningOnLine(expect.WarningMessage):
"""Tests that a warning message with a file/line number is emitted."""
shader = FileShader(
"""#version 400
layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
glslc_args = ['-c', shader]
expected_warning = [
shader, ':2: warning: attribute deprecated in version 130; ',
'may be removed in future release\n1 warning generated.\n']
@inside_glslc_testsuite('ErrorMessages')
class SuppressedWarningOnLine(expect.SuccessfulReturn):
"""Tests that a warning message with a file/line number is suppressed in the
presence of -w."""
shader = FileShader(
"""#version 400
layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
glslc_args = ['-c', shader, '-w']
@inside_glslc_testsuite('ErrorMessages')
class WarningOnLineAsError(expect.ErrorMessage):
"""Tests that with -Werror an error message with a file/line
number is emitted instead of a warning."""
shader = FileShader(
"""#version 400
layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
glslc_args = ['-c', shader, '-Werror']
expected_error = [
shader, ':2: error: attribute deprecated in version 130; ',
'may be removed in future release\n1 error generated.\n']
@inside_glslc_testsuite('ErrorMessages')
class WarningAndError(expect.ErrorMessage):
"""Tests that both warnings and errors are emitted together."""
shader = FileShader(
"""#version 400
layout(location = 0) attribute float x;
int main() {
}
""", '.vert')
glslc_args = ['-c', shader]
expected_error = [
shader, ':2: warning: attribute deprecated in version 130; ',
'may be removed in future release\n',
shader, ":3: error: 'int' : entry point cannot return a value\n",
shader, ":3: error: '' : function does not return a value: main\n",
'1 warning and 2 errors generated.\n']
@inside_glslc_testsuite('ErrorMessages')
class SuppressedWarningAndError(expect.ErrorMessage):
"""Tests that only warnings are suppressed in the presence of -w."""
shader = FileShader(
"""#version 400
layout(location = 0) attribute float x;
int main() {
}
""", '.vert')
glslc_args = ['-c', shader, '-w']
expected_error = [
shader, ":3: error: 'int' : entry point cannot return a value\n",
shader, ":3: error: '' : function does not return a value: main\n",
'2 errors generated.\n']
@inside_glslc_testsuite('ErrorMessages')
class WarningAsErrorAndError(expect.ErrorMessage):
"""Tests that with -Werror an warnings and errors are emitted as errors."""
shader = FileShader(
"""#version 400
layout(location = 0) attribute float x;
int main() {
}
""", '.vert')
glslc_args = ['-c', shader, '-Werror']
expected_error = [
shader, ':2: error: attribute deprecated in version 130; ',
'may be removed in future release\n',
shader, ":3: error: 'int' : entry point cannot return a value\n",
shader, ":3: error: '' : function does not return a value: main\n",
'3 errors generated.\n']
@inside_glslc_testsuite('ErrorMessages')
class StdinErrorMessages(expect.StdoutMatch, expect.StderrMatch):
"""Tests that error messages using input from stdin are correct."""
shader = StdinShader(
"""#version 140
int a() {
}
void main() {
int x = a();
}
""")
glslc_args = ['-c', '-fshader-stage=vertex', shader]
expected_stdout = ''
expected_stderr = [
"<stdin>:2: error: '' : function does not return a value: a\n",
'1 error generated.\n']
@inside_glslc_testsuite('ErrorMessages')
class WarningAsErrorMultipleFiles(expect.ErrorMessage):
"""Tests that with -Werror multiple files emit errors instead of warnings.
"""
shader = FileShader(
"""#version 400
layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
shader2 = FileShader(
"""#version 550
void main() {
}
""", '.vert')
glslc_args = ['-c', '-std=400', shader, '-Werror', shader2]
expected_error = [
shader, ':2: error: attribute deprecated in version 130; ',
'may be removed in future release\n',
shader2, ': error: (version, profile) forced to be (400, none),'
' while in source code it is (550, none)\n',
'2 errors generated.\n']
@inside_glslc_testsuite('ErrorMessages')
class SuppressedWarningAsError(expect.SuccessfulReturn):
"""Tests that nothing is returned in the presence of -w -Werror."""
shader = FileShader(
"""#version 400
layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
glslc_args = ['-c', shader, '-w', '-Werror']
@inside_glslc_testsuite('ErrorMessages')
class MultipleSuppressed(expect.SuccessfulReturn):
"""Tests that multiple -w arguments are supported."""
shader = FileShader(
"""#version 400
layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
glslc_args = ['-w', '-c', shader, '-w', '-w', '-w']
@inside_glslc_testsuite('ErrorMessages')
class MultipleSuppressedFiles(expect.SuccessfulReturn):
"""Tests that -w suppresses warnings from all files."""
shader = FileShader(
"""#version 400
layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
shader2 = FileShader(
"""#version 400
layout(location = 0) attribute float x;
void main() {
}
""", '.vert')
glslc_args = ['-w', '-c', shader, shader2]

View File

@@ -0,0 +1,365 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDNoArg(expect.ErrorMessage):
"""Tests -D without macroname."""
glslc_args = ['-D']
expected_error = [
"glslc: error: argument to '-D' is missing\n",
'glslc: error: no input files\n']
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDXeqY(expect.ValidObjectFile):
"""Tests -DX=Y."""
shader = FileShader('#version 150\nvoid main(){X=vec4(1.);}', '.vert')
glslc_args = ['-c', '-DX=gl_Position', shader]
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDXeq(expect.ValidObjectFile):
"""Tests -DX=."""
shader = FileShader('#version 150\nvoid main(){X}', '.vert')
glslc_args = ['-c', '-DX=', shader]
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDX(expect.ValidObjectFile):
"""Tests -DX."""
shader = FileShader('#version 150\nvoid main(){X}', '.vert')
glslc_args = ['-c', '-DX', shader]
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDeq(expect.ErrorMessage):
"""Tests -D=.
This is actually allowed by clang, though the resulting #define
causes a preprocessing error.
"""
shader = FileShader('#version 150\nvoid main(){}', '.vert')
glslc_args = ['-c', '-D=', shader]
# TODO(antiagainst): figure out what should we report as the line number
# for errors in predefined macros and fix here.
expected_error = [
"<command line>:2: error: '#define' : must be followed by macro name\n",
'1 error generated.\n']
@inside_glslc_testsuite('OptionCapD')
class TestMultipleDashCapD(expect.ValidObjectFile):
"""Tests multiple -D occurrences."""
shader = FileShader('#version 150\nvoid main(){X Y a=Z;}', '.vert')
glslc_args = ['-c', '-DX', '-DY=int', '-DZ=(1+2)', shader]
@inside_glslc_testsuite('OptionCapD')
class TestMultipleDashCapDOfSameName(expect.ValidObjectFile):
"""Tests multiple -D occurrences with same macro name."""
shader = FileShader('#version 150\nvoid main(){X Y a=Z;}', '.vert')
glslc_args = ['-c', '-DX=main', '-DY=int', '-DZ=(1+2)', '-DX', shader]
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDGL_(expect.ErrorMessage):
"""Tests that we cannot -D macros beginning with GL_."""
shader = FileShader('#version 150\nvoid main(){}', '.vert')
glslc_args = ['-DGL_ES=1', shader]
expected_error = [
"glslc: error: names beginning with 'GL_' cannot be "
'defined: -DGL_ES=1\n']
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDReservedMacro(expect.WarningMessage):
"""Tests that we cannot -D GLSL's predefined macros."""
shader = FileShader('#version 150\nvoid main(){}', '.vert')
# Consecutive underscores are banned anywhere in the name.
glslc_args = [
'-D__LINE__=1', '-Dmid__dle', '-Dend__', '-D_single_is_valid_', shader]
w = 'glslc: warning: names containing consecutive underscores are reserved: '
expected_warning = [w, '-D__LINE__=1\n', w, '-Dmid__dle\n', w, '-Dend__\n']
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDWithVersion(expect.ErrorMessage):
"""Tests -D works well when #version is present."""
shader = FileShader(
"""#version 310 es
void main(){X}
void foo(){Y}""", '.vert')
glslc_args = ['-DX=', '-DY=return 3;', shader]
expected_error = [
shader, ":3: error: 'return' : void function cannot return a value\n",
'1 error generated.\n']
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDWithCommentBeforeVersion(expect.ErrorMessage):
"""Tests -D works well with #version preceded by comments."""
shader = FileShader(
"""// comment 1
/*
* comment 2
*/
#version 450 core
void main(){X}
void foo(){Y}""", '.vert')
glslc_args = ['-DX=', '-DY=return 3;', shader]
expected_error = [
shader, ":7: error: 'return' : void function cannot return a value\n",
'1 error generated.\n']
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDWithCommentAfterVersion(expect.ErrorMessage):
"""Tests -D works well with #version followed by comments."""
shader = FileShader(
"""
#version 150 core /*
comment
*/
void main(){X}
void foo(){Y}""", '.vert')
glslc_args = ['-DX=', '-DY=return 3;', shader]
expected_error = [
shader, ":7: error: 'return' : void function cannot return a value\n",
'1 error generated.\n']
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDWithDashStd(expect.ErrorMessageSubstr):
"""Tests -D works well with -std."""
shader = FileShader('void main(){X}\nvoid foo(){Y}', '.vert')
glslc_args = ['-DX=', '-DY=return 3;', '-std=310es', shader]
expected_error_substr = [
shader, ":2: error: 'return' : void function cannot return a value\n",
'1 error generated.\n']
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDWithDashStdAndVersion(expect.ErrorMessage):
"""Tests -D works well with both -std and #version."""
shader = FileShader(
"""#version 310 es
void main(){X}
void foo(){Y}""", '.vert')
glslc_args = ['-DX=', '-DY=return 3;', '-std=450core', shader]
expected_error = [
shader, ': warning: (version, profile) forced to be (450, ',
'core), while in source code it is (310, es)\n',
shader, ":3: error: 'return' : void function cannot return a value\n",
'1 warning and 1 error generated.\n']
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDWithDashStdAndVersionAndComments(expect.ErrorMessage):
"""Tests -D works well with -std, #version, and comments around it."""
shader = FileShader(
"""// comment before
#version 310 es /* comment after
*/
void main(){X}
void foo(){Y}""", '.vert')
glslc_args = ['-DX=', '-DY=return 3;', '-std=450core', shader]
expected_error = [
shader, ': warning: (version, profile) forced to be (450, core), while '
'in source code it is (310, es)\n',
shader, ":7: error: 'return' : void function cannot return a value\n",
'1 warning and 1 error generated.\n']
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDWithDashE(expect.ReturnCodeIsZero,
expect.StdoutMatch):
"""Tests -E outputs expanded -D macros."""
shader = FileShader(
"""
void main(){Y}
""", '.vert')
glslc_args = ['-DY=return 3;', '-E', '-std=450core', shader]
expected_stdout = [
"""
void main() { return 3; }
"""]
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDWithDashEIfDef(expect.ReturnCodeIsZero,
expect.StdoutMatch):
"""Tests -E processes -DX #ifdefs correctly."""
shader = FileShader(
"""
#ifdef X
void f() { }
#else
void f() { int x; }
#endif
void main(){ return 3; }
""", '.vert')
glslc_args = ['-DX', '-E', '-std=450core', shader]
expected_stdout = [
"""
void f() { }
void main() { return 3; }
"""]
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDWithDashEIfNDef(expect.ReturnCodeIsZero,
expect.StdoutMatch):
"""Tests -E processes -DX #ifndefs correctly."""
shader = FileShader(
"""
#ifndef X
void f() { }
#else
void f() { int x; }
#endif
void main(){ return 3; }
""", '.vert')
glslc_args = ['-DX', '-E', '-std=450core', shader]
expected_stdout = [
"""
void f() { int x; }
void main() { return 3; }
"""]
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDWithDashEEqIfDef(expect.ReturnCodeIsZero,
expect.StdoutMatch):
"""Tests -E processes -DX= #ifdefs correctly."""
shader = FileShader(
"""
#ifdef X
void f() { }
#else
void f() { int x; }
#endif
void main() { return 3; }
""", '.vert')
glslc_args = ['-DX=', '-E', '-std=450core', shader]
expected_stdout = [
"""
void f() { }
void main() { return 3; }
"""]
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDWithDashEEqIfNDef(expect.ReturnCodeIsZero,
expect.StdoutMatch):
"""Tests -E processes -DX= #ifndefs correctly."""
shader = FileShader(
"""
#ifndef X
void f() { }
#else
void f() { int x; }
#endif
void main(){ return 3; }
""", '.vert')
glslc_args = ['-DX=', '-E', '-std=450core', shader]
expected_stdout = [
"""
void f() { int x; }
void main() { return 3; }
"""]
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDWithDashEFunctionMacro(expect.ReturnCodeIsZero,
expect.StdoutMatch):
"""Tests -E processes -D function macros correctly."""
shader = FileShader(
"""
void main(){ return FOO(3); }
""", '.vert')
glslc_args = ['-DFOO(x)=(2*x+1)*x*x', '-E', '-std=450core', shader]
expected_stdout = [
"""
void main() { return(2 * 3 + 1) * 3 * 3; }
"""]
@inside_glslc_testsuite('OptionCapD')
class TestDashCapDWithDashENestedMacro(expect.ReturnCodeIsZero,
expect.StdoutMatch):
"""Tests -E processes referencing -D options correctly."""
shader = FileShader(
"""
void main() { return X; }
""", '.vert')
glslc_args = ['-DY=4', '-DX=Y', '-E', '-std=450core', shader]
expected_stdout = [
"""
void main() { return 4; }
"""]

View File

@@ -0,0 +1,348 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader, StdinShader
@inside_glslc_testsuite('OptionCapE')
class TestDashCapENoDefs(expect.StdoutMatch):
"""Tests -E without any defines."""
shader = FileShader('#version 140\nvoid main(){}', '.vert')
expected_stdout = '#version 140\nvoid main() { }\n'
glslc_args = ['-E', shader]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEGlslFileAccepted(expect.StdoutMatch):
"""Tests -E if we provide a .glsl file without an explicit stage."""
shader = FileShader('#version 140\nvoid main(){}', '.glsl')
expected_stdout = '#version 140\nvoid main() { }\n'
glslc_args = ['-E', shader]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapESingleDefine(expect.StdoutMatch):
"""Tests -E with command-line define."""
shader = FileShader('#version 140\nvoid main(){ int a = X; }', '.vert')
expected_stdout = '#version 140\nvoid main() { int a = 4; }\n'
glslc_args = ['-DX=4', '-E', shader]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEExpansion(expect.StdoutMatch):
"""Tests -E with macro expansion."""
shader = FileShader('''#version 140
#define X 4
void main() {
int a = X;
}
''', '.vert')
expected_stdout = '''#version 140
void main() {
int a = 4;
}
'''
glslc_args = ['-E', shader]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEFunctionMacro(expect.StdoutMatch):
"""Tests -E with function-style macro expansion."""
shader = FileShader('''#version 140
#define X(A) 4+A
void main() {
int a = X(1);
}
''', '.vert')
expected_stdout = '''#version 140
void main() {
int a = 4 + 1;
}
'''
glslc_args = ['-E', shader]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEPragma(expect.StdoutMatch):
"""Tests -E to make sure pragmas get retained."""
shader = FileShader('''#version 140
#pragma optimize(off)
void main() {
}
''', '.vert')
expected_stdout = '''#version 140
#pragma optimize(off)
void main() {
}
'''
glslc_args = ['-E', shader]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEExtension(expect.StdoutMatch):
"""Tests -E to make sure extensions get retained."""
shader = FileShader('''#version 140
#extension foo: require
void main() {
}
''', '.vert')
expected_stdout = '''#version 140
#extension foo : require
void main() {
}
'''
glslc_args = ['-E', shader]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapELine(expect.StdoutMatch):
"""Tests -E to make sure line numbers get retained."""
shader = FileShader('''#version 140
#define X 4
#line X
#line 2 3
void main() {
}
''', '.vert')
expected_stdout = '''#version 140
#line 4
#line 2 3
void main() {
}
'''
glslc_args = ['-E', shader]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEError(expect.ErrorMessage):
"""Tests -E to make sure #errors get retained."""
shader = FileShader('''#version 140
#if 1
#error This is an error
#endif
void main() {
}
''', '.vert')
expected_error = [
shader, ':3: error: \'#error\' : This is an error\n',
'1 error generated.\n']
glslc_args = ['-E', shader]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEStdin(expect.StdoutMatch):
"""Tests to make sure -E works with stdin."""
shader = StdinShader('''#version 140
void main() {
}
''')
expected_stdout = '''#version 140
void main() {
}
'''
glslc_args = ['-E', '-fshader-stage=vertex', shader]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEStdinDoesNotRequireShaderStage(expect.StdoutMatch):
"""Tests to make sure -E works with stdin even when no shader-stage
is specified."""
shader = StdinShader('''#version 140
void main() {
}
''')
expected_stdout = '''#version 140
void main() {
}
'''
glslc_args = ['-E', shader]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEMultipleFiles(expect.StdoutMatch):
"""Tests to make sure -E works with multiple files."""
shader = StdinShader('''#version 140
void main() {
}
''')
shader2 = FileShader('''#version 140
void function() {
}
''', '.vert')
expected_stdout = '''#version 140
void main() {
}
#version 140
void function() {
}
'''
glslc_args = ['-E', '-fshader-stage=vertex', shader, shader2]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEMultipleFilesWithoutStage(expect.StdoutMatch):
"""Tests to make sure -E works with multiple files even if we do not
specify a stage."""
shader = StdinShader('''#version 140
void main() {
}
''')
shader2 = FileShader('''#version 140
void function() {
}
''', '.glsl')
expected_stdout = '''#version 140
void main() {
}
#version 140
void function() {
}
'''
glslc_args = ['-E', shader, shader2]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEOutputFile(expect.SuccessfulReturn, expect.ValidFileContents):
"""Tests to make sure -E works with output files."""
shader = FileShader('''#version 140
void function() {
}
''', '.vert')
expected_file_contents = '''#version 140
void function() {
}
'''
target_filename = 'foo'
glslc_args = ['-E', shader, '-ofoo']
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEWithS(expect.StdoutMatch):
"""Tests -E in the presence of -S."""
shader = FileShader('#version 140\nvoid main(){}', '.vert')
expected_stdout = '#version 140\nvoid main() { }\n'
glslc_args = ['-E', '-S', shader]
@inside_glslc_testsuite('OptionCapE')
class TestMultipileDashCapE(expect.StdoutMatch):
"""Tests that using -E multiple times works."""
shader = FileShader('#version 140\nvoid main(){}', '.vert')
expected_stdout = '#version 140\nvoid main() { }\n'
glslc_args = ['-E', '-E', shader, '-E']
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEAfterFile(expect.StdoutMatch):
"""Tests that using -E after the filename also works."""
shader = FileShader('#version 140\nvoid main(){}', '.vert')
expected_stdout = '#version 140\nvoid main() { }\n'
glslc_args = [shader, '-E']
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEWithDashC(expect.StdoutMatch):
"""Tests to make sure -E works in the presence of -c."""
shader = FileShader('''#version 140
void main() {
}
''', '.vert')
shader2 = FileShader('''#version 140
void function() {
}
''', '.vert')
expected_stdout = '''#version 140
void main() {
}
#version 140
void function() {
}
'''
glslc_args = ['-E', '-c', shader, shader2]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEWithPPErrors(expect.ErrorMessage):
"""Tests to make sure -E outputs error messages for preprocessing errors."""
shader = FileShader('''#version 310 es
#extension s enable // missing :
#defin A // Bad define
#if X // In glsl X must be defined for X to work.
// Lack of endif.
void main() {
}
''', '.vert')
expected_error = [
shader, ':2: error: \'#extension\' : \':\' missing after extension',
' name\n',
shader, ':3: error: \'#\' : invalid directive: defin\n',
shader, ':4: error: \'preprocessor evaluation\' : undefined macro in',
' expression not allowed in es profile X\n',
shader, ':8: error: \'\' : missing #endif\n',
'4 errors generated.\n']
glslc_args = ['-E', shader]
@inside_glslc_testsuite('OptionCapE')
class TestDashCapEStdinErrors(expect.ErrorMessage):
"""Tests that -E outputs error messages correctly for stdin input."""
shader = StdinShader('''#version 310 es
#extension s enable // missing :
void main() {
}
''')
expected_error = [
'<stdin>:2: error: \'#extension\' : \':\' missing after extension',
' name\n',
'1 error generated.\n']
glslc_args = ['-E', shader]

View File

@@ -0,0 +1,754 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
import os.path
import sys
from environment import File, Directory
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
from glslc_test_framework import GlslCTest
MINIMAL_SHADER = '#version 140\nvoid main() {}'
EMPTY_SHADER_IN_CURDIR = Directory('.', [File('shader.vert', MINIMAL_SHADER)])
EMPTY_SHADER_IN_SUBDIR = Directory('subdir',
[File('shader.vert', MINIMAL_SHADER)])
def process_test_specified_dependency_info_rules(test_specified_rules):
"""A helper function to process the expected dependency info rules
specified in tests before checking the actual dependency rule output.
This is required because the filename and path of temporary files created
through FileShader is unknown at the time the expected dependency info rules
are declared.
Note this function process the given rule list in-place.
"""
for rule in test_specified_rules:
# If the 'target' value is not a hard-coded file name but a
# FileShader, we need its full path, append extension to it and
# strip the directory component from it to get the complete target
# name.
if isinstance(rule['target'], FileShader):
rule['target'] = rule['target'].filename
if 'target_extension' in rule:
if rule['target_extension'] is not None:
rule['target'] = rule['target'] + rule['target_extension']
rule.pop('target_extension')
rule['target'] = os.path.basename(rule['target'])
# The dependency set may have FileShader too, we need to replace
# them with their absolute paths.
dependent_file_name_set = set()
for dependent_file in rule['dependency']:
if isinstance(dependent_file, FileShader):
dependent_file_name_set.add(dependent_file.filename)
else:
dependent_file_name_set.add(dependent_file)
rule['dependency'] = dependent_file_name_set
def parse_text_rules(text_lines):
""" A helper function to read text lines and construct and returns a list of
dependency rules which can be used for comparison.
The list is built with the text order. Each rule is described in the
following way:
{'target': <target name>, 'dependency': <set of dependent filenames>}
"""
rules = []
for line in text_lines:
if line.strip() == "":
continue
rule = {'target': line.split(': ')[0].strip(),
'dependency': set(line.split(': ')[-1].strip().split(' '))}
rules.append(rule)
return rules
class DependencyInfoStdoutMatch(GlslCTest):
"""Mixin class for tests that can expect dependency info in Stdout.
To mix in this class, the subclass needs to provide
dependency_rules_expected as a list of dictionaries, each dictionary
describes one expected make rule for a target file. A expected rule should
be specified in the following way:
rule = {'target': <target name>,
'target_extension': <.spv, .spvasm or None>,
'dependency': <dependent file names>}
The 'target_extension' field is optional, its value will be appended to
'target' to get complete target name.
And the list 'dependency_rules_expected' is a list of such rules and the
order of the rules does matter.
"""
def check_stdout_dependency_info(self, status):
if not status.stdout:
return False, 'Expect dependency rules on stdout'
if sys.version_info[0] == 2:
rules = parse_text_rules(status.stdout.decode('utf-8').split('\n'))
elif sys.version_info[0] == 3:
rules = parse_text_rules(str(status.stdout,
encoding='utf-8',
errors='ignore').split('\n'))
process_test_specified_dependency_info_rules(
self.dependency_rules_expected)
if self.dependency_rules_expected != rules:
return False, ('Incorrect dependency info:\n{ac_rules}\n'
'Expected:\n{ex_rules}\n'
'Stdout output:\n{ac_stdout}\n'.format(
ac_rules=rules,
ex_rules=self.dependency_rules_expected,
ac_stdout=status.stdout))
return True, ''
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMSingleInputRelativePathNoInclude(DependencyInfoStdoutMatch):
"""Tests -M with single input file which doesn't contain #include and is
represented in relative path.
e.g. glslc -M shader.vert
=> shader.vert.spv: shader.vert
"""
environment = EMPTY_SHADER_IN_CURDIR
glslc_args = ['-M', 'shader.vert']
dependency_rules_expected = [{'target': "shader.vert.spv",
'dependency': {"shader.vert"}}]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMSingleInputAbsolutePathNoInclude(DependencyInfoStdoutMatch):
"""Tests -M with single input file which doesn't contain #include and is
represented in absolute path.
e.g. glslc -M /usr/local/shader.vert
=> shader.vert.spv: /usr/local/shader.vert
"""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = ['-M', shader]
dependency_rules_expected = [{'target': shader,
'target_extension': '.spv',
'dependency': {shader}}]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMSingleInputRelativePathWithInclude(
DependencyInfoStdoutMatch):
"""Tests -M with single input file which does contain #include and is
represented in relative path.
e.g. glslc -M a.vert
=> a.vert.spv: a.vert b.vert
"""
environment = Directory('.', [
File('a.vert', '#version 140\n#include "b.vert"\nvoid main(){}\n'),
File('b.vert', 'void foo(){}\n'),
])
glslc_args = ['-M', 'a.vert']
dependency_rules_expected = [{'target': 'a.vert.spv',
'dependency': {'a.vert', 'b.vert'}}]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMSingleInputRelativePathWithIncludeSubdir(
DependencyInfoStdoutMatch):
"""Tests -M with single input file which does #include another file in a
subdirectory of current directory and is represented in relative path.
e.g. glslc -M a.vert
=> a.vert.spv: a.vert include/b.vert
"""
environment = Directory('.', [
File('a.vert', ('#version 140\n#include "include/b.vert"'
'\nvoid main(){}\n')),
Directory('include', [File('b.vert', 'void foo(){}\n')]),
])
glslc_args = ['-M', 'a.vert']
dependency_rules_expected = [{'target': 'a.vert.spv',
'dependency': {'a.vert', 'include/b.vert'}}]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMSingleInputRelativePathWithDashI(DependencyInfoStdoutMatch):
"""Tests -M with single input file works with -I option. The #include
directive does not specify 'include/' for the file to be include.
e.g. glslc -M a.vert -I include
=> a.vert.spv: a.vert include/b.vert
"""
environment = Directory('.', [
File('a.vert', ('#version 140\n#include "b.vert"'
'\nvoid main(){}\n')),
Directory('include', [File('b.vert', 'void foo(){}\n')]),
])
glslc_args = ['-M', 'a.vert', '-I', 'include']
dependency_rules_expected = [{'target': 'a.vert.spv',
'dependency': {'a.vert', 'include/b.vert'}}]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMSingleInputRelativePathWithNestedInclude(
DependencyInfoStdoutMatch):
"""Tests -M with single input file under nested #include case. The input file
is represented in relative path.
e.g. glslc -M a.vert
=> a.vert.spv: a.vert b.vert c.vert
"""
environment = Directory('.', [
File('a.vert', '#version 140\n#include "b.vert"\nvoid main(){}\n'),
File('b.vert', 'void foo(){}\n#include "c.vert"\n'),
File('c.vert', 'void bar(){}\n'),
])
glslc_args = ['-M', 'a.vert']
dependency_rules_expected = [{'target': 'a.vert.spv',
'dependency':
{'a.vert', 'b.vert', 'c.vert'}}]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMMultipleInputRelativePathNoInclude(
DependencyInfoStdoutMatch):
"""Tests -M with multiple input file which don't contain #include and are
represented in relative paths.
e.g. glslc -M a.vert b.vert
=> a.vert.spv: a.vert
b.vert.spv: b.vert
"""
environment = Directory('.', [
File('a.vert', MINIMAL_SHADER),
File('b.vert', MINIMAL_SHADER),
])
glslc_args = ['-M', 'a.vert', 'b.vert']
dependency_rules_expected = [{'target': 'a.vert.spv',
'dependency': {'a.vert'}},
{'target': 'b.vert.spv',
'dependency': {'b.vert'}}, ]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMMultipleInputAbsolutePathNoInclude(
DependencyInfoStdoutMatch):
"""Tests -M with single input file which doesn't contain #include and is
represented in absolute path.
e.g. glslc -M /usr/local/a.vert /usr/local/b.vert
=> a.vert.spv: /usr/local/a.vert
b.vert.spv: /usr/local/b.vert
"""
shader_a = FileShader(MINIMAL_SHADER, '.vert')
shader_b = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = ['-M', shader_a, shader_b]
dependency_rules_expected = [{'target': shader_a,
'target_extension': '.spv',
'dependency': {shader_a}},
{'target': shader_b,
'target_extension': '.spv',
'dependency': {shader_b}}, ]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMDashCapMT(DependencyInfoStdoutMatch):
"""Tests -MT works with -M. User can specify the target object name in the
generated dependency info.
e.g. glslc -M shader.vert -MT target
=> target: shader.vert
"""
environment = EMPTY_SHADER_IN_CURDIR
glslc_args = ['-M', 'shader.vert', '-MT', 'target']
dependency_rules_expected = [{'target': 'target',
'dependency': {'shader.vert'}}]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMInputAbsolutePathWithInclude(DependencyInfoStdoutMatch):
"""Tests -M have included files represented in absolute paths when the input
file is represented in absolute path.
E.g. Assume a.vert has '#include "b.vert"'
glslc -M /usr/local/a.vert
=> a.vert.spv: /usr/local/a.vert /usr/local/b.vert
"""
environment = Directory('.', [File('b.vert', 'void foo(){}\n')])
shader_main = FileShader(
'#version 140\n#include "b.vert"\nvoid main(){}\n', '.vert')
glslc_args = ['-M', shader_main]
dependency_rules_expected = [{
'target': shader_main,
'target_extension': '.spv',
'dependency': {shader_main}
# The dependency here is not complete. we can not get the absolute path
# of b.vert here. It will be added in check_stdout_dependency_info()
}]
def check_stdout_dependency_info(self, status):
# Add the absolute path of b.vert to the dependency set
self.dependency_rules_expected[0]['dependency'].add(os.path.dirname(
self.shader_main.filename) + '/b.vert')
return DependencyInfoStdoutMatch.check_stdout_dependency_info(self,
status)
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMSingleInputAbsolutePathWithIncludeSubdir(
DependencyInfoStdoutMatch):
"""Tests -M with single input file which does #include another file in a
subdirectory of current directory and is represented in absolute path.
e.g. glslc -M /usr/local/a.vert
=> a.vert.spv: /usr/local/a.vert /usr/local/include/b.vert
"""
environment = Directory('.', [
Directory('include', [File('b.vert', 'void foo(){}\n')]),
])
shader_main = FileShader('#version 140\n#include "include/b.vert"\n',
'.vert')
glslc_args = ['-M', shader_main]
dependency_rules_expected = [{
'target': shader_main,
'target_extension': '.spv',
'dependency': {shader_main}
# The dependency here is not complete. we can not get the absolute
# path of include/b.vert here. It will be added in
# check_stdout_dependency_info()
}]
def check_stdout_dependency_info(self, status):
# Add the absolute path of include/b.vert to the dependency set
self.dependency_rules_expected[0]['dependency'].add(os.path.dirname(
self.shader_main.filename) + '/include/b.vert')
return DependencyInfoStdoutMatch.check_stdout_dependency_info(self,
status)
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMOverridesOtherModes(DependencyInfoStdoutMatch):
"""Tests -M overrides other compiler mode options, includeing -E, -c and -S.
"""
environment = Directory('.', [
File('a.vert', MINIMAL_SHADER),
File('b.vert', MINIMAL_SHADER),
])
glslc_args = ['-M', '-E', '-c', '-S', 'a.vert', 'b.vert']
dependency_rules_expected = [{'target': 'a.vert.spv',
'dependency': {'a.vert'}},
{'target': 'b.vert.spv',
'dependency': {'b.vert'}}]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMMEquivalentToCapM(DependencyInfoStdoutMatch):
"""Tests that -MM behaves as -M.
e.g. glslc -MM shader.vert
=> shader.vert.spv: shader.vert
"""
environment = EMPTY_SHADER_IN_CURDIR
glslc_args = ['-MM', 'shader.vert']
dependency_rules_expected = [{'target': 'shader.vert.spv',
'dependency': {'shader.vert'}}]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMImpliesDashCapE(DependencyInfoStdoutMatch,
expect.NoOutputOnStderr):
"""Tests that -M implies -E, a .glsl file without an explict stage should
not generate an error.
e.g. glslc -M shader.glsl
=> shader.spv: shader.glsl
<no error message should be generated>
"""
environment = Directory('.', [File('shader.glsl', MINIMAL_SHADER)])
glslc_args = ['-M', 'shader.glsl']
dependency_rules_expected = [{'target': 'shader.spv',
'dependency': {'shader.glsl'}}]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMImpliesDashW(DependencyInfoStdoutMatch,
expect.NoOutputOnStderr):
"""Tests that -M implies -w, a deprecated attribute should not generate
warning message.
e.g. glslc -M shader.vert
=> shader.vert.spv: shader.vert
<no warning message should be generated>
"""
environment = Directory('.', [File(
'shader.vert', """#version 400
layout(location=0) attribute float x;
void main() {}""")])
glslc_args = ['-M', 'shader.vert']
dependency_rules_expected = [{'target': 'shader.vert.spv',
'dependency': {'shader.vert'}}]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMMImpliesDashCapE(DependencyInfoStdoutMatch,
expect.NoOutputOnStderr):
"""Tests that -M implies -E, a .glsl file without an explict stage should
not generate an error.
e.g. glslc -MM shader.glsl
=> shader.spv: shader.glsl
<no error message should be generated>
"""
environment = Directory('.', [File('shader.glsl', MINIMAL_SHADER)])
glslc_args = ['-MM', 'shader.glsl']
dependency_rules_expected = [{'target': 'shader.spv',
'dependency': {'shader.glsl'}}]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMMImpliesDashW(DependencyInfoStdoutMatch,
expect.NoOutputOnStderr):
"""Tests that -MM implies -w, a deprecated attribute should not generate
warning message.
e.g. glslc -MM shader.vert
=> shader.vert.spv: shader.vert
<no warning message should be generated>
"""
environment = Directory('.', [File(
'shader.vert', """
#version 400
layout(location = 0) attribute float x;
void main() {}""")])
glslc_args = ['-MM', 'shader.vert']
dependency_rules_expected = [{'target': 'shader.vert.spv',
'dependency': {'shader.vert'}}]
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMD(expect.ValidFileContents, expect.ValidNamedObjectFile):
"""Tests that -MD generates dependency info file and compilation output.
e.g. glslc -MD shader.vert
=> <a.spv: valid SPIR-V object file>
=> <shader.vert.spv.d: dependency info>
"""
environment = EMPTY_SHADER_IN_CURDIR
glslc_args = ['-MD', 'shader.vert']
expected_object_filenames = ('a.spv', )
target_filename = 'shader.vert.spv.d'
expected_file_contents = ['shader.vert.spv: shader.vert\n']
class DependencyInfoFileMatch(GlslCTest):
"""Mixin class for tests that can expect dependency info files.
To mix in this class, subclasses need to provide dependency_info_filenames
and dependency_info_files_expected_contents which are two lists.
list dependency_info_filenames contains the dependency info file names and
list dependency_info_files_expected_contents contains the expected matching
dependency rules.
The item order of the two lists should match, which means:
dependency_info_files_expected_contents[i] should describe the
dependency rules saved in dependency_info_filenames[i]
The content of each dependency info file is described in same 'list of dict'
structure explained in class DependencyInfoStdoutMatch's doc string.
"""
def check_dependency_info_files(self, status):
dep_info_files = \
[os.path.join(status.directory,
f) for f in self.dependency_info_filenames]
for i, df in enumerate(dep_info_files):
if not os.path.isfile(df):
return False, 'Cannot find file: ' + df
try:
with open(df, 'r') as dff:
content = dff.read()
rules = parse_text_rules(content.split('\n'))
process_test_specified_dependency_info_rules(
self.dependency_info_files_expected_contents[i])
if self.dependency_info_files_expected_contents[
i] != rules:
return False, (
'Incorrect dependency info:\n{ac_rules}\n'
'Expected:\n{ex_rules}\n'
'Incorrect file output:\n{ac_out}\n'
'Incorrect dependency info file:\n{ac_file}\n'.format(
ac_rules=rules,
ex_rules=self.dependency_rules_expected,
ac_stdout=content,
ac_file=df))
except IOError:
return False, ('Could not open dependency info file ' + df +
' for reading')
return True, ''
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMWorksWithDashO(DependencyInfoFileMatch):
"""Tests -M works with -o option. When user specifies an output file name
with -o, the dependency info should be dumped to the user specified output
file.
"""
environment = EMPTY_SHADER_IN_CURDIR
glslc_args = ['-M', 'shader.vert', '-o', 'dep_info']
dependency_info_filenames = ('dep_info', )
dependency_info_files_expected_contents = []
dependency_info_files_expected_contents.append(
[{'target': 'shader.vert.spv',
'dependency': {'shader.vert'}}])
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMDMultipleFile(expect.ValidNamedObjectFile,
DependencyInfoFileMatch):
"""Tests that -MD generates dependency info file for multiple files.
e.g. glslc -MD a.vert b.vert -c
=> <a.vert.spv: valid SPIR-V object file>
=> <a.vert.spv.d: dependency info: "a.vert.spv: a.vert">
=> <b.vert.spv: valid SPIR-V object file>
=> <b.vert.spv.d: dependency info: "b.vert.spv: b.vert">
"""
environment = Directory('.', [File('a.vert', MINIMAL_SHADER),
File('b.vert', MINIMAL_SHADER)])
glslc_args = ['-MD', 'a.vert', 'b.vert', '-c']
expected_object_filenames = ('a.vert.spv', 'b.vert.spv', )
dependency_info_filenames = ['a.vert.spv.d', 'b.vert.spv.d']
dependency_info_files_expected_contents = []
dependency_info_files_expected_contents.append([{'target': 'a.vert.spv',
'dependency': {'a.vert'}}
])
dependency_info_files_expected_contents.append([{'target': 'b.vert.spv',
'dependency': {'b.vert'}}
])
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMDMultipleFilePreprocessingOnlyMode(expect.StdoutMatch,
DependencyInfoFileMatch):
"""Tests that -MD generates dependency info file for multiple files in
preprocessing only mode.
e.g. glslc -MD a.vert b.vert -E
=> stdout: preprocess result of a.vert and b.vert
=> <a.vert.spv.d: dependency info: "a.vert.spv: a.vert">
=> <b.vert.spv.d: dependency info: "b.vert.spv: b.vert">
"""
environment = Directory('.', [File('a.vert', MINIMAL_SHADER),
File('b.vert', MINIMAL_SHADER)])
glslc_args = ['-MD', 'a.vert', 'b.vert', '-E']
dependency_info_filenames = ['a.vert.spv.d', 'b.vert.spv.d']
dependency_info_files_expected_contents = []
dependency_info_files_expected_contents.append([{'target': 'a.vert.spv',
'dependency': {'a.vert'}}
])
dependency_info_files_expected_contents.append([{'target': 'b.vert.spv',
'dependency': {'b.vert'}}
])
expected_stdout = ("#version 140\nvoid main() { }\n"
"#version 140\nvoid main() { }\n")
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMDMultipleFileDisassemblyMode(expect.ValidNamedAssemblyFile,
DependencyInfoFileMatch):
"""Tests that -MD generates dependency info file for multiple files in
disassembly mode.
e.g. glslc -MD a.vert b.vert -S
=> <a.vert.spvasm: valid SPIR-V assembly file>
=> <a.vert.spvasm.d: dependency info: "a.vert.spvasm: a.vert">
=> <b.vert.spvasm: valid SPIR-V assembly file>
=> <b.vert.spvasm.d: dependency info: "b.vert.spvasm: b.vert">
"""
environment = Directory('.', [File('a.vert', MINIMAL_SHADER),
File('b.vert', MINIMAL_SHADER)])
glslc_args = ['-MD', 'a.vert', 'b.vert', '-S']
expected_assembly_filenames = ('a.vert.spvasm', 'b.vert.spvasm', )
dependency_info_filenames = ['a.vert.spvasm.d', 'b.vert.spvasm.d']
dependency_info_files_expected_contents = []
dependency_info_files_expected_contents.append([{'target': 'a.vert.spvasm',
'dependency': {'a.vert'}}
])
dependency_info_files_expected_contents.append([{'target': 'b.vert.spvasm',
'dependency': {'b.vert'}}
])
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMT(expect.ValidFileContents, expect.ValidNamedObjectFile):
"""Tests that -MT generates dependency info file with specified target label.
e.g. glslc -MD shader.vert -MT target_label
=> <a.spv: valid SPIR-V object file>
=> <shader.vert.spv.d: dependency info: "target_label: shader.vert">
"""
environment = EMPTY_SHADER_IN_CURDIR
glslc_args = ['-MD', 'shader.vert', '-MT', 'target_label']
expected_object_filenames = ('a.spv', )
target_filename = 'shader.vert.spv.d'
expected_file_contents = ['target_label: shader.vert\n']
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMF(expect.ValidFileContents, expect.ValidNamedObjectFile):
"""Tests that -MF dumps dependency info into specified file.
e.g. glslc -MD shader.vert -MF dep_file
=> <a.spv: valid SPIR-V object file>
=> <dep_file: dependency info: "shader.vert.spv: shader.vert">
"""
environment = EMPTY_SHADER_IN_CURDIR
glslc_args = ['-MD', 'shader.vert', '-MF', 'dep_file']
expected_object_filenames = ('a.spv', )
target_filename = 'dep_file'
expected_file_contents = ['shader.vert.spv: shader.vert\n']
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMDSpecifyOutputFileName(expect.ValidFileContents,
expect.ValidNamedObjectFile):
"""Tests that -MD has the default dependency info file name and target
label correct when -o <output_file_name> appears in the command line.
The default dependency info file name and target label should be deduced
from the linking-disabled compilation output.
e.g. glslc -MD subdir/shader.vert -c -o output
=> <./output: valid SPIR-V object file>
=> <./output.d: dependency info: "output: shader.vert">
"""
environment = EMPTY_SHADER_IN_SUBDIR
glslc_args = ['-MD', 'subdir/shader.vert', '-c', '-o', 'output']
expected_object_filenames = ('output', )
target_filename = 'output.d'
expected_file_contents = ['output: subdir/shader.vert\n']
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMDWithDashMFDashMTDashO(expect.ValidFileContents,
expect.ValidNamedObjectFile):
"""Tests that -MD, -MF, -MT and -o gernates dependency info file and
compilation output file correctly
e.g. glslc -MD subdir/shader.vert -c -o subdir/out -MF dep_info -MT label
=> <subdir/out: valid SPIR-V object file>
=> <dep_info: dependency info: "label: shader.vert">
"""
environment = EMPTY_SHADER_IN_SUBDIR
glslc_args = ['-MD', 'subdir/shader.vert', '-c', '-o', 'subdir/out', '-MF',
'dep_info', '-MT', 'label']
expected_object_filenames = ('subdir/out', )
target_filename = 'dep_info'
expected_file_contents = ['label: subdir/shader.vert\n']
@inside_glslc_testsuite('OptionsCapM')
class TestDashCapMDWithDashMFDashMTDashODisassemblyMode(
expect.ValidFileContents, expect.ValidNamedAssemblyFile):
"""Tests that -MD, -MF, -MT and -o gernates dependency info file and
compilation output file correctly in disassembly mode
e.g. glslc -MD subdir/shader.vert -s -o subdir/out -MF dep_info -MT label
=> <subdir/out: valid SPIR-V object file>
=> <dep_info: dependency info: "label: shader.vert">
"""
environment = EMPTY_SHADER_IN_SUBDIR
glslc_args = ['-MD', 'subdir/shader.vert', '-S', '-o', 'subdir/out', '-MF',
'dep_info', '-MT', 'label']
expected_assembly_filenames = ('subdir/out', )
target_filename = 'dep_info'
expected_file_contents = ['label: subdir/shader.vert\n']
@inside_glslc_testsuite('OptionsCapM')
class TestErrorSetBothDashCapMAndDashCapMD(expect.StderrMatch):
"""Tests that when both -M (or -MM) and -MD are specified, glslc should exit
with an error message complaining the case and neither dependency info
output nor compilation output. This test has -MD before -M flag.
"""
environment = EMPTY_SHADER_IN_CURDIR
glslc_args = ['-MD', '-M', 'shader.vert']
expected_stderr = ['glslc: error: both -M (or -MM) and -MD are specified. '
'Only one should be used at one time.\n']
@inside_glslc_testsuite('OptionsCapM')
class TestErrorSetBothDashCapMDAndDashCapM(expect.StderrMatch):
"""Tests that when both -M (or -MM) and -MD are specified, glslc should exit
with an error message complaining the case and neither dependency info
output nor compilation output. This test has -M before -MD flag.
"""
environment = EMPTY_SHADER_IN_CURDIR
glslc_args = ['-M', '-MD', 'shader.vert']
expected_stderr = ['glslc: error: both -M (or -MM) and -MD are specified. '
'Only one should be used at one time.\n']
@inside_glslc_testsuite('OptionsCapM')
class TestErrorDashCapMFWithMultipleInputFiles(expect.StderrMatch):
"""Tests that when -MF option is specified, only one input file should be
provided."""
environment = Directory('.', [File('a.vert', MINIMAL_SHADER),
File('b.vert', MINIMAL_SHADER)])
glslc_args = ['-MD', 'a.vert', 'b.vert', '-c', '-MF', 'dep_info']
expected_stderr = ['glslc: error: '
'to specify dependency info file name or dependency '
'info target, only one input file is allowed.\n']
@inside_glslc_testsuite('OptionsCapM')
class TestErrorDashCapMTWithMultipleInputFiles(expect.StderrMatch):
"""Tests that when -MT option is specified, only one input file should be
provided."""
environment = Directory('.', [File('a.vert', MINIMAL_SHADER),
File('b.vert', MINIMAL_SHADER)])
glslc_args = ['-M', 'a.vert', 'b.vert', '-c', '-MT', 'target']
expected_stderr = ['glslc: error: '
'to specify dependency info file name or dependency '
'info target, only one input file is allowed.\n']
@inside_glslc_testsuite('OptionsCapM')
class TestErrorDashCapMFMissingDashMAndDashMD(expect.StderrMatch):
"""Tests that when only -MF is specified while -M and -MD are not specified,
glslc should emit an error complaining that the user must specifiy either
-M (-MM) or -MD to generate dependency info.
"""
environment = EMPTY_SHADER_IN_CURDIR
glslc_args = ['-MF', 'dep_info', 'shader.vert', '-c']
expected_stderr = ['glslc: error: '
'to generate dependencies you must specify either -M '
'(-MM) or -MD\n']
@inside_glslc_testsuite('OptionsCapM')
class TestErrorDashCapMTMissingDashMAndMDWith(expect.StderrMatch):
"""Tests that when only -MF and -MT is specified while -M and -MD are not
specified, glslc should emit an error complaining that the user must
specifiy either -M (-MM) or -MD to generate dependency info.
"""
environment = EMPTY_SHADER_IN_CURDIR
glslc_args = ['-MF', 'dep_info', '-MT', 'target', 'shader.vert', '-c']
expected_stderr = ['glslc: error: '
'to generate dependencies you must specify either -M '
'(-MM) or -MD\n']
@inside_glslc_testsuite('OptionsCapM')
class TestErrorMissingDependencyInfoFileName(expect.StderrMatch):
"""Tests that dependency file name is missing when -MF is specified."""
environment = EMPTY_SHADER_IN_CURDIR
glslc_args = ['target', 'shader.vert', '-c', '-MF']
expected_stderr = ['glslc: error: '
'missing dependency info filename after \'-MF\'\n']
@inside_glslc_testsuite('OptionsCapM')
class TestErrorMissingDependencyTargetName(expect.StderrMatch):
"""Tests that dependency target name is missing when -MT is specified."""
environment = EMPTY_SHADER_IN_CURDIR
glslc_args = ['target', 'shader.vert', '-c', '-MT']
expected_stderr = ['glslc: error: '
'missing dependency info target after \'-MT\'\n']

View File

@@ -0,0 +1,165 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
import os.path
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader, StdinShader
def simple_vertex_shader():
return """#version 310 es
void main() {
gl_Position = vec4(1., 2., 3., 4.);
}"""
def simple_fragment_shader():
return """#version 310 es
void main() {
gl_FragDepth = 10.;
}"""
def simple_compute_shader():
return """#version 310 es
void main() {
uvec3 temp = gl_WorkGroupID;
}"""
@inside_glslc_testsuite('OptionDashCapS')
class TestSingleDashCapSSingleFile(expect.ValidAssemblyFile):
"""Tests that -S works with a single file."""
shader = FileShader(simple_vertex_shader(), '.vert')
glslc_args = ['-S', shader]
@inside_glslc_testsuite('OptionDashCapS')
class TestSingleFileSingleDashCapS(expect.ValidAssemblyFile):
"""Tests that the position of -S doesn't matter."""
shader = FileShader(simple_vertex_shader(), '.vert')
glslc_args = [shader, '-S']
@inside_glslc_testsuite('OptionDashCapS')
class TestSingleDashCapSMultipleFiles(expect.ValidAssemblyFile):
"""Tests that -S works with multiple files."""
shader1 = FileShader(simple_vertex_shader(), '.vert')
shader2 = FileShader(simple_vertex_shader(), '.vert')
shader3 = FileShader(simple_fragment_shader(), '.frag')
glslc_args = ['-S', shader1, shader2, shader3]
@inside_glslc_testsuite('OptionDashCapS')
class TestMultipleDashCapSSingleFile(expect.ValidAssemblyFile):
"""Tests that multiple -Ss works as one."""
shader = FileShader(simple_vertex_shader(), '.vert')
glslc_args = ['-S', '-S', shader, '-S']
@inside_glslc_testsuite('OptionDashCapS')
class TestMultipleDashCapSMultipleFiles(expect.ValidAssemblyFile):
"""Tests a mix of -Ss and files."""
shader1 = FileShader(simple_fragment_shader(), '.frag')
shader2 = FileShader(simple_vertex_shader(), '.vert')
shader3 = FileShader(simple_compute_shader(), '.comp')
glslc_args = ['-S', shader1, '-S', '-S', shader2, '-S', shader3, '-S']
@inside_glslc_testsuite('OptionDashCapS')
class TestDashCapSWithDashC(expect.ValidAssemblyFile):
"""Tests that -S overwrites -c."""
shader1 = FileShader(simple_fragment_shader(), '.frag')
shader2 = FileShader(simple_vertex_shader(), '.vert')
glslc_args = ['-c', '-S', shader1, '-c', '-c', shader2]
@inside_glslc_testsuite('OptionDashCapS')
class TestDashCapSWithDashFShaderStage(expect.ValidAssemblyFile):
"""Tests that -S works with -fshader-stage=."""
shader1 = FileShader(simple_fragment_shader(), '.glsl')
shader2 = FileShader(simple_vertex_shader(), '.glsl')
shader3 = FileShader(simple_compute_shader(), '.glsl')
glslc_args = ['-S',
'-fshader-stage=fragment', shader1,
'-fshader-stage=vertex', shader2,
'-fshader-stage=compute', shader3]
@inside_glslc_testsuite('OptionDashCapS')
class TestDashCapSWithDashStd(expect.ValidAssemblyFileWithWarning):
"""Tests that -S works with -std=."""
shader1 = FileShader(simple_fragment_shader(), '.frag')
shader2 = FileShader(simple_vertex_shader(), '.vert')
shader3 = FileShader(simple_compute_shader(), '.comp')
glslc_args = ['-S', '-std=450', shader1, shader2, shader3]
w = (': warning: (version, profile) forced to be (450, none), '
'while in source code it is (310, es)\n')
expected_warning = [
shader1, w, shader2, w, shader3, w, '3 warnings generated.\n']
@inside_glslc_testsuite('OptionDashCapS')
class TestDashCapSWithDashOSingleFile(expect.SuccessfulReturn,
expect.CorrectAssemblyFilePreamble):
"""Tests that -S works with -o on a single file."""
shader = FileShader(simple_fragment_shader(), '.frag')
glslc_args = ['-S', '-o', 'blabla', shader]
def check_output_blabla(self, status):
output_name = os.path.join(status.directory, 'blabla')
return self.verify_assembly_file_preamble(output_name)
@inside_glslc_testsuite('OptionDashCapS')
class TestDashCapSWithDashOMultipleFiles(expect.ErrorMessage):
"""Tests that -S works with -o on a single file."""
shader1 = FileShader(simple_fragment_shader(), '.frag')
shader2 = FileShader(simple_vertex_shader(), '.vert')
glslc_args = ['-S', '-o', 'blabla', shader1, shader2]
expected_error = ['glslc: error: cannot specify -o when '
'generating multiple output files\n']
@inside_glslc_testsuite('OptionDashCapS')
class TestDashCapSWithStdIn(expect.ValidAssemblyFile):
"""Tests that -S works with stdin."""
shader = StdinShader(simple_fragment_shader())
glslc_args = ['-S', '-fshader-stage=fragment', shader]
@inside_glslc_testsuite('OptionDashCapS')
class TestDashCapSWithStdOut(
expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch):
"""Tests that -S works with stdout."""
shader = FileShader(simple_fragment_shader(), '.frag')
glslc_args = ['-S', '-o', '-', shader]
expected_stdout = True
expected_stderr = ''

View File

@@ -0,0 +1,55 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
def empty_es_310_shader():
return '#version 310 es\n void main() {}\n'
@inside_glslc_testsuite('OptionC')
class TestSingleDashCSingleFile(expect.ValidObjectFile):
"""Tests that glslc accepts -c [filename]."""
shader = FileShader(empty_es_310_shader(), '.vert')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('OptionC')
class TestSingleFileSingleDashC(expect.ValidObjectFile):
"""Tests that glslc accepts [filename] -c."""
shader = FileShader(empty_es_310_shader(), '.vert')
glslc_args = [shader, '-c']
@inside_glslc_testsuite('OptionC')
class TestMultipleFiles(expect.ValidObjectFile):
"""Tests that glslc accepts -c and multiple source files."""
shader1 = FileShader(empty_es_310_shader(), '.vert')
shader2 = FileShader(empty_es_310_shader(), '.frag')
glslc_args = ['-c', shader1, shader2]
@inside_glslc_testsuite('OptionC')
class TestMultipleDashC(expect.ValidObjectFile):
"""Tests that glslc accepts multiple -c and treated them as one."""
shader1 = FileShader(empty_es_310_shader(), '.vert')
shader2 = FileShader(empty_es_310_shader(), '.vert')
glslc_args = ['-c', shader1, '-c', '-c', shader2]

View File

@@ -0,0 +1,180 @@
# Copyright 2016 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from environment import File, Directory
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
MINIMAL_SHADER = '#version 310 es\nvoid main() {}'
EMPTY_SHADER_IN_CWD = Directory('.', [File('shader.vert', MINIMAL_SHADER)])
ASSEMBLY_WITH_DEBUG_SOURCE = [
"""; SPIR-V
; Version: 1.0
; Generator: Google Shaderc over Glslang; 11
; Bound: 7
; Schema: 0
OpCapability Shader
%2 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %main "main"
%1 = OpString "shader.vert"
OpSource ESSL 310 %1 "// OpModuleProcessed entry-point main
// OpModuleProcessed client vulkan100
// OpModuleProcessed target-env vulkan1.0
// OpModuleProcessed entry-point main
#line 1
#version 310 es
void main() {}"
OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
OpSourceExtension "GL_GOOGLE_include_directive"
OpName %main "main"
%void = OpTypeVoid
%4 = OpTypeFunction %void
OpLine %1 2 11
%main = OpFunction %void None %4
%6 = OpLabel
OpLine %1 2 0
OpReturn
OpFunctionEnd
"""
]
ASSEMBLY_O0 = [
"""; SPIR-V
; Version: 1.0
; Generator: Google Shaderc over Glslang; 11
; Bound: 6
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %main "main"
OpSource ESSL 310
OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
OpSourceExtension "GL_GOOGLE_include_directive"
OpName %main "main"
%void = OpTypeVoid
%3 = OpTypeFunction %void
%main = OpFunction %void None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
"""]
ASSEMBLY_O = [
"""; SPIR-V
; Version: 1.0
; Generator: Google Shaderc over Glslang; 11
; Bound: 6
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %4 "main"
%void = OpTypeVoid
%3 = OpTypeFunction %void
%4 = OpFunction %void None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
"""]
ASSEMBLY_Os = [
"""; SPIR-V
; Version: 1.0
; Generator: Google Shaderc over Glslang; 11
; Bound: 6
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %4 "main"
%void = OpTypeVoid
%3 = OpTypeFunction %void
%4 = OpFunction %void None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
"""]
@inside_glslc_testsuite('OptionDashCapO')
class TestDashCapO0(expect.ValidFileContents):
"""Tests that -O0 works."""
environment = EMPTY_SHADER_IN_CWD
glslc_args = ['-S', '-O0', 'shader.vert']
target_filename = 'shader.vert.spvasm'
expected_file_contents = ASSEMBLY_O0
@inside_glslc_testsuite('OptionDashCapO')
class TestDashCapOPerformance(expect.ValidFileContents):
"""Tests -O works."""
environment = EMPTY_SHADER_IN_CWD
glslc_args = ['-S', '-O', 'shader.vert']
target_filename = 'shader.vert.spvasm'
expected_file_contents = ASSEMBLY_O
@inside_glslc_testsuite('OptionDashCapO')
class TestDashCapOs(expect.ValidFileContents):
"""Tests that -Os works."""
environment = EMPTY_SHADER_IN_CWD
glslc_args = ['-S', '-Os', 'shader.vert']
target_filename = 'shader.vert.spvasm'
expected_file_contents = ASSEMBLY_Os
@inside_glslc_testsuite('OptionDashCapO')
class TestDashCapOOverriding(expect.ValidFileContents):
"""Tests that if there are multiple -O's, only the last one takes effect."""
environment = EMPTY_SHADER_IN_CWD
glslc_args = ['-S', '-Os', '-O0', '-Os', '-O0', 'shader.vert']
target_filename = 'shader.vert.spvasm'
expected_file_contents = ASSEMBLY_O0
@inside_glslc_testsuite('OptionDashCapO')
class TestDashCapOWithDashG(expect.ValidFileContents):
"""Tests that -g restrains -O from turning on strip debug info."""
environment = EMPTY_SHADER_IN_CWD
glslc_args = ['-S', '-Os', '-g', 'shader.vert']
target_filename = 'shader.vert.spvasm'
expected_file_contents = ASSEMBLY_WITH_DEBUG_SOURCE
@inside_glslc_testsuite('OptionDashCapO')
class TestDashGWithDashCapO(expect.ValidFileContents):
"""Tests that -g restrains -O from turning on strip debug info."""
environment = EMPTY_SHADER_IN_CWD
glslc_args = ['-S', '-g', '-Os', 'shader.vert']
target_filename = 'shader.vert.spvasm'
expected_file_contents = ASSEMBLY_WITH_DEBUG_SOURCE
@inside_glslc_testsuite('OptionDashCapO')
class TestWrongOptLevel(expect.NoGeneratedFiles, expect.ErrorMessage):
"""Tests erroring out with wrong optimization level."""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = ['-c', '-O2', shader]
expected_error = "glslc: error: invalid value '2' in '-O2'\n"

View File

@@ -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"

View File

@@ -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'

View File

@@ -0,0 +1,55 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
def empty_es_310_shader():
return '#version 310 es\n void main() {}\n'
@inside_glslc_testsuite('OptionG')
class TestSingleDashGSingleFile(expect.ValidObjectFile):
"""Tests that glslc accepts -g [filename]. Need -c for now too."""
shader = FileShader(empty_es_310_shader(), '.vert')
glslc_args = ['-c', '-g', shader]
@inside_glslc_testsuite('OptionG')
class TestSingleFileSingleDashG(expect.ValidObjectFile):
"""Tests that glslc accepts [filename] -g -c."""
shader = FileShader(empty_es_310_shader(), '.vert')
glslc_args = [shader, '-g', '-c']
@inside_glslc_testsuite('OptionG')
class TestMultipleFiles(expect.ValidObjectFile):
"""Tests that glslc accepts -g and multiple source files."""
shader1 = FileShader(empty_es_310_shader(), '.vert')
shader2 = FileShader(empty_es_310_shader(), '.frag')
glslc_args = ['-c', shader1, '-g', shader2]
@inside_glslc_testsuite('OptionG')
class TestMultipleDashG(expect.ValidObjectFile):
"""Tests that glslc accepts multiple -g and treated them as one."""
shader1 = FileShader(empty_es_310_shader(), '.vert')
shader2 = FileShader(empty_es_310_shader(), '.vert')
glslc_args = ['-c', '-g', shader1, '-g', '-g', shader2]

View File

@@ -0,0 +1,98 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
import os.path
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader, TempFileName
from builtins import bytes
@inside_glslc_testsuite('OptionDashO')
class TestOptionDashOConcatenatedArg(expect.SuccessfulReturn,
expect.CorrectObjectFilePreamble):
"""Tests that we can concatenate -o and the output filename."""
shader = FileShader('#version 140\nvoid main() {}', '.vert')
glslc_args = ['-ofoo', shader]
def check_output_foo(self, status):
output_name = os.path.join(status.directory, 'foo')
return self.verify_object_file_preamble(output_name)
@inside_glslc_testsuite('OptionDashO')
class ManyOutputFilesWithDashO(expect.ErrorMessage):
"""Tests -o and -c with several files generates an error."""
shader1 = FileShader('', '.vert')
shader2 = FileShader('', '.frag')
glslc_args = ['-o', 'foo', '-c', shader1, shader2]
expected_error = [
'glslc: error: cannot specify -o when '
'generating multiple output files\n']
@inside_glslc_testsuite('OptionDashO')
class OutputFileLocation(expect.SuccessfulReturn,
expect.CorrectObjectFilePreamble):
"""Tests that the -o flag puts a file in a new location."""
shader = FileShader('#version 310 es\nvoid main() {}', '.frag')
glslc_args = [shader, '-o', TempFileName('a.out')]
def check_output_a_out(self, status):
output_name = os.path.join(status.directory, 'a.out')
return self.verify_object_file_preamble(output_name)
@inside_glslc_testsuite('OptionDashO')
class DashOMissingArgumentIsAnError(expect.ErrorMessage):
"""Tests that -o without an argument is an error."""
glslc_args = ['-o']
expected_error = ['glslc: error: argument to \'-o\' is missing ' +
'(expected 1 value)\n']
@inside_glslc_testsuite('OptionDashO')
class OutputFileBinaryAvoidsCRLFTranslation(expect.ReturnCodeIsZero,
expect.NoOutputOnStderr,
expect.NoGeneratedFiles,
expect.CorrectBinaryLengthAndPreamble):
"""Tests that the -o flag emits a binary file without CR/LF translation.
"""
# A shader whose compiled output has three bytes that are newlines.
# If the output stream converts the newlines to CR/LF, then we end up
# with a file that is 4k + 3 bytes long. That will be caught by the
# object file checks.
SHADER_WITH_THREE_NEWLINES_IN_BINARY = """#version 450
layout(location = 0) out uint ovar;
void main() { ovar = 9; }
"""
shader = FileShader(SHADER_WITH_THREE_NEWLINES_IN_BINARY, '.vert')
glslc_args = [shader, '-o', '-']
def check_stdout_binary(self, status):
binary = bytes(status.stdout)
newlines = [x for x in binary if x == ord('\n')]
num_newlines = len(newlines)
if num_newlines % 4 == 0:
return False, "Bad test. Need nontrivial number of newlines"
if num_newlines != 2:
return False, ("Update this test. Expected 3 newlines in the "
"binary, but found {}").format(num_newlines)
return self.verify_binary_length_and_header(bytes(status.stdout))

View File

@@ -0,0 +1,145 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
MINIMAL_SHADER = "#version 140\nvoid main(){}"
# This one is valid GLSL but not valid HLSL.
GLSL_VERTEX_SHADER = "#version 140\nvoid main(){ gl_Position = vec4(1.0);}"
# This one is GLSL but without leading #version. Should result in
# a parser error when compiled as HLSL.
GLSL_VERTEX_SHADER_WITHOUT_VERSION = "void main(){ gl_Position = vec4(1.0);}"
# This one is valid HLSL but not valid GLSL.
# Use entry point "main" so we don't have to specify -fentry-point
HLSL_VERTEX_SHADER = "float4 main() : SV_POSITION { return float4(1.0); }"
@inside_glslc_testsuite('OptionDashX')
class TestDashXNoArg(expect.ErrorMessage):
"""Tests -x with nothing."""
glslc_args = ['-x']
expected_error = [
"glslc: error: argument to '-x' is missing (expected 1 value)\n",
'glslc: error: no input files\n']
@inside_glslc_testsuite('OptionDashX')
class TestDashXGlslOnGlslShader(expect.ValidObjectFile):
"""Tests -x glsl on a GLSL shader."""
shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
glslc_args = ['-x', 'glsl', '-c', shader]
@inside_glslc_testsuite('OptionDashX')
class TestDashXGlslOnHlslShader(expect.ErrorMessageSubstr):
"""Tests -x glsl on an HLSL shader."""
shader = FileShader(HLSL_VERTEX_SHADER, '.vert')
glslc_args = ['-x', 'glsl', '-c', shader]
expected_error_substr = ["error: #version: Desktop shaders for Vulkan SPIR-V"
" require version 140 or higher\n"]
@inside_glslc_testsuite('OptionDashX')
class TestDashXHlslOnGlslShader(expect.ErrorMessageSubstr):
"""Tests -x hlsl on a GLSL shader."""
shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
glslc_args = ['-x', 'hlsl', '-c', shader]
expected_error_substr = ["error: '#version' : invalid preprocessor command\n"]
@inside_glslc_testsuite('OptionDashX')
class TestDashXHlslOnGlslShaderWithoutVertex(expect.ErrorMessageSubstr):
"""Tests -x hlsl on a GLSL shader without leading #version."""
shader = FileShader(GLSL_VERTEX_SHADER_WITHOUT_VERSION, '.vert')
glslc_args = ['-x', 'hlsl', '-c', shader]
expected_error_substr = ["error: 'vec4' : no matching overloaded function found\n"]
@inside_glslc_testsuite('OptionDashX')
class TestDashXWrongParam(expect.ErrorMessage):
"""Tests -x with wrong parameter."""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = ['-x', 'gl', shader]
expected_error = ["glslc: error: language not recognized: 'gl'\n"]
@inside_glslc_testsuite('OptionDashX')
class TestMultipleDashX(expect.ValidObjectFile):
"""Tests that multiple -x works with a single language."""
shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
glslc_args = ['-c', '-x', 'glsl', '-x', 'glsl', shader, '-x', 'glsl']
@inside_glslc_testsuite('OptionDashX')
class TestMultipleDashXMixedLanguages(expect.ValidObjectFile):
"""Tests that multiple -x works with different languages."""
glsl_shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
hlsl_shader = FileShader(HLSL_VERTEX_SHADER, '.vert')
glslc_args = ['-c', '-x', 'hlsl', hlsl_shader,
'-x', 'glsl', glsl_shader,
'-x', 'hlsl', hlsl_shader,
'-x', 'glsl', glsl_shader]
@inside_glslc_testsuite('OptionDashX')
class TestMultipleDashXCorrectWrong(expect.ErrorMessage):
"""Tests -x glsl -x [wrong-language]."""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = ['-x', 'glsl', '-x', 'foo', shader]
expected_error = ["glslc: error: language not recognized: 'foo'\n"]
@inside_glslc_testsuite('OptionDashX')
class TestMultipleDashXWrongCorrect(expect.ErrorMessage):
"""Tests -x [wrong-language] -x glsl."""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = ['-xbar', '-x', 'glsl', shader]
expected_error = ["glslc: error: language not recognized: 'bar'\n"]
@inside_glslc_testsuite('OptionDashX')
class TestDashXGlslConcatenated(expect.ValidObjectFile):
"""Tests -xglsl."""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = ['-xglsl', shader, '-c']
@inside_glslc_testsuite('OptionDashX')
class TestDashXWrongParamConcatenated(expect.ErrorMessage):
"""Tests -x concatenated with a wrong language."""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = ['-xsl', shader]
expected_error = ["glslc: error: language not recognized: 'sl'\n"]
@inside_glslc_testsuite('OptionDashX')
class TestDashXEmpty(expect.ErrorMessage):
"""Tests -x ''."""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = ['-x', '', shader]
expected_error = ["glslc: error: language not recognized: ''\n"]

View File

@@ -0,0 +1,44 @@
# Copyright 2016 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
import re
@inside_glslc_testsuite('OptionDashDashVersion')
class TestVersionContainsShaderc(expect.StdoutMatch, expect.ReturnCodeIsZero):
"""Tests --version output contains 'shaderc'."""
glslc_args = ['--version']
expected_stdout = re.compile('^shaderc')
@inside_glslc_testsuite('OptionDashDashVersion')
class TestVersionContainsSpirvTools(expect.StdoutMatch, expect.ReturnCodeIsZero):
"""Tests --version output contains 'spirv-tools'."""
glslc_args = ['--version']
expected_stdout = re.compile('\nspirv-tools')
@inside_glslc_testsuite('OptionDashDashVersion')
class TestVersionContainsGlslang(expect.StdoutMatch, expect.ReturnCodeIsZero):
"""Tests --version output contains 'glslang'."""
glslc_args = ['--version']
expected_stdout = re.compile('\nglslang')
@inside_glslc_testsuite('OptionDashDashVersion')
class TestVersionContainsTarget(expect.StdoutMatch, expect.ReturnCodeIsZero):
"""Tests --version output contains 'Target:'."""
glslc_args = ['--version']
expected_stdout = re.compile('\nTarget: SPIR-V \d+\.\d+')

View File

@@ -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"

View File

@@ -0,0 +1,59 @@
# Copyright 2018 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
# A GLSL shader with a separate sampler and texture2D object
GLSL_SHADER_SEPARATE_IMAGE_SAMPLER = """#version 460
layout (location=0) in vec2 in_UV;
layout (location=0) out vec4 out_Color;
layout (set=0,binding=0) uniform sampler u_Sampler;
layout (set=0,binding=0) uniform texture2D u_Tex;
void main() {
out_Color = texture(sampler2D(u_Tex, u_Sampler), in_UV);
}"""
# An HLSL fragment shader with the usual Texture2D and SamplerState pair
HLSL_SHADER_SEPARATE_IMAGE_SAMPLER = """
Texture2D u_Tex;
SamplerState u_Sampler;
float4 Frag(float2 uv) : COLOR0 {
return u_Tex.Sample(u_Sampler, uv);
}"""
@inside_glslc_testsuite('OptionFAutoCombinedImageSampler')
class FAutoCombinedImageSamplerCheckGLSL(expect.ValidAssemblyFileWithSubstr):
"""Tests that the compiler combines GLSL sampler and texture2D objects."""
shader = FileShader(GLSL_SHADER_SEPARATE_IMAGE_SAMPLER, '.frag')
glslc_args = ['-S', '-fauto-combined-image-sampler', shader]
expected_assembly_substr = """%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
%11 = OpTypeSampledImage %10
%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
%u_Tex = OpVariable %_ptr_UniformConstant_11 UniformConstant"""
@inside_glslc_testsuite('OptionFAutoCombinedImageSampler')
class FAutoCombinedImageSamplerCheckHLSL(expect.ValidAssemblyFileWithSubstr):
"""Tests that the HLSL compiler combines HLSL Texture2D and SamplerState objects into SPIRV SampledImage."""
shader = FileShader(HLSL_SHADER_SEPARATE_IMAGE_SAMPLER, '.hlsl')
glslc_args = ['-S', '-fshader-stage=frag', '-fentry-point=Frag', '-fauto-combined-image-sampler', shader]
expected_assembly_substr = """%14 = OpTypeImage %float 2D 0 0 0 1 Unknown
%15 = OpTypeSampledImage %14
%_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15
%u_Tex = OpVariable %_ptr_UniformConstant_15 UniformConstant"""

View File

@@ -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"

View File

@@ -0,0 +1,113 @@
# Copyright 2016 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
MINIMAL_SHADER = "#version 140\nvoid main(){}"
# This one is valid GLSL but not valid HLSL.
GLSL_VERTEX_SHADER = "#version 140\nvoid main(){ gl_Position = vec4(1.0);}"
# This one is valid HLSL but not valid GLSL.
HLSL_VERTEX_SHADER = "float4 EntryPoint() : SV_POSITION { return float4(1.0); }"
HLSL_VERTEX_SHADER_WITH_MAIN = "float4 main() : SV_POSITION { return float4(1.0); }"
HLSL_VERTEX_SHADER_WITH_FOOBAR = "float4 Foobar() : SV_POSITION { return float4(1.0); }"
# Expected assembly code within certain shaders.
ASSEMBLY_ENTRY_POINT = "OpEntryPoint Vertex %EntryPoint \"EntryPoint\""
ASSEMBLY_MAIN = "OpEntryPoint Vertex %main \"main\""
ASSEMBLY_FOOBAR = "OpEntryPoint Vertex %Foobar \"Foobar\""
@inside_glslc_testsuite('OptionFEntryPoint')
class TestEntryPointDefaultsToMainForGlsl(expect.ValidAssemblyFileWithSubstr):
"""Tests that entry point name defaults to "main" in a GLSL shader."""
shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
glslc_args = ['-S', shader]
expected_assembly_substr = ASSEMBLY_MAIN
@inside_glslc_testsuite('OptionFEntryPoint')
class TestEntryPointDefaultsToMainForHlsl(expect.ValidAssemblyFileWithSubstr):
"""Tests that entry point name defaults to "main" in an HLSL shader."""
shader = FileShader(HLSL_VERTEX_SHADER_WITH_MAIN, '.vert')
glslc_args = ['-x', 'hlsl', '-S', shader]
expected_assembly_substr = ASSEMBLY_MAIN
@inside_glslc_testsuite('OptionFEntryPoint')
class TestFEntryPointMainOnGlslShader(expect.ValidAssemblyFileWithSubstr):
"""Tests -fentry-point=main with a GLSL shader."""
shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
glslc_args = ['-fentry-point=main', '-S', shader]
expected_assembly_substr = ASSEMBLY_MAIN
@inside_glslc_testsuite('OptionFEntryPoint')
class TestFEntryPointMainOnHlslShaderNotMatchingSource(expect.ValidObjectFileWithWarning):
"""Tests -x hlsl on an HLSL shader with -fentry-point=main
not matching the source."""
shader = FileShader(HLSL_VERTEX_SHADER, '.vert')
glslc_args = ['-x', 'hlsl', '-fentry-point=main', '-c', shader]
expected_warning = [shader,
': warning: Linking vertex stage: Entry point not found\n'
'1 warning generated.\n']
@inside_glslc_testsuite('OptionFEntryPoint')
class TestFEntryPointSpecifiedOnHlslShaderInDisassembly(expect.ValidObjectFileWithAssemblySubstr):
"""Tests -x hlsl on an HLSL shader with -fentry-point=EntryPoint
matching source."""
shader = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT)
glslc_args = ['-x', 'hlsl', '-fentry-point=EntryPoint', '-c', shader]
@inside_glslc_testsuite('OptionFEntryPoint')
class TestFEntryPointAffectsSubsequentShaderFiles(expect.ValidObjectFileWithAssemblySubstr):
"""Tests -x hlsl affects several subsequent shader source files."""
shader1 = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT)
shader2 = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT)
glslc_args = ['-x', 'hlsl', '-fentry-point=EntryPoint', '-c', shader1, shader2]
@inside_glslc_testsuite('OptionFEntryPoint')
class TestFEntryPointOverridesItself(expect.ValidObjectFileWithAssemblySubstr):
"""Tests that a later -fentry-point option overrides an earlier use."""
shader = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT)
glslc_args = ['-x', 'hlsl', '-fentry-point=foobar', '-fentry-point=EntryPoint',
'-c', shader]
@inside_glslc_testsuite('OptionFEntryPoint')
class TestFEntryPointDefaultAndTwoOthers(expect.ValidObjectFileWithAssemblySubstr):
"""Tests three shaders with different entry point names. The first uses "main"
with default entry point processing, and the remaining shaders get their
own -fentry-point argument."""
shaderMain = FileShader(HLSL_VERTEX_SHADER_WITH_MAIN, '.vert',
assembly_substr=ASSEMBLY_MAIN)
shaderEntryPoint = FileShader(HLSL_VERTEX_SHADER, '.vert',
assembly_substr=ASSEMBLY_ENTRY_POINT)
shaderFoobar = FileShader(HLSL_VERTEX_SHADER_WITH_FOOBAR, '.vert',
assembly_substr=ASSEMBLY_FOOBAR)
glslc_args = ['-x', 'hlsl', '-c', shaderMain,
'-fentry-point=EntryPoint', shaderEntryPoint,
'-fentry-point=Foobar', shaderFoobar]

View File

@@ -0,0 +1,46 @@
# Copyright 2018 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
HLSL_SHADER_WITH_HALF_TYPE = """
float4 main() : SV_Target0 {
half h0 = (half)0.0;
half h1 = (half)1.0;
half h2 = (half)2.0;
half h3 = (half)3.0;
half4 v = (half4)(h0,h1,h2,h3) * (half)2.0;
return (float4)(v);
}
"""
@inside_glslc_testsuite('OptionFHlsl16BitTypes')
class TestHlsl16BitTypes_EnablesCapability(expect.ValidAssemblyFileWithSubstr):
"""Tests that -fhlsl_16bit_types enables the 16bit floating point capability."""
shader = FileShader(HLSL_SHADER_WITH_HALF_TYPE, '.frag')
glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-16bit-types', '-fauto-bind-uniforms', shader]
expected_assembly_substr = 'OpCapability Float16';
@inside_glslc_testsuite('OptionFHlsl16BitTypes')
class TestHlsl16BitTypes_CreatesType(expect.ValidAssemblyFileWithSubstr):
"""Tests that -fhlsl_16bit_types creates the 16bit floating point capability."""
shader = FileShader(HLSL_SHADER_WITH_HALF_TYPE, '.frag')
glslc_args = ['-S', '-x', 'hlsl', '-fhlsl-16bit-types', '-fauto-bind-uniforms', shader]
expected_assembly_substr = '= OpTypeFloat 16';

View File

@@ -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'

View File

@@ -0,0 +1,378 @@
# Copyright 2016 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from environment import File, Directory
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
def shader_source_with_tex_offset(offset):
"""Returns a vertex shader using a texture access with the given offset."""
return """#version 450
layout (binding=0) uniform sampler1D tex;
void main() { vec4 x = textureOffset(tex, 1.0, """ + str(offset) + "); }"
def shader_with_tex_offset(offset):
"""Returns a vertex FileShader using a texture access with the given offset."""
return FileShader(shader_source_with_tex_offset(offset), ".vert")
@inside_glslc_testsuite('OptionFLimit')
class TestFLimitNoEqual(expect.ErrorMessage):
"""Tests -flimit without equal."""
glslc_args = ['-flimit']
expected_error = ["glslc: error: unknown argument: '-flimit'\n"]
@inside_glslc_testsuite('OptionFLimit')
class TestFLimitJustEqual(expect.ValidObjectFile):
"""Tests -flimit= with no argument."""
shader = shader_with_tex_offset(0);
glslc_args = ['-c', shader, '-flimit=']
@inside_glslc_testsuite('OptionFLimit')
class TestFLimitJustEqualMaxOffset(expect.ValidObjectFile):
"""Tests -flimit= with no argument. The shader uses max offset."""
shader = shader_with_tex_offset(7);
glslc_args = ['-c', shader, '-flimit=']
@inside_glslc_testsuite('OptionFLimit')
class TestFLimitJustEqualMinOffset(expect.ValidObjectFile):
"""Tests -flimit= with no argument. The shader uses min offset."""
shader = shader_with_tex_offset(-8);
glslc_args = ['-c', shader, '-flimit=']
@inside_glslc_testsuite('OptionFLimit')
class TestFLimitJustEqualBelowMinOffset(expect.ErrorMessageSubstr):
"""Tests -flimit= with no argument. The shader uses below min default offset."""
shader = shader_with_tex_offset(-9);
glslc_args = ['-c', shader, '-flimit=']
expected_error_substr = ["'texel offset' : value is out of range"]
@inside_glslc_testsuite('OptionFLimit')
class TestFLimitLowerThanDefaultMinOffset(expect.ValidObjectFile):
"""Tests -flimit= with lower than default argument. The shader uses below min offset."""
shader = shader_with_tex_offset(-9);
glslc_args = ['-c', shader, '-flimit= MinProgramTexelOffset -9 ']
@inside_glslc_testsuite('OptionFLimit')
class TestFLimitIgnoredLangFeatureSettingSample(expect.ValidObjectFile):
"""Tests -flimit= an ignored option."""
shader = FileShader("#version 150\nvoid main() { while(true); }", '.vert')
glslc_args = ['-c', shader, '-flimit=whileLoops 0']
@inside_glslc_testsuite('OptionFLimit')
class TestFLimitLowerThanDefaultMinOffset(expect.ValidObjectFile):
"""Tests -flimit= with lower than default argument. The shader uses that offset."""
shader = shader_with_tex_offset(-9);
glslc_args = ['-c', shader, '-flimit= MinProgramTexelOffset -9 ']
@inside_glslc_testsuite('OptionFLimitFile')
class TestFLimitFileNoArg(expect.ErrorMessage):
"""Tests -flimit-file without an argument"""
shader = shader_with_tex_offset(-9);
glslc_args = ['-c', shader, '-flimit-file']
expected_error = "glslc: error: argument to '-flimit-file' is missing\n"
@inside_glslc_testsuite('OptionFLimitFile')
class TestFLimitFileMissingFile(expect.ErrorMessageSubstr):
"""Tests -flimit-file without an argument"""
shader = shader_with_tex_offset(-9);
glslc_args = ['-c', shader, '-flimit-file', 'i do not exist']
expected_error_substr = "glslc: error: cannot open input file: 'i do not exist'";
@inside_glslc_testsuite('OptionFLimitFile')
class TestFLimitFileSetsLowerMinTexelOffset(expect.ValidObjectFile):
"""Tests -flimit-file with lower than default argument. The shader uses that offset."""
limits_file = File('limits.txt', 'MinProgramTexelOffset -9')
shader = File('shader.vert', shader_source_with_tex_offset(-9));
environment = Directory('.', [limits_file, shader])
glslc_args = ['-c', shader.name, '-flimit-file', limits_file.name]
@inside_glslc_testsuite('OptionFLimitFile')
class TestFLimitFileInvalidContents(expect.ErrorMessage):
"""Tests -flimit-file bad file contents."""
limits_file = File('limits.txt', 'thisIsBad')
shader = File('shader.vert', shader_source_with_tex_offset(-9));
environment = Directory('.', [limits_file, shader])
glslc_args = ['-c', shader.name, '-flimit-file', limits_file.name]
expected_error = 'glslc: error: -flimit-file error: invalid resource limit: thisIsBad\n'
## Mesh shading
def mesh_shader_with_params(kwargs):
"""Returns a mesh shader as a FileShader, with given parameters"""
import sys
source = """#version 450
#extension {} : enable
layout(local_size_x={}) in;
layout(local_size_y={}) in;
layout(local_size_z={}) in;
layout(triangles) out;
layout(max_vertices={}) out;
layout(max_primitives={}) out;
layout(triangles) out;
void main() {{ }}
""".format(kwargs['extension'],kwargs['x'],kwargs['y'],kwargs['z'],kwargs['max_vert'],kwargs['max_prim'])
return FileShader(source,".mesh")
def task_shader_with_params(kwargs):
"""Returns a task shader as a FileShader, with given parameters"""
import sys
source = """#version 450
#extension {} : enable
layout(local_size_x={}) in;
layout(local_size_y={}) in;
layout(local_size_z={}) in;
void main() {{ }}
""".format(kwargs['extension'],kwargs['x'],kwargs['y'],kwargs['z'])
return FileShader(source,".task")
def meshDefaults(nv_or_ext,show=False):
result = dict({
# See Glslang's glslang/ResourceLimits/ResourceLimits.cpp
'nv': { 'extension': 'GL_NV_mesh_shader', 'x': 32, 'y': 1, 'z': 1, 'max_vert': 256, 'max_prim': 512 },
'ext': { 'extension': 'GL_EXT_mesh_shader', 'x': 128, 'y': 128, 'z': 128, 'max_vert': 256, 'max_prim': 256 }
})[nv_or_ext]
if show:
import sys
print(result,file=sys.stderr)
return result
## GL_NV_mesh_shader
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_NV_X_ok(expect.ValidObjectFile):
shader = mesh_shader_with_params(meshDefaults('nv'))
glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeX_NV 32']
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_NV_X_bad(expect.ErrorMessageSubstr):
shader = mesh_shader_with_params(meshDefaults('nv'))
expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeNV"
glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeX_NV 31']
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_NV_Y_ok(expect.ValidObjectFile):
shader = mesh_shader_with_params(meshDefaults('nv'))
glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeY_NV 1']
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_NV_Y_bad(expect.ErrorMessageSubstr):
d = meshDefaults('nv')
d['y'] = 3
shader = mesh_shader_with_params(d)
expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeNV"
glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeY_NV 2']
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_NV_Z_ok(expect.ValidObjectFile):
shader = mesh_shader_with_params(meshDefaults('nv'))
glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeZ_NV 1']
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_NV_Z_bad(expect.ErrorMessageSubstr):
d = meshDefaults('nv')
d['z'] = 3
shader = mesh_shader_with_params(d)
expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeNV"
glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeZ_NV 2']
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_NV_MaxVert_ok(expect.ValidObjectFile):
shader = mesh_shader_with_params(meshDefaults('nv'))
glslc_args = ['-c', shader, '-flimit= MaxMeshOutputVerticesNV 256']
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_NV_MaxVert_bad(expect.ErrorMessageSubstr):
shader = mesh_shader_with_params(meshDefaults('nv'))
expected_error_substr = "'max_vertices' : too large, must be less than gl_MaxMeshOutputVerticesNV"
glslc_args = ['-c', shader, '-flimit= MaxMeshOutputVerticesNV 255']
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_NV_MaxPrim_ok(expect.ValidObjectFile):
shader = mesh_shader_with_params(meshDefaults('nv'))
glslc_args = ['-c', shader, '-flimit= MaxMeshOutputPrimitivesNV 512']
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_NV_MaxPrim_bad(expect.ErrorMessageSubstr):
shader = mesh_shader_with_params(meshDefaults('nv'))
expected_error_substr = "'max_primitives' : too large, must be less than gl_MaxMeshOutputPrimitivesNV"
glslc_args = ['-c', shader, '-flimit= MaxMeshOutputPrimitivesNV 511']
@inside_glslc_testsuite('OptionFLimit_Task')
class TestFLimitTaskShader_NV_X_ok(expect.ValidObjectFile):
shader = task_shader_with_params(meshDefaults('nv'))
glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeX_NV 32']
@inside_glslc_testsuite('OptionFLimit_Task')
class TestFLimitTaskShader_NV_X_bad(expect.ErrorMessageSubstr):
shader = task_shader_with_params(meshDefaults('nv'))
expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeNV"
glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeX_NV 31']
@inside_glslc_testsuite('OptionFLimit_Task')
class TestFLimitTaskShader_NV_Y_ok(expect.ValidObjectFile):
shader = task_shader_with_params(meshDefaults('nv'))
glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeY_NV 1']
@inside_glslc_testsuite('OptionFLimit_Task')
class TestFLimitTaskShader_NV_Y_bad(expect.ErrorMessageSubstr):
d = meshDefaults('nv')
d['y'] = 3
shader = task_shader_with_params(d)
expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeNV"
glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeY_NV 2']
@inside_glslc_testsuite('OptionFLimit_Task')
class TestFLimitTaskShader_NV_Z_ok(expect.ValidObjectFile):
shader = task_shader_with_params(meshDefaults('nv'))
glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeZ_NV 1']
@inside_glslc_testsuite('OptionFLimit_Task')
class TestFLimitTaskShader_NV_Z_bad(expect.ErrorMessageSubstr):
d = meshDefaults('nv')
d['z'] = 3
shader = task_shader_with_params(d)
expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeNV"
glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeZ_NV 2']
# TODO: Test MaxMeshViewCountNV
## GL_EXT_mesh_shader
## It requires SPIR-V 1.4
s14 = '--target-spv=spv1.4'
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_EXT_X_ok(expect.ValidObjectFile1_4):
shader = mesh_shader_with_params(meshDefaults('ext'))
glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeX_EXT 128', s14]
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_EXT_X_bad(expect.ErrorMessageSubstr):
shader = mesh_shader_with_params(meshDefaults('ext'))
expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeEXT"
glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeX_EXT 127', s14]
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_EXT_Y_ok(expect.ValidObjectFile1_4):
shader = mesh_shader_with_params(meshDefaults('ext'))
glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeY_EXT 128', s14]
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_EXT_Y_bad(expect.ErrorMessageSubstr):
shader = mesh_shader_with_params(meshDefaults('ext'))
expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeEXT"
glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeY_EXT 127', s14]
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_EXT_Z_ok(expect.ValidObjectFile1_4):
shader = mesh_shader_with_params(meshDefaults('ext'))
glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeZ_EXT 128', s14]
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_EXT_Z_bad(expect.ErrorMessageSubstr):
shader = mesh_shader_with_params(meshDefaults('ext'))
expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeEXT"
glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeZ_EXT 127', s14]
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_EXT_MaxVert_ok(expect.ValidObjectFile1_4):
shader = mesh_shader_with_params(meshDefaults('ext'))
glslc_args = ['-c', shader, '-flimit= MaxMeshOutputVerticesEXT 256', s14]
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_EXT_MaxVert_bad(expect.ErrorMessageSubstr):
shader = mesh_shader_with_params(meshDefaults('ext'))
expected_error_substr = "'max_vertices' : too large, must be less than gl_MaxMeshOutputVerticesEXT"
glslc_args = ['-c', shader, '-flimit= MaxMeshOutputVerticesEXT 255', s14]
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_EXT_MaxPrim_ok(expect.ValidObjectFile1_4):
shader = mesh_shader_with_params(meshDefaults('ext'))
glslc_args = ['-c', shader, '-flimit= MaxMeshOutputPrimitivesEXT 256', s14]
@inside_glslc_testsuite('OptionFLimit_Mesh')
class TestFLimitMeshShader_EXT_MaxPrim_bad(expect.ErrorMessageSubstr):
shader = mesh_shader_with_params(meshDefaults('ext'))
expected_error_substr = "'max_primitives' : too large, must be less than gl_MaxMeshOutputPrimitivesEXT"
glslc_args = ['-c', shader, '-flimit= MaxMeshOutputPrimitivesEXT 255', s14]
@inside_glslc_testsuite('OptionFLimit_Task')
class TestFLimitTaskShader_EXT_X_ok(expect.ValidObjectFile1_4):
shader = task_shader_with_params(meshDefaults('ext'))
glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeX_EXT 128', s14]
@inside_glslc_testsuite('OptionFLimit_Task')
class TestFLimitTaskShader_EXT_X_bad(expect.ErrorMessageSubstr):
shader = task_shader_with_params(meshDefaults('ext'))
expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeEXT"
glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeX_EXT 127', s14]
@inside_glslc_testsuite('OptionFLimit_Task')
class TestFLimitTaskShader_EXT_Y_ok(expect.ValidObjectFile1_4):
shader = task_shader_with_params(meshDefaults('ext'))
glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeY_EXT 128', s14]
@inside_glslc_testsuite('OptionFLimit_Task')
class TestFLimitTaskShader_EXT_Y_bad(expect.ErrorMessageSubstr):
import sys
d = meshDefaults('ext',True)
print("TaskShader_EXT_Y_bad {}".format(str(d)),file=sys.stderr)
shader = task_shader_with_params(meshDefaults('ext',True))
expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeEXT"
glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeY_EXT 127', s14]
@inside_glslc_testsuite('OptionFLimit_Task')
class TestFLimitTaskShader_EXT_Z_ok(expect.ValidObjectFile1_4):
shader = task_shader_with_params(meshDefaults('ext'))
glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeZ_EXT 128', s14]
@inside_glslc_testsuite('OptionFLimit_Task')
class TestFLimitTaskShader_EXT_Z_bad(expect.ErrorMessageSubstr):
shader = task_shader_with_params(meshDefaults('ext'))
expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeEXT"
glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeZ_EXT 127', s14]
# TODO: Test MaxMeshViewCountEXT

View File

@@ -0,0 +1,70 @@
# Copyright 2023 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
# A GLSL shader with unused bindings.
GLSL_SHADER_WITH_UNUSED_BINDINGS = """#version 450
layout(binding=0) buffer InputA { vec4 x[]; } inputA;
layout(binding=1) buffer InputB { vec4 x[]; } inputB;
layout(binding=2) buffer Output { vec4 x[]; } outputO;
void main() {}
"""
@inside_glslc_testsuite('OptionFPreserveBindings')
class TestFPreserveBindingsInputA(expect.ValidAssemblyFileWithSubstr):
"""Tests that the compiler preserves bindings when optimizations are
enabled."""
shader = FileShader(GLSL_SHADER_WITH_UNUSED_BINDINGS, '.comp')
glslc_args = ['-S', '-O', shader, '-fpreserve-bindings']
# Check the first buffer.
expected_assembly_substr = "Binding 0"
@inside_glslc_testsuite('OptionFPreserveBindings')
class TestFPreserveBindingsInputB(expect.ValidAssemblyFileWithSubstr):
"""Tests that the compiler preserves bindings when optimizations are
enabled."""
shader = FileShader(GLSL_SHADER_WITH_UNUSED_BINDINGS, '.comp')
glslc_args = ['-S', '-O', shader, '-fpreserve-bindings']
# Check the first buffer.
expected_assembly_substr = "Binding 1"
@inside_glslc_testsuite('OptionFPreserveBindings')
class TestFPreserveBindingsOutputO(expect.ValidAssemblyFileWithSubstr):
"""Tests that the compiler preserves bindings when optimizations are
enabled."""
shader = FileShader(GLSL_SHADER_WITH_UNUSED_BINDINGS, '.comp')
glslc_args = ['-S', '-O', shader, '-fpreserve-bindings']
# Check the first buffer.
expected_assembly_substr = "Binding 2"
@inside_glslc_testsuite('OptionFPreserveBindings')
class TestFNoPreserveBindings(expect.ValidAssemblyFileWithoutSubstr):
"""Tests that the compiler removes bindings when -fpreserve-bindings is not
set."""
shader = FileShader(GLSL_SHADER_WITH_UNUSED_BINDINGS, '.comp')
glslc_args = ['-S', '-O', shader]
# Check that all binding decorations are gone.
unexpected_assembly_substr = "OpDecorate"

View File

@@ -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

View File

@@ -0,0 +1,195 @@
# Copyright 2016 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
import re
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
MINIMAL_SHADER = '#version 140\nvoid main() {}'
# Regular expression patterns for the minimal shader. The magic number should
# match exactly, and there should not be a trailing comma at the end of the
# list. When -mfmt=c is specified, curly brackets should be presented.
MINIMAL_SHADER_NUM_FORMAT_PATTERN = "^0x07230203.*[0-9a-f]$"
MINIMAL_SHADER_C_FORMAT_PATTERN = "^\{0x07230203.*[0-9a-f]\}"
ERROR_SHADER = '#version 140\n#error\nvoid main() {}'
@inside_glslc_testsuite('OptionMfmt')
class TestFmtCWorksWithDashC(expect.ValidFileContents):
"""Tests that -mfmt=c works with -c for single input file. SPIR-V binary
code output should be emitted as a C-style initializer list in the output
file.
"""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = [shader, '-c', '-mfmt=c', '-o', 'output_file']
target_filename = 'output_file'
expected_file_contents = re.compile(MINIMAL_SHADER_C_FORMAT_PATTERN, re.S)
@inside_glslc_testsuite('OptionMfmt')
class TestFmtNumWorksWithDashC(expect.ValidFileContents):
"""Tests that -mfmt=num works with -c for single input file. SPIR-V binary
code output should be emitted as a list of hex numbers in the output file.
"""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = [shader, '-c', '-mfmt=num', '-o', 'output_file']
target_filename = 'output_file'
expected_file_contents = re.compile(MINIMAL_SHADER_NUM_FORMAT_PATTERN, re.S)
@inside_glslc_testsuite('OptionMfmt')
class TestFmtBinWorksWithDashC(expect.ValidObjectFile):
"""Tests that -mfmt=bin works with -c for single input file. This test
should simply have the SPIR-V binary generated.
"""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = [shader, '-c', '-mfmt=bin']
@inside_glslc_testsuite('OptionMfmt')
class TestFmtCWithLinking(expect.ValidFileContents):
"""Tests that -mfmt=c works when linkding is enabled (no -c specified).
SPIR-V binary code should be emitted as a C-style initializer list in the
output file.
"""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = [shader, '-mfmt=c']
target_filename = 'a.spv'
expected_file_contents = re.compile(MINIMAL_SHADER_C_FORMAT_PATTERN, re.S)
@inside_glslc_testsuite('OptionMfmt')
class TestFmtNumWithLinking(expect.ValidFileContents):
"""Tests that -mfmt=num works when linkding is enabled (no -c specified).
SPIR-V binary code should be emitted as a C-style initializer list in the
output file.
"""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = [shader, '-mfmt=num']
target_filename = 'a.spv'
expected_file_contents = re.compile(MINIMAL_SHADER_NUM_FORMAT_PATTERN, re.S)
@inside_glslc_testsuite('OptionMfmt')
class TestFmtCErrorWhenOutputDisasembly(expect.ErrorMessage):
"""Tests that specifying '-mfmt=c' when the compiler is set to
disassembly mode should trigger an error.
"""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = [shader, '-mfmt=c', '-S', '-o', 'output_file']
expected_error = ("glslc: error: cannot emit output as a C-style "
"initializer list when only preprocessing the source\n")
@inside_glslc_testsuite('OptionMfmt')
class TestFmtNumErrorWhenOutputDisasembly(expect.ErrorMessage):
"""Tests that specifying '-mfmt=num' when the compiler is set to
disassembly mode should trigger an error.
"""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = [shader, '-mfmt=num', '-S', '-o', 'output_file']
expected_error = (
"glslc: error: cannot emit output as a list of hex numbers "
"when only preprocessing the source\n")
@inside_glslc_testsuite('OptionMfmt')
class TestFmtBinErrorWhenOutputDisasembly(expect.ErrorMessage):
"""Tests that specifying '-mfmt=bin' when the compiler is set to
disassembly mode should trigger an error.
"""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = [shader, '-mfmt=bin', '-S', '-o', 'output_file']
expected_error = ("glslc: error: cannot emit output as a binary "
"when only preprocessing the source\n")
@inside_glslc_testsuite('OptionMfmt')
class TestFmtNumErrorWhenOutputPreprocess(expect.ErrorMessage):
"""Tests that specifying '-mfmt=num' when the compiler is set to
preprocessing only mode should trigger an error.
"""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = [shader, '-mfmt=num', '-E', '-o', 'output_file']
expected_error = (
"glslc: error: cannot emit output as a list of hex numbers "
"when only preprocessing the source\n")
@inside_glslc_testsuite('OptionMfmt')
class TestFmtCErrorWithDashCapM(expect.ErrorMessage):
"""Tests that specifying '-mfmt=c' should trigger an error when the
compiler is set to dump dependency info as the output (-M or -MM is
specified).
"""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = [shader, '-mfmt=c', '-M', '-o', 'output_file']
expected_error = ("glslc: error: cannot emit output as a C-style "
"initializer list when only preprocessing the source\n")
@inside_glslc_testsuite('OptionMfmt')
class TestFmtCWorksWithDashCapMD(expect.ValidFileContents):
"""Tests that -mfmt=c works with '-c -MD'. SPIR-V binary code
should be emitted as a C-style initializer list in the output file.
"""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = [shader, '-mfmt=c', '-c', '-MD', '-o', 'output_file']
target_filename = 'output_file'
expected_file_contents = re.compile(MINIMAL_SHADER_C_FORMAT_PATTERN, re.S)
@inside_glslc_testsuite('OptionMfmt')
class TestFmtNumWorksWithDashCapMD(expect.ValidFileContents):
"""Tests that -mfmt=num works with '-c -MD'. SPIR-V binary code
should be emitted as a C-style initializer list in the output file.
"""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = [shader, '-mfmt=num', '-c', '-MD', '-o', 'output_file']
target_filename = 'output_file'
expected_file_contents = re.compile(MINIMAL_SHADER_NUM_FORMAT_PATTERN, re.S)
@inside_glslc_testsuite('OptionMfmt')
class TestFmtCExitsElegantlyWithErrorInShader(expect.ErrorMessage):
"""Tests that the compiler fails elegantly with -mfmt=c when there are
errors in the input shader.
"""
shader = FileShader(ERROR_SHADER, '.vert')
glslc_args = [shader, '-mfmt=c']
expected_error = [shader, ':3: error: \'#error\' :\n',
'1 error generated.\n']
@inside_glslc_testsuite('OptionMfmt')
class TestFmtNumExitsElegantlyWithErrorInShader(expect.ErrorMessage):
"""Tests that the compiler fails elegantly with -mfmt=num when there are
errors in the input shader.
"""
shader = FileShader(ERROR_SHADER, '.vert')
glslc_args = [shader, '-mfmt=num']
expected_error = [shader, ':3: error: \'#error\' :\n',
'1 error generated.\n']
@inside_glslc_testsuite('OptionMfmt')
class TestFmtBinExitsElegantlyWithErrorInShader(expect.ErrorMessage):
"""Tests that the compiler fails elegantly with -mfmt=binary when there are
errors in the input shader.
"""
shader = FileShader(ERROR_SHADER, '.vert')
glslc_args = [shader, '-mfmt=bin']
expected_error = [shader, ':3: error: \'#error\' :\n',
'1 error generated.\n']

View File

@@ -0,0 +1,224 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
def simple_vertex_shader():
return """#version 310 es
void main() {
gl_Position = vec4(1., 2., 3., 4.);
}"""
def simple_hlsl_vertex_shader():
# Use "main" so we don't have to specify -fentry-point
return """float4 main() : SV_POSITION { return float4(1.0); } """
def simple_fragment_shader():
return """#version 310 es
void main() {
gl_FragDepth = 10.;
}"""
def simple_tessellation_control_shader():
return """#version 440 core
layout(vertices = 3) out;
void main() { }"""
def simple_tessellation_evaluation_shader():
return """#version 440 core
layout(triangles) in;
void main() { }"""
def simple_geometry_shader():
return """#version 150 core
layout (triangles) in;
layout (line_strip, max_vertices = 4) out;
void main() { }"""
def simple_compute_shader():
return """#version 310 es
void main() {
uvec3 temp = gl_WorkGroupID;
}"""
@inside_glslc_testsuite('OptionShaderStage')
class TestShaderStageWithGlslExtension(expect.ValidObjectFile):
"""Tests -fshader-stage with .glsl extension."""
shader = FileShader(simple_vertex_shader(), '.glsl')
glslc_args = ['-c', '-fshader-stage=vertex', shader]
@inside_glslc_testsuite('OptionShaderStage')
class TestShaderStageWithHlslExtension(expect.ValidObjectFile):
"""Tests -fshader-stage with .hlsl extension."""
shader = FileShader(simple_hlsl_vertex_shader(), '.hlsl')
glslc_args = ['-c', '-fshader-stage=vertex', shader]
@inside_glslc_testsuite('OptionShaderStage')
class TestShaderStageWithKnownExtension(expect.ValidObjectFile):
"""Tests -fshader-stage with known extension."""
shader = FileShader(simple_fragment_shader(), '.frag')
glslc_args = ['-c', '-fshader-stage=fragment', shader]
@inside_glslc_testsuite('OptionShaderStage')
class TestShaderStageWithUnknownExtension(expect.ValidObjectFile):
"""Tests -fshader-stage with unknown extension."""
shader = FileShader(simple_vertex_shader(), '.unknown')
glslc_args = ['-c', '-fshader-stage=vertex', shader]
@inside_glslc_testsuite('OptionShaderStage')
class TestShaderStageWithNoExtension(expect.ValidObjectFile):
"""Tests -fshader-stage with no extension."""
shader = FileShader(simple_vertex_shader(), '')
glslc_args = ['-c', '-fshader-stage=vertex', shader]
@inside_glslc_testsuite('OptionShaderStage')
class TestAllShaderStages(expect.ValidObjectFile):
"""Tests all possible -fshader-stage values."""
shader1 = FileShader(simple_vertex_shader(), '.glsl')
shader2 = FileShader(simple_fragment_shader(), '.glsl')
shader3 = FileShader(simple_tessellation_control_shader(), '.glsl')
shader4 = FileShader(simple_tessellation_evaluation_shader(), '.glsl')
shader5 = FileShader(simple_geometry_shader(), '.glsl')
shader6 = FileShader(simple_compute_shader(), '.glsl')
glslc_args = [
'-c',
'-fshader-stage=vertex', shader1,
'-fshader-stage=fragment', shader2,
'-fshader-stage=tesscontrol', shader3,
'-fshader-stage=tesseval', shader4,
'-fshader-stage=geometry', shader5,
'-fshader-stage=compute', shader6]
@inside_glslc_testsuite('OptionShaderStage')
class TestShaderStageOverwriteFileExtension(expect.ValidObjectFile):
"""Tests -fshader-stage has precedence over file extension."""
# a vertex shader camouflaged with .frag extension
shader = FileShader(simple_vertex_shader(), '.frag')
# Command line says it's vertex shader. Should compile successfully
# as a vertex shader.
glslc_args = ['-c', '-fshader-stage=vertex', shader]
@inside_glslc_testsuite('OptionShaderStage')
class TestShaderStageLatterOverwriteFormer(expect.ValidObjectFile):
"""Tests a latter -fshader-stage overwrite a former one."""
shader = FileShader(simple_vertex_shader(), '.glsl')
glslc_args = [
'-c', '-fshader-stage=fragment', '-fshader-stage=vertex', shader]
@inside_glslc_testsuite('OptionShaderStage')
class TestShaderStageWithMultipleFiles(expect.ValidObjectFile):
"""Tests -fshader-stage covers all subsequent files."""
shader1 = FileShader(simple_vertex_shader(), '.glsl')
# a vertex shader with .frag extension
shader2 = FileShader(simple_vertex_shader(), '.frag')
shader3 = FileShader(simple_vertex_shader(), '.a_vert_shader')
glslc_args = ['-c', '-fshader-stage=vertex', shader1, shader2, shader3]
@inside_glslc_testsuite('OptionShaderStage')
class TestShaderStageMultipleShaderStage(expect.ValidObjectFile):
"""Tests multiple -fshader-stage."""
shader1 = FileShader(simple_vertex_shader(), '.glsl')
shader2 = FileShader(simple_fragment_shader(), '.frag')
shader3 = FileShader(simple_vertex_shader(), '.a_vert_shader')
glslc_args = [
'-c',
'-fshader-stage=vertex', shader1,
'-fshader-stage=fragment', shader2,
'-fshader-stage=vertex', shader3]
@inside_glslc_testsuite('OptionShaderStage')
class TestFileExtensionBeforeShaderStage(expect.ValidObjectFile):
"""Tests that file extensions before -fshader-stage are not affected."""
# before -fshader-stage
shader1 = FileShader(simple_vertex_shader(), '.vert')
# after -fshader-stage
shader2 = FileShader(simple_fragment_shader(), '.frag')
shader3 = FileShader(simple_fragment_shader(), '.vert')
glslc_args = ['-c', shader1, '-fshader-stage=fragment', shader2, shader3]
@inside_glslc_testsuite('OptionShaderStage')
class TestShaderStageWrongShaderStageValue(expect.ErrorMessage):
"""Tests that wrong shader stage value results in an error."""
shader = FileShader(simple_vertex_shader(), '.glsl')
glslc_args = ['-c', '-fshader-stage=unknown', shader]
expected_error = ["glslc: error: stage not recognized: 'unknown'\n"]
@inside_glslc_testsuite('OptionShaderStage')
class TestShaderStageGlslExtensionMissingShaderStage(expect.ErrorMessage):
"""Tests that missing -fshader-stage for .glsl extension results in
an error."""
shader = FileShader(simple_vertex_shader(), '.glsl')
glslc_args = ['-c', shader]
expected_error = [
"glslc: error: '", shader,
"': .glsl file encountered but no -fshader-stage specified ahead\n"]
@inside_glslc_testsuite('OptionShaderStage')
class TestShaderStageHlslExtensionMissingShaderStage(expect.ErrorMessage):
"""Tests that missing -fshader-stage for .hlsl extension results in
an error."""
shader = FileShader(simple_hlsl_vertex_shader(), '.hlsl')
glslc_args = ['-c', '-x', 'hlsl', shader]
expected_error = [
"glslc: error: '", shader,
"': .hlsl file encountered but no -fshader-stage specified ahead\n"]
@inside_glslc_testsuite('OptionShaderStage')
class TestShaderStageUnknownExtensionMissingShaderStage(expect.ErrorMessage):
"""Tests that missing -fshader-stage for unknown extension results in
an error."""
shader = FileShader(simple_vertex_shader(), '.a_vert_shader')
glslc_args = ['-c', shader]
expected_error = [
"glslc: error: '", shader,
"': file not recognized: File format not recognized\n"]

View File

@@ -0,0 +1,312 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
def core_vert_shader_without_version():
# gl_ClipDistance doesn't exist in es profile (at least until 3.10).
return 'void main() { gl_ClipDistance[0] = 5.; }'
def core_frag_shader_without_version():
# gl_SampleID appears in core profile from 4.00.
# gl_sampleID doesn't exsit in es profile (at least until 3.10).
return 'void main() { int temp = gl_SampleID; }'
def hlsl_compute_shader_with_barriers():
# Use "main" to avoid the need for -fentry-point
return 'void main() { AllMemoryBarrierWithGroupSync(); }'
@inside_glslc_testsuite('OptionStd')
class TestStdNoArg(expect.ErrorMessage):
"""Tests -std alone."""
glslc_args = ['-std']
expected_error = ["glslc: error: unknown argument: '-std'\n"]
@inside_glslc_testsuite('OptionStd')
class TestStdEqNoArg(expect.ErrorMessage):
"""Tests -std= with no argument."""
glslc_args = ['-std=']
expected_error = ["glslc: error: invalid value '' in '-std='\n"]
@inside_glslc_testsuite('OptionStd')
class TestStdEqSpaceArg(expect.ErrorMessage):
"""Tests -std= <version-profile>."""
shader = FileShader(core_frag_shader_without_version(), '.frag')
glslc_args = ['-c', '-std=', '450core', shader]
expected_error = ["glslc: error: invalid value '' in '-std='\n"]
# TODO(dneto): The error message changes with different versions of glslang.
@inside_glslc_testsuite('OptionStd')
class TestMissingVersionAndStd(expect.ErrorMessageSubstr):
"""Tests that missing both #version and -std results in errors."""
shader = FileShader(core_frag_shader_without_version(), '.frag')
glslc_args = ['-c', shader]
expected_error_substr = ['error:']
@inside_glslc_testsuite('OptionStd')
class TestMissingVersionButHavingStd(expect.ValidObjectFile):
"""Tests that correct -std fixes missing #version."""
shader = FileShader(core_frag_shader_without_version(), '.frag')
glslc_args = ['-c', '-std=450core', shader]
@inside_glslc_testsuite('OptionStd')
class TestGLSL460(expect.ValidObjectFile):
"""Tests that GLSL version 4.6 is supported."""
shader = FileShader(core_frag_shader_without_version(), '.frag')
glslc_args = ['-c', '-std=460', shader]
@inside_glslc_testsuite('OptionStd')
class TestGLSL460Core(expect.ValidObjectFile):
"""Tests that GLSL version 4.6 core profile is supported."""
shader = FileShader(core_frag_shader_without_version(), '.frag')
glslc_args = ['-c', '-std=460core', shader]
@inside_glslc_testsuite('OptionStd')
class TestESSL320(expect.ValidObjectFile):
"""Tests that ESSL version 3.2 is supported."""
shader = FileShader(core_frag_shader_without_version(), '.frag')
glslc_args = ['-c', '-std=320es', shader]
@inside_glslc_testsuite('OptionStd')
class TestStdIgnoredInHlsl(expect.ValidObjectFile):
"""Tests HLSL compilation ignores -std."""
# Compute shaders are not available in OpenGL 150
shader = FileShader(hlsl_compute_shader_with_barriers(), '.comp')
glslc_args = ['-c', '-x', 'hlsl', '-std=150', shader]
@inside_glslc_testsuite('OptionStd')
class TestMissingVersionAndWrongStd(expect.ErrorMessage):
"""Tests missing #version and wrong -std results in errors."""
shader = FileShader(core_frag_shader_without_version(), '.frag')
glslc_args = ['-c', '-std=310es', shader]
expected_error = [
shader, ":1: error: 'gl_SampleID' : required extension not requested: "
'GL_OES_sample_variables\n1 error generated.\n']
@inside_glslc_testsuite('OptionStd')
class TestConflictingVersionAndStd(expect.ValidObjectFileWithWarning):
"""Tests that with both #version and -std, -std takes precedence."""
# Wrong #version here on purpose.
shader = FileShader(
'#version 310 es\n' + core_frag_shader_without_version(), '.frag')
# -std overwrites the wrong #version.
glslc_args = ['-c', '-std=450core', shader]
expected_warning = [
shader, ': warning: (version, profile) forced to be (450, core), while '
'in source code it is (310, es)\n1 warning generated.\n']
@inside_glslc_testsuite('OptionStd')
class TestMultipleStd(expect.ValidObjectFile):
"""Tests that for multiple -std, the last one takes effect."""
shader = FileShader(core_frag_shader_without_version(), '.frag')
glslc_args = ['-c', '-std=100', '-std=310es', shader, '-std=450core']
@inside_glslc_testsuite('OptionStd')
class TestMultipleFiles(expect.ValidObjectFileWithWarning):
"""Tests that -std covers all files."""
shader1 = FileShader(core_frag_shader_without_version(), '.frag')
shader2 = FileShader(core_vert_shader_without_version(), '.vert')
shader3 = FileShader(
'#version 310 es\n' + core_frag_shader_without_version(), '.frag')
glslc_args = ['-c', '-std=450core', shader1, shader2, shader3]
expected_warning = [
shader3, ': warning: (version, profile) forced to be (450, '
'core), while in source code it is (310, es)\n'
'1 warning generated.\n']
@inside_glslc_testsuite('OptionStd')
class TestUnkownProfile(expect.ErrorMessage):
"""Tests that -std rejects unknown profile."""
shader = FileShader(core_frag_shader_without_version(), '.frag')
glslc_args = ['-c', '-std=450google', shader]
expected_error = [
"glslc: error: invalid value '450google' in '-std=450google'\n"]
@inside_glslc_testsuite('OptionStd')
class TestUnkownVersion(expect.ErrorMessage):
"""Tests that -std rejects unknown version."""
shader = FileShader(core_frag_shader_without_version(), '.frag')
glslc_args = ['-c', '-std=42core', shader]
expected_error = [
"glslc: error: invalid value '42core' in '-std=42core'\n"]
@inside_glslc_testsuite('OptionStd')
class TestTotallyWrongStdValue(expect.ErrorMessage):
"""Tests that -std rejects totally wrong -std value."""
shader = FileShader(core_vert_shader_without_version(), '.vert')
glslc_args = ['-c', '-std=wrong42', shader]
expected_error = [
"glslc: error: invalid value 'wrong42' in '-std=wrong42'\n"]
@inside_glslc_testsuite('OptionStd')
class TestVersionInsideSlashSlashComment(expect.ValidObjectFileWithWarning):
"""Tests that -std substitutes the correct #version string."""
# The second #version string should be substituted and this shader
# should compile successfully with -std=450core.
shader = FileShader(
'// #version 310 es\n#version 310 es\n' +
core_vert_shader_without_version(), '.vert')
glslc_args = ['-c', '-std=450core', shader]
expected_warning = [
shader, ': warning: (version, profile) forced to be (450, core), while '
'in source code it is (310, es)\n1 warning generated.\n']
@inside_glslc_testsuite('OptionStd')
class TestVersionInsideSlashStarComment(expect.ValidObjectFileWithWarning):
"""Tests that -std substitutes the correct #version string."""
# The second #version string should be substituted and this shader
# should compile successfully with -std=450core.
shader = FileShader(
'/* #version 310 es */\n#version 310 es\n' +
core_vert_shader_without_version(), '.vert')
glslc_args = ['-c', '-std=450core', shader]
expected_warning = [
shader, ': warning: (version, profile) forced to be (450, core), while '
'in source code it is (310, es)\n1 warning generated.\n']
@inside_glslc_testsuite('OptionStd')
class TestCommentBeforeVersion(expect.ValidObjectFileWithWarning):
"""Tests that comments before #version (same line) is correctly handled."""
shader = FileShader(
'/* some comment */ #version 150\n' +
core_vert_shader_without_version(), '.vert')
glslc_args = ['-c', '-std=450', shader]
expected_warning = [
shader, ': warning: (version, profile) forced to be (450, none), while '
'in source code it is (150, none)\n1 warning generated.\n']
@inside_glslc_testsuite('OptionStd')
class TestCommentAfterVersion(expect.ValidObjectFileWithWarning):
"""Tests that multiple-line comments after #version is correctly handled."""
shader = FileShader(
'#version 150 compatibility ' +
'/* start \n second line \n end */\n' +
core_vert_shader_without_version(), '.vert')
glslc_args = ['-c', '-std=450core', shader]
expected_warning = [
shader, ': warning: (version, profile) forced to be (450, core), while '
'in source code it is (150, compatibility)\n1 warning generated.\n']
# The following test case is disabled because of a bug in glslang.
# When checking non-newline whitespaces, glslang only recognizes
# ' ' and '\t', leaving '\v' and '\f' unhandled. The following test
# case exposes this problem. It should be turned on once a fix for
# glslang is landed.
#@inside_glslc_testsuite('OptionStd')
class TestSpaceAroundVersion(expect.ValidObjectFileWithWarning):
"""Tests that space around #version is correctly handled."""
shader = FileShader(
'\t \t # \t \f\f version \v \t\t 310 \v\v \t es \n' +
core_vert_shader_without_version(), '.vert')
glslc_args = ['-c', '-std=450core', shader]
expected_warning = [
shader, ': warning: (version, profile) forced to be (450, core), while '
'in source code it is (310, es)\n1 warning generated.\n']
@inside_glslc_testsuite('OptionStd')
class TestVersionInsideCrazyComment(expect.ValidObjectFileWithWarning):
"""Tests that -std substitutes the correct #version string."""
# The fourth #version string should be substituted and this shader
# should compile successfully with -std=450core.
shader = FileShader(
'/* */ /* // /* #version 310 es */\n' + # /*-style comment
'// /* */ /* /* // #version 310 es\n' + # //-style comment
'///*////*//*/*/ #version 310 es*/\n' + # //-style comment
'#version 310 es\n' + core_vert_shader_without_version(), '.vert')
glslc_args = ['-c', '-std=450core', shader]
expected_warning = [
shader, ': warning: (version, profile) forced to be (450, core), while '
'in source code it is (310, es)\n1 warning generated.\n']
@inside_glslc_testsuite('OptionStd')
class TestVersionMissingProfile(expect.ErrorMessage):
"""Tests that missing required profile in -std results in an error."""
shader = FileShader('#version 140\nvoid main() {}', '.vert')
glslc_args = ['-c', '-std=310', shader]
expected_error = [
shader, ': error: #version: versions 300, 310, and 320 require ',
"specifying the 'es' profile\n1 error generated.\n"]
@inside_glslc_testsuite('OptionStd')
class TestVersionRedundantProfile(expect.ErrorMessageSubstr):
"""Tests that adding non-required profile in -std results in an error."""
shader = FileShader('#version 140\nvoid main() {}', '.vert')
glslc_args = ['-c', '-std=100core', shader]
expected_error_substr = [
shader, ': error: #version: versions before 150 do not allow '
'a profile token\n']

View File

@@ -0,0 +1,197 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
def opengl_compat_fragment_shader():
return """#version 330
uniform highp sampler2D tex;
void main() {
gl_FragColor = texture2D(tex, vec2(0.0, 0.0));
}"""
def opengl_vertex_shader():
return """#version 330
void main() { int t = gl_VertexID; }"""
def vulkan_vertex_shader():
return """#version 310 es
void main() { int t = gl_VertexIndex; }"""
def vulkan_compute_subgroup_shader():
"""Returns a compute shader that requires Vulkan 1.1"""
return """#version 450
#extension GL_KHR_shader_subgroup_basic : enable
void main() { subgroupBarrier(); }"""
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqOpenglCompatWithOpenGlCompatShader(expect.ErrorMessageSubstr):
"""Tests that compiling OpenGL Compatibility Fragment shader with
--target-env=opengl_compat works correctly"""
shader = FileShader(opengl_compat_fragment_shader(), '.frag')
glslc_args = ['--target-env=opengl_compat', '-c', shader]
expected_error_substr = "error: opengl_compat is no longer supported"
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqOpenglWithOpenGlCompatShader(expect.ErrorMessageSubstr):
"""Tests the error message of compiling OpenGL Compatibility Fragment shader
with --target-env=opengl"""
shader = FileShader(opengl_compat_fragment_shader(), '.frag')
glslc_args = ['--target-env=opengl', shader]
# Glslang does not give a pretty message. Make sure we get an error.
expected_error_substr = "errors generated"
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqOpenglCompatWithOpenGlVertexShader(expect.ErrorMessageSubstr):
"""Tests that compiling OpenGL vertex shader with --target-env=opengl_compat
generates valid SPIR-V code"""
shader = FileShader(opengl_vertex_shader(), '.vert')
glslc_args = ['--target-env=opengl_compat', '-c', shader]
expected_error_substr = "error: opengl_compat is no longer supported"
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqOpenglWithOpenGlVertexShader(expect.ValidObjectFile):
"""Tests that compiling OpenGL vertex shader with --target-env=opengl
generates valid SPIR-V code"""
shader = FileShader(opengl_vertex_shader(), '.vert')
glslc_args = ['--target-env=opengl', '-c', shader]
@inside_glslc_testsuite('OptionTargetEnv')
class TestDefaultTargetEnvWithVulkanShader(expect.ValidObjectFile):
"""Tests that compiling a Vulkan-specific shader with a default
target environment succeeds"""
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqVulkanWithVulkan1_0ShaderSucceeds(expect.ValidObjectFile):
"""Tests that compiling a Vulkan-specific Vulkan 1.0 shader succeeds with
--target-env=vulkan"""
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['--target-env=vulkan', '-c', shader]
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqVulkan1_0WithVulkan1_0ShaderSucceeds(expect.ValidObjectFile):
"""Tests that compiling a Vulkan-specific Vulkan 1.0 shader succeeds with
--target-env=vulkan1.0"""
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['--target-env=vulkan1.0', '-c', shader]
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqVulkan1_0WithVulkan1_1ShaderFails(expect.ErrorMessageSubstr):
shader = FileShader(vulkan_compute_subgroup_shader(), '.comp')
glslc_args = ['--target-env=vulkan1.0', '-c', shader]
expected_error_substr = "error: 'subgroup op' : requires SPIR-V 1.3"
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqVulkan1_1WithVulkan1_0ShaderSucceeds(expect.ValidObjectFile1_3):
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['--target-env=vulkan1.1', '-c', shader]
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqVulkan1_1WithVulkan1_1ShaderSucceeds(expect.ValidObjectFile1_3):
shader = FileShader(vulkan_compute_subgroup_shader(), '.comp')
glslc_args = ['--target-env=vulkan1.1', '-c', shader]
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqVulkan1_2WithVulkan1_0ShaderSucceeds(expect.ValidObjectFile1_5):
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['--target-env=vulkan1.2', '-c', shader]
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqVulkan1_2WithVulkan1_1ShaderSucceeds(expect.ValidObjectFile1_5):
shader = FileShader(vulkan_compute_subgroup_shader(), '.comp')
glslc_args = ['--target-env=vulkan1.2', '-c', shader]
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqVulkan1_2WithVulkan1_0ShaderSucceeds(expect.ValidObjectFile1_6):
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['--target-env=vulkan1.3', '-c', shader]
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqVulkan1_2WithVulkan1_1ShaderSucceeds(expect.ValidObjectFile1_6):
shader = FileShader(vulkan_compute_subgroup_shader(), '.comp')
glslc_args = ['--target-env=vulkan1.3', '-c', shader]
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqOpenGL4_5WithOpenGLShaderSucceeds(expect.ValidObjectFile):
shader = FileShader(opengl_vertex_shader(), '.vert')
glslc_args = ['--target-env=opengl4.5', '-c', shader]
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqOpenGL4_6WithOpenGLShaderFailsUnsupported(expect.ErrorMessageSubstr):
shader = FileShader(opengl_vertex_shader(), '.vert')
glslc_args = ['--target-env=opengl4.6', '-c', shader]
expected_error_substr = "invalid value 'opengl4.6' in '--target-env=opengl4.6'"
# Note: Negative tests are covered in the libshaderc_util unit tests.
# For example, that an OpenGL-specific shader should fail to compile
# for Vulkan, or a Vulkan-specific shader should fail to compile for
# OpenGL.
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqNoArg(expect.ErrorMessage):
"""Tests the error message of assigning empty string to --target-env"""
shader = FileShader(opengl_vertex_shader(), '.vert')
glslc_args = ['--target-env=', shader]
expected_error = ["glslc: error: invalid value ",
"'' in '--target-env='\n"]
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvNoEqNoArg(expect.ErrorMessage):
"""Tests the error message of using --target-env without equal sign and
arguments"""
shader = FileShader(opengl_vertex_shader(), '.vert')
glslc_args = ['--target-env', shader]
expected_error = ["glslc: error: unsupported option: ",
"'--target-env'\n"]
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvNoEqWithArg(expect.ErrorMessage):
"""Tests the error message of using --target-env without equal sign but
arguments"""
shader = FileShader(opengl_vertex_shader(), '.vert')
glslc_args = ['--target-env', 'opengl', shader]
expected_error = ["glslc: error: unsupported option: ",
"'--target-env'\n"]
@inside_glslc_testsuite('OptionTargetEnv')
class TestTargetEnvEqWrongArg(expect.ErrorMessage):
"""Tests the error message of using --target-env with wrong argument"""
shader = FileShader(opengl_vertex_shader(), '.vert')
glslc_args = ['--target-env=wrong_arg', shader]
expected_error = ["glslc: error: invalid value ",
"'wrong_arg' in '--target-env=wrong_arg'\n"]

View File

@@ -0,0 +1,125 @@
# Copyright 2019 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
def vulkan_vertex_shader():
return """#version 310 es
void main() { int t = gl_VertexIndex; }"""
def vulkan_compute_subgroup_shader():
"""Returns a compute shader that requires Vulkan 1.1 and SPIR-V 1.3"""
return """#version 450
#extension GL_KHR_shader_subgroup_basic : enable
void main() { subgroupBarrier(); }"""
@inside_glslc_testsuite('OptionTargetSpv')
class TestDefaultTargetSpvWithVulkanShader(expect.ValidObjectFile):
"""Tests that compiling a Vulkan-specific shader with a default
target environment succeeds"""
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('OptionTargetSpv')
class TestDefaultTargetSpvWithShaderRequiringSpv1p3Fails(expect.ErrorMessageSubstr):
"""Tests that compiling a shader requiring SPIR-V 1.3 with default SPIR-V
target should fail.
"""
shader = FileShader(vulkan_compute_subgroup_shader(), '.comp')
glslc_args = ['-c', shader]
expected_error_substr = ["error: 'subgroup op' : requires SPIR-V 1.3\n"]
@inside_glslc_testsuite('OptionTargetSpv')
class TestTargetSpv1p2WithShaderRequiringSpv1p3Fails(expect.ErrorMessageSubstr):
"""Tests that compiling a shader requiring SPIR-V 1.3 but targeting 1.2
should fail.
"""
shader = FileShader(vulkan_compute_subgroup_shader(), '.comp')
glslc_args = ['--target-spv=spv1.2', '-c', shader]
expected_error_substr = ["error: 'subgroup op' : requires SPIR-V 1.3\n"]
@inside_glslc_testsuite('OptionTargetSpv')
class TestTargetSpv1p3(expect.ValidObjectFile1_3):
"""Tests that compiling to spv1.3 succeeds and generates SPIR-V 1.3 binary."""
shader = FileShader(vulkan_compute_subgroup_shader(), '.comp')
glslc_args = ['--target-spv=spv1.3', '-c', shader]
@inside_glslc_testsuite('OptionTargetSpv')
class TestTargetSpv1p4(expect.ValidObjectFile1_4):
"""Tests that compiling to spv1.4 succeeds and generates SPIR-V 1.4 binary."""
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['--target-spv=spv1.4', '-c', shader]
@inside_glslc_testsuite('OptionTargetSpv')
class TestTargetSpv1p5(expect.ValidObjectFile1_5):
"""Tests that compiling to spv1.5 succeeds and generates SPIR-V 1.5 binary."""
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['--target-spv=spv1.5', '-c', shader]
@inside_glslc_testsuite('OptionTargetSpv')
class TestTargetSpv1p5(expect.ValidObjectFile1_6):
"""Tests that compiling to spv1.6 succeeds and generates SPIR-V 1.6 binary."""
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['--target-spv=spv1.6', '-c', shader]
### Option parsing error cases
@inside_glslc_testsuite('OptionTargetSpv')
class TestTargetSpvNoArg(expect.ErrorMessage):
"""Tests the error message of assigning empty string to --target-spv"""
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['--target-spv=', shader]
expected_error = ["glslc: error: invalid value ",
"'' in '--target-spv='\n"]
@inside_glslc_testsuite('OptionTargetSpv')
class TestTargetSpvNoEqNoArg(expect.ErrorMessage):
"""Tests the error message of using --target-spv without equal sign and
arguments"""
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['--target-spv', shader]
expected_error = ["glslc: error: unsupported option: ",
"'--target-spv'\n"]
@inside_glslc_testsuite('OptionTargetSpv')
class TestTargetSpvNoEqWithArg(expect.ErrorMessage):
"""Tests the error message of using --target-spv without equal sign but
arguments"""
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['--target-spv', 'spv1.3', shader]
expected_error = ["glslc: error: unsupported option: ",
"'--target-spv'\n"]
@inside_glslc_testsuite('OptionTargetSpv')
class TestTargetSpvEqWrongArg(expect.ErrorMessage):
"""Tests the error message of using --target-spv with wrong argument"""
shader = FileShader(vulkan_vertex_shader(), '.vert')
glslc_args = ['--target-spv=wrong_arg', shader]
expected_error = ["glslc: error: invalid value ",
"'wrong_arg' in '--target-spv=wrong_arg'\n"]

View File

@@ -0,0 +1,390 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
import os.path
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader, StdinShader, TempFileName
@inside_glslc_testsuite('File')
class SimpleFileCompiled(expect.ValidObjectFile):
"""Tests whether or not a simple glsl file compiles."""
shader = FileShader('#version 310 es\nvoid main() {}', '.frag')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('File')
class NotSpecifyingOutputName(expect.SuccessfulReturn,
expect.CorrectObjectFilePreamble):
"""Tests that when there is no -o and -E/-S/-c specified, output as a.spv."""
shader = FileShader('#version 140\nvoid main() {}', '.frag')
glslc_args = [shader]
def check_output_a_spv(self, status):
output_name = os.path.join(status.directory, 'a.spv')
return self.verify_object_file_preamble(output_name)
@inside_glslc_testsuite('Parameters')
class HelpParameters(
expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch):
"""Tests the --help flag outputs correctly and does not produce and error."""
glslc_args = ['--help']
expected_stdout = '''glslc - Compile shaders into SPIR-V
Usage: glslc [options] file...
An input file of - represents standard input.
Options:
-c Only run preprocess, compile, and assemble steps.
-Dmacro[=defn] Add an implicit macro definition.
-E Outputs only the results of the preprocessing step.
Output defaults to standard output.
-fauto-bind-uniforms
Automatically assign bindings to uniform variables that
don't have an explicit 'binding' layout in the shader
source.
-fauto-map-locations
Automatically assign locations to uniform variables that
don't have an explicit 'location' layout in the shader
source.
-fauto-combined-image-sampler
Removes sampler variables and converts existing textures
to combined image-samplers.
-fentry-point=<name>
Specify the entry point name for HLSL compilation, for
all subsequent source files. Default is "main".
-fhlsl-16bit-types
Enable 16-bit type support for HLSL.
-fhlsl_functionality1, -fhlsl-functionality1
Enable extension SPV_GOOGLE_hlsl_functionality1 for HLSL
compilation.
-fhlsl-iomap Use HLSL IO mappings for bindings.
-fhlsl-offsets Use HLSL offset rules for packing members of blocks.
Affects only GLSL. HLSL rules are always used for HLSL.
-finvert-y Invert position.Y output in vertex shader.
-flimit=<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.
-fpreserve-bindings
Preserve all binding declarations, even if those bindings
are not used.
-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.
-h Display available options.
--help Display available options.
-I <value> Add directory to include search path.
-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 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.
-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 client environment, and the semantics
of warnings and errors. An optional suffix can specify
the client version. Values are:
vulkan1.0 # The default
vulkan1.1
vulkan1.2
vulkan1.3
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.
the default for vulkan1.3 is spv1.6.
Values are:
spv1.0, spv1.1, spv1.2, spv1.3, spv1.4, spv1.5, spv1.6
--version Display compiler version information.
-w Suppresses all warning messages.
-Werror Treat all warnings as errors.
-x <language> Treat subsequent input files as having type <language>.
Valid languages are: glsl, hlsl.
For files ending in .hlsl the default is hlsl.
Otherwise the default is glsl.
'''
expected_stderr = ''
@inside_glslc_testsuite('Parameters')
class HelpIsNotTooWide(expect.StdoutNoWiderThan80Columns):
"""Tests that --help output is not too wide."""
glslc_args = ['--help']
@inside_glslc_testsuite('Parameters')
class UnknownSingleLetterArgument(expect.ErrorMessage):
"""Tests that an unknown argument triggers an error message."""
glslc_args = ['-a']
expected_error = ["glslc: error: unknown argument: '-a'\n"]
@inside_glslc_testsuite('Parameters')
class UnknownMultiLetterArgument(expect.ErrorMessage):
"""Tests that an unknown argument triggers an error message."""
glslc_args = ['-zzz']
expected_error = ["glslc: error: unknown argument: '-zzz'\n"]
@inside_glslc_testsuite('Parameters')
class UnsupportedOption(expect.ErrorMessage):
"""Tests that an unsupported option triggers an error message."""
glslc_args = ['--unsupported-option']
expected_error = [
"glslc: error: unsupported option: '--unsupported-option'\n"]
@inside_glslc_testsuite('File')
class FileNotFound(expect.ErrorMessage):
"""Tests the error message if a file cannot be found."""
blabla_file = TempFileName('blabla.frag')
glslc_args = [blabla_file]
expected_error = [
"glslc: error: cannot open input file: '", blabla_file,
"': No such file or directory\n"]
@inside_glslc_testsuite('Unsupported')
class LinkingNotSupported(expect.ErrorMessage):
"""Tests the error message generated by linking not supported yet."""
shader1 = FileShader('#version 140\nvoid main() {}', '.vert')
shader2 = FileShader('#version 140\nvoid main() {}', '.frag')
glslc_args = [shader1, shader2]
expected_error = [
'glslc: error: linking multiple files is not supported yet. ',
'Use -c to compile files individually.\n']
@inside_glslc_testsuite('Unsupported')
class MultipleStdinUnsupported(expect.ErrorMessage):
"""Tests the error message generated by having more than one - input."""
glslc_args = ['-c', '-fshader-stage=vertex', '-', '-']
expected_error = [
'glslc: error: specifying standard input "-" as input more'
' than once is not allowed.\n']
@inside_glslc_testsuite('Parameters')
class StdinWithoutShaderStage(expect.StdoutMatch, expect.StderrMatch):
"""Tests that you must use -fshader-stage when specifying - as input."""
shader = StdinShader(
"""#version 140
int a() {
}
void main() {
int x = a();
}
""")
glslc_args = [shader]
expected_stdout = ''
expected_stderr = [
"glslc: error: '-': -fshader-stage required when input is from "
'standard input "-"\n']
@inside_glslc_testsuite('Parameters')
class LimitsHelp(expect.StdoutMatch, expect.StderrMatch):
"""Tests --show-limits shows correct output."""
glslc_args = ['--show-limits']
expected_stderr = ''
expected_stdout = """MaxLights 8
MaxClipPlanes 6
MaxTextureUnits 2
MaxTextureCoords 8
MaxVertexAttribs 16
MaxVertexUniformComponents 4096
MaxVaryingFloats 60
MaxVertexTextureImageUnits 16
MaxCombinedTextureImageUnits 80
MaxTextureImageUnits 16
MaxFragmentUniformComponents 1024
MaxDrawBuffers 8
MaxVertexUniformVectors 256
MaxVaryingVectors 15
MaxFragmentUniformVectors 256
MaxVertexOutputVectors 16
MaxFragmentInputVectors 15
MinProgramTexelOffset -8
MaxProgramTexelOffset 7
MaxClipDistances 8
MaxComputeWorkGroupCountX 65535
MaxComputeWorkGroupCountY 65535
MaxComputeWorkGroupCountZ 65535
MaxComputeWorkGroupSizeX 1024
MaxComputeWorkGroupSizeY 1024
MaxComputeWorkGroupSizeZ 64
MaxComputeUniformComponents 512
MaxComputeTextureImageUnits 16
MaxComputeImageUniforms 8
MaxComputeAtomicCounters 8
MaxComputeAtomicCounterBuffers 1
MaxVaryingComponents 60
MaxVertexOutputComponents 64
MaxGeometryInputComponents 64
MaxGeometryOutputComponents 128
MaxFragmentInputComponents 128
MaxImageUnits 8
MaxCombinedImageUnitsAndFragmentOutputs 8
MaxCombinedShaderOutputResources 8
MaxImageSamples 0
MaxVertexImageUniforms 0
MaxTessControlImageUniforms 0
MaxTessEvaluationImageUniforms 0
MaxGeometryImageUniforms 0
MaxFragmentImageUniforms 8
MaxCombinedImageUniforms 8
MaxGeometryTextureImageUnits 16
MaxGeometryOutputVertices 256
MaxGeometryTotalOutputComponents 1024
MaxGeometryUniformComponents 512
MaxGeometryVaryingComponents 60
MaxTessControlInputComponents 128
MaxTessControlOutputComponents 128
MaxTessControlTextureImageUnits 16
MaxTessControlUniformComponents 1024
MaxTessControlTotalOutputComponents 4096
MaxTessEvaluationInputComponents 128
MaxTessEvaluationOutputComponents 128
MaxTessEvaluationTextureImageUnits 16
MaxTessEvaluationUniformComponents 1024
MaxTessPatchComponents 120
MaxPatchVertices 32
MaxTessGenLevel 64
MaxViewports 16
MaxVertexAtomicCounters 0
MaxTessControlAtomicCounters 0
MaxTessEvaluationAtomicCounters 0
MaxGeometryAtomicCounters 0
MaxFragmentAtomicCounters 8
MaxCombinedAtomicCounters 8
MaxAtomicCounterBindings 1
MaxVertexAtomicCounterBuffers 0
MaxTessControlAtomicCounterBuffers 0
MaxTessEvaluationAtomicCounterBuffers 0
MaxGeometryAtomicCounterBuffers 0
MaxFragmentAtomicCounterBuffers 0
MaxCombinedAtomicCounterBuffers 1
MaxAtomicCounterBufferSize 32
MaxTransformFeedbackBuffers 4
MaxTransformFeedbackInterleavedComponents 64
MaxCullDistances 8
MaxCombinedClipAndCullDistances 8
MaxSamples 4
MaxMeshOutputVerticesNV 256
MaxMeshOutputPrimitivesNV 512
MaxMeshWorkGroupSizeX_NV 32
MaxMeshWorkGroupSizeY_NV 1
MaxMeshWorkGroupSizeZ_NV 1
MaxTaskWorkGroupSizeX_NV 32
MaxTaskWorkGroupSizeY_NV 1
MaxTaskWorkGroupSizeZ_NV 1
MaxMeshViewCountNV 4
MaxMeshOutputVerticesEXT 256
MaxMeshOutputPrimitivesEXT 256
MaxMeshWorkGroupSizeX_EXT 128
MaxMeshWorkGroupSizeY_EXT 128
MaxMeshWorkGroupSizeZ_EXT 128
MaxTaskWorkGroupSizeX_EXT 128
MaxTaskWorkGroupSizeY_EXT 128
MaxTaskWorkGroupSizeZ_EXT 128
MaxMeshViewCountEXT 4
MaxDualSourceDrawBuffersEXT 1
"""

View File

@@ -0,0 +1,143 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A number of placeholders and their rules for expansion when used in tests.
These placeholders, when used in glslc_args or expected_* variables of
GlslCTest, have special meanings. In glslc_args, they will be substituted by
the result of instantiate_for_glslc_args(), while in expected_*, by
instantiate_for_expectation(). A TestCase instance will be passed in as
argument to the instantiate_*() methods.
"""
import os
import tempfile
from string import Template
from builtins import bytes
class PlaceHolderException(Exception):
"""Exception class for PlaceHolder."""
pass
class PlaceHolder(object):
"""Base class for placeholders."""
def instantiate_for_glslc_args(self, testcase):
"""Instantiation rules for glslc_args.
This method will be called when the current placeholder appears in
glslc_args.
Returns:
A string to replace the current placeholder in glslc_args.
"""
raise PlaceHolderException('Subclass should implement this function.')
def instantiate_for_expectation(self, testcase):
"""Instantiation rules for expected_*.
This method will be called when the current placeholder appears in
expected_*.
Returns:
A string to replace the current placeholder in expected_*.
"""
raise PlaceHolderException('Subclass should implement this function.')
class FileShader(PlaceHolder):
"""Stands for a shader whose source code is in a file."""
def __init__(self, source, suffix, assembly_substr=None):
assert isinstance(source, str)
assert isinstance(suffix, str)
self.source = source
self.suffix = suffix
self.filename = None
# If provided, this is a substring which is expected to be in
# the disassembly of the module generated from this input file.
self.assembly_substr = assembly_substr
def instantiate_for_glslc_args(self, testcase):
"""Creates a temporary file and writes the source into it.
Returns:
The name of the temporary file.
"""
shader, self.filename = tempfile.mkstemp(
dir=testcase.directory, suffix=self.suffix)
shader_object = os.fdopen(shader, 'w')
shader_object.write(self.source)
shader_object.close()
return self.filename
def instantiate_for_expectation(self, testcase):
assert self.filename is not None
return self.filename
class StdinShader(PlaceHolder):
"""Stands for a shader whose source code is from stdin."""
def __init__(self, source):
assert isinstance(source, str)
self.source = source
self.filename = None
def instantiate_for_glslc_args(self, testcase):
"""Writes the source code back to the TestCase instance."""
testcase.stdin_shader = bytes(self.source, 'utf-8')
self.filename = '-'
return self.filename
def instantiate_for_expectation(self, testcase):
assert self.filename is not None
return self.filename
class TempFileName(PlaceHolder):
"""Stands for a temporary file's name."""
def __init__(self, filename):
assert isinstance(filename, str)
assert filename != ''
self.filename = filename
def instantiate_for_glslc_args(self, testcase):
return os.path.join(testcase.directory, self.filename)
def instantiate_for_expectation(self, testcase):
return os.path.join(testcase.directory, self.filename)
class SpecializedString(PlaceHolder):
"""Returns a string that has been specialized based on TestCase.
The string is specialized by expanding it as a string.Template
with all of the specialization being done with each $param replaced
by the associated member on TestCase.
"""
def __init__(self, filename):
assert isinstance(filename, str)
assert filename != ''
self.filename = filename
def instantiate_for_glslc_args(self, testcase):
return Template(self.filename).substitute(vars(testcase))
def instantiate_for_expectation(self, testcase):
return Template(self.filename).substitute(vars(testcase))

View File

@@ -0,0 +1,461 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from environment import Directory, File
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader, StdinShader
VERTEX_ONLY_SHADER_WITH_PRAGMA = \
"""#version 310 es
#pragma shader_stage(vertex)
void main() {
gl_Position = vec4(1.);
}"""
FRAGMENT_ONLY_SHADER_WITH_PRAGMA = \
"""#version 310 es
#pragma shader_stage(fragment)
void main() {
gl_FragDepth = 10.;
}"""
TESS_CONTROL_ONLY_SHADER_WITH_PRAGMA = \
"""#version 440 core
#pragma shader_stage(tesscontrol)
layout(vertices = 3) out;
void main() { }"""
TESS_EVAL_ONLY_SHADER_WITH_PRAGMA = \
"""#version 440 core
#pragma shader_stage(tesseval)
layout(triangles) in;
void main() { }"""
GEOMETRY_ONLY_SHDER_WITH_PRAGMA = \
"""#version 150 core
#pragma shader_stage(geometry)
layout (triangles) in;
layout (line_strip, max_vertices = 4) out;
void main() { }"""
COMPUTE_ONLY_SHADER_WITH_PRAGMA = \
"""#version 310 es
#pragma shader_stage(compute)
void main() {
uvec3 temp = gl_WorkGroupID;
}"""
# In the following tests,
# PSS stands for PragmaShaderStage, and OSS stands for OptionShaderStage.
@inside_glslc_testsuite('PragmaShaderStage')
class TestPSSWithGlslExtension(expect.ValidObjectFile):
"""Tests #pragma shader_stage() with .glsl extension."""
shader = FileShader(VERTEX_ONLY_SHADER_WITH_PRAGMA, '.glsl')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('PragmaShaderStage')
class TestPSSWithUnkownExtension(expect.ValidObjectFile):
"""Tests #pragma shader_stage() with unknown extension."""
shader = FileShader(VERTEX_ONLY_SHADER_WITH_PRAGMA, '.unkown')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('PragmaShaderStage')
class TestPSSWithStdin(expect.ValidObjectFile):
"""Tests #pragma shader_stage() with stdin."""
shader = StdinShader(VERTEX_ONLY_SHADER_WITH_PRAGMA)
glslc_args = ['-c', shader]
@inside_glslc_testsuite('PragmaShaderStage')
class TestPSSWithSameShaderExtension(expect.ValidObjectFile):
"""Tests that #pragma shader_stage() specifies the same stage as file
extesion."""
shader = FileShader(VERTEX_ONLY_SHADER_WITH_PRAGMA, '.vert')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('PragmaShaderStage')
class TestPSSOverrideShaderExtension(expect.ValidObjectFile):
"""Tests that #pragma shader_stage() overrides file extension."""
shader = FileShader(VERTEX_ONLY_SHADER_WITH_PRAGMA, '.frag')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('PragmaShaderStage')
class TestOSSOverridePSS(expect.ValidObjectFile):
"""Tests that -fshader-stage overrides #pragma shader_stage()."""
# wrong pragma and wrong file extension
shader = FileShader(
"""#version 310 es
#pragma shader_stage(fragment)
void main() {
gl_Position = vec4(1.);
}""", '.frag')
# -fshader-stage to the rescue! ^.^
glslc_args = ['-c', '-fshader-stage=vertex', shader]
@inside_glslc_testsuite('PragmaShaderStage')
class TestMultipleSamePSS(expect.ValidObjectFile):
"""Tests that multiple identical #pragma shader_stage() works."""
shader = FileShader(
"""#version 310 es
#pragma shader_stage(vertex)
#pragma shader_stage(vertex)
void main() {
#pragma shader_stage(vertex)
gl_Position = vec4(1.);
#pragma shader_stage(vertex)
}
#pragma shader_stage(vertex)
#pragma shader_stage(vertex)
""", '.glsl')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('PragmaShaderStage')
class TestConflictingPSS(expect.ErrorMessage):
"""Conflicting #pragma shader_stage() directives result in an error."""
shader = FileShader(
"""#version 310 es
#pragma shader_stage(vertex)
void main() {
gl_Position = vec4(1.);
}
#pragma shader_stage(fragment)
""", '.glsl')
glslc_args = ['-c', shader]
expected_error = [
shader, ":6: error: '#pragma': conflicting stages for 'shader_stage' "
"#pragma: 'fragment' (was 'vertex' at ", shader, ':2)\n']
@inside_glslc_testsuite('PragmaShaderStage')
class TestAllPSSValues(expect.ValidObjectFile):
"""Tests all possible #pragma shader_stage() values."""
shader1 = FileShader(VERTEX_ONLY_SHADER_WITH_PRAGMA, '.glsl')
shader2 = FileShader(FRAGMENT_ONLY_SHADER_WITH_PRAGMA, '.glsl')
shader3 = FileShader(TESS_CONTROL_ONLY_SHADER_WITH_PRAGMA, '.glsl')
shader4 = FileShader(TESS_EVAL_ONLY_SHADER_WITH_PRAGMA, '.glsl')
shader5 = FileShader(GEOMETRY_ONLY_SHDER_WITH_PRAGMA, '.glsl')
shader6 = FileShader(COMPUTE_ONLY_SHADER_WITH_PRAGMA, '.glsl')
glslc_args = ['-c', shader1, shader2, shader3, shader4, shader5, shader6]
@inside_glslc_testsuite('PragmaShaderStage')
class TestWrongPSSValue(expect.ErrorMessage):
"""Tests that #pragma shader_stage([wrong-stage]) results in an error."""
shader = FileShader(
"""#version 310 es
#pragma shader_stage(superstage)
void main() {
gl_Position = vec4(1.);
}
""", '.glsl')
glslc_args = ['-c', shader]
expected_error = [
shader, ":2: error: '#pragma': invalid stage for 'shader_stage' "
"#pragma: 'superstage'\n"]
@inside_glslc_testsuite('PragmaShaderStage')
class TestEmptyPSSValue(expect.ErrorMessage):
"""Tests that #pragma shader_stage([empty]) results in an error."""
shader = FileShader(
"""#version 310 es
#pragma shader_stage()
void main() {
gl_Position = vec4(1.);
}
""", '.glsl')
glslc_args = ['-c', shader]
expected_error = [
shader, ":2: error: '#pragma': invalid stage for 'shader_stage' "
"#pragma: ''\n"]
@inside_glslc_testsuite('PragmaShaderStage')
class TestFirstPSSBeforeNonPPCode(expect.ErrorMessage):
"""Tests that the first #pragma shader_stage() should appear before
any non-preprocessing code."""
shader = FileShader(
"""#version 310 es
#ifndef REMOVE_UNUSED_FUNCTION
int inc(int i) { return i + 1; }
#endif
#pragma shader_stage(vertex)
void main() {
gl_Position = vec4(1.);
}
""", '.glsl')
glslc_args = ['-c', shader]
expected_error = [
shader, ":5: error: '#pragma': the first 'shader_stage' #pragma "
'must appear before any non-preprocessing code\n']
@inside_glslc_testsuite('PragmaShaderStage')
class TestPSSMultipleErrors(expect.ErrorMessage):
"""Tests that if there are multiple errors, they are all reported."""
shader = FileShader(
"""#version 310 es
#pragma shader_stage(idontknow)
#pragma shader_stage(vertex)
void main() {
gl_Position = vec4(1.);
}
#pragma shader_stage(fragment)
""", '.glsl')
glslc_args = ['-c', shader]
expected_error = [
shader, ":2: error: '#pragma': invalid stage for 'shader_stage' "
"#pragma: 'idontknow'\n",
shader, ":3: error: '#pragma': conflicting stages for 'shader_stage' "
"#pragma: 'vertex' (was 'idontknow' at ", shader, ':2)\n',
shader, ":7: error: '#pragma': conflicting stages for 'shader_stage' "
"#pragma: 'fragment' (was 'idontknow' at ", shader, ':2)\n']
@inside_glslc_testsuite('PragmaShaderStage')
class TestSpacesAroundPSS(expect.ValidObjectFile):
"""Tests that spaces around #pragma shader_stage() works."""
shader = FileShader(
"""#version 310 es
# pragma shader_stage ( vertex )
void main() {
gl_Position = vec4(1.);
}
""", '.glsl')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('PragmaShaderStage')
class TestTabsAroundPSS(expect.ValidObjectFile):
"""Tests that tabs around #pragma shader_stage() works."""
shader = FileShader(
"""#version 310 es
\t\t#\tpragma\t\t\tshader_stage\t\t(\t\t\t\tvertex\t\t)\t\t\t\t
void main() {
gl_Position = vec4(1.);
}
""", '.glsl')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('PragmaShaderStage')
class TestPSSWithMacro(expect.ValidObjectFile):
"""Tests that #pragma shader_stage() works with macros."""
shader = FileShader(
"""#version 310 es
#if 0
some random stuff here which can cause a problem
#else
# pragma shader_stage(vertex)
#endif
void main() {
gl_Position = vec4(1.);
}
""", '.glsl')
glslc_args = ['-c', shader]
@inside_glslc_testsuite('PragmaShaderStage')
class TestPSSWithCmdLineMacroDef(expect.ValidObjectFile):
"""Tests that macro definitions passed in from command line work."""
shader = FileShader(
"""#version 310 es
#ifdef IS_A_VERTEX_SHADER
# pragma shader_stage(vertex)
#else
# pragma shader_stage(fragment)
#endif
void main() {
gl_Position = vec4(1.);
}
""", '.glsl')
glslc_args = ['-c', '-DIS_A_VERTEX_SHADER', shader]
@inside_glslc_testsuite('PragmaShaderStage')
class TestNoMacroExpansionInsidePSS(expect.ErrorMessage):
"""Tests that there is no macro expansion inside #pragma shader_stage()."""
shader = FileShader(
"""#version 310 es
#pragma shader_stage(STAGE_FROM_CMDLINE)
void main() {
gl_Position = vec4(1.);
}
""", '.glsl')
glslc_args = ['-c', '-DSTAGE_FROM_CMDLINE=vertex', shader]
expected_error = [
shader, ":2: error: '#pragma': invalid stage for 'shader_stage' "
"#pragma: 'STAGE_FROM_CMDLINE'\n"]
@inside_glslc_testsuite('PragmaShaderStage')
class TestPSSWithPoundLine310(expect.ErrorMessage):
"""Tests that #pragma shader_stage() works with #line."""
shader = FileShader(
"""#version 310 es
#pragma shader_stage(unknown)
#line 42
#pragma shader_stage(google)
#line 100
#pragma shader_stage(elgoog)
void main() {
gl_Position = vec4(1.);
}
""", '.glsl')
glslc_args = ['-c', shader]
expected_error = [
shader, ":2: error: '#pragma': invalid stage for 'shader_stage' "
"#pragma: 'unknown'\n",
shader, ":42: error: '#pragma': conflicting stages for 'shader_stage' "
"#pragma: 'google' (was 'unknown' at ", shader, ':2)\n',
shader, ":100: error: '#pragma': conflicting stages for 'shader_stage' "
"#pragma: 'elgoog' (was 'unknown' at ", shader, ':2)\n']
@inside_glslc_testsuite('PragmaShaderStage')
class TestPSSWithPoundLine150(expect.ErrorMessage):
"""Tests that #pragma shader_stage() works with #line.
For older desktop versions, a #line directive specify the line number of
the #line directive, not the next line.
"""
shader = FileShader(
"""#version 150
#pragma shader_stage(unknown)
#line 42
#pragma shader_stage(google)
#line 100
#pragma shader_stage(elgoog)
void main() {
gl_Position = vec4(1.);
}
""", '.glsl')
glslc_args = ['-c', shader]
expected_error = [
shader, ":2: error: '#pragma': invalid stage for 'shader_stage' "
"#pragma: 'unknown'\n",
shader, ":43: error: '#pragma': conflicting stages for 'shader_stage' "
"#pragma: 'google' (was 'unknown' at ", shader, ':2)\n',
shader, ":101: error: '#pragma': conflicting stages for 'shader_stage' "
"#pragma: 'elgoog' (was 'unknown' at ", shader, ':2)\n']
@inside_glslc_testsuite('PragmaShaderStage')
class ErrorBeforePragma(expect.ErrorMessage):
"""Tests that errors before pragmas are emitted."""
shader = FileShader(
"""#version 310 es
#something
#pragma shader_stage(vertex)
void main() {
gl_Position = vec4(1.);
}
""", '.glsl')
glslc_args = ['-c', shader]
expected_error = [shader, ':2: error: \'#\' : invalid directive:',
' something\n'
'1 error generated.\n']
@inside_glslc_testsuite('PragmaShaderStage')
class TestPSSfromIncludedFile(expect.ValidObjectFile):
"""Tests that #pragma shader_stage() from included files works."""
environment = Directory('.', [
File('a.glsl', '#version 140\n#include "b.glsl"\n'
'void main() { gl_Position = vec4(1.); }\n'),
File('b.glsl', '#pragma shader_stage(vertex)')])
glslc_args = ['-c', 'a.glsl']
@inside_glslc_testsuite('PragmaShaderStage')
class TestConflictingPSSfromIncludingAndIncludedFile(expect.ErrorMessage):
"""Tests that conflicting #pragma shader_stage() from including and
included files results in an error with the correct location spec."""
environment = Directory('.', [
File('a.vert',
'#version 140\n'
'#pragma shader_stage(fragment)\n'
'void main() { gl_Position = vec4(1.); }\n'
'#include "b.glsl"\n'),
File('b.glsl', '#pragma shader_stage(vertex)')])
glslc_args = ['-c', 'a.vert']
expected_error = [
"b.glsl:1: error: '#pragma': conflicting stages for 'shader_stage' "
"#pragma: 'vertex' (was 'fragment' at a.vert:2)\n"]
@inside_glslc_testsuite('PragmaShaderStage')
class TestPSSWithFileNameBasedPoundLine(expect.ErrorMessage):
"""Tests that #pragma shader_stage() works with filename-based #line."""
shader = FileShader(
"""#version 310 es
#pragma shader_stage(unknown)
#line 42 "abc"
#pragma shader_stage(google)
#line 100 "def"
#pragma shader_stage(elgoog)
void main() {
gl_Position = vec4(1.);
}
""", '.glsl')
glslc_args = ['-c', shader]
expected_error = [
shader, ":2: error: '#pragma': invalid stage for 'shader_stage' "
"#pragma: 'unknown'\n",
"abc:42: error: '#pragma': conflicting stages for 'shader_stage' "
"#pragma: 'google' (was 'unknown' at ", shader, ':2)\n',
"def:100: error: '#pragma': conflicting stages for 'shader_stage' "
"#pragma: 'elgoog' (was 'unknown' at ", shader, ':2)\n']

View File

@@ -0,0 +1,37 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import expect
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader, StdinShader
@inside_glslc_testsuite('StdInOut')
class VerifyStdinWorks(expect.ValidObjectFile):
"""Tests glslc accepts vertex shader extension (.vert)."""
shader = StdinShader('#version 140\nvoid main() { }')
glslc_args = ['-c', '-fshader-stage=vertex', shader]
@inside_glslc_testsuite('StdInOut')
class VerifyStdoutWorks(
expect.ReturnCodeIsZero, expect.StdoutMatch, expect.StderrMatch):
shader = FileShader('#version 140\nvoid main() {}', '.vert')
glslc_args = [shader, '-o', '-']
# We expect SOME stdout, we just do not care what.
expected_stdout = True
expected_stderr = ''

View File

@@ -0,0 +1,221 @@
# Copyright 2015 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os.path
import expect
from environment import File, Directory
from glslc_test_framework import inside_glslc_testsuite
from placeholder import FileShader
MINIMAL_SHADER = '#version 140\nvoid main() {}'
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirNoArg(expect.ErrorMessage):
"""Tests -working-directory. Behavior cribbed from Clang."""
glslc_args = ['-working-directory']
expected_error = [
"glslc: error: argument to '-working-directory' is missing "
'(expected 1 value)\n',
'glslc: error: no input files\n']
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirEqNoArg(expect.ErrorMessage):
"""Tests -working-directory=<empty>. Behavior cribbed from Clang."""
glslc_args = ['-working-directory=']
expected_error = ['glslc: error: no input files\n']
EMPTY_SHADER_IN_SUBDIR = Directory(
'subdir', [File('shader.vert', MINIMAL_SHADER)])
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirEqNoArgCompileFile(expect.ValidNamedObjectFile):
"""Tests -working-directory=<empty> when compiling input file."""
environment = Directory('.', [EMPTY_SHADER_IN_SUBDIR])
glslc_args = ['-c', '-working-directory=', 'subdir/shader.vert']
# Output file should be generated into subdir/.
expected_object_filenames = ('subdir/shader.vert.spv',)
# @inside_glslc_testsuite('WorkDir')
class TestMultipleWorkDir(expect.ValidNamedObjectFile):
"""Tests that if there are multiple -working-directory=<dir> specified,
only the last one takes effect."""
environment = Directory('.', [EMPTY_SHADER_IN_SUBDIR])
glslc_args = ['-c', '-working-directory=i-dont-exist',
'-working-directory', 'i-think/me-neither',
'-working-directory=subdir', 'shader.vert']
# Output file should be generated into subdir/.
expected_object_filenames = ('subdir/shader.vert.spv',)
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirPosition(expect.ValidNamedObjectFile):
"""Tests that -working-directory=<dir> affects all files before and after
it on the command line."""
environment = Directory('subdir', [
File('shader.vert', MINIMAL_SHADER),
File('cool.frag', MINIMAL_SHADER),
File('bla.vert', MINIMAL_SHADER)
])
glslc_args = ['-c', 'shader.vert', 'bla.vert',
'-working-directory=subdir', 'cool.frag']
# Output file should be generated into subdir/.
expected_object_filenames = (
'subdir/shader.vert.spv', 'subdir/cool.frag.spv', 'subdir/bla.vert.spv')
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirDeepDir(expect.ValidNamedObjectFile):
"""Tests that -working-directory=<dir> works with directory hierarchies."""
environment = Directory('subdir', [
Directory('subsubdir', [
File('one.vert', MINIMAL_SHADER),
File('two.frag', MINIMAL_SHADER)
]),
File('zero.vert', MINIMAL_SHADER)
])
glslc_args = ['-c', 'zero.vert', 'subsubdir/one.vert',
'subsubdir/two.frag', '-working-directory=subdir']
# Output file should be generated into subdir/.
expected_object_filenames = (
'subdir/zero.vert.spv', 'subdir/subsubdir/one.vert.spv',
'subdir/subsubdir/two.frag.spv')
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirCompileFile(expect.ValidNamedObjectFile):
"""Tests -working-directory=<dir> when compiling input file."""
environment = Directory('.', [EMPTY_SHADER_IN_SUBDIR])
glslc_args = ['-c', '-working-directory=subdir', 'shader.vert']
# Output file should be generated into subdir/.
expected_object_filenames = ('subdir/shader.vert.spv',)
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirCompileFileOutput(expect.ValidNamedObjectFile):
"""Tests -working-directory=<dir> when compiling input file and specifying
output filename."""
environment = Directory('.', [
Directory('subdir', [
Directory('bin', []),
File('shader.vert', MINIMAL_SHADER)
])
])
glslc_args = ['-c', '-o', 'bin/spv', '-working-directory=subdir',
'shader.vert']
# Output file should be generated into subdir/bin/.
expected_object_filenames = ('subdir/bin/spv',)
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirArgNoEq(expect.ValidNamedObjectFile):
"""Tests -working-directory <dir>."""
environment = Directory('.', [EMPTY_SHADER_IN_SUBDIR])
glslc_args = ['-working-directory', 'subdir', 'shader.vert']
expected_object_filenames = ('a.spv',)
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirEqInArg(expect.ValidNamedObjectFile):
"""Tests -working-directory=<dir-with-equal-sign-inside>."""
environment = Directory('.', [
Directory('=subdir', [File('shader.vert', MINIMAL_SHADER)]),
])
glslc_args = ['-working-directory==subdir', 'shader.vert']
expected_object_filenames = ('a.spv',)
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirCompileFileAbsolutePath(expect.ValidObjectFile):
"""Tests -working-directory=<dir> when compiling input file with absolute
path."""
shader = FileShader(MINIMAL_SHADER, '.vert')
glslc_args = ['-c', '-working-directory=subdir', shader]
# The -working-directory flag should not affect the placement of the link file.
# The following tests ensure that.
class WorkDirDoesntAffectLinkedFile(expect.ValidNamedObjectFile):
"""A base class for tests asserting that -working-directory has no impact
on the location of the output link file.
"""
environment = Directory('.', [
Directory('subdir', [
File('shader.vert', MINIMAL_SHADER),
# Try to fake glslc into putting the linked file here, though it
# shouldn't (because -working-directory doesn't impact -o).
Directory('bin', [])]),
File('shader.vert', "fake file, doesn't compile."),
Directory('bin', [])])
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirLinkFileDefaultLocation(WorkDirDoesntAffectLinkedFile):
"""Tests that -working-directory doesn't impact the default link-file
location.
"""
glslc_args = ['-working-directory=subdir', 'shader.vert']
expected_object_filenames = ('a.spv',)
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirLinkFileExplicit(WorkDirDoesntAffectLinkedFile):
"""Tests that -working-directory doesn't impact the named link-file
location.
"""
glslc_args = ['-o', 'b.spv', '-working-directory=subdir', 'shader.vert']
expected_object_filenames = ('b.spv',)
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirLinkFileInSubdir(WorkDirDoesntAffectLinkedFile):
"""Tests that -working-directory doesn't impact the link-file sent into an
existing subdirectory.
"""
glslc_args = ['-o', 'bin/spv', '-working-directory=subdir', 'shader.vert']
expected_object_filenames = ('bin/spv',)
# @inside_glslc_testsuite('WorkDir')
class TestWorkDirLinkFileInvalidPath(expect.ErrorMessage):
"""Tests that -working-directory doesn't impact the error generated for an
invalid -o path.
"""
environment = Directory('.', [
Directory('subdir', [
File('shader.vert', MINIMAL_SHADER),
Directory('missing', [])]), # Present here, but missing in parent.
File('shader.vert', "fake file, doesn't compile.")])
glslc_args = [
'-o', 'missing/spv', '-working-directory=subdir', 'shader.vert']
expected_error = ['glslc: error: cannot open output file: ',
"'missing/spv': No such file or directory\n"]

View File

@@ -0,0 +1,60 @@
#!/bin/bash
# Copyright (C) 2017-2022 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Android Build Script.
# Fail on any error.
set -e
. /bin/using.sh # Declare the bash `using` function for configuring toolchains.
# Display commands being run.
set -x
using cmake-3.17.2
using ninja-1.10.0
using ndk-r25c # Sets ANDROID_NDK_HOME, pointing at the NDK's root dir
cd $ROOT_DIR
./utils/git-sync-deps
mkdir build
cd $ROOT_DIR/build
# Invoke the build.
BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
echo $(date): Starting build...
cmake \
-GNinja \
-DCMAKE_MAKE_PROGRAM=ninja \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_ABI="$TARGET_ARCH" \
-DSHADERC_SKIP_TESTS=ON \
-DSPIRV_SKIP_TESTS=ON \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \
-DANDROID_NDK=$ANDROID_NDK_HOME ..
echo $(date): Build glslang library...
ninja glslang
echo $(date): Build everything...
ninja
echo $(date): Check Shaderc for copyright notices...
ninja check-copyright
echo $(date): Build completed.

View File

@@ -0,0 +1,38 @@
#!/bin/bash
# Copyright (C) 2020-2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Linux Build Script.
set -e # Fail on any error.
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd )"
ROOT_DIR="$( cd "${SCRIPT_DIR}/../.." >/dev/null 2>&1 && pwd )"
TARGET_ARCH="$1"
# --privileged is required for some sanitizer builds, as they seem to require
# PTRACE privileges
docker run --rm -i \
--privileged \
--volume "${ROOT_DIR}:${ROOT_DIR}" \
--volume "${KOKORO_ARTIFACTS_DIR}:${KOKORO_ARTIFACTS_DIR}" \
--workdir "${ROOT_DIR}" \
--env ROOT_DIR="${ROOT_DIR}" \
--env SCRIPT_DIR="${SCRIPT_DIR}" \
--env TARGET_ARCH="${TARGET_ARCH}" \
--env KOKORO_ARTIFACTS_DIR="${KOKORO_ARTIFACTS_DIR}" \
--entrypoint "${SCRIPT_DIR}/build-docker.sh" \
"gcr.io/shaderc-build/radial-build:latest"

View File

@@ -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"

View File

@@ -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

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

Some files were not shown because too many files have changed in this diff Show More