Add shaderc v2022.1 for GLSL to SPIR-V shaders

Ran ./utils/git-sync-deps already, removed some unneeded files
This commit is contained in:
Benau 2022-03-17 12:21:20 +08:00
parent c19327aaeb
commit bc1d885bd1
1342 changed files with 479529 additions and 1 deletions

View File

@ -242,6 +242,33 @@ else()
endif()
if(NOT SERVER_ONLY)
find_library(SHADERC_LIBRARY NAMES shaderc_shared libshaderc_shared)
find_path(SHADERC_INCLUDEDIR NAMES shaderc/shaderc.hpp PATHS)
if (NOT SHADERC_LIBRARY OR NOT SHADERC_INCLUDEDIR)
set(SHADERC_SKIP_INSTALL ON CACHE INTERNAL "Skip installation" FORCE)
set(SHADERC_SKIP_TESTS ON CACHE INTERNAL "Skip building tests" FORCE)
set(SHADERC_SKIP_EXAMPLES ON CACHE INTERNAL "Skip building examples" FORCE)
set(SHADERC_SKIP_COPYRIGHT_CHECK ON CACHE INTERNAL "Skip copyright check" FORCE)
set(SPIRV_HEADERS_SKIP_INSTALL ON CACHE INTERNAL "Skip install" FORCE)
set(SPIRV_HEADERS_SKIP_EXAMPLES ON CACHE INTERNAL "Skip building examples" FORCE)
set(SKIP_SPIRV_TOOLS_INSTALL ON CACHE INTERNAL "Skip installation" FORCE)
set(SPIRV_SKIP_TESTS ON CACHE INTERNAL "Skip tests" FORCE)
set(SPIRV_SKIP_EXECUTABLES ON CACHE INTERNAL "Skip executables" FORCE)
set(ENABLE_GLSLANG_BINARIES OFF CACHE INTERNAL "Builds glslangValidator and spirv-remap" FORCE)
set(ENABLE_CTEST OFF CACHE INTERNAL "Enable ctest" FORCE)
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/shaderc")
include_directories(BEFORE "${PROJECT_SOURCE_DIR}/lib/shaderc/libshaderc/include")
SET(SHADERC_LIBRARY shaderc)
message(STATUS "System shaderc not found, use the bundled one.")
else()
include_directories("${SHADERC_INCLUDEDIR}")
MESSAGE(STATUS "Use system shaderc: ${SHADERC_LIBRARY}")
endif()
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/graphics_engine")
include_directories(BEFORE "${PROJECT_SOURCE_DIR}/lib/graphics_engine/include")
endif()
@ -739,7 +766,8 @@ if(NOT SERVER_ONLY)
graphics_utils
graphics_engine
${SDL2_LIBRARY}
tinygettext)
tinygettext
${SHADERC_LIBRARY})
endif()
if(UNIX AND NOT APPLE)

View File

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

9
lib/shaderc/AUTHORS 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.

76
lib/shaderc/Android.mk Normal file
View File

@ -0,0 +1,76 @@
# 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 \
libOGLCompiler.a \
libOSDependent.a \
libshaderc.a \
libshaderc_util.a \
libSPIRV.a \
libHLSL.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
$(NDK_APP_LIBS_OUT)/../include/shaderc/$(1) : \
$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/$(1)
$(call host-mkdir,$(NDK_APP_LIBS_OUT)/../include/shaderc)
$(call host-cp,$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/$(1) \
,$(NDK_APP_LIBS_OUT)/../include/shaderc/$(1))
endef
define gen_libshaderc
$(1)/combine.ar: $(addprefix $(1)/, $(ALL_LIBS))
@echo "create libshaderc_combined.a" > $(1)/combine.ar
$(foreach lib,$(ALL_LIBS),
@echo "addlib $(lib)" >> $(1)/combine.ar
)
@echo "save" >> $(1)/combine.ar
@echo "end" >> $(1)/combine.ar
$(1)/libshaderc_combined.a: $(addprefix $(1)/, $(ALL_LIBS)) $(1)/combine.ar
@echo "[$(TARGET_ARCH_ABI)] Combine: libshaderc_combined.a <= $(ALL_LIBS)"
@cd $(1) && $(TARGET_AR) -M < combine.ar && cd $(ROOT_SHADERC_PATH)
@$(TARGET_STRIP) --strip-debug $(1)/libshaderc_combined.a
$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a: \
$(1)/libshaderc_combined.a
$(call host-mkdir,$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI))
$(call host-cp,$(1)/libshaderc_combined.a \
,$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a)
ifndef HEADER_TARGET
HEADER_TARGET=1
$(eval $(foreach H,$(SHADERC_HEADERS),$(call gen_libshaderc_header,$(H))))
endif
libshaderc_combined: \
$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a
endef
libshaderc_combined: $(SHADERC_HEADERS_IN_OUT_DIR)
$(eval $(call gen_libshaderc,$(TARGET_OUT)))

101
lib/shaderc/BUILD.gn 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" ]
}
}

304
lib/shaderc/CHANGES Normal file
View File

@ -0,0 +1,304 @@
Revision history for Shaderc
v2022.1 2022-01-27
- 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

165
lib/shaderc/CMakeLists.txt Normal file
View File

@ -0,0 +1,165 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 2.8.12)
project(shaderc)
enable_testing()
if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
message(STATUS "No build type selected, default to Debug")
set(CMAKE_BUILD_TYPE "Debug")
endif()
message(STATUS "Shaderc: build type is \"${CMAKE_BUILD_TYPE}\".")
option(SHADERC_ENABLE_WGSL_OUTPUT "Enable WGSL output" OFF)
option(SHADERC_SKIP_INSTALL "Skip installation" ${SHADERC_SKIP_INSTALL})
if(NOT ${SHADERC_SKIP_INSTALL})
set(SHADERC_ENABLE_INSTALL ON)
endif()
option(SHADERC_SKIP_TESTS "Skip building tests" ${SHADERC_SKIP_TESTS})
if(NOT ${SHADERC_SKIP_TESTS})
set(SHADERC_ENABLE_TESTS ON)
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 11)
include(GNUInstallDirs)
include(cmake/setup_build.cmake)
include(cmake/utils.cmake)
include(CheckCXXCompilerFlag)
set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS ${DISABLE_EXCEPTIONS} CACHE BOOL "Coupling SPIRV-Cross exception conversion to DISABLE_EXCEPTIONS" FORCE)
if(DISABLE_EXCEPTIONS)
# Need to set additional values here, since some of the wrapped code occurs in
# .h/.hpp files, so maybe included outside of the library.
add_definitions(-DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS)
endif()
# These flags are not supported on Windows and some older version of GCC
# that our bots use.
# Warning about implicit fallthrough in switch blocks
check_cxx_compiler_flag(-Wimplicit-fallthrough COMPILER_SUPPORTS_FALLTHROUGH_WARNING)
if (COMPILER_SUPPORTS_FALLTHROUGH_WARNING)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wimplicit-fallthrough")
endif()
# Warning about extra semi-colons
check_cxx_compiler_flag(-Wextra-semi COMPILER_SUPPORTS_EXTRA_SEMI_WARNING)
if (COMPILER_SUPPORTS_EXTRA_SEMI_WARNING)
add_compile_options("-Wextra-semi")
endif()
find_host_package(PythonInterp 3 REQUIRED)
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"
${SHADERC_ENABLE_SHARED_CRT})
if (NOT SHADERC_ENABLE_SHARED_CRT)
# Link executables statically by replacing /MD with /MT everywhere.
foreach(flag_var
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if(${flag_var} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endif(${flag_var} MATCHES "/MD")
endforeach(flag_var)
endif(NOT SHADERC_ENABLE_SHARED_CRT)
endif(MSVC)
# Configure subdirectories.
# We depend on these for later projects, so they should come first.
add_subdirectory(third_party)
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)
define_pkg_config_file(shaderc_static "-lshaderc ${EXTRA_STATIC_PKGCONFIG_LIBS} -lshaderc_util")
define_pkg_config_file(shaderc_combined -lshaderc_combined)

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
lib/shaderc/CONTRIBUTORS 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>

33
lib/shaderc/DEPS Normal file
View File

@ -0,0 +1,33 @@
use_relative_paths = True
vars = {
'google_git': 'https://github.com/google',
'khronos_git': 'https://github.com/KhronosGroup',
'effcee_revision' : '2ec8f8738118cc483b67c04a759fee53496c5659',
'glslang_revision': 'c34bb3b6c55f6ab084124ad964be95a699700d34',
'googletest_revision': '389cb68b87193358358ae87cc56d257fd0d80189',
're2_revision': '7107ebc4fbf7205151d8d2a57b2fc6e7853125d4',
'spirv_headers_revision': 'b42ba6d92faf6b4938e6f22ddd186dbdacc98d78',
'spirv_tools_revision': 'b846f8f1dc2d79f2b5ce27d5ad901f885da1cf82',
}
deps = {
'third_party/effcee': Var('google_git') + '/effcee.git@' +
Var('effcee_revision'),
'third_party/googletest': Var('google_git') + '/googletest.git@' +
Var('googletest_revision'),
'third_party/glslang': Var('khronos_git') + '/glslang.git@' +
Var('glslang_revision'),
'third_party/re2': Var('google_git') + '/re2.git@' +
Var('re2_revision'),
'third_party/spirv-headers': Var('khronos_git') + '/SPIRV-Headers.git@' +
Var('spirv_headers_revision'),
'third_party/spirv-tools': Var('khronos_git') + '/SPIRV-Tools.git@' +
Var('spirv_tools_revision'),
}

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
lib/shaderc/Dockerfile 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
lib/shaderc/LICENSE 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.

262
lib/shaderc/README.md Normal file
View File

@ -0,0 +1,262 @@
# 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 r18b.
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.
Shaderc depends on the [Google Test](https://github.com/google/googletest)
testing framework.
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:
(Skip building threaded unit tests due to
[Googletest bug 606](https://github.com/google/googletest/issues/606))
```sh
cd $BUILD_DIR
cmake -GNinja -DCMAKE_BUILD_TYPE={Debug|Release|RelWithDebInfo} $SOURCE_DIR \
-DCMAKE_TOOLCHAIN_FILE=$SOURCE_DIR/cmake/linux-mingw-toolchain.cmake \
-Dgtest_disable_pthreads=ON
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:
- [CMake](http://www.cmake.org/): for generating compilation targets.
- [Python 3](http://www.python.org/): for utility scripts and running the test suite.
On Linux, the following tools should be installed:
- [`gcov`](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html): for testing code
coverage, provided by the `gcc` package on Ubuntu.
- [`lcov`](http://ltp.sourceforge.net/coverage/lcov.php): a graphical frontend
for `gcov`, provided by the `lcov` package on Ubuntu.
- [`genhtml`](http://linux.die.net/man/1/genhtml): for creating reports in html
format from `lcov` output, provided by the `lcov` package on Ubuntu.
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.
On Windows, the following tools should be installed and available on your path:
- Visual Studio 2015 or later. Previous versions of Visual Studio may work but
are untested and unsupported.
- Git - including the associated tools, Bash, `diff`.
Optionally, the following tools may be installed on any OS:
- [`asciidoctor`](http://asciidoctor.org/): for generating 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).
## Test coverage
On Linux, you can obtain test coverage as follows:
```sh
cd $BUILD_DIR
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DENABLE_CODE_COVERAGE=ON $SOURCE_DIR
ninja
ninja report-coverage
```
Then the coverage report can be found under the `$BUILD_DIR/coverage-report`
directory.
## Bindings
Bindings are maintained by third parties, may contain content
offered under a different license, and may reference or contain
older versions of Shaderc and its dependencies.
* **Python:** [pyshaderc][pyshaderc]
* **Rust:** [shaderc-rs][shaderc-rs]
* **Go:** [gshaderc][gshaderc]
* **.NET:** [shaderc.net][shadercdotnet]
* **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,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,141 @@
# 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(PythonInterp 3 REQUIRED)
endif()
option(ENABLE_CODE_COVERAGE "Enable collecting code coverage." OFF)
if (ENABLE_CODE_COVERAGE)
message(STATUS "Shaderc: code coverage report is on.")
if (NOT UNIX)
message(FATAL_ERROR "Code coverage on non-UNIX system not supported yet.")
endif()
if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
message(FATAL_ERROR "Code coverage with non-Debug build can be misleading.")
endif()
find_program(LCOV_EXE NAMES lcov)
if (NOT LCOV_EXE)
message(FATAL_ERROR "lcov was not found")
endif()
find_program(GENHTML_EXE NAMES genhtml)
if (NOT GENHTML_EXE)
message(FATAL_ERROR "genhtml was not found")
endif()
set(LCOV_BASE_DIR ${CMAKE_BINARY_DIR})
set(LCOV_INFO_FILE ${LCOV_BASE_DIR}/lcov.info)
set(COVERAGE_STAT_HTML_DIR ${LCOV_BASE_DIR}/coverage-report)
add_custom_target(clean-coverage
# Remove all gcov .gcda files in the directory recursively.
COMMAND ${LCOV_EXE} --directory . --zerocounters -q
# Remove all lcov .info files.
COMMAND ${CMAKE_COMMAND} -E remove ${LCOV_INFO_FILE}
# Remove all html report files.
COMMAND ${CMAKE_COMMAND} -E remove_directory ${COVERAGE_STAT_HTML_DIR}
# TODO(antiagainst): the following two commands are here to remedy the
# problem of "reached unexpected end of file" experienced by lcov.
# The symptom is that some .gcno files are wrong after code change and
# recompiling. We don't know the exact reason yet. Figure it out.
# Remove all .gcno files in the directory recursively.
COMMAND ${PYTHON_EXECUTABLE}
${shaderc_SOURCE_DIR}/utils/remove-file-by-suffix.py . ".gcno"
# .gcno files are not tracked by CMake. So no recompiling is triggered
# even if they are missing. Unfortunately, we just removed all of them
# in the above.
COMMAND ${CMAKE_COMMAND} --build . --target clean
WORKING_DIRECTORY ${LCOV_BASE_DIR}
COMMENT "Clean coverage files"
)
add_custom_target(report-coverage
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}
# Run all tests.
COMMAND ctest --output-on-failure
# Collect coverage data from gcov .gcda files.
COMMAND ${LCOV_EXE} --directory . --capture -o ${LCOV_INFO_FILE}
# Remove coverage info for system header files.
COMMAND ${LCOV_EXE}
--remove ${LCOV_INFO_FILE} '/usr/include/*' -o ${LCOV_INFO_FILE}
# Remove coverage info for external and third_party code.
COMMAND ${LCOV_EXE}
--remove ${LCOV_INFO_FILE} '${shaderc_SOURCE_DIR}/ext/*'
-o ${LCOV_INFO_FILE}
COMMAND ${LCOV_EXE}
--remove ${LCOV_INFO_FILE} '${shaderc_SOURCE_DIR}/third_party/*'
-o ${LCOV_INFO_FILE}
# Remove coverage info for tests.
COMMAND ${LCOV_EXE}
--remove ${LCOV_INFO_FILE} '*_test.cc' -o ${LCOV_INFO_FILE}
# Generate html report file.
COMMAND ${GENHTML_EXE}
${LCOV_INFO_FILE} -t "Coverage Report" -o ${COVERAGE_STAT_HTML_DIR}
DEPENDS clean-coverage
WORKING_DIRECTORY ${LCOV_BASE_DIR}
COMMENT "Collect and analyze coverage data"
)
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)

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}

View File

@ -0,0 +1,223 @@
# 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}")
target_compile_options(${TARGET} PRIVATE -std=c++11)
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)
set(libname
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${new_target}${CMAKE_STATIC_LIBRARY_SUFFIX})
if (MSVC)
string(REPLACE ";" ">;$<TARGET_FILE:" temp_string "${all_libs}")
set(lib_target_list "$<TARGET_FILE:${temp_string}>")
add_custom_command(OUTPUT ${libname}
DEPENDS ${all_libs}
COMMAND lib.exe ${lib_target_list} /OUT:${libname} /NOLOGO)
elseif(APPLE)
string(REPLACE ";" ">;$<TARGET_FILE:" temp_string "${all_libs}")
set(lib_target_list "$<TARGET_FILE:${temp_string}>")
add_custom_command(OUTPUT ${libname}
DEPENDS ${all_libs}
COMMAND libtool -static -o ${libname} ${lib_target_list})
else()
string(REPLACE ";" "> \naddlib $<TARGET_FILE:" temp_string "${all_libs}")
set(start_of_file
"create ${libname}\naddlib $<TARGET_FILE:${temp_string}>")
set(build_script_file "${start_of_file}\nsave\nend\n")
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${new_target}.ar"
CONTENT ${build_script_file}
CONDITION 1)
add_custom_command(OUTPUT ${libname}
DEPENDS ${all_libs}
COMMAND ${CMAKE_AR} -M < ${new_target}.ar)
endif()
add_custom_target(${new_target}_genfile ALL
DEPENDS ${libname})
# CMake needs to be able to see this as another normal library,
# so import the newly created library as an imported library,
# and set up the dependencies on the custom target.
add_library(${new_target} STATIC IMPORTED)
set_target_properties(${new_target}
PROPERTIES IMPORTED_LOCATION ${libname})
add_dependencies(${new_target} ${new_target}_genfile)
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
lib/shaderc/downloads.md 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 2017](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2017_release.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_linux_clang_release.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_macos_clang_release.html) |
| [MSVC 2015](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2015_release.html) | [gcc](https://storage.googleapis.com/shaderc/badges/build_link_linux_gcc_release.html) | |
## Debug
| Windows | Linux | MacOS |
| --- | --- | --- |
| [MSVC 2017](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2017_debug.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_linux_clang_debug.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_macos_clang_debug.html) |
| | [gcc](https://storage.googleapis.com/shaderc/badges/build_link_linux_gcc_debug.html) | |

View File

@ -0,0 +1,29 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cc .cpp .cxx
LOCAL_MODULE:=shaderc
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/include
LOCAL_SRC_FILES:=src/shaderc.cc
# The Shaderc third_party/Android.mk deduces SPVHEADERS_LOCAL_PATH,
# or delegates that responsibility to SPIRV-Tools' Android.mk.
LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include $(SPVHEADERS_LOCAL_PATH)/include
LOCAL_STATIC_LIBRARIES:=shaderc_util SPIRV-Tools-opt
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -DENABLE_HLSL=1
LOCAL_EXPORT_CPPFLAGS:=-std=c++11
LOCAL_EXPORT_LDFLAGS:=-latomic
include $(BUILD_STATIC_LIBRARY)

View File

@ -0,0 +1,131 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
project(libshaderc)
# Even though shaderc.hpp is a headers-only library, adding
# a dependency here will force clients of the library to rebuild
# when it changes.
set(SHADERC_SOURCES
include/shaderc/shaderc.h
include/shaderc/shaderc.hpp
src/shaderc.cc
src/shaderc_private.h
)
add_library(shaderc STATIC ${SHADERC_SOURCES})
shaderc_default_compile_options(shaderc)
target_include_directories(shaderc
PUBLIC include
PRIVATE ${glslang_SOURCE_DIR}
${SPIRV-Headers_SOURCE_DIR}/include)
add_library(shaderc_shared SHARED ${SHADERC_SOURCES})
shaderc_default_compile_options(shaderc_shared)
target_include_directories(shaderc_shared
PUBLIC include
PRIVATE ${glslang_SOURCE_DIR}
${SPIRV-Headers_SOURCE_DIR}/include)
target_compile_definitions(shaderc_shared
PRIVATE SHADERC_IMPLEMENTATION
PUBLIC SHADERC_SHAREDLIB
)
set_target_properties(shaderc_shared PROPERTIES SOVERSION 1)
if(SHADERC_ENABLE_INSTALL)
install(
FILES
include/shaderc/env.h
include/shaderc/status.h
include/shaderc/visibility.h
include/shaderc/shaderc.h
include/shaderc/shaderc.hpp
DESTINATION
${CMAKE_INSTALL_INCLUDEDIR}/shaderc)
install(TARGETS shaderc shaderc_shared
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif(SHADERC_ENABLE_INSTALL)
find_package(Threads)
set(SHADERC_LIBS
glslang OSDependent OGLCompiler glslang ${CMAKE_THREAD_LIBS_INIT}
shaderc_util
SPIRV # from glslang
SPIRV-Tools
)
target_link_libraries(shaderc PRIVATE ${SHADERC_LIBS})
target_link_libraries(shaderc_shared PRIVATE ${SHADERC_LIBS})
shaderc_add_tests(
TEST_PREFIX shaderc
LINK_LIBS shaderc
INCLUDE_DIRS include ${shaderc_SOURCE_DIR}/libshaderc_util/include ${glslang_SOURCE_DIR}
${spirv-tools_SOURCE_DIR}/include
${SPIRV-Headers_SOURCE_DIR}/include
TEST_NAMES
shaderc
shaderc_cpp
shaderc_private)
shaderc_add_tests(
TEST_PREFIX shaderc_shared
LINK_LIBS shaderc_shared SPIRV-Tools
INCLUDE_DIRS include ${shaderc_SOURCE_DIR}/libshaderc_util/include ${glslang_SOURCE_DIR}
${spirv-tools_SOURCE_DIR}/include
${SPIRV-Headers_SOURCE_DIR}/include
TEST_NAMES
shaderc
shaderc_cpp
shaderc_private)
shaderc_combine_static_lib(shaderc_combined shaderc)
if(SHADERC_ENABLE_INSTALL)
# Since shaderc_combined is defined as an imported library, we cannot use the
# install() directive to install it. Install it like a normal file.
get_target_property(generated_location shaderc_combined LOCATION)
string(REGEX MATCH "Visual Studio .*" vs_generator "${CMAKE_GENERATOR}")
if (NOT "${vs_generator}" STREQUAL "")
# With Visual Studio generators, the LOCATION property is not properly
# expanded according to the current build configuration. We need to work
# around this problem by manually substitution.
string(REPLACE "$(Configuration)" "\${CMAKE_INSTALL_CONFIG_NAME}"
install_location "${generated_location}")
install(FILES ${install_location} DESTINATION ${CMAKE_INSTALL_LIBDIR})
else()
install(FILES ${generated_location} DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
endif(SHADERC_ENABLE_INSTALL)
shaderc_add_tests(
TEST_PREFIX shaderc_combined
LINK_LIBS shaderc_combined ${CMAKE_THREAD_LIBS_INIT}
INCLUDE_DIRS include ${shaderc_SOURCE_DIR}/libshaderc_util/include ${glslang_SOURCE_DIR}
${spirv-tools_SOURCE_DIR}/include
${SPIRV-Headers_SOURCE_DIR}/include
TEST_NAMES
shaderc
shaderc_cpp)
if(${SHADERC_ENABLE_TESTS})
add_executable(shaderc_c_smoke_test ./src/shaderc_c_smoke_test.c)
shaderc_default_c_compile_options(shaderc_c_smoke_test)
target_include_directories(shaderc_c_smoke_test PUBLIC ${shaderc_SOURCE_DIR}/libshaderc_util/include)
target_link_libraries(shaderc_c_smoke_test PRIVATE shaderc)
add_test(NAME shaderc_c_smoke_test COMMAND shaderc_c_smoke_test)
endif()

View File

@ -0,0 +1,52 @@
# libshaderc
A library for compiling shader strings into SPIR-V.
## Build Artifacts
There are two main shaderc libraries that are created during a CMake
compilation. The first is `libshaderc`, which is a static library
containing just the functionality exposed by libshaderc. It depends
on other compilation targets `glslang`, `OSDependent`, `OGLCompiler`,
`shaderc_util`, `SPIRV`, `HLSL`, `SPIRV-Tools`, and `SPIRV-Tools-opt`.
The other is `libshaderc_combined`, which is a static library containing
libshaderc and all of its dependencies.
## Integrating libshaderc
There are several ways of integrating libshaderc into external projects.
1. If the external project uses CMake, then `shaderc/CMakeLists.txt` can be
included into the external project's CMake configuration and shaderc can be used
as a link target.
This is the simplest way to use libshaderc in an external project.
2. If the external project uses CMake and is building for Linux or Android,
`target_link_libraries(shaderc_combined)` can instead be specified. This is
functionally identical to the previous option.
3. If the external project does not use CMake, then the external project can
instead directly use the generated libraries. `shaderc/libshaderc/include`
should be added to the include path, and
`build/libshaderc/libshaderc_combined.a` should be linked. Note that on some
platforms `-lpthread` should also be specified.
4. If the external project does not use CMake and cannot use
`libshaderc_combined`, the following libraries or their platform-dependent
counterparts should be linked in the order specified.
* `build/libshaderc/libshaderc.a`
* `build/third_party/glslang/glslang/glslang.a`
* `build/third_party/glslang/glslang/OSDependent/{Platform}/libOSDependent.a`
* `build/third_party/glslang/OGLCompilersDLL/libOGLCompiler.a`
* `build/third_party/glslang/libglslang.a`
* `build/shaderc_util/libshaderc_util.a`
* `build/third_party/glslang/SPIRV/libSPIRV.a`
* `build/third_party/glslang/hlsl/libHLSL.a`
* `build/third_party/spirv-tools/libSPIRV-Tools-opt.a`
* `build/third_party/spirv-tools/libSPIRV-Tools.a`
5. If building for Android using the Android NDK, `shaderc/Android.mk` can be
included in the application's `Android.mk` and `LOCAL_STATIC_LIBRARIES:=shaderc`
can be specified. See `shaderc/android_test` for an example.

View File

@ -0,0 +1,72 @@
// Copyright 2018 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SHADERC_ENV_H_
#define SHADERC_ENV_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
shaderc_target_env_vulkan, // SPIR-V under Vulkan semantics
shaderc_target_env_opengl, // SPIR-V under OpenGL semantics
// NOTE: SPIR-V code generation is not supported for shaders under OpenGL
// compatibility profile.
shaderc_target_env_opengl_compat, // SPIR-V under OpenGL semantics,
// including compatibility profile
// functions
shaderc_target_env_webgpu, // Deprecated, SPIR-V under WebGPU
// semantics
shaderc_target_env_default = shaderc_target_env_vulkan
} shaderc_target_env;
typedef enum {
// For Vulkan, use Vulkan's mapping of version numbers to integers.
// See vulkan.h
shaderc_env_version_vulkan_1_0 = ((1u << 22)),
shaderc_env_version_vulkan_1_1 = ((1u << 22) | (1 << 12)),
shaderc_env_version_vulkan_1_2 = ((1u << 22) | (2 << 12)),
shaderc_env_version_vulkan_1_3 = ((1u << 22) | (3 << 12)),
// For OpenGL, use the number from #version in shaders.
// TODO(dneto): Currently no difference between OpenGL 4.5 and 4.6.
// See glslang/Standalone/Standalone.cpp
// TODO(dneto): Glslang doesn't accept a OpenGL client version of 460.
shaderc_env_version_opengl_4_5 = 450,
shaderc_env_version_webgpu, // Deprecated, WebGPU env never defined versions
} shaderc_env_version;
// The known versions of SPIR-V.
typedef enum {
// Use the values used for word 1 of a SPIR-V binary:
// - bits 24 to 31: zero
// - bits 16 to 23: major version number
// - bits 8 to 15: minor version number
// - bits 0 to 7: zero
shaderc_spirv_version_1_0 = 0x010000u,
shaderc_spirv_version_1_1 = 0x010100u,
shaderc_spirv_version_1_2 = 0x010200u,
shaderc_spirv_version_1_3 = 0x010300u,
shaderc_spirv_version_1_4 = 0x010400u,
shaderc_spirv_version_1_5 = 0x010500u,
shaderc_spirv_version_1_6 = 0x010600u
} shaderc_spirv_version;
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // SHADERC_ENV_H_

View File

@ -0,0 +1,585 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SHADERC_SHADERC_H_
#define SHADERC_SHADERC_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "shaderc/env.h"
#include "shaderc/status.h"
#include "shaderc/visibility.h"
// Source language kind.
typedef enum {
shaderc_source_language_glsl,
shaderc_source_language_hlsl,
} shaderc_source_language;
typedef enum {
// Forced shader kinds. These shader kinds force the compiler to compile the
// source code as the specified kind of shader.
shaderc_vertex_shader,
shaderc_fragment_shader,
shaderc_compute_shader,
shaderc_geometry_shader,
shaderc_tess_control_shader,
shaderc_tess_evaluation_shader,
shaderc_glsl_vertex_shader = shaderc_vertex_shader,
shaderc_glsl_fragment_shader = shaderc_fragment_shader,
shaderc_glsl_compute_shader = shaderc_compute_shader,
shaderc_glsl_geometry_shader = shaderc_geometry_shader,
shaderc_glsl_tess_control_shader = shaderc_tess_control_shader,
shaderc_glsl_tess_evaluation_shader = shaderc_tess_evaluation_shader,
// Deduce the shader kind from #pragma annotation in the source code. Compiler
// will emit error if #pragma annotation is not found.
shaderc_glsl_infer_from_source,
// Default shader kinds. Compiler will fall back to compile the source code as
// the specified kind of shader when #pragma annotation is not found in the
// source code.
shaderc_glsl_default_vertex_shader,
shaderc_glsl_default_fragment_shader,
shaderc_glsl_default_compute_shader,
shaderc_glsl_default_geometry_shader,
shaderc_glsl_default_tess_control_shader,
shaderc_glsl_default_tess_evaluation_shader,
shaderc_spirv_assembly,
shaderc_raygen_shader,
shaderc_anyhit_shader,
shaderc_closesthit_shader,
shaderc_miss_shader,
shaderc_intersection_shader,
shaderc_callable_shader,
shaderc_glsl_raygen_shader = shaderc_raygen_shader,
shaderc_glsl_anyhit_shader = shaderc_anyhit_shader,
shaderc_glsl_closesthit_shader = shaderc_closesthit_shader,
shaderc_glsl_miss_shader = shaderc_miss_shader,
shaderc_glsl_intersection_shader = shaderc_intersection_shader,
shaderc_glsl_callable_shader = shaderc_callable_shader,
shaderc_glsl_default_raygen_shader,
shaderc_glsl_default_anyhit_shader,
shaderc_glsl_default_closesthit_shader,
shaderc_glsl_default_miss_shader,
shaderc_glsl_default_intersection_shader,
shaderc_glsl_default_callable_shader,
shaderc_task_shader,
shaderc_mesh_shader,
shaderc_glsl_task_shader = shaderc_task_shader,
shaderc_glsl_mesh_shader = shaderc_mesh_shader,
shaderc_glsl_default_task_shader,
shaderc_glsl_default_mesh_shader,
} shaderc_shader_kind;
typedef enum {
shaderc_profile_none, // Used if and only if GLSL version did not specify
// profiles.
shaderc_profile_core,
shaderc_profile_compatibility, // Disabled. This generates an error
shaderc_profile_es,
} shaderc_profile;
// Optimization level.
typedef enum {
shaderc_optimization_level_zero, // no optimization
shaderc_optimization_level_size, // optimize towards reducing code size
shaderc_optimization_level_performance, // optimize towards performance
} shaderc_optimization_level;
// Resource limits.
typedef enum {
shaderc_limit_max_lights,
shaderc_limit_max_clip_planes,
shaderc_limit_max_texture_units,
shaderc_limit_max_texture_coords,
shaderc_limit_max_vertex_attribs,
shaderc_limit_max_vertex_uniform_components,
shaderc_limit_max_varying_floats,
shaderc_limit_max_vertex_texture_image_units,
shaderc_limit_max_combined_texture_image_units,
shaderc_limit_max_texture_image_units,
shaderc_limit_max_fragment_uniform_components,
shaderc_limit_max_draw_buffers,
shaderc_limit_max_vertex_uniform_vectors,
shaderc_limit_max_varying_vectors,
shaderc_limit_max_fragment_uniform_vectors,
shaderc_limit_max_vertex_output_vectors,
shaderc_limit_max_fragment_input_vectors,
shaderc_limit_min_program_texel_offset,
shaderc_limit_max_program_texel_offset,
shaderc_limit_max_clip_distances,
shaderc_limit_max_compute_work_group_count_x,
shaderc_limit_max_compute_work_group_count_y,
shaderc_limit_max_compute_work_group_count_z,
shaderc_limit_max_compute_work_group_size_x,
shaderc_limit_max_compute_work_group_size_y,
shaderc_limit_max_compute_work_group_size_z,
shaderc_limit_max_compute_uniform_components,
shaderc_limit_max_compute_texture_image_units,
shaderc_limit_max_compute_image_uniforms,
shaderc_limit_max_compute_atomic_counters,
shaderc_limit_max_compute_atomic_counter_buffers,
shaderc_limit_max_varying_components,
shaderc_limit_max_vertex_output_components,
shaderc_limit_max_geometry_input_components,
shaderc_limit_max_geometry_output_components,
shaderc_limit_max_fragment_input_components,
shaderc_limit_max_image_units,
shaderc_limit_max_combined_image_units_and_fragment_outputs,
shaderc_limit_max_combined_shader_output_resources,
shaderc_limit_max_image_samples,
shaderc_limit_max_vertex_image_uniforms,
shaderc_limit_max_tess_control_image_uniforms,
shaderc_limit_max_tess_evaluation_image_uniforms,
shaderc_limit_max_geometry_image_uniforms,
shaderc_limit_max_fragment_image_uniforms,
shaderc_limit_max_combined_image_uniforms,
shaderc_limit_max_geometry_texture_image_units,
shaderc_limit_max_geometry_output_vertices,
shaderc_limit_max_geometry_total_output_components,
shaderc_limit_max_geometry_uniform_components,
shaderc_limit_max_geometry_varying_components,
shaderc_limit_max_tess_control_input_components,
shaderc_limit_max_tess_control_output_components,
shaderc_limit_max_tess_control_texture_image_units,
shaderc_limit_max_tess_control_uniform_components,
shaderc_limit_max_tess_control_total_output_components,
shaderc_limit_max_tess_evaluation_input_components,
shaderc_limit_max_tess_evaluation_output_components,
shaderc_limit_max_tess_evaluation_texture_image_units,
shaderc_limit_max_tess_evaluation_uniform_components,
shaderc_limit_max_tess_patch_components,
shaderc_limit_max_patch_vertices,
shaderc_limit_max_tess_gen_level,
shaderc_limit_max_viewports,
shaderc_limit_max_vertex_atomic_counters,
shaderc_limit_max_tess_control_atomic_counters,
shaderc_limit_max_tess_evaluation_atomic_counters,
shaderc_limit_max_geometry_atomic_counters,
shaderc_limit_max_fragment_atomic_counters,
shaderc_limit_max_combined_atomic_counters,
shaderc_limit_max_atomic_counter_bindings,
shaderc_limit_max_vertex_atomic_counter_buffers,
shaderc_limit_max_tess_control_atomic_counter_buffers,
shaderc_limit_max_tess_evaluation_atomic_counter_buffers,
shaderc_limit_max_geometry_atomic_counter_buffers,
shaderc_limit_max_fragment_atomic_counter_buffers,
shaderc_limit_max_combined_atomic_counter_buffers,
shaderc_limit_max_atomic_counter_buffer_size,
shaderc_limit_max_transform_feedback_buffers,
shaderc_limit_max_transform_feedback_interleaved_components,
shaderc_limit_max_cull_distances,
shaderc_limit_max_combined_clip_and_cull_distances,
shaderc_limit_max_samples,
} shaderc_limit;
// Uniform resource kinds.
// In Vulkan, uniform resources are bound to the pipeline via descriptors
// with numbered bindings and sets.
typedef enum {
// Image and image buffer.
shaderc_uniform_kind_image,
// Pure sampler.
shaderc_uniform_kind_sampler,
// Sampled texture in GLSL, and Shader Resource View in HLSL.
shaderc_uniform_kind_texture,
// Uniform Buffer Object (UBO) in GLSL. Cbuffer in HLSL.
shaderc_uniform_kind_buffer,
// Shader Storage Buffer Object (SSBO) in GLSL.
shaderc_uniform_kind_storage_buffer,
// Unordered Access View, in HLSL. (Writable storage image or storage
// buffer.)
shaderc_uniform_kind_unordered_access_view,
} shaderc_uniform_kind;
// Usage examples:
//
// Aggressively release compiler resources, but spend time in initialization
// for each new use.
// shaderc_compiler_t compiler = shaderc_compiler_initialize();
// shaderc_compilation_result_t result = shaderc_compile_into_spv(
// compiler, "#version 450\nvoid main() {}", 27,
// shaderc_glsl_vertex_shader, "main.vert", "main", nullptr);
// // Do stuff with compilation results.
// shaderc_result_release(result);
// shaderc_compiler_release(compiler);
//
// Keep the compiler object around for a long time, but pay for extra space
// occupied.
// shaderc_compiler_t compiler = shaderc_compiler_initialize();
// // On the same, other or multiple simultaneous threads.
// shaderc_compilation_result_t result = shaderc_compile_into_spv(
// compiler, "#version 450\nvoid main() {}", 27,
// shaderc_glsl_vertex_shader, "main.vert", "main", nullptr);
// // Do stuff with compilation results.
// shaderc_result_release(result);
// // Once no more compilations are to happen.
// shaderc_compiler_release(compiler);
// An opaque handle to an object that manages all compiler state.
typedef struct shaderc_compiler* shaderc_compiler_t;
// Returns a shaderc_compiler_t that can be used to compile modules.
// A return of NULL indicates that there was an error initializing the compiler.
// Any function operating on shaderc_compiler_t must offer the basic
// thread-safety guarantee.
// [http://herbsutter.com/2014/01/13/gotw-95-solution-thread-safety-and-synchronization/]
// That is: concurrent invocation of these functions on DIFFERENT objects needs
// no synchronization; concurrent invocation of these functions on the SAME
// object requires synchronization IF AND ONLY IF some of them take a non-const
// argument.
SHADERC_EXPORT shaderc_compiler_t shaderc_compiler_initialize(void);
// Releases the resources held by the shaderc_compiler_t.
// After this call it is invalid to make any future calls to functions
// involving this shaderc_compiler_t.
SHADERC_EXPORT void shaderc_compiler_release(shaderc_compiler_t);
// An opaque handle to an object that manages options to a single compilation
// result.
typedef struct shaderc_compile_options* shaderc_compile_options_t;
// Returns a default-initialized shaderc_compile_options_t that can be used
// to modify the functionality of a compiled module.
// A return of NULL indicates that there was an error initializing the options.
// Any function operating on shaderc_compile_options_t must offer the
// basic thread-safety guarantee.
SHADERC_EXPORT shaderc_compile_options_t
shaderc_compile_options_initialize(void);
// Returns a copy of the given shaderc_compile_options_t.
// If NULL is passed as the parameter the call is the same as
// shaderc_compile_options_init.
SHADERC_EXPORT shaderc_compile_options_t shaderc_compile_options_clone(
const shaderc_compile_options_t options);
// Releases the compilation options. It is invalid to use the given
// shaderc_compile_options_t object in any future calls. It is safe to pass
// NULL to this function, and doing such will have no effect.
SHADERC_EXPORT void shaderc_compile_options_release(
shaderc_compile_options_t options);
// Adds a predefined macro to the compilation options. This has the same
// effect as passing -Dname=value to the command-line compiler. If value
// is NULL, it has the same effect as passing -Dname to the command-line
// compiler. If a macro definition with the same name has previously been
// added, the value is replaced with the new value. The macro name and
// value are passed in with char pointers, which point to their data, and
// the lengths of their data. The strings that the name and value pointers
// point to must remain valid for the duration of the call, but can be
// modified or deleted after this function has returned. In case of adding
// a valueless macro, the value argument should be a null pointer or the
// value_length should be 0u.
SHADERC_EXPORT void shaderc_compile_options_add_macro_definition(
shaderc_compile_options_t options, const char* name, size_t name_length,
const char* value, size_t value_length);
// Sets the source language. The default is GLSL.
SHADERC_EXPORT void shaderc_compile_options_set_source_language(
shaderc_compile_options_t options, shaderc_source_language lang);
// Sets the compiler mode to generate debug information in the output.
SHADERC_EXPORT void shaderc_compile_options_set_generate_debug_info(
shaderc_compile_options_t options);
// Sets the compiler optimization level to the given level. Only the last one
// takes effect if multiple calls of this function exist.
SHADERC_EXPORT void shaderc_compile_options_set_optimization_level(
shaderc_compile_options_t options, shaderc_optimization_level level);
// Forces the GLSL language version and profile to a given pair. The version
// number is the same as would appear in the #version annotation in the source.
// Version and profile specified here overrides the #version annotation in the
// source. Use profile: 'shaderc_profile_none' for GLSL versions that do not
// define profiles, e.g. versions below 150.
SHADERC_EXPORT void shaderc_compile_options_set_forced_version_profile(
shaderc_compile_options_t options, int version, shaderc_profile profile);
// Source text inclusion via #include is supported with a pair of callbacks
// to an "includer" on the client side. The first callback processes an
// inclusion request, and returns an include result. The includer owns
// the contents of the result, and those contents must remain valid until the
// second callback is invoked to release the result. Both callbacks take a
// user_data argument to specify the client context.
// To return an error, set the source_name to an empty string and put your
// error message in content.
// An include result.
typedef struct shaderc_include_result {
// The name of the source file. The name should be fully resolved
// in the sense that it should be a unique name in the context of the
// includer. For example, if the includer maps source names to files in
// a filesystem, then this name should be the absolute path of the file.
// For a failed inclusion, this string is empty.
const char* source_name;
size_t source_name_length;
// The text contents of the source file in the normal case.
// For a failed inclusion, this contains the error message.
const char* content;
size_t content_length;
// User data to be passed along with this request.
void* user_data;
} shaderc_include_result;
// The kinds of include requests.
enum shaderc_include_type {
shaderc_include_type_relative, // E.g. #include "source"
shaderc_include_type_standard // E.g. #include <source>
};
// An includer callback type for mapping an #include request to an include
// result. The user_data parameter specifies the client context. The
// requested_source parameter specifies the name of the source being requested.
// The type parameter specifies the kind of inclusion request being made.
// The requesting_source parameter specifies the name of the source containing
// the #include request. The includer owns the result object and its contents,
// and both must remain valid until the release callback is called on the result
// object.
typedef shaderc_include_result* (*shaderc_include_resolve_fn)(
void* user_data, const char* requested_source, int type,
const char* requesting_source, size_t include_depth);
// An includer callback type for destroying an include result.
typedef void (*shaderc_include_result_release_fn)(
void* user_data, shaderc_include_result* include_result);
// Sets includer callback functions.
SHADERC_EXPORT void shaderc_compile_options_set_include_callbacks(
shaderc_compile_options_t options, shaderc_include_resolve_fn resolver,
shaderc_include_result_release_fn result_releaser, void* user_data);
// Sets the compiler mode to suppress warnings, overriding warnings-as-errors
// mode. When both suppress-warnings and warnings-as-errors modes are
// turned on, warning messages will be inhibited, and will not be emitted
// as error messages.
SHADERC_EXPORT void shaderc_compile_options_set_suppress_warnings(
shaderc_compile_options_t options);
// Sets the target shader environment, affecting which warnings or errors will
// be issued. The version will be for distinguishing between different versions
// of the target environment. The version value should be either 0 or
// a value listed in shaderc_env_version. The 0 value maps to Vulkan 1.0 if
// |target| is Vulkan, and it maps to OpenGL 4.5 if |target| is OpenGL.
SHADERC_EXPORT void shaderc_compile_options_set_target_env(
shaderc_compile_options_t options,
shaderc_target_env target,
uint32_t version);
// Sets the target SPIR-V version. The generated module will use this version
// of SPIR-V. Each target environment determines what versions of SPIR-V
// it can consume. Defaults to the highest version of SPIR-V 1.0 which is
// required to be supported by the target environment. E.g. Default to SPIR-V
// 1.0 for Vulkan 1.0 and SPIR-V 1.3 for Vulkan 1.1.
SHADERC_EXPORT void shaderc_compile_options_set_target_spirv(
shaderc_compile_options_t options, shaderc_spirv_version version);
// Sets the compiler mode to treat all warnings as errors. Note the
// suppress-warnings mode overrides this option, i.e. if both
// warning-as-errors and suppress-warnings modes are set, warnings will not
// be emitted as error messages.
SHADERC_EXPORT void shaderc_compile_options_set_warnings_as_errors(
shaderc_compile_options_t options);
// Sets a resource limit.
SHADERC_EXPORT void shaderc_compile_options_set_limit(
shaderc_compile_options_t options, shaderc_limit limit, int value);
// Sets whether the compiler should automatically assign bindings to uniforms
// that aren't already explicitly bound in the shader source.
SHADERC_EXPORT void shaderc_compile_options_set_auto_bind_uniforms(
shaderc_compile_options_t options, bool auto_bind);
// Sets whether the compiler should automatically remove sampler variables
// and convert image variables to combined image-sampler variables.
SHADERC_EXPORT void shaderc_compile_options_set_auto_combined_image_sampler(
shaderc_compile_options_t options, bool upgrade);
// Sets whether the compiler should use HLSL IO mapping rules for bindings.
// Defaults to false.
SHADERC_EXPORT void shaderc_compile_options_set_hlsl_io_mapping(
shaderc_compile_options_t options, bool hlsl_iomap);
// Sets whether the compiler should determine block member offsets using HLSL
// packing rules instead of standard GLSL rules. Defaults to false. Only
// affects GLSL compilation. HLSL rules are always used when compiling HLSL.
SHADERC_EXPORT void shaderc_compile_options_set_hlsl_offsets(
shaderc_compile_options_t options, bool hlsl_offsets);
// Sets the base binding number used for for a uniform resource type when
// automatically assigning bindings. For GLSL compilation, sets the lowest
// automatically assigned number. For HLSL compilation, the regsiter number
// assigned to the resource is added to this specified base.
SHADERC_EXPORT void shaderc_compile_options_set_binding_base(
shaderc_compile_options_t options,
shaderc_uniform_kind kind,
uint32_t base);
// Like shaderc_compile_options_set_binding_base, but only takes effect when
// compiling a given shader stage. The stage is assumed to be one of vertex,
// fragment, tessellation evaluation, tesselation control, geometry, or compute.
SHADERC_EXPORT void shaderc_compile_options_set_binding_base_for_stage(
shaderc_compile_options_t options, shaderc_shader_kind shader_kind,
shaderc_uniform_kind kind, uint32_t base);
// Sets whether the compiler should automatically assign locations to
// uniform variables that don't have explicit locations in the shader source.
SHADERC_EXPORT void shaderc_compile_options_set_auto_map_locations(
shaderc_compile_options_t options, bool auto_map);
// Sets a descriptor set and binding for an HLSL register in the given stage.
// This method keeps a copy of the string data.
SHADERC_EXPORT void shaderc_compile_options_set_hlsl_register_set_and_binding_for_stage(
shaderc_compile_options_t options, shaderc_shader_kind shader_kind,
const char* reg, const char* set, const char* binding);
// Like shaderc_compile_options_set_hlsl_register_set_and_binding_for_stage,
// but affects all shader stages.
SHADERC_EXPORT void shaderc_compile_options_set_hlsl_register_set_and_binding(
shaderc_compile_options_t options, const char* reg, const char* set,
const char* binding);
// Sets whether the compiler should enable extension
// SPV_GOOGLE_hlsl_functionality1.
SHADERC_EXPORT void shaderc_compile_options_set_hlsl_functionality1(
shaderc_compile_options_t options, bool enable);
// Sets whether the compiler should invert position.Y output in vertex shader.
SHADERC_EXPORT void shaderc_compile_options_set_invert_y(
shaderc_compile_options_t options, bool enable);
// Sets whether the compiler generates code for max and min builtins which,
// if given a NaN operand, will return the other operand. Similarly, the clamp
// builtin will favour the non-NaN operands, as if clamp were implemented
// as a composition of max and min.
SHADERC_EXPORT void shaderc_compile_options_set_nan_clamp(
shaderc_compile_options_t options, bool enable);
// An opaque handle to the results of a call to any shaderc_compile_into_*()
// function.
typedef struct shaderc_compilation_result* shaderc_compilation_result_t;
// Takes a GLSL source string and the associated shader kind, input file
// name, compiles it according to the given additional_options. If the shader
// kind is not set to a specified kind, but shaderc_glslc_infer_from_source,
// the compiler will try to deduce the shader kind from the source
// string and a failure in deducing will generate an error. Currently only
// #pragma annotation is supported. If the shader kind is set to one of the
// default shader kinds, the compiler will fall back to the default shader
// kind in case it failed to deduce the shader kind from source string.
// The input_file_name is a null-termintated string. It is used as a tag to
// identify the source string in cases like emitting error messages. It
// doesn't have to be a 'file name'.
// The source string will be compiled into SPIR-V binary and a
// shaderc_compilation_result will be returned to hold the results.
// The entry_point_name null-terminated string defines the name of the entry
// point to associate with this GLSL source. If the additional_options
// parameter is not null, then the compilation is modified by any options
// present. May be safely called from multiple threads without explicit
// synchronization. If there was failure in allocating the compiler object,
// null will be returned.
SHADERC_EXPORT shaderc_compilation_result_t shaderc_compile_into_spv(
const shaderc_compiler_t compiler, const char* source_text,
size_t source_text_size, shaderc_shader_kind shader_kind,
const char* input_file_name, const char* entry_point_name,
const shaderc_compile_options_t additional_options);
// Like shaderc_compile_into_spv, but the result contains SPIR-V assembly text
// instead of a SPIR-V binary module. The SPIR-V assembly syntax is as defined
// by the SPIRV-Tools open source project.
SHADERC_EXPORT shaderc_compilation_result_t shaderc_compile_into_spv_assembly(
const shaderc_compiler_t compiler, const char* source_text,
size_t source_text_size, shaderc_shader_kind shader_kind,
const char* input_file_name, const char* entry_point_name,
const shaderc_compile_options_t additional_options);
// Like shaderc_compile_into_spv, but the result contains preprocessed source
// code instead of a SPIR-V binary module
SHADERC_EXPORT shaderc_compilation_result_t shaderc_compile_into_preprocessed_text(
const shaderc_compiler_t compiler, const char* source_text,
size_t source_text_size, shaderc_shader_kind shader_kind,
const char* input_file_name, const char* entry_point_name,
const shaderc_compile_options_t additional_options);
// Takes an assembly string of the format defined in the SPIRV-Tools project
// (https://github.com/KhronosGroup/SPIRV-Tools/blob/master/syntax.md),
// assembles it into SPIR-V binary and a shaderc_compilation_result will be
// returned to hold the results.
// The assembling will pick options suitable for assembling specified in the
// additional_options parameter.
// May be safely called from multiple threads without explicit synchronization.
// If there was failure in allocating the compiler object, null will be
// returned.
SHADERC_EXPORT shaderc_compilation_result_t shaderc_assemble_into_spv(
const shaderc_compiler_t compiler, const char* source_assembly,
size_t source_assembly_size,
const shaderc_compile_options_t additional_options);
// The following functions, operating on shaderc_compilation_result_t objects,
// offer only the basic thread-safety guarantee.
// Releases the resources held by the result object. It is invalid to use the
// result object for any further operations.
SHADERC_EXPORT void shaderc_result_release(shaderc_compilation_result_t result);
// Returns the number of bytes of the compilation output data in a result
// object.
SHADERC_EXPORT size_t shaderc_result_get_length(const shaderc_compilation_result_t result);
// Returns the number of warnings generated during the compilation.
SHADERC_EXPORT size_t shaderc_result_get_num_warnings(
const shaderc_compilation_result_t result);
// Returns the number of errors generated during the compilation.
SHADERC_EXPORT size_t shaderc_result_get_num_errors(const shaderc_compilation_result_t result);
// Returns the compilation status, indicating whether the compilation succeeded,
// or failed due to some reasons, like invalid shader stage or compilation
// errors.
SHADERC_EXPORT shaderc_compilation_status shaderc_result_get_compilation_status(
const shaderc_compilation_result_t);
// Returns a pointer to the start of the compilation output data bytes, either
// SPIR-V binary or char string. When the source string is compiled into SPIR-V
// binary, this is guaranteed to be castable to a uint32_t*. If the result
// contains assembly text or preprocessed source text, the pointer will point to
// the resulting array of characters.
SHADERC_EXPORT const char* shaderc_result_get_bytes(const shaderc_compilation_result_t result);
// Returns a null-terminated string that contains any error messages generated
// during the compilation.
SHADERC_EXPORT const char* shaderc_result_get_error_message(
const shaderc_compilation_result_t result);
// Provides the version & revision of the SPIR-V which will be produced
SHADERC_EXPORT void shaderc_get_spv_version(unsigned int* version, unsigned int* revision);
// Parses the version and profile from a given null-terminated string
// containing both version and profile, like: '450core'. Returns false if
// the string can not be parsed. Returns true when the parsing succeeds. The
// parsed version and profile are returned through arguments.
SHADERC_EXPORT bool shaderc_parse_version_profile(const char* str, int* version,
shaderc_profile* profile);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // SHADERC_SHADERC_H_

View File

@ -0,0 +1,602 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SHADERC_SHADERC_HPP_
#define SHADERC_SHADERC_HPP_
#include <memory>
#include <string>
#include <vector>
#include "shaderc.h"
namespace shaderc {
// A CompilationResult contains the compiler output, compilation status,
// and messages.
//
// The compiler output is stored as an array of elements and accessed
// via random access iterators provided by cbegin() and cend(). The iterators
// are contiguous in the sense of "Contiguous Iterators: A Refinement of
// Random Access Iterators", Nevin Liber, C++ Library Evolution Working
// Group Working Paper N3884.
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3884.pdf
//
// Methods begin() and end() are also provided to enable range-based for.
// They are synonyms to cbegin() and cend(), respectively.
template <typename OutputElementType>
class CompilationResult {
public:
typedef OutputElementType element_type;
// The type used to describe the begin and end iterators on the
// compiler output.
typedef const OutputElementType* const_iterator;
// Upon creation, the CompilationResult takes ownership of the
// shaderc_compilation_result instance. During destruction of the
// CompilationResult, the shaderc_compilation_result will be released.
explicit CompilationResult(shaderc_compilation_result_t compilation_result)
: compilation_result_(compilation_result) {}
CompilationResult() : compilation_result_(nullptr) {}
~CompilationResult() { shaderc_result_release(compilation_result_); }
CompilationResult(CompilationResult&& other) : compilation_result_(nullptr) {
*this = std::move(other);
}
CompilationResult& operator=(CompilationResult&& other) {
if (compilation_result_) {
shaderc_result_release(compilation_result_);
}
compilation_result_ = other.compilation_result_;
other.compilation_result_ = nullptr;
return *this;
}
// Returns any error message found during compilation.
std::string GetErrorMessage() const {
if (!compilation_result_) {
return "";
}
return shaderc_result_get_error_message(compilation_result_);
}
// Returns the compilation status, indicating whether the compilation
// succeeded, or failed due to some reasons, like invalid shader stage or
// compilation errors.
shaderc_compilation_status GetCompilationStatus() const {
if (!compilation_result_) {
return shaderc_compilation_status_null_result_object;
}
return shaderc_result_get_compilation_status(compilation_result_);
}
// Returns a random access (contiguous) iterator pointing to the start
// of the compilation output. It is valid for the lifetime of this object.
// If there is no compilation result, then returns nullptr.
const_iterator cbegin() const {
if (!compilation_result_) return nullptr;
return reinterpret_cast<const_iterator>(
shaderc_result_get_bytes(compilation_result_));
}
// Returns a random access (contiguous) iterator pointing to the end of
// the compilation output. It is valid for the lifetime of this object.
// If there is no compilation result, then returns nullptr.
const_iterator cend() const {
if (!compilation_result_) return nullptr;
return cbegin() +
shaderc_result_get_length(compilation_result_) /
sizeof(OutputElementType);
}
// Returns the same iterator as cbegin().
const_iterator begin() const { return cbegin(); }
// Returns the same iterator as cend().
const_iterator end() const { return cend(); }
// Returns the number of warnings generated during the compilation.
size_t GetNumWarnings() const {
if (!compilation_result_) {
return 0;
}
return shaderc_result_get_num_warnings(compilation_result_);
}
// Returns the number of errors generated during the compilation.
size_t GetNumErrors() const {
if (!compilation_result_) {
return 0;
}
return shaderc_result_get_num_errors(compilation_result_);
}
private:
CompilationResult(const CompilationResult& other) = delete;
CompilationResult& operator=(const CompilationResult& other) = delete;
shaderc_compilation_result_t compilation_result_;
};
// A compilation result for a SPIR-V binary module, which is an array
// of uint32_t words.
using SpvCompilationResult = CompilationResult<uint32_t>;
// A compilation result in SPIR-V assembly syntax.
using AssemblyCompilationResult = CompilationResult<char>;
// Preprocessed source text.
using PreprocessedSourceCompilationResult = CompilationResult<char>;
// Contains any options that can have default values for a compilation.
class CompileOptions {
public:
CompileOptions() { options_ = shaderc_compile_options_initialize(); }
~CompileOptions() { shaderc_compile_options_release(options_); }
CompileOptions(const CompileOptions& other) {
options_ = shaderc_compile_options_clone(other.options_);
}
CompileOptions(CompileOptions&& other) {
options_ = other.options_;
other.options_ = nullptr;
}
// Adds a predefined macro to the compilation options. It behaves the same as
// shaderc_compile_options_add_macro_definition in shaderc.h.
void AddMacroDefinition(const char* name, size_t name_length,
const char* value, size_t value_length) {
shaderc_compile_options_add_macro_definition(options_, name, name_length,
value, value_length);
}
// Adds a valueless predefined macro to the compilation options.
void AddMacroDefinition(const std::string& name) {
AddMacroDefinition(name.c_str(), name.size(), nullptr, 0u);
}
// Adds a predefined macro to the compilation options.
void AddMacroDefinition(const std::string& name, const std::string& value) {
AddMacroDefinition(name.c_str(), name.size(), value.c_str(), value.size());
}
// Sets the compiler mode to generate debug information in the output.
void SetGenerateDebugInfo() {
shaderc_compile_options_set_generate_debug_info(options_);
}
// Sets the compiler optimization level to the given level. Only the last one
// takes effect if multiple calls of this function exist.
void SetOptimizationLevel(shaderc_optimization_level level) {
shaderc_compile_options_set_optimization_level(options_, level);
}
// A C++ version of the libshaderc includer interface.
class IncluderInterface {
public:
// Handles shaderc_include_resolver_fn callbacks.
virtual shaderc_include_result* GetInclude(const char* requested_source,
shaderc_include_type type,
const char* requesting_source,
size_t include_depth) = 0;
// Handles shaderc_include_result_release_fn callbacks.
virtual void ReleaseInclude(shaderc_include_result* data) = 0;
virtual ~IncluderInterface() = default;
};
// Sets the includer instance for libshaderc to call during compilation, as
// described in shaderc_compile_options_set_include_callbacks(). Callbacks
// are routed to this includer's methods.
void SetIncluder(std::unique_ptr<IncluderInterface>&& includer) {
includer_ = std::move(includer);
shaderc_compile_options_set_include_callbacks(
options_,
[](void* user_data, const char* requested_source, int type,
const char* requesting_source, size_t include_depth) {
auto* sub_includer = static_cast<IncluderInterface*>(user_data);
return sub_includer->GetInclude(
requested_source, static_cast<shaderc_include_type>(type),
requesting_source, include_depth);
},
[](void* user_data, shaderc_include_result* include_result) {
auto* sub_includer = static_cast<IncluderInterface*>(user_data);
return sub_includer->ReleaseInclude(include_result);
},
includer_.get());
}
// Forces the GLSL language version and profile to a given pair. The version
// number is the same as would appear in the #version annotation in the
// source. Version and profile specified here overrides the #version
// annotation in the source. Use profile: 'shaderc_profile_none' for GLSL
// versions that do not define profiles, e.g. versions below 150.
void SetForcedVersionProfile(int version, shaderc_profile profile) {
shaderc_compile_options_set_forced_version_profile(options_, version,
profile);
}
// Sets the compiler mode to suppress warnings. Note this option overrides
// warnings-as-errors mode. When both suppress-warnings and warnings-as-errors
// modes are turned on, warning messages will be inhibited, and will not be
// emitted as error message.
void SetSuppressWarnings() {
shaderc_compile_options_set_suppress_warnings(options_);
}
// Sets the source language. The default is GLSL.
void SetSourceLanguage(shaderc_source_language lang) {
shaderc_compile_options_set_source_language(options_, lang);
}
// Sets the target shader environment, affecting which warnings or errors will
// be issued. The version will be for distinguishing between different
// versions of the target environment. The version value should be either 0
// or a value listed in shaderc_env_version. The 0 value maps to Vulkan 1.0
// if |target| is Vulkan, and it maps to OpenGL 4.5 if |target| is OpenGL.
void SetTargetEnvironment(shaderc_target_env target, uint32_t version) {
shaderc_compile_options_set_target_env(options_, target, version);
}
// Sets the target SPIR-V version. The generated module will use this version
// of SPIR-V. Each target environment determines what versions of SPIR-V
// it can consume. Defaults to the highest version of SPIR-V 1.0 which is
// required to be supported by the target environment. E.g. Default to SPIR-V
// 1.0 for Vulkan 1.0 and SPIR-V 1.3 for Vulkan 1.1.
void SetTargetSpirv(shaderc_spirv_version version) {
shaderc_compile_options_set_target_spirv(options_, version);
}
// Sets the compiler mode to make all warnings into errors. Note the
// suppress-warnings mode overrides this option, i.e. if both
// warning-as-errors and suppress-warnings modes are set on, warnings will not
// be emitted as error message.
void SetWarningsAsErrors() {
shaderc_compile_options_set_warnings_as_errors(options_);
}
// Sets a resource limit.
void SetLimit(shaderc_limit limit, int value) {
shaderc_compile_options_set_limit(options_, limit, value);
}
// Sets whether the compiler should automatically assign bindings to uniforms
// that aren't already explicitly bound in the shader source.
void SetAutoBindUniforms(bool auto_bind) {
shaderc_compile_options_set_auto_bind_uniforms(options_, auto_bind);
}
// Sets whether the compiler should automatically remove sampler variables
// and convert image variables to combined image sampler variables.
void SetAutoSampledTextures(bool auto_sampled) {
shaderc_compile_options_set_auto_combined_image_sampler(options_,
auto_sampled);
}
// Sets whether the compiler should use HLSL IO mapping rules for bindings.
// Defaults to false.
void SetHlslIoMapping(bool hlsl_iomap) {
shaderc_compile_options_set_hlsl_io_mapping(options_, hlsl_iomap);
}
// Sets whether the compiler should determine block member offsets using HLSL
// packing rules instead of standard GLSL rules. Defaults to false. Only
// affects GLSL compilation. HLSL rules are always used when compiling HLSL.
void SetHlslOffsets(bool hlsl_offsets) {
shaderc_compile_options_set_hlsl_offsets(options_, hlsl_offsets);
}
// Sets the base binding number used for for a uniform resource type when
// automatically assigning bindings. For GLSL compilation, sets the lowest
// automatically assigned number. For HLSL compilation, the regsiter number
// assigned to the resource is added to this specified base.
void SetBindingBase(shaderc_uniform_kind kind, uint32_t base) {
shaderc_compile_options_set_binding_base(options_, kind, base);
}
// Like SetBindingBase, but only takes effect when compiling a given shader
// stage. The stage is assumed to be one of vertex, fragment, tessellation
// evaluation, tesselation control, geometry, or compute.
void SetBindingBaseForStage(shaderc_shader_kind shader_kind,
shaderc_uniform_kind kind, uint32_t base) {
shaderc_compile_options_set_binding_base_for_stage(options_, shader_kind,
kind, base);
}
// Sets whether the compiler automatically assigns locations to
// uniform variables that don't have explicit locations.
void SetAutoMapLocations(bool auto_map) {
shaderc_compile_options_set_auto_map_locations(options_, auto_map);
}
// Sets a descriptor set and binding for an HLSL register in the given stage.
// Copies the parameter strings.
void SetHlslRegisterSetAndBindingForStage(shaderc_shader_kind shader_kind,
const std::string& reg,
const std::string& set,
const std::string& binding) {
shaderc_compile_options_set_hlsl_register_set_and_binding_for_stage(
options_, shader_kind, reg.c_str(), set.c_str(), binding.c_str());
}
// Sets a descriptor set and binding for an HLSL register in any stage.
// Copies the parameter strings.
void SetHlslRegisterSetAndBinding(const std::string& reg,
const std::string& set,
const std::string& binding) {
shaderc_compile_options_set_hlsl_register_set_and_binding(
options_, reg.c_str(), set.c_str(), binding.c_str());
}
// Sets whether the compiler should enable extension
// SPV_GOOGLE_hlsl_functionality1.
void SetHlslFunctionality1(bool enable) {
shaderc_compile_options_set_hlsl_functionality1(options_, enable);
}
// Sets whether the compiler should invert position.Y output in vertex shader.
void SetInvertY(bool enable) {
shaderc_compile_options_set_invert_y(options_, enable);
}
// Sets whether the compiler should generates code for max an min which,
// if given a NaN operand, will return the other operand. Similarly, the
// clamp builtin will favour the non-NaN operands, as if clamp were
// implemented as a composition of max and min.
void SetNanClamp(bool enable) {
shaderc_compile_options_set_nan_clamp(options_, enable);
}
private:
CompileOptions& operator=(const CompileOptions& other) = delete;
shaderc_compile_options_t options_;
std::unique_ptr<IncluderInterface> includer_;
friend class Compiler;
};
// The compilation context for compiling source to SPIR-V.
class Compiler {
public:
Compiler() : compiler_(shaderc_compiler_initialize()) {}
~Compiler() { shaderc_compiler_release(compiler_); }
Compiler(Compiler&& other) {
compiler_ = other.compiler_;
other.compiler_ = nullptr;
}
bool IsValid() const { return compiler_ != nullptr; }
// Compiles the given source GLSL and returns a SPIR-V binary module
// compilation result.
// The source_text parameter must be a valid pointer.
// The source_text_size parameter must be the length of the source text.
// The shader_kind parameter either forces the compilation to be done with a
// specified shader kind, or hint the compiler how to determine the exact
// shader kind. If the shader kind is set to shaderc_glslc_infer_from_source,
// the compiler will try to deduce the shader kind from the source string and
// a failure in this proess will generate an error. Currently only #pragma
// annotation is supported. If the shader kind is set to one of the default
// shader kinds, the compiler will fall back to the specified default shader
// kind in case it failed to deduce the shader kind from the source string.
// The input_file_name is a null-termintated string. It is used as a tag to
// identify the source string in cases like emitting error messages. It
// doesn't have to be a 'file name'.
// The entry_point_name parameter is a null-terminated string specifying
// the entry point name for HLSL compilation. For GLSL compilation, the
// entry point name is assumed to be "main".
// The compilation is passed any options specified in the CompileOptions
// parameter.
// It is valid for the returned CompilationResult object to outlive this
// compiler object.
// Note when the options_ has disassembly mode or preprocessing only mode set
// on, the returned CompilationResult will hold a text string, instead of a
// SPIR-V binary generated with default options.
SpvCompilationResult CompileGlslToSpv(const char* source_text,
size_t source_text_size,
shaderc_shader_kind shader_kind,
const char* input_file_name,
const char* entry_point_name,
const CompileOptions& options) const {
shaderc_compilation_result_t compilation_result = shaderc_compile_into_spv(
compiler_, source_text, source_text_size, shader_kind, input_file_name,
entry_point_name, options.options_);
return SpvCompilationResult(compilation_result);
}
// Compiles the given source shader and returns a SPIR-V binary module
// compilation result.
// Like the first CompileGlslToSpv method but assumes the entry point name
// is "main".
SpvCompilationResult CompileGlslToSpv(const char* source_text,
size_t source_text_size,
shaderc_shader_kind shader_kind,
const char* input_file_name,
const CompileOptions& options) const {
return CompileGlslToSpv(source_text, source_text_size, shader_kind,
input_file_name, "main", options);
}
// Compiles the given source GLSL and returns a SPIR-V binary module
// compilation result.
// Like the previous CompileGlslToSpv method but uses default options.
SpvCompilationResult CompileGlslToSpv(const char* source_text,
size_t source_text_size,
shaderc_shader_kind shader_kind,
const char* input_file_name) const {
shaderc_compilation_result_t compilation_result =
shaderc_compile_into_spv(compiler_, source_text, source_text_size,
shader_kind, input_file_name, "main", nullptr);
return SpvCompilationResult(compilation_result);
}
// Compiles the given source shader and returns a SPIR-V binary module
// compilation result.
// Like the first CompileGlslToSpv method but the source is provided as
// a std::string, and we assume the entry point is "main".
SpvCompilationResult CompileGlslToSpv(const std::string& source_text,
shaderc_shader_kind shader_kind,
const char* input_file_name,
const CompileOptions& options) const {
return CompileGlslToSpv(source_text.data(), source_text.size(), shader_kind,
input_file_name, options);
}
// Compiles the given source shader and returns a SPIR-V binary module
// compilation result.
// Like the first CompileGlslToSpv method but the source is provided as
// a std::string.
SpvCompilationResult CompileGlslToSpv(const std::string& source_text,
shaderc_shader_kind shader_kind,
const char* input_file_name,
const char* entry_point_name,
const CompileOptions& options) const {
return CompileGlslToSpv(source_text.data(), source_text.size(), shader_kind,
input_file_name, entry_point_name, options);
}
// Compiles the given source GLSL and returns a SPIR-V binary module
// compilation result.
// Like the previous CompileGlslToSpv method but assumes the entry point
// name is "main".
SpvCompilationResult CompileGlslToSpv(const std::string& source_text,
shaderc_shader_kind shader_kind,
const char* input_file_name) const {
return CompileGlslToSpv(source_text.data(), source_text.size(), shader_kind,
input_file_name);
}
// Assembles the given SPIR-V assembly and returns a SPIR-V binary module
// compilation result.
// The assembly should follow the syntax defined in the SPIRV-Tools project
// (https://github.com/KhronosGroup/SPIRV-Tools/blob/master/syntax.md).
// It is valid for the returned CompilationResult object to outlive this
// compiler object.
// The assembling will pick options suitable for assembling specified in the
// CompileOptions parameter.
SpvCompilationResult AssembleToSpv(const char* source_assembly,
size_t source_assembly_size,
const CompileOptions& options) const {
return SpvCompilationResult(shaderc_assemble_into_spv(
compiler_, source_assembly, source_assembly_size, options.options_));
}
// Assembles the given SPIR-V assembly and returns a SPIR-V binary module
// compilation result.
// Like the first AssembleToSpv method but uses the default compiler options.
SpvCompilationResult AssembleToSpv(const char* source_assembly,
size_t source_assembly_size) const {
return SpvCompilationResult(shaderc_assemble_into_spv(
compiler_, source_assembly, source_assembly_size, nullptr));
}
// Assembles the given SPIR-V assembly and returns a SPIR-V binary module
// compilation result.
// Like the first AssembleToSpv method but the source is provided as a
// std::string.
SpvCompilationResult AssembleToSpv(const std::string& source_assembly,
const CompileOptions& options) const {
return SpvCompilationResult(
shaderc_assemble_into_spv(compiler_, source_assembly.data(),
source_assembly.size(), options.options_));
}
// Assembles the given SPIR-V assembly and returns a SPIR-V binary module
// compilation result.
// Like the first AssembleToSpv method but the source is provided as a
// std::string and also uses default compiler options.
SpvCompilationResult AssembleToSpv(const std::string& source_assembly) const {
return SpvCompilationResult(shaderc_assemble_into_spv(
compiler_, source_assembly.data(), source_assembly.size(), nullptr));
}
// Compiles the given source GLSL and returns the SPIR-V assembly text
// compilation result.
// Options are similar to the first CompileToSpv method.
AssemblyCompilationResult CompileGlslToSpvAssembly(
const char* source_text, size_t source_text_size,
shaderc_shader_kind shader_kind, const char* input_file_name,
const char* entry_point_name, const CompileOptions& options) const {
shaderc_compilation_result_t compilation_result =
shaderc_compile_into_spv_assembly(
compiler_, source_text, source_text_size, shader_kind,
input_file_name, entry_point_name, options.options_);
return AssemblyCompilationResult(compilation_result);
}
// Compiles the given source GLSL and returns the SPIR-V assembly text
// compilation result.
// Similare to the previous method, but assumes entry point name is "main".
AssemblyCompilationResult CompileGlslToSpvAssembly(
const char* source_text, size_t source_text_size,
shaderc_shader_kind shader_kind, const char* input_file_name,
const CompileOptions& options) const {
return CompileGlslToSpvAssembly(source_text, source_text_size, shader_kind,
input_file_name, "main", options);
}
// Compiles the given source GLSL and returns the SPIR-V assembly text
// result. Like the first CompileGlslToSpvAssembly method but the source
// is provided as a std::string. Options are otherwise similar to
// the first CompileToSpv method.
AssemblyCompilationResult CompileGlslToSpvAssembly(
const std::string& source_text, shaderc_shader_kind shader_kind,
const char* input_file_name, const char* entry_point_name,
const CompileOptions& options) const {
return CompileGlslToSpvAssembly(source_text.data(), source_text.size(),
shader_kind, input_file_name,
entry_point_name, options);
}
// Compiles the given source GLSL and returns the SPIR-V assembly text
// result. Like the previous CompileGlslToSpvAssembly method but assumes
// the entry point name is "main".
AssemblyCompilationResult CompileGlslToSpvAssembly(
const std::string& source_text, shaderc_shader_kind shader_kind,
const char* input_file_name, const CompileOptions& options) const {
return CompileGlslToSpvAssembly(source_text, shader_kind, input_file_name,
"main", options);
}
// Preprocesses the given source GLSL and returns the preprocessed
// source text as a compilation result.
// Options are similar to the first CompileToSpv method.
PreprocessedSourceCompilationResult PreprocessGlsl(
const char* source_text, size_t source_text_size,
shaderc_shader_kind shader_kind, const char* input_file_name,
const CompileOptions& options) const {
shaderc_compilation_result_t compilation_result =
shaderc_compile_into_preprocessed_text(
compiler_, source_text, source_text_size, shader_kind,
input_file_name, "main", options.options_);
return PreprocessedSourceCompilationResult(compilation_result);
}
// Preprocesses the given source GLSL and returns text result. Like the first
// PreprocessGlsl method but the source is provided as a std::string.
// Options are otherwise similar to the first CompileToSpv method.
PreprocessedSourceCompilationResult PreprocessGlsl(
const std::string& source_text, shaderc_shader_kind shader_kind,
const char* input_file_name, const CompileOptions& options) const {
return PreprocessGlsl(source_text.data(), source_text.size(), shader_kind,
input_file_name, options);
}
private:
Compiler(const Compiler&) = delete;
Compiler& operator=(const Compiler& other) = delete;
shaderc_compiler_t compiler_;
};
} // namespace shaderc
#endif // SHADERC_SHADERC_HPP_

View File

@ -0,0 +1,39 @@
// Copyright 2018 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SHADERC_STATUS_H_
#define SHADERC_STATUS_H_
#ifdef __cplusplus
extern "C" {
#endif
// Indicate the status of a compilation.
typedef enum {
shaderc_compilation_status_success = 0,
shaderc_compilation_status_invalid_stage = 1, // error stage deduction
shaderc_compilation_status_compilation_error = 2,
shaderc_compilation_status_internal_error = 3, // unexpected failure
shaderc_compilation_status_null_result_object = 4,
shaderc_compilation_status_invalid_assembly = 5,
shaderc_compilation_status_validation_error = 6,
shaderc_compilation_status_transformation_error = 7,
shaderc_compilation_status_configuration_error = 8,
} shaderc_compilation_status;
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // SHADERC_STATUS_H_

View File

@ -0,0 +1,37 @@
// Copyright 2018 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SHADERC_VISIBILITY_H_
#define SHADERC_VISIBILITY_H_
// SHADERC_EXPORT tags symbol that will be exposed by the shared libraries.
#if defined(SHADERC_SHAREDLIB)
#if defined(_WIN32)
#if defined(SHADERC_IMPLEMENTATION)
#define SHADERC_EXPORT __declspec(dllexport)
#else
#define SHADERC_EXPORT __declspec(dllimport)
#endif
#else
#if defined(SHADERC_IMPLEMENTATION)
#define SHADERC_EXPORT __attribute__((visibility("default")))
#else
#define SHADERC_EXPORT
#endif
#endif
#else
#define SHADERC_EXPORT
#endif
#endif // SHADERC_VISIBILITY_H_

View File

@ -0,0 +1,413 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef COMMON_SHADERS_FOR_TESTS_H_
#define COMMON_SHADERS_FOR_TESTS_H_
#ifdef __cplusplus
extern "C" {
#endif
// The minimal shader, without a version directive.
const char kMinimalShaderWithoutVersion[] = "void main(){}";
// The minimal shader, with a version directive.
const char kMinimalShader[] =
"#version 140\n"
"void main(){}";
const char kMinimalHlslShader[] =
"float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION\n"
"{ return float4(1.0, 2.0, 3.0, 4.0); }";
const char kMinimalShaderWithMacro[] =
"#version 140\n"
"#define E main\n"
"void E(){}\n";
// The minimal shader that needs valueless predefinition of 'E' to compile.
const char kValuelessPredefinitionShader[] =
"#version 140\n"
"#ifdef E\n"
"void main(){}\n"
"#else\n"
"#error\n"
"#endif";
// By default the compiler will emit a warning on line 2 complaining
// that 'float' is a deprecated attribute in version 130. Use verison 140
// because some versions of glslang will error out for a too-low version
// when generating SPIR-V.
const char kDeprecatedAttributeShader[] =
"#version 400\n"
"layout(location = 0) attribute float x;\n"
"void main() {}\n";
// By default the compiler will emit a warning as version 550 is an unknown
// version.
const char kMinimalUnknownVersionShader[] =
"#version 550\n"
"void main() {}\n";
// gl_ClipDistance doesn't exist in es profile (at least until 3.10).
const char kCoreVertShaderWithoutVersion[] =
"void main() {\n"
"gl_ClipDistance[0] = 5.;\n"
"}\n";
// Generated debug information should contain the name of the vector:
// debug_info_sample.
const char kMinimalDebugInfoShader[] =
"#version 140\n"
"void main(){\n"
"vec2 debug_info_sample = vec2(1.0,1.0);\n"
"}\n";
// Compiler should generate two errors.
const char kTwoErrorsShader[] =
"#version 150\n"
"#error\n"
"#error\n"
"void main(){}\n";
// Compiler should generate two warnings.
const char kTwoWarningsShader[] =
"#version 400\n"
"layout(location = 0) attribute float x;\n"
"layout(location = 1) attribute float y;\n"
"void main(){}\n";
// A shader that compiles under OpenGL compatibility profile rules,
// but not OpenGL core profile rules.
const char kOpenGLCompatibilityFragmentShader[] =
R"(#version 100
uniform highp sampler2D tex;
void main() {
gl_FragColor = texture2D(tex, vec2(0.0,0.0));
})";
// A shader that compiles under OpenGL core profile rules.
const char kOpenGLVertexShader[] =
R"(#version 330
void main() { int t = gl_VertexID; })";
// Empty 310 es shader. It is valid for vertex, fragment, compute shader kind.
const char kEmpty310ESShader[] =
"#version 310 es\n"
"void main() {}\n";
// Vertex only shader.
const char kVertexOnlyShader[] =
"#version 310 es\n"
"void main() {\n"
" gl_Position = vec4(1.);\n"
"}";
// TessControl only shader.
const char kTessControlOnlyShader[] =
"#version 440 core\n"
"layout(vertices = 3) out;\n"
"void main() { }";
// TessEvaluation only shader.
const char kTessEvaluationOnlyShader[] =
"#version 440 core\n"
"layout(triangles) in;\n"
"void main() { }";
// Geometry only shader.
const char kGeometryOnlyShader[] =
"#version 150 core\n"
"layout (triangles) in;\n"
"layout (line_strip, max_vertices = 4) out;\n"
"void main() { }";
// Vertex only shader with #pragma annotation.
const char kVertexOnlyShaderWithPragma[] =
"#version 310 es\n"
"#pragma shader_stage(vertex)\n"
"void main() {\n"
" gl_Position = vec4(1.);\n"
"}";
// Fragment only shader with #pragma annotation.
const char kFragmentOnlyShaderWithPragma[] =
"#version 310 es\n"
"#pragma shader_stage(fragment)\n"
"void main() {\n"
" gl_FragDepth = 10.;\n"
"}";
// TessControl only shader with #pragma annotation.
const char kTessControlOnlyShaderWithPragma[] =
"#version 440 core\n"
"#pragma shader_stage(tesscontrol)\n"
"layout(vertices = 3) out;\n"
"void main() { }";
// TessEvaluation only shader with #pragma annotation.
const char kTessEvaluationOnlyShaderWithPragma[] =
"#version 440 core\n"
"#pragma shader_stage(tesseval)\n"
"layout(triangles) in;\n"
"void main() { }";
// Geometry only shader with #pragma annotation.
const char kGeometryOnlyShaderWithPragma[] =
"#version 150 core\n"
"#pragma shader_stage(geometry)\n"
"layout (triangles) in;\n"
"layout (line_strip, max_vertices = 4) out;\n"
"void main() { }";
// Compute only shader with #pragma annotation.
const char kComputeOnlyShaderWithPragma[] =
"#version 310 es\n"
"#pragma shader_stage(compute)\n"
"void main() {\n"
" uvec3 temp = gl_WorkGroupID;\n"
"}";
// NV mesh shader without #pragma.
const char kNVMeshShader[] =
"#version 450\n"
"#extension GL_NV_mesh_shader : enable\n"
"layout(local_size_x=8) in;\n"
"layout(max_vertices=5) out;\n"
"layout(max_primitives=10) out;\n"
"layout(triangles) out;\n"
"void main() {\n"
" gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_Position = vec4(0.0);\n"
"}\n";
// NV mesh shader with #pragma annotation.
const char kNVMeshShaderWithPragma[] =
"#version 450\n"
"#extension GL_NV_mesh_shader : enable\n"
"#pragma shader_stage(mesh)\n"
"layout(local_size_x=8) in;\n"
"layout(max_vertices=5) out;\n"
"layout(max_primitives=10) out;\n"
"layout(triangles) out;\n"
"void main() {\n"
" gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_Position = vec4(0.0);\n"
"}\n";
// NV task shader without #pragma annotation.
const char kNVTaskShader[] =
"#version 450\n"
"#extension GL_NV_mesh_shader : enable\n"
"layout(local_size_x=8) in;\n"
"void main() {\n"
" gl_TaskCountNV = 2;\n"
"}\n";
// NV task shader with #pragma annotation.
const char kNVTaskShaderWithPragma[] =
"#version 450\n"
"#extension GL_NV_mesh_shader : enable\n"
"#pragma shader_stage(task)\n"
"layout(local_size_x=8) in;\n"
"void main() {\n"
" gl_TaskCountNV = 2;\n"
"}\n";
// Vertex only shader with invalid #pragma annotation.
const char kVertexOnlyShaderWithInvalidPragma[] =
"#version 310 es\n"
"#pragma shader_stage(fragment)\n"
"void main() {\n"
" gl_Position = vec4(1.);\n"
"}";
// Parts of a valid disassembly of a minimal shader. We only check certain
// parts since Glslang code generation changes in incidental ways.
const char* kMinimalShaderDisassemblySubstrings[] = {
"; SPIR-V\n"
"; Version: 1.0\n"
"; Generator: Google Shaderc over Glslang; 10\n"
"; Bound:",
" OpCapability Shader\n",
" %1 = OpExtInstImport \"GLSL.std.450\"\n",
" OpMemoryModel Logical GLSL450\n",
" OpReturn\n",
" OpFunctionEnd\n"};
const char* kMinimalShaderDebugInfoDisassemblySubstrings[] = {
"; SPIR-V\n"
"; Version: 1.0\n"
"; Generator: Google Shaderc over Glslang; 10\n"
"; Bound:",
" OpCapability Shader\n",
" %2 = OpExtInstImport \"GLSL.std.450\"\n",
" OpMemoryModel Logical GLSL450\n",
" OpReturn\n",
" OpFunctionEnd\n"};
const char kMinimalShaderAssembly[] = R"(
; SPIR-V
; Version: 1.0
; Generator: Google Shaderc over Glslang; 10
; Bound: 6
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %4 "main"
OpSource ESSL 310
OpName %4 "main"
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd)";
const char kShaderWithUniformsWithoutBindings[] =
R"(#version 450
#extension GL_ARB_sparse_texture2 : enable
uniform texture2D my_tex;
uniform sampler my_sam;
layout(rgba32f) uniform image2D my_img;
layout(rgba32f) uniform imageBuffer my_imbuf;
uniform block { float x; float y; } my_ubo;
void main() {
texture(sampler2D(my_tex,my_sam),vec2(1.0));
vec4 t;
sparseImageLoadARB(my_img,ivec2(0),t);
imageLoad(my_imbuf,42);
float x = my_ubo.x;
})";
// A GLSL vertex shader with a weirdly packed block.
const char kGlslShaderWeirdPacking[] =
R"(#version 450
layout(set=0, binding=0)
buffer B { float x; vec3 foo; } my_ssbo;
void main() { my_ssbo.x = 1.0; })";
// A HLSL fragment shader with a weirdly packed block.
const char kHlslFragShaderWithRegisters[] =
R"(Buffer<float> t4 : register(t4);
Buffer<float> t5 : register(t5);
float4 main() : SV_Target0 {
return float4(t4.Load(0) + t5.Load(1));
})";
// A GLSL compute shader using a regular barrier.
const char kGlslShaderComputeBarrier[] =
R"(#version 450
void main() { barrier(); })";
// A GLSL compute shader using the Subgroups feature.
const char kGlslShaderComputeSubgroupBarrier[] =
R"(#version 450
#extension GL_KHR_shader_subgroup_basic : enable
void main() { subgroupBarrier(); })";
// A GLSL task shader using a regular barrier.
const char kGlslShaderTaskBarrier[] =
R"(#version 450
#extension GL_NV_mesh_shader : enable
layout(local_size_x = 32) in;
void main() { barrier(); })";
// A GLSL task shader using the Subgroups feature.
const char kGlslShaderTaskSubgroupBarrier[] =
R"(#version 450
#extension GL_NV_mesh_shader : enable
#extension GL_KHR_shader_subgroup_basic : enable
layout(local_size_x = 32) in;
void main() { subgroupBarrier(); })";
// A GLSL mesh shader using a regular barrier.
const char kGlslShaderMeshBarrier[] =
R"(#version 450
#extension GL_NV_mesh_shader : enable
layout(local_size_x = 32) in;
layout(max_vertices=81) out;
layout(max_primitives=32) out;
layout(triangles) out;
void main() { barrier(); })";
// A GLSL mesh shader using the Subgroups feature.
const char kGlslShaderMeshSubgroupBarrier[] =
R"(#version 450
#extension GL_NV_mesh_shader : enable
#extension GL_KHR_shader_subgroup_basic : enable
layout(local_size_x = 32) in;
layout(max_vertices=81) out;
layout(max_primitives=32) out;
layout(triangles) out;
void main() { subgroupBarrier(); })";
const char kGlslMultipleFnShader[] =
R"(#version 450
layout(location=0) flat in int inVal;
layout(location=0) out int outVal;
int foo(int a) { return a; }
void main() { outVal = foo(inVal); })";
const char kHlslShaderWithCounterBuffer[] =
R"(RWStructuredBuffer<uint> Ainc;
float4 main() : SV_Target0 {
return float4(Ainc.IncrementCounter(), 0, 0, 0);
})";
const char kHlslWaveActiveSumeComputeShader[] =
R"(struct S { uint val; uint result; };
[[vk::binding(0,0)]]
RWStructuredBuffer<S> MyBuffer;
[numthreads(32, 1, 1)]
void main(uint3 id : SV_DispatchThreadID) {
MyBuffer[id.x].result = WaveActiveSum(MyBuffer[id.x].val);
})";
const char kHlslMemLayoutResourceSelect[] =
R"(cbuffer Foo { float a; float3 b; }
[[vk::binding(0,0)]]
Texture2D Tex;
[[vk::binding(1,0)]]
SamplerState Sampler1;
[[vk::binding(2,0)]]
SamplerState Sampler2;
static const int val = 42;
float4 main() : SV_Target {
SamplerState samp;
if (val > 5)
samp = Sampler1;
else
samp = Sampler2;
return Tex.Sample(samp, float2(0.5, 0.5)) + float4(a, b);
})";
const char kGlslShaderWithClamp[] =
R"(#version 450
layout(location=0) in vec4 i;
layout(location=0) out vec4 o;
void main() { o = clamp(i, vec4(0.5), vec4(1.0)); }
)";
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // COMMON_SHADERS_FOR_TESTS_H_

View File

@ -0,0 +1,794 @@
// 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 <algorithm>
#include <cassert>
#include <cstdint>
#include <memory>
#include <sstream>
#include <vector>
#include "libshaderc_util/compiler.h"
#include "libshaderc_util/counting_includer.h"
#include "libshaderc_util/resources.h"
#include "libshaderc_util/spirv_tools_wrapper.h"
#include "libshaderc_util/version_profile.h"
#include "shaderc_private.h"
#include "spirv/unified1/spirv.hpp"
#if (defined(_MSC_VER) && !defined(_CPPUNWIND)) || !defined(__EXCEPTIONS)
#define TRY_IF_EXCEPTIONS_ENABLED
#define CATCH_IF_EXCEPTIONS_ENABLED(X) if (0)
#else
#define TRY_IF_EXCEPTIONS_ENABLED try
#define CATCH_IF_EXCEPTIONS_ENABLED(X) catch (X)
#endif
namespace {
// Returns shader stage (ie: vertex, fragment, etc.) in response to forced
// shader kinds. If the shader kind is not a forced kind, returns EshLangCount
// to let #pragma annotation or shader stage deducer determine the stage to
// use.
EShLanguage GetForcedStage(shaderc_shader_kind kind) {
switch (kind) {
case shaderc_glsl_vertex_shader:
return EShLangVertex;
case shaderc_glsl_fragment_shader:
return EShLangFragment;
case shaderc_glsl_compute_shader:
return EShLangCompute;
case shaderc_glsl_geometry_shader:
return EShLangGeometry;
case shaderc_glsl_tess_control_shader:
return EShLangTessControl;
case shaderc_glsl_tess_evaluation_shader:
return EShLangTessEvaluation;
case shaderc_glsl_raygen_shader:
return EShLangRayGenNV;
case shaderc_glsl_anyhit_shader:
return EShLangAnyHitNV;
case shaderc_glsl_closesthit_shader:
return EShLangClosestHitNV;
case shaderc_glsl_miss_shader:
return EShLangMissNV;
case shaderc_glsl_intersection_shader:
return EShLangIntersectNV;
case shaderc_glsl_callable_shader:
return EShLangCallableNV;
case shaderc_glsl_task_shader:
return EShLangTaskNV;
case shaderc_glsl_mesh_shader:
return EShLangMeshNV;
case shaderc_glsl_infer_from_source:
case shaderc_glsl_default_vertex_shader:
case shaderc_glsl_default_fragment_shader:
case shaderc_glsl_default_compute_shader:
case shaderc_glsl_default_geometry_shader:
case shaderc_glsl_default_tess_control_shader:
case shaderc_glsl_default_tess_evaluation_shader:
case shaderc_glsl_default_raygen_shader:
case shaderc_glsl_default_anyhit_shader:
case shaderc_glsl_default_closesthit_shader:
case shaderc_glsl_default_miss_shader:
case shaderc_glsl_default_intersection_shader:
case shaderc_glsl_default_callable_shader:
case shaderc_glsl_default_task_shader:
case shaderc_glsl_default_mesh_shader:
case shaderc_spirv_assembly:
return EShLangCount;
}
assert(0 && "Unhandled shaderc_shader_kind");
return EShLangCount;
}
// A wrapper functor class to be used as stage deducer for libshaderc_util
// Compile() interface. When the given shader kind is one of the default shader
// kinds, this functor will be called if #pragma is not found in the source
// code. And it returns the corresponding shader stage. When the shader kind is
// a forced shader kind, this functor won't be called and it simply returns
// EShLangCount to make the syntax correct. When the shader kind is set to
// shaderc_glsl_deduce_from_pragma, this functor also returns EShLangCount, but
// the compiler should emit error if #pragma annotation is not found in this
// case.
class StageDeducer {
public:
explicit StageDeducer(
shaderc_shader_kind kind = shaderc_glsl_infer_from_source)
: kind_(kind), error_(false){}
// The method that underlying glslang will call to determine the shader stage
// to be used in current compilation. It is called only when there is neither
// forced shader kind (or say stage, in the view of glslang), nor #pragma
// annotation in the source code. This method transforms an user defined
// 'default' shader kind to the corresponding shader stage. As this is the
// last trial to determine the shader stage, failing to find the corresponding
// shader stage will record an error.
// Note that calling this method more than once during one compilation will
// have the error recorded for the previous call been overwriten by the next
// call.
EShLanguage operator()(std::ostream* /*error_stream*/,
const shaderc_util::string_piece& /*error_tag*/) {
EShLanguage stage = GetDefaultStage(kind_);
if (stage == EShLangCount) {
error_ = true;
} else {
error_ = false;
}
return stage;
}
// Returns true if there is error during shader stage deduction.
bool error() const { return error_; }
private:
// Gets the corresponding shader stage for a given 'default' shader kind. All
// other kinds are mapped to EShLangCount which should not be used.
EShLanguage GetDefaultStage(shaderc_shader_kind kind) const {
switch (kind) {
case shaderc_glsl_vertex_shader:
case shaderc_glsl_fragment_shader:
case shaderc_glsl_compute_shader:
case shaderc_glsl_geometry_shader:
case shaderc_glsl_tess_control_shader:
case shaderc_glsl_tess_evaluation_shader:
case shaderc_glsl_infer_from_source:
case shaderc_glsl_raygen_shader:
case shaderc_glsl_anyhit_shader:
case shaderc_glsl_closesthit_shader:
case shaderc_glsl_miss_shader:
case shaderc_glsl_intersection_shader:
case shaderc_glsl_callable_shader:
case shaderc_glsl_task_shader:
case shaderc_glsl_mesh_shader:
return EShLangCount;
case shaderc_glsl_default_vertex_shader:
return EShLangVertex;
case shaderc_glsl_default_fragment_shader:
return EShLangFragment;
case shaderc_glsl_default_compute_shader:
return EShLangCompute;
case shaderc_glsl_default_geometry_shader:
return EShLangGeometry;
case shaderc_glsl_default_tess_control_shader:
return EShLangTessControl;
case shaderc_glsl_default_tess_evaluation_shader:
return EShLangTessEvaluation;
case shaderc_glsl_default_raygen_shader:
return EShLangRayGenNV;
case shaderc_glsl_default_anyhit_shader:
return EShLangAnyHitNV;
case shaderc_glsl_default_closesthit_shader:
return EShLangClosestHitNV;
case shaderc_glsl_default_miss_shader:
return EShLangMissNV;
case shaderc_glsl_default_intersection_shader:
return EShLangIntersectNV;
case shaderc_glsl_default_callable_shader:
return EShLangCallableNV;
case shaderc_glsl_default_task_shader:
return EShLangTaskNV;
case shaderc_glsl_default_mesh_shader:
return EShLangMeshNV;
case shaderc_spirv_assembly:
return EShLangCount;
}
assert(0 && "Unhandled shaderc_shader_kind");
return EShLangCount;
}
shaderc_shader_kind kind_;
bool error_;
};
// A bridge between the libshaderc includer and libshaderc_util includer.
class InternalFileIncluder : public shaderc_util::CountingIncluder {
public:
InternalFileIncluder(const shaderc_include_resolve_fn resolver,
const shaderc_include_result_release_fn result_releaser,
void* user_data)
: resolver_(resolver),
result_releaser_(result_releaser),
user_data_(user_data){}
InternalFileIncluder()
: resolver_(nullptr), result_releaser_(nullptr), user_data_(nullptr){}
private:
// Check the validity of the callbacks.
bool AreValidCallbacks() const {
return resolver_ != nullptr && result_releaser_ != nullptr;
}
// Maps CountingIncluder IncludeType value to a shaderc_include_type
// value.
shaderc_include_type GetIncludeType(IncludeType type) {
switch (type) {
case IncludeType::Local:
return shaderc_include_type_relative;
case IncludeType::System:
return shaderc_include_type_standard;
default:
break;
}
assert(0 && "Unhandled IncludeType");
return shaderc_include_type_relative;
}
// Resolves an include request for the requested source of the given
// type in the context of the specified requesting source. On success,
// returns a newly allocated IncludeResponse containing the fully resolved
// name of the requested source and the contents of that source.
// On failure, returns a newly allocated IncludeResponse where the
// resolved name member is an empty string, and the contents members
// contains error details.
virtual glslang::TShader::Includer::IncludeResult* include_delegate(
const char* requested_source, const char* requesting_source,
IncludeType type, size_t include_depth) override {
if (!AreValidCallbacks()) {
static const char kUnexpectedIncludeError[] =
"#error unexpected include directive";
return new glslang::TShader::Includer::IncludeResult{
"", kUnexpectedIncludeError, strlen(kUnexpectedIncludeError),
nullptr};
}
shaderc_include_result* include_result =
resolver_(user_data_, requested_source, GetIncludeType(type),
requesting_source, include_depth);
// Make a glslang IncludeResult from a shaderc_include_result. The
// user_data member of the IncludeResult is a pointer to the
// shaderc_include_result object, so we can later release the latter.
return new glslang::TShader::Includer::IncludeResult{
std::string(include_result->source_name,
include_result->source_name_length),
include_result->content, include_result->content_length,
include_result};
}
// Releases the given IncludeResult.
virtual void release_delegate(
glslang::TShader::Includer::IncludeResult* result) override {
if (result && result_releaser_) {
result_releaser_(user_data_,
static_cast<shaderc_include_result*>(result->userData));
}
delete result;
}
const shaderc_include_resolve_fn resolver_;
const shaderc_include_result_release_fn result_releaser_;
void* user_data_;
};
// Converts the target env to the corresponding one in shaderc_util::Compiler.
shaderc_util::Compiler::TargetEnv GetCompilerTargetEnv(shaderc_target_env env) {
switch (env) {
case shaderc_target_env_opengl:
return shaderc_util::Compiler::TargetEnv::OpenGL;
case shaderc_target_env_opengl_compat:
return shaderc_util::Compiler::TargetEnv::OpenGLCompat;
case shaderc_target_env_webgpu:
assert(false);
break;
case shaderc_target_env_vulkan:
default:
break;
}
return shaderc_util::Compiler::TargetEnv::Vulkan;
}
shaderc_util::Compiler::TargetEnvVersion GetCompilerTargetEnvVersion(
uint32_t version_number) {
using namespace shaderc_util;
if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_0) ==
version_number) {
return Compiler::TargetEnvVersion::Vulkan_1_0;
}
if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_1) ==
version_number) {
return Compiler::TargetEnvVersion::Vulkan_1_1;
}
if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_2) ==
version_number) {
return Compiler::TargetEnvVersion::Vulkan_1_2;
}
if (static_cast<uint32_t>(Compiler::TargetEnvVersion::Vulkan_1_3) ==
version_number) {
return Compiler::TargetEnvVersion::Vulkan_1_3;
}
if (static_cast<uint32_t>(Compiler::TargetEnvVersion::OpenGL_4_5) ==
version_number) {
return Compiler::TargetEnvVersion::OpenGL_4_5;
}
return Compiler::TargetEnvVersion::Default;
}
// Returns the Compiler::Limit enum for the given shaderc_limit enum.
shaderc_util::Compiler::Limit CompilerLimit(shaderc_limit limit) {
switch (limit) {
#define RESOURCE(NAME, FIELD, CNAME) \
case shaderc_limit_##CNAME: \
return shaderc_util::Compiler::Limit::NAME;
#include "libshaderc_util/resources.inc"
#undef RESOURCE
default:
break;
}
assert(0 && "Should not have reached here");
return static_cast<shaderc_util::Compiler::Limit>(0);
}
// Returns the Compiler::UniformKind for the given shaderc_uniform_kind.
shaderc_util::Compiler::UniformKind GetUniformKind(shaderc_uniform_kind kind) {
switch (kind) {
case shaderc_uniform_kind_texture:
return shaderc_util::Compiler::UniformKind::Texture;
case shaderc_uniform_kind_sampler:
return shaderc_util::Compiler::UniformKind::Sampler;
case shaderc_uniform_kind_image:
return shaderc_util::Compiler::UniformKind::Image;
case shaderc_uniform_kind_buffer:
return shaderc_util::Compiler::UniformKind::Buffer;
case shaderc_uniform_kind_storage_buffer:
return shaderc_util::Compiler::UniformKind::StorageBuffer;
case shaderc_uniform_kind_unordered_access_view:
return shaderc_util::Compiler::UniformKind::UnorderedAccessView;
}
assert(0 && "Should not have reached here");
return static_cast<shaderc_util::Compiler::UniformKind>(0);
}
// Returns the Compiler::Stage for generic stage values in shaderc_shader_kind.
shaderc_util::Compiler::Stage GetStage(shaderc_shader_kind kind) {
switch (kind) {
case shaderc_vertex_shader:
return shaderc_util::Compiler::Stage::Vertex;
case shaderc_fragment_shader:
return shaderc_util::Compiler::Stage::Fragment;
case shaderc_compute_shader:
return shaderc_util::Compiler::Stage::Compute;
case shaderc_tess_control_shader:
return shaderc_util::Compiler::Stage::TessControl;
case shaderc_tess_evaluation_shader:
return shaderc_util::Compiler::Stage::TessEval;
case shaderc_geometry_shader:
return shaderc_util::Compiler::Stage::Geometry;
default:
break;
}
assert(0 && "Should not have reached here");
return static_cast<shaderc_util::Compiler::Stage>(0);
}
} // anonymous namespace
struct shaderc_compile_options {
shaderc_target_env target_env = shaderc_target_env_default;
uint32_t target_env_version = 0;
shaderc_util::Compiler compiler;
shaderc_include_resolve_fn include_resolver = nullptr;
shaderc_include_result_release_fn include_result_releaser = nullptr;
void* include_user_data = nullptr;
};
shaderc_compile_options_t shaderc_compile_options_initialize() {
return new (std::nothrow) shaderc_compile_options;
}
shaderc_compile_options_t shaderc_compile_options_clone(
const shaderc_compile_options_t options) {
if (!options) {
return shaderc_compile_options_initialize();
}
return new (std::nothrow) shaderc_compile_options(*options);
}
void shaderc_compile_options_release(shaderc_compile_options_t options) {
delete options;
}
void shaderc_compile_options_add_macro_definition(
shaderc_compile_options_t options, const char* name, size_t name_length,
const char* value, size_t value_length) {
options->compiler.AddMacroDefinition(name, name_length, value, value_length);
}
void shaderc_compile_options_set_source_language(
shaderc_compile_options_t options, shaderc_source_language set_lang) {
auto lang = shaderc_util::Compiler::SourceLanguage::GLSL;
if (set_lang == shaderc_source_language_hlsl)
lang = shaderc_util::Compiler::SourceLanguage::HLSL;
options->compiler.SetSourceLanguage(lang);
}
void shaderc_compile_options_set_generate_debug_info(
shaderc_compile_options_t options) {
options->compiler.SetGenerateDebugInfo();
}
void shaderc_compile_options_set_optimization_level(
shaderc_compile_options_t options, shaderc_optimization_level level) {
auto opt_level = shaderc_util::Compiler::OptimizationLevel::Zero;
switch (level) {
case shaderc_optimization_level_size:
opt_level = shaderc_util::Compiler::OptimizationLevel::Size;
break;
case shaderc_optimization_level_performance:
opt_level = shaderc_util::Compiler::OptimizationLevel::Performance;
break;
default:
break;
}
options->compiler.SetOptimizationLevel(opt_level);
}
void shaderc_compile_options_set_forced_version_profile(
shaderc_compile_options_t options, int version, shaderc_profile profile) {
// Transfer the profile parameter from public enum type to glslang internal
// enum type. No default case here so that compiler will complain if new enum
// member is added later but not handled here.
switch (profile) {
case shaderc_profile_none:
options->compiler.SetForcedVersionProfile(version, ENoProfile);
break;
case shaderc_profile_core:
options->compiler.SetForcedVersionProfile(version, ECoreProfile);
break;
case shaderc_profile_compatibility:
options->compiler.SetForcedVersionProfile(version, ECompatibilityProfile);
break;
case shaderc_profile_es:
options->compiler.SetForcedVersionProfile(version, EEsProfile);
break;
}
}
void shaderc_compile_options_set_include_callbacks(
shaderc_compile_options_t options, shaderc_include_resolve_fn resolver,
shaderc_include_result_release_fn result_releaser, void* user_data) {
options->include_resolver = resolver;
options->include_result_releaser = result_releaser;
options->include_user_data = user_data;
}
void shaderc_compile_options_set_suppress_warnings(
shaderc_compile_options_t options) {
options->compiler.SetSuppressWarnings();
}
void shaderc_compile_options_set_target_env(shaderc_compile_options_t options,
shaderc_target_env target,
uint32_t version) {
options->target_env = target;
options->compiler.SetTargetEnv(GetCompilerTargetEnv(target),
GetCompilerTargetEnvVersion(version));
}
void shaderc_compile_options_set_target_spirv(shaderc_compile_options_t options,
shaderc_spirv_version ver) {
// We made the values match, so we can get away with a static cast.
options->compiler.SetTargetSpirv(
static_cast<shaderc_util::Compiler::SpirvVersion>(ver));
}
void shaderc_compile_options_set_warnings_as_errors(
shaderc_compile_options_t options) {
options->compiler.SetWarningsAsErrors();
}
void shaderc_compile_options_set_limit(shaderc_compile_options_t options,
shaderc_limit limit, int value) {
options->compiler.SetLimit(CompilerLimit(limit), value);
}
void shaderc_compile_options_set_auto_bind_uniforms(
shaderc_compile_options_t options, bool auto_bind) {
options->compiler.SetAutoBindUniforms(auto_bind);
}
void shaderc_compile_options_set_auto_combined_image_sampler(
shaderc_compile_options_t options, bool upgrade) {
options->compiler.SetAutoCombinedImageSampler(upgrade);
}
void shaderc_compile_options_set_hlsl_io_mapping(
shaderc_compile_options_t options, bool hlsl_iomap) {
options->compiler.SetHlslIoMapping(hlsl_iomap);
}
void shaderc_compile_options_set_hlsl_offsets(shaderc_compile_options_t options,
bool hlsl_offsets) {
options->compiler.SetHlslOffsets(hlsl_offsets);
}
void shaderc_compile_options_set_binding_base(shaderc_compile_options_t options,
shaderc_uniform_kind kind,
uint32_t base) {
options->compiler.SetAutoBindingBase(GetUniformKind(kind), base);
}
void shaderc_compile_options_set_binding_base_for_stage(
shaderc_compile_options_t options, shaderc_shader_kind shader_kind,
shaderc_uniform_kind kind, uint32_t base) {
options->compiler.SetAutoBindingBaseForStage(GetStage(shader_kind),
GetUniformKind(kind), base);
}
void shaderc_compile_options_set_auto_map_locations(
shaderc_compile_options_t options, bool auto_map) {
options->compiler.SetAutoMapLocations(auto_map);
}
void shaderc_compile_options_set_hlsl_register_set_and_binding_for_stage(
shaderc_compile_options_t options, shaderc_shader_kind shader_kind,
const char* reg, const char* set, const char* binding) {
options->compiler.SetHlslRegisterSetAndBindingForStage(GetStage(shader_kind),
reg, set, binding);
}
void shaderc_compile_options_set_hlsl_register_set_and_binding(
shaderc_compile_options_t options, const char* reg, const char* set,
const char* binding) {
options->compiler.SetHlslRegisterSetAndBinding(reg, set, binding);
}
void shaderc_compile_options_set_hlsl_functionality1(
shaderc_compile_options_t options, bool enable) {
options->compiler.EnableHlslFunctionality1(enable);
}
void shaderc_compile_options_set_invert_y(
shaderc_compile_options_t options, bool enable) {
options->compiler.EnableInvertY(enable);
}
void shaderc_compile_options_set_nan_clamp(shaderc_compile_options_t options,
bool enable) {
options->compiler.SetNanClamp(enable);
}
shaderc_compiler_t shaderc_compiler_initialize() {
shaderc_compiler_t compiler = new (std::nothrow) shaderc_compiler;
if (compiler) {
compiler->initializer.reset(new shaderc_util::GlslangInitializer);
}
return compiler;
}
void shaderc_compiler_release(shaderc_compiler_t compiler) {
delete compiler;
}
namespace {
shaderc_compilation_result_t CompileToSpecifiedOutputType(
const shaderc_compiler_t compiler, const char* source_text,
size_t source_text_size, shaderc_shader_kind shader_kind,
const char* input_file_name, const char* entry_point_name,
const shaderc_compile_options_t additional_options,
shaderc_util::Compiler::OutputType output_type) {
auto* result = new (std::nothrow) shaderc_compilation_result_vector;
if (!result) return nullptr;
if (!input_file_name) {
result->messages = "Input file name string was null.";
result->num_errors = 1;
result->compilation_status = shaderc_compilation_status_compilation_error;
return result;
}
result->compilation_status = shaderc_compilation_status_invalid_stage;
bool compilation_succeeded = false; // In case we exit early.
std::vector<uint32_t> compilation_output_data;
size_t compilation_output_data_size_in_bytes = 0u;
if (!compiler->initializer) return result;
TRY_IF_EXCEPTIONS_ENABLED {
std::stringstream errors;
size_t total_warnings = 0;
size_t total_errors = 0;
std::string input_file_name_str(input_file_name);
EShLanguage forced_stage = GetForcedStage(shader_kind);
shaderc_util::string_piece source_string =
shaderc_util::string_piece(source_text, source_text + source_text_size);
StageDeducer stage_deducer(shader_kind);
if (additional_options) {
InternalFileIncluder includer(additional_options->include_resolver,
additional_options->include_result_releaser,
additional_options->include_user_data);
// Depends on return value optimization to avoid extra copy.
std::tie(compilation_succeeded, compilation_output_data,
compilation_output_data_size_in_bytes) =
additional_options->compiler.Compile(
source_string, forced_stage, input_file_name_str, entry_point_name,
// stage_deducer has a flag: error_, which we need to check later.
// We need to make this a reference wrapper, so that std::function
// won't make a copy for this callable object.
std::ref(stage_deducer), includer, output_type, &errors,
&total_warnings, &total_errors);
} else {
// Compile with default options.
InternalFileIncluder includer;
std::tie(compilation_succeeded, compilation_output_data,
compilation_output_data_size_in_bytes) =
shaderc_util::Compiler().Compile(
source_string, forced_stage, input_file_name_str, entry_point_name,
std::ref(stage_deducer), includer, output_type, &errors,
&total_warnings, &total_errors);
}
result->messages = errors.str();
result->SetOutputData(std::move(compilation_output_data));
result->output_data_size = compilation_output_data_size_in_bytes;
result->num_warnings = total_warnings;
result->num_errors = total_errors;
if (compilation_succeeded) {
result->compilation_status = shaderc_compilation_status_success;
} else {
// Check whether the error is caused by failing to deduce the shader
// stage. If it is the case, set the error type to shader kind error.
// Otherwise, set it to compilation error.
result->compilation_status =
stage_deducer.error() ? shaderc_compilation_status_invalid_stage
: shaderc_compilation_status_compilation_error;
}
}
CATCH_IF_EXCEPTIONS_ENABLED(...) {
result->compilation_status = shaderc_compilation_status_internal_error;
}
return result;
}
} // anonymous namespace
shaderc_compilation_result_t shaderc_compile_into_spv(
const shaderc_compiler_t compiler, const char* source_text,
size_t source_text_size, shaderc_shader_kind shader_kind,
const char* input_file_name, const char* entry_point_name,
const shaderc_compile_options_t additional_options) {
return CompileToSpecifiedOutputType(
compiler, source_text, source_text_size, shader_kind, input_file_name,
entry_point_name, additional_options,
shaderc_util::Compiler::OutputType::SpirvBinary);
}
shaderc_compilation_result_t shaderc_compile_into_spv_assembly(
const shaderc_compiler_t compiler, const char* source_text,
size_t source_text_size, shaderc_shader_kind shader_kind,
const char* input_file_name, const char* entry_point_name,
const shaderc_compile_options_t additional_options) {
return CompileToSpecifiedOutputType(
compiler, source_text, source_text_size, shader_kind, input_file_name,
entry_point_name, additional_options,
shaderc_util::Compiler::OutputType::SpirvAssemblyText);
}
shaderc_compilation_result_t shaderc_compile_into_preprocessed_text(
const shaderc_compiler_t compiler, const char* source_text,
size_t source_text_size, shaderc_shader_kind shader_kind,
const char* input_file_name, const char* entry_point_name,
const shaderc_compile_options_t additional_options) {
return CompileToSpecifiedOutputType(
compiler, source_text, source_text_size, shader_kind, input_file_name,
entry_point_name, additional_options,
shaderc_util::Compiler::OutputType::PreprocessedText);
}
shaderc_compilation_result_t shaderc_assemble_into_spv(
const shaderc_compiler_t compiler, const char* source_assembly,
size_t source_assembly_size,
const shaderc_compile_options_t additional_options) {
auto* result = new (std::nothrow) shaderc_compilation_result_spv_binary;
if (!result) return nullptr;
result->compilation_status = shaderc_compilation_status_invalid_assembly;
if (!compiler->initializer) return result;
if (source_assembly == nullptr) return result;
TRY_IF_EXCEPTIONS_ENABLED {
spv_binary assembling_output_data = nullptr;
std::string errors;
const auto target_env = additional_options ? additional_options->target_env
: shaderc_target_env_default;
const uint32_t target_env_version =
additional_options ? additional_options->target_env_version : 0;
const bool assembling_succeeded = shaderc_util::SpirvToolsAssemble(
GetCompilerTargetEnv(target_env),
GetCompilerTargetEnvVersion(target_env_version),
{source_assembly, source_assembly + source_assembly_size},
&assembling_output_data, &errors);
result->num_errors = !assembling_succeeded;
if (assembling_succeeded) {
result->SetOutputData(assembling_output_data);
result->output_data_size =
assembling_output_data->wordCount * sizeof(uint32_t);
result->compilation_status = shaderc_compilation_status_success;
} else {
result->messages = std::move(errors);
result->compilation_status = shaderc_compilation_status_invalid_assembly;
}
}
CATCH_IF_EXCEPTIONS_ENABLED(...) {
result->compilation_status = shaderc_compilation_status_internal_error;
}
return result;
}
size_t shaderc_result_get_length(const shaderc_compilation_result_t result) {
return result->output_data_size;
}
size_t shaderc_result_get_num_warnings(
const shaderc_compilation_result_t result) {
return result->num_warnings;
}
size_t shaderc_result_get_num_errors(
const shaderc_compilation_result_t result) {
return result->num_errors;
}
const char* shaderc_result_get_bytes(
const shaderc_compilation_result_t result) {
return result->GetBytes();
}
void shaderc_result_release(shaderc_compilation_result_t result) {
delete result;
}
const char* shaderc_result_get_error_message(
const shaderc_compilation_result_t result) {
return result->messages.c_str();
}
shaderc_compilation_status shaderc_result_get_compilation_status(
const shaderc_compilation_result_t result) {
return result->compilation_status;
}
void shaderc_get_spv_version(unsigned int* version, unsigned int* revision) {
*version = spv::Version;
*revision = spv::Revision;
}
bool shaderc_parse_version_profile(const char* str, int* version,
shaderc_profile* profile) {
EProfile glslang_profile;
bool success = shaderc_util::ParseVersionProfile(
std::string(str, strlen(str)), version, &glslang_profile);
if (!success) return false;
switch (glslang_profile) {
case EEsProfile:
*profile = shaderc_profile_es;
return true;
case ECoreProfile:
*profile = shaderc_profile_core;
return true;
case ECompatibilityProfile:
*profile = shaderc_profile_compatibility;
return true;
case ENoProfile:
*profile = shaderc_profile_none;
return true;
case EBadProfile:
case EProfileCount:
return false;
}
// Shouldn't reach here, all profile enum should be handled above.
// Be strict to return false.
return false;
}

View File

@ -0,0 +1,54 @@
// Copyright 2016 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "shaderc/shaderc.h"
#include <assert.h>
#include <string.h>
// Because we want to test this as a plain old C file, we cannot use
// gtest, so just run a simple smoke test.
int main() {
const char* test_program =
"#version 310 es\n"
"layout(location = 0) in highp vec4 vtxColor;\n"
"layout(location = 0) out highp vec4 outColor;\n"
"void main() {\n"
" outColor = vtxColor;"
"}\n";
shaderc_compiler_t compiler;
shaderc_compilation_result_t result;
shaderc_compile_options_t options;
compiler = shaderc_compiler_initialize();
options = shaderc_compile_options_initialize();
shaderc_compile_options_add_macro_definition(options, "FOO", 3, "1", 1);
result = shaderc_compile_into_spv(
compiler, test_program, strlen(test_program),
shaderc_glsl_fragment_shader, "a.glsl", "main", options);
assert(result);
if (shaderc_result_get_compilation_status(result) !=
shaderc_compilation_status_success) {
// Early exit on failure.
return -1;
}
shaderc_result_release(result);
shaderc_compile_options_release(options);
shaderc_compiler_release(compiler);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_SRC_SHADERC_PRIVATE_H_
#define LIBSHADERC_SRC_SHADERC_PRIVATE_H_
#include <cassert>
#include <cstdint>
#include <string>
#include <vector>
#include "shaderc/shaderc.h"
#include "libshaderc_util/compiler.h"
#include "spirv-tools/libspirv.h"
// Described in shaderc.h.
struct shaderc_compilation_result {
virtual ~shaderc_compilation_result() {}
// Returns the data from this compilation as a sequence of bytes.
virtual const char* GetBytes() const = 0;
// The size of the output data in term of bytes.
size_t output_data_size = 0;
// Compilation messages.
std::string messages;
// Number of errors.
size_t num_errors = 0;
// Number of warnings.
size_t num_warnings = 0;
// Compilation status.
shaderc_compilation_status compilation_status =
shaderc_compilation_status_null_result_object;
};
// Compilation result class using a vector for holding the compilation
// output data.
class shaderc_compilation_result_vector : public shaderc_compilation_result {
public:
~shaderc_compilation_result_vector() = default;
void SetOutputData(std::vector<uint32_t>&& data) {
output_data_ = std::move(data);
}
const char* GetBytes() const override {
return reinterpret_cast<const char*>(output_data_.data());
}
private:
// Compilation output data. In normal compilation mode, it contains the
// compiled SPIR-V binary code. In disassembly and preprocessing-only mode, it
// contains a null-terminated string which is the text output. For text
// output, extra bytes with value 0x00 might be appended to complete the last
// uint32_t element.
std::vector<uint32_t> output_data_;
};
// Compilation result class using a spv_binary for holding the compilation
// output data.
class shaderc_compilation_result_spv_binary
: public shaderc_compilation_result {
public:
~shaderc_compilation_result_spv_binary() { spvBinaryDestroy(output_data_); }
void SetOutputData(spv_binary data) { output_data_ = data; }
const char* GetBytes() const override {
return reinterpret_cast<const char*>(output_data_->code);
}
private:
spv_binary output_data_ = nullptr;
};
namespace shaderc_util {
class GlslangInitializer;
}
struct shaderc_compiler {
std::unique_ptr<shaderc_util::GlslangInitializer> initializer;
};
// Converts a shader stage from shaderc_shader_kind into a shaderc_util::Compiler::Stage.
// This is only valid for a specifically named shader stage, e.g. vertex through fragment,
// or compute.
inline shaderc_util::Compiler::Stage shaderc_convert_specific_stage(
shaderc_shader_kind kind) {
switch (kind) {
case shaderc_vertex_shader:
return shaderc_util::Compiler::Stage::Vertex;
case shaderc_fragment_shader:
return shaderc_util::Compiler::Stage::Fragment;
case shaderc_tess_control_shader:
return shaderc_util::Compiler::Stage::TessControl;
case shaderc_tess_evaluation_shader:
return shaderc_util::Compiler::Stage::TessEval;
case shaderc_geometry_shader:
return shaderc_util::Compiler::Stage::Geometry;
case shaderc_compute_shader:
return shaderc_util::Compiler::Stage::Compute;
case shaderc_raygen_shader:
return shaderc_util::Compiler::Stage::RayGenNV;
case shaderc_intersection_shader:
return shaderc_util::Compiler::Stage::IntersectNV;
case shaderc_anyhit_shader:
return shaderc_util::Compiler::Stage::AnyHitNV;
case shaderc_closesthit_shader:
return shaderc_util::Compiler::Stage::ClosestHitNV;
case shaderc_miss_shader:
return shaderc_util::Compiler::Stage::MissNV;
case shaderc_callable_shader:
return shaderc_util::Compiler::Stage::CallableNV;
case shaderc_task_shader:
return shaderc_util::Compiler::Stage::TaskNV;
case shaderc_mesh_shader:
return shaderc_util::Compiler::Stage::MeshNV;
default:
// We don't care about the other kinds.
break;
}
// This should not occur.
assert(false && "Should have specified a specific stage");
return shaderc_util::Compiler::Stage::TessEval;
}
#endif // LIBSHADERC_SRC_SHADERC_PRIVATE_H_

View File

@ -0,0 +1,50 @@
// Copyright 2017 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <gmock/gmock.h>
#include "shaderc_private.h"
namespace {
TEST(ConvertSpecificStage, Exhaustive) {
EXPECT_EQ(shaderc_util::Compiler::Stage::Vertex,
shaderc_convert_specific_stage(shaderc_vertex_shader));
EXPECT_EQ(shaderc_util::Compiler::Stage::Fragment,
shaderc_convert_specific_stage(shaderc_fragment_shader));
EXPECT_EQ(shaderc_util::Compiler::Stage::TessControl,
shaderc_convert_specific_stage(shaderc_tess_control_shader));
EXPECT_EQ(shaderc_util::Compiler::Stage::TessEval,
shaderc_convert_specific_stage(shaderc_tess_evaluation_shader));
EXPECT_EQ(shaderc_util::Compiler::Stage::Geometry,
shaderc_convert_specific_stage(shaderc_geometry_shader));
EXPECT_EQ(shaderc_util::Compiler::Stage::Compute,
shaderc_convert_specific_stage(shaderc_compute_shader));
EXPECT_EQ(shaderc_util::Compiler::Stage::RayGenNV,
shaderc_convert_specific_stage(shaderc_raygen_shader));
EXPECT_EQ(shaderc_util::Compiler::Stage::AnyHitNV,
shaderc_convert_specific_stage(shaderc_anyhit_shader));
EXPECT_EQ(shaderc_util::Compiler::Stage::ClosestHitNV,
shaderc_convert_specific_stage(shaderc_closesthit_shader));
EXPECT_EQ(shaderc_util::Compiler::Stage::IntersectNV,
shaderc_convert_specific_stage(shaderc_intersection_shader));
EXPECT_EQ(shaderc_util::Compiler::Stage::MissNV,
shaderc_convert_specific_stage(shaderc_miss_shader));
EXPECT_EQ(shaderc_util::Compiler::Stage::CallableNV,
shaderc_convert_specific_stage(shaderc_callable_shader));
EXPECT_EQ(shaderc_util::Compiler::Stage::TaskNV,
shaderc_convert_specific_stage(shaderc_task_shader));
EXPECT_EQ(shaderc_util::Compiler::Stage::MeshNV,
shaderc_convert_specific_stage(shaderc_mesh_shader));
}
} // anonymous namespace

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:=shaderc_util
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -DENABLE_HLSL=1
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/include
LOCAL_SRC_FILES:=src/args.cc \
src/compiler.cc \
src/file_finder.cc \
src/io_shaderc.cc \
src/message.cc \
src/resources.cc \
src/shader_stage.cc \
src/spirv_tools_wrapper.cc \
src/version_profile.cc
LOCAL_STATIC_LIBRARIES:=SPIRV SPIRV-Tools-opt
LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include
include $(BUILD_STATIC_LIBRARY)

View File

@ -0,0 +1,89 @@
# Copyright 2020 The Shaderc Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
project(libshaderc_util)
add_library(shaderc_util STATIC
include/libshaderc_util/counting_includer.h
include/libshaderc_util/file_finder.h
include/libshaderc_util/format.h
include/libshaderc_util/io_shaderc.h
include/libshaderc_util/mutex.h
include/libshaderc_util/message.h
include/libshaderc_util/resources.h
include/libshaderc_util/spirv_tools_wrapper.h
include/libshaderc_util/string_piece.h
include/libshaderc_util/universal_unistd.h
include/libshaderc_util/version_profile.h
src/args.cc
src/compiler.cc
src/file_finder.cc
src/io_shaderc.cc
src/message.cc
src/resources.cc
src/shader_stage.cc
src/spirv_tools_wrapper.cc
src/version_profile.cc
)
shaderc_default_compile_options(shaderc_util)
target_include_directories(shaderc_util
PUBLIC include PRIVATE ${glslang_SOURCE_DIR})
# We use parts of Glslang's HLSL compilation interface, which
# now requires this preprocessor definition.
add_definitions(-DENABLE_HLSL)
find_package(Threads)
target_link_libraries(shaderc_util PRIVATE
glslang OSDependent OGLCompiler HLSL glslang SPIRV
SPIRV-Tools-opt ${CMAKE_THREAD_LIBS_INIT})
shaderc_add_tests(
TEST_PREFIX shaderc_util
LINK_LIBS shaderc_util
TEST_NAMES
counting_includer
string_piece
format
file_finder
io_shaderc
message
mutex
version_profile)
if(${SHADERC_ENABLE_TESTS})
target_include_directories(shaderc_util_counting_includer_test
PRIVATE ${glslang_SOURCE_DIR})
target_include_directories(shaderc_util_version_profile_test
PRIVATE ${glslang_SOURCE_DIR})
endif()
shaderc_add_tests(
TEST_PREFIX shaderc_util
LINK_LIBS shaderc_util
INCLUDE_DIRS
${glslang_SOURCE_DIR}
${spirv-tools_SOURCE_DIR}/include
TEST_NAMES
compiler)
# This target copies content of testdata into the build directory.
add_custom_target(testdata COMMAND
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/testdata/copy-to-build.cmake
COMMENT "Copy testdata into build directory")
if(${SHADERC_ENABLE_TESTS})
add_dependencies(shaderc_util_file_finder_test testdata)
add_dependencies(shaderc_util_io_shaderc_test testdata)
endif()

View File

@ -0,0 +1,41 @@
// Copyright 2019 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_INC_ARGS_H
#define LIBSHADERC_UTIL_INC_ARGS_H
#include <cstdint>
#include <string>
#include "libshaderc_util/string_piece.h"
namespace shaderc_util {
// Gets the option argument for the option at *index in argv in a way consistent
// with clang/gcc. On success, returns true and writes the parsed argument into
// *option_argument. Returns false if any errors occur. After calling this
// function, *index will be the index of the last command line argument
// consumed.
bool GetOptionArgument(int argc, char** argv, int* index,
const std::string& option,
string_piece* option_argument);
// Parses the given string as a number of the specified type. Returns true
// if parsing succeeded, and stores the parsed value via |value|.
// (I've worked out the general case for this in
// SPIRV-Tools source/util/parse_number.h. -- dneto)
bool ParseUint32(const std::string& str, uint32_t* value);
} // namespace shaderc_util
#endif // LIBSHADERC_UTIL_INC_ARGS_H

View File

@ -0,0 +1,621 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_INC_COMPILER_H
#define LIBSHADERC_UTIL_INC_COMPILER_H
#include <array>
#include <cassert>
#include <functional>
#include <mutex>
#include <ostream>
#include <string>
#include <unordered_map>
#include <utility>
#include "glslang/Public/ShaderLang.h"
#include "counting_includer.h"
#include "file_finder.h"
#include "mutex.h"
#include "resources.h"
#include "string_piece.h"
// Fix a typo in glslang/Public/ShaderLang.h
#define EShTargetClientVersion EshTargetClientVersion
namespace shaderc_util {
// To break recursive including. This header is already included in
// spirv_tools_wrapper.h, so cannot include spirv_tools_wrapper.h here.
enum class PassId;
// Initializes glslang on creation, and destroys it on completion.
// Used to tie gslang process operations to object lifetimes.
// Additionally initialization/finalization of glslang is not thread safe, so
// synchronizes these operations.
class GlslangInitializer {
public:
GlslangInitializer();
~GlslangInitializer();
private:
static unsigned int initialize_count_;
// Using a bare pointer here to avoid any global class construction at the
// beginning of the execution.
static std::mutex* glslang_mutex_;
};
// Maps macro names to their definitions. Stores string_pieces, so the
// underlying strings must outlive it.
using MacroDictionary = std::unordered_map<std::string, std::string>;
// Holds all of the state required to compile source GLSL into SPIR-V.
class Compiler {
public:
// Source language
enum class SourceLanguage {
GLSL, // The default
HLSL,
};
// Target environment.
enum class TargetEnv {
Vulkan, // Default to Vulkan 1.0
OpenGL, // Default to OpenGL 4.5
OpenGLCompat, // Support removed. Generates error if used.
};
// Target environment versions. These numbers match those used by Glslang.
enum class TargetEnvVersion : uint32_t {
Default = 0, // Default for the corresponding target environment
// For Vulkan, use numbering scheme from vulkan.h
Vulkan_1_0 = ((1 << 22)), // Vulkan 1.0
Vulkan_1_1 = ((1 << 22) | (1 << 12)), // Vulkan 1.1
Vulkan_1_2 = ((1 << 22) | (2 << 12)), // Vulkan 1.2
Vulkan_1_3 = ((1 << 22) | (3 << 12)), // Vulkan 1.2
// For OpenGL, use the numbering from #version in shaders.
OpenGL_4_5 = 450,
};
// SPIR-V version.
enum class SpirvVersion : uint32_t {
v1_0 = 0x010000u,
v1_1 = 0x010100u,
v1_2 = 0x010200u,
v1_3 = 0x010300u,
v1_4 = 0x010400u,
v1_5 = 0x010500u,
v1_6 = 0x010600u,
};
enum class OutputType {
SpirvBinary, // A binary module, as defined by the SPIR-V specification.
SpirvAssemblyText, // Assembly syntax defined by the SPIRV-Tools project.
PreprocessedText, // Preprocessed source code.
};
// Supported optimization levels.
enum class OptimizationLevel {
Zero, // No optimization.
Size, // Optimization towards reducing code size.
Performance, // Optimization towards better performance.
};
// Resource limits. These map to the "max*" fields in
// glslang::TBuiltInResource.
enum class Limit {
#define RESOURCE(NAME, FIELD, CNAME) NAME,
#include "resources.inc"
#undef RESOURCE
};
// Types of uniform variables.
enum class UniformKind {
// Image, and image buffer.
Image = 0,
// Pure sampler.
Sampler = 1,
// Sampled texture in GLSL.
// Shader Resource View, for HLSL. (Read-only image or storage buffer.)
Texture = 2,
// Uniform Buffer Object, or UBO, in GLSL.
// Also a Cbuffer in HLSL.
Buffer = 3,
// Shader Storage Buffer Object, or SSBO
StorageBuffer = 4,
// Uniform Access View, in HLSL. (Writable storage image or storage
// buffer.)
UnorderedAccessView = 5,
};
enum { kNumUniformKinds = int(UniformKind::UnorderedAccessView) + 1 };
// Shader pipeline stage.
// TODO(dneto): Replaces interface uses of EShLanguage with this enum.
enum class Stage {
Vertex,
TessEval,
TessControl,
Geometry,
Fragment,
Compute,
RayGenNV,
IntersectNV,
AnyHitNV,
ClosestHitNV,
MissNV,
CallableNV,
TaskNV,
MeshNV,
StageEnd,
};
enum { kNumStages = int(Stage::StageEnd) };
// Returns a std::array of all the Stage values.
const std::array<Stage, kNumStages>& stages() const {
static std::array<Stage, kNumStages> values{{
Stage::Vertex,
Stage::TessEval,
Stage::TessControl,
Stage::Geometry,
Stage::Fragment,
Stage::Compute,
Stage::RayGenNV,
Stage::IntersectNV,
Stage::AnyHitNV,
Stage::ClosestHitNV,
Stage::MissNV,
Stage::CallableNV,
Stage::TaskNV,
Stage::MeshNV,
}};
return values;
}
// Creates an default compiler instance targeting at Vulkan environment. Uses
// version 110 and no profile specification as the default for GLSL.
Compiler()
// The default version for glsl is 110, or 100 if you are using an es
// profile. But we want to default to a non-es profile.
: default_version_(110),
default_profile_(ENoProfile),
force_version_profile_(false),
warnings_as_errors_(false),
suppress_warnings_(false),
generate_debug_info_(false),
enabled_opt_passes_(),
target_env_(TargetEnv::Vulkan),
target_env_version_(TargetEnvVersion::Default),
target_spirv_version_(SpirvVersion::v1_0),
target_spirv_version_is_forced_(false),
source_language_(SourceLanguage::GLSL),
limits_(kDefaultTBuiltInResource),
auto_bind_uniforms_(false),
auto_combined_image_sampler_(false),
auto_binding_base_(),
auto_map_locations_(false),
hlsl_iomap_(false),
hlsl_offsets_(false),
hlsl_legalization_enabled_(true),
hlsl_functionality1_enabled_(false),
invert_y_enabled_(false),
nan_clamp_(false),
hlsl_explicit_bindings_() {}
// Requests that the compiler place debug information into the object code,
// such as identifier names and line numbers.
void SetGenerateDebugInfo();
// Sets the optimization level to the given level. Only the last one takes
// effect if multiple calls of this method exist.
void SetOptimizationLevel(OptimizationLevel level);
// Enables or disables HLSL legalization passes.
void EnableHlslLegalization(bool hlsl_legalization_enabled);
// Enables or disables extension SPV_GOOGLE_hlsl_functionality1
void EnableHlslFunctionality1(bool enable);
// Enables or disables invert position.Y output in vertex shader.
void EnableInvertY(bool enable);
// Sets whether the compiler generates code for max and min builtins which,
// if given a NaN operand, will return the other operand. Also, the clamp
// builtin will favour the non-NaN operands, as if clamp were implemented
// as a composition of max and min.
void SetNanClamp(bool enable);
// When a warning is encountered it treat it as an error.
void SetWarningsAsErrors();
// Any warning message generated is suppressed before it is output.
void SetSuppressWarnings();
// Adds an implicit macro definition obeyed by subsequent CompileShader()
// calls. The macro and definition should be passed in with their char*
// pointer and their lengths. They can be modified or deleted after this
// function has returned.
void AddMacroDefinition(const char* macro, size_t macro_length,
const char* definition, size_t definition_length);
// Sets the target environment, including version. The version value should
// be 0 or one of the values from TargetEnvVersion. The default value maps
// to Vulkan 1.0 if the target environment is Vulkan, and it maps to OpenGL
// 4.5 if the target environment is OpenGL.
void SetTargetEnv(TargetEnv env,
TargetEnvVersion version = TargetEnvVersion::Default);
// Sets the target version of SPIR-V. The module will use this version
// of SPIR-V. Defaults to the highest version of SPIR-V required to be
// supported by the target environment. E.g. default to SPIR-V 1.0 for
// Vulkan 1.0, and SPIR-V 1.3 for Vulkan 1.1.
void SetTargetSpirv(SpirvVersion version);
// Sets the souce language.
void SetSourceLanguage(SourceLanguage lang);
// Forces (without any verification) the default version and profile for
// subsequent CompileShader() calls.
void SetForcedVersionProfile(int version, EProfile profile);
// Sets a resource limit.
void SetLimit(Limit limit, int value);
// Returns the current limit.
int GetLimit(Limit limit) const;
// Set whether the compiler automatically assigns bindings to
// uniform variables that don't have explicit bindings.
void SetAutoBindUniforms(bool auto_bind) { auto_bind_uniforms_ = auto_bind; }
// Sets whether the compiler should automatically remove sampler variables
// and convert image variables to combined image-sampler variables.
void SetAutoCombinedImageSampler(bool auto_combine) {
auto_combined_image_sampler_ = auto_combine;
}
// Sets the lowest binding number used when automatically assigning bindings
// for uniform resources of the given type, for all shader stages. The default
// base is zero.
void SetAutoBindingBase(UniformKind kind, uint32_t base) {
for (auto stage : stages()) {
SetAutoBindingBaseForStage(stage, kind, base);
}
}
// Sets the lowest binding number used when automatically assigning bindings
// for uniform resources of the given type for a specific shader stage. The
// default base is zero.
void SetAutoBindingBaseForStage(Stage stage, UniformKind kind,
uint32_t base) {
auto_binding_base_[static_cast<int>(stage)][static_cast<int>(kind)] = base;
}
// Sets whether the compiler automatically assigns locations to
// uniform variables that don't have explicit locations.
void SetAutoMapLocations(bool auto_map) { auto_map_locations_ = auto_map; }
// Use HLSL IO mapping rules for bindings. Default is false.
void SetHlslIoMapping(bool hlsl_iomap) { hlsl_iomap_ = hlsl_iomap; }
// Use HLSL rules for offsets in "transparent" memory. These allow for
// tighter packing of some combinations of types than standard GLSL packings.
void SetHlslOffsets(bool hlsl_offsets) { hlsl_offsets_ = hlsl_offsets; }
// Sets an explicit set and binding for the given HLSL register.
void SetHlslRegisterSetAndBinding(const std::string& reg,
const std::string& set,
const std::string& binding) {
for (auto stage : stages()) {
SetHlslRegisterSetAndBindingForStage(stage, reg, set, binding);
}
}
// Sets an explicit set and binding for the given HLSL register in the given
// shader stage. For example,
// SetHlslRegisterSetAndBinding(Stage::Fragment, "t1", "4", "5")
// means register "t1" in a fragment shader should map to binding 5 in set 4.
// (Glslang wants this data as strings, not ints or enums.) The string data is
// copied.
void SetHlslRegisterSetAndBindingForStage(Stage stage, const std::string& reg,
const std::string& set,
const std::string& binding) {
hlsl_explicit_bindings_[static_cast<int>(stage)].push_back(reg);
hlsl_explicit_bindings_[static_cast<int>(stage)].push_back(set);
hlsl_explicit_bindings_[static_cast<int>(stage)].push_back(binding);
}
// Compiles the shader source in the input_source_string parameter.
//
// If the forced_shader stage parameter is not EShLangCount then
// the shader is assumed to be of the given stage.
//
// For HLSL compilation, entry_point_name is the null-terminated string for
// the entry point. For GLSL compilation, entry_point_name is ignored, and
// compilation assumes the entry point is named "main".
//
// The stage_callback function will be called if a shader_stage has
// not been forced and the stage can not be determined
// from the shader text. Any #include directives are parsed with the given
// includer.
//
// The initializer parameter must be a valid GlslangInitializer object.
// Acquire will be called on the initializer and the result will be
// destroyed before the function ends.
//
// The output_type parameter determines what kind of output should be
// produced.
//
// Any error messages are written as if the file name were error_tag.
// Any errors are written to the error_stream parameter.
// total_warnings and total_errors are incremented once for every
// warning or error encountered respectively.
//
// Returns a tuple consisting of three fields. 1) a boolean which is true when
// the compilation succeeded, and false otherwise; 2) a vector of 32-bit words
// which contains the compilation output data, either compiled SPIR-V binary
// code, or the text string generated in preprocessing-only or disassembly
// mode; 3) the size of the output data in bytes. When the output is SPIR-V
// binary code, the size is the number of bytes of valid data in the vector.
// If the output is a text string, the size equals the length of that string.
std::tuple<bool, std::vector<uint32_t>, size_t> Compile(
const string_piece& input_source_string, EShLanguage forced_shader_stage,
const std::string& error_tag, const char* entry_point_name,
const std::function<EShLanguage(std::ostream* error_stream,
const string_piece& error_tag)>&
stage_callback,
CountingIncluder& includer, OutputType output_type,
std::ostream* error_stream, size_t* total_warnings, size_t* total_errors) const;
static EShMessages GetDefaultRules() {
return static_cast<EShMessages>(EShMsgSpvRules | EShMsgVulkanRules |
EShMsgCascadingErrors);
}
protected:
// Preprocesses a shader whose filename is filename and content is
// shader_source. If preprocessing is successful, returns true, the
// preprocessed shader, and any warning message as a tuple. Otherwise,
// returns false, an empty string, and error messages as a tuple.
//
// The error_tag parameter is the name to use for outputting errors.
// The shader_source parameter is the input shader's source text.
// The shader_preamble parameter is a context-specific preamble internally
// prepended to shader_text without affecting the validity of its #version
// position.
//
// Any #include directives are processed with the given includer.
//
// If force_version_profile_ is set, the shader's version/profile is forced
// to be default_version_/default_profile_ regardless of the #version
// directive in the source code.
std::tuple<bool, std::string, std::string> PreprocessShader(
const std::string& error_tag, const string_piece& shader_source,
const string_piece& shader_preamble, CountingIncluder& includer) const;
// Cleans up the preamble in a given preprocessed shader.
//
// The error_tag parameter is the name to be given for the main file.
// The pound_extension parameter is the #extension directive we prepended to
// the original shader source code via preamble.
// The num_include_directives parameter is the number of #include directives
// appearing in the original shader source code.
// The is_for_next_line means whether the #line sets the line number for the
// next line.
//
// If no #include directive is used in the shader source code, we can safely
// delete the #extension directive we injected via preamble. Otherwise, we
// need to adjust it if there exists a #version directive in the original
// shader source code.
std::string CleanupPreamble(const string_piece& preprocessed_shader,
const string_piece& error_tag,
const string_piece& pound_extension,
int num_include_directives,
bool is_for_next_line) const;
// Determines version and profile from command line, or the source code.
// Returns the decoded version and profile pair on success. Otherwise,
// returns (0, ENoProfile).
std::pair<int, EProfile> DeduceVersionProfile(
const std::string& preprocessed_shader) const;
// Determines the shader stage from pragmas embedded in the source text if
// possible. In the returned pair, the glslang EShLanguage is the shader
// stage deduced. If no #pragma directives for shader stage exist, it's
// EShLangCount. If errors occur, the second element in the pair is the
// error message. Otherwise, it's an empty string.
std::pair<EShLanguage, std::string> GetShaderStageFromSourceCode(
string_piece filename, const std::string& preprocessed_shader) const;
// Determines version and profile from command line, or the source code.
// Returns the decoded version and profile pair on success. Otherwise,
// returns (0, ENoProfile).
std::pair<int, EProfile> DeduceVersionProfile(
const std::string& preprocessed_shader);
// Gets version and profile specification from the given preprocessedshader.
// Returns the decoded version and profile pair on success. Otherwise,
// returns (0, ENoProfile).
std::pair<int, EProfile> GetVersionProfileFromSourceCode(
const std::string& preprocessed_shader) const;
// Version to use when force_version_profile_ is true.
int default_version_;
// Profile to use when force_version_profile_ is true.
EProfile default_profile_;
// When true, use the default version and profile from eponymous data members.
bool force_version_profile_;
// Macro definitions that must be available to reference in the shader source.
MacroDictionary predefined_macros_;
// When true, treat warnings as errors.
bool warnings_as_errors_;
// Supress warnings when true.
bool suppress_warnings_;
// When true, compilation will generate debug info with the binary SPIR-V
// output.
bool generate_debug_info_;
// Optimization passes to be applied.
std::vector<PassId> enabled_opt_passes_;
// The target environment to compile with. This controls the glslang
// EshMessages bitmask, which determines which dialect of GLSL and which
// SPIR-V codegen semantics are used. This impacts the warning & error
// messages as well as the set of available builtins, as per the
// implementation of glslang.
TargetEnv target_env_;
// The version number of the target environment. The numbering scheme is
// particular to each target environment. If this is 0, then use a default
// for that particular target environment. See libshaders/shaderc/shaderc.h
// for those defaults.
TargetEnvVersion target_env_version_;
// The SPIR-V version to be used for the generated module. Defaults to 1.0.
SpirvVersion target_spirv_version_;
// True if the user explicitly set the target SPIR-V version.
bool target_spirv_version_is_forced_;
// The source language. Defaults to GLSL.
SourceLanguage source_language_;
// The resource limits to be used.
TBuiltInResource limits_;
// True if the compiler should automatically bind uniforms that don't
// have explicit bindings.
bool auto_bind_uniforms_;
// True if the compiler should automatically remove sampler variables
// and convert image variables to combined image-sampler variables.
bool auto_combined_image_sampler_;
// The base binding number per uniform type, per stage, used when automatically
// binding uniforms that don't hzve explicit bindings in the shader source.
// The default is zero.
uint32_t auto_binding_base_[kNumStages][kNumUniformKinds];
// True if the compiler should automatically map uniforms that don't
// have explicit locations.
bool auto_map_locations_;
// True if the compiler should use HLSL IO mapping rules when compiling HLSL.
bool hlsl_iomap_;
// True if the compiler should determine block member offsets using HLSL
// packing rules instead of standard GLSL rules.
bool hlsl_offsets_;
// True if the compiler should perform legalization optimization passes if
// source language is HLSL.
bool hlsl_legalization_enabled_;
// True if the compiler should support extension SPV_GOOGLE_hlsl_functionality1.
bool hlsl_functionality1_enabled_;
// True if the compiler should invert position.Y output in vertex shader.
bool invert_y_enabled_;
// True if the compiler generates code for max and min builtins which,
// if given a NaN operand, will return the other operand. Also, the clamp
// builtin will favour the non-NaN operands, as if clamp were implemented
// as a composition of max and min.
bool nan_clamp_;
// A sequence of triples, each triple representing a specific HLSL register
// name, and the set and binding numbers it should be mapped to, but in
// the form of strings. This is how Glslang wants to consume the data.
std::vector<std::string> hlsl_explicit_bindings_[kNumStages];
};
// Converts a string to a vector of uint32_t by copying the content of a given
// string to the vector and returns it. Appends '\0' at the end if extra bytes
// are required to complete the last element.
std::vector<uint32_t> ConvertStringToVector(const std::string& str);
// Converts a valid Glslang shader stage value to a Compiler::Stage value.
inline Compiler::Stage ConvertToStage(EShLanguage stage) {
switch (stage) {
case EShLangVertex:
return Compiler::Stage::Vertex;
case EShLangTessControl:
return Compiler::Stage::TessEval;
case EShLangTessEvaluation:
return Compiler::Stage::TessControl;
case EShLangGeometry:
return Compiler::Stage::Geometry;
case EShLangFragment:
return Compiler::Stage::Fragment;
case EShLangCompute:
return Compiler::Stage::Compute;
case EShLangRayGenNV:
return Compiler::Stage::RayGenNV;
case EShLangIntersectNV:
return Compiler::Stage::IntersectNV;
case EShLangAnyHitNV:
return Compiler::Stage::AnyHitNV;
case EShLangClosestHitNV:
return Compiler::Stage::ClosestHitNV;
case EShLangMissNV:
return Compiler::Stage::MissNV;
case EShLangCallableNV:
return Compiler::Stage::CallableNV;
case EShLangTaskNV:
return Compiler::Stage::TaskNV;
case EShLangMeshNV:
return Compiler::Stage::MeshNV;
default:
break;
}
assert(false && "Invalid case");
return Compiler::Stage::Compute;
}
// A GlslangClientInfo captures target client version and desired SPIR-V
// version.
struct GlslangClientInfo {
GlslangClientInfo() {}
GlslangClientInfo(const std::string& e, glslang::EShClient c,
glslang::EShTargetClientVersion cv,
glslang::EShTargetLanguage l,
glslang::EShTargetLanguageVersion lv)
: error(e),
client(c),
client_version(cv),
target_language(l),
target_language_version(lv) {}
std::string error; // Empty if ok, otherwise contains the error message.
glslang::EShClient client = glslang::EShClientNone;
glslang::EShTargetClientVersion client_version;
glslang::EShTargetLanguage target_language = glslang::EShTargetSpv;
glslang::EShTargetLanguageVersion target_language_version =
glslang::EShTargetSpv_1_0;
};
// Returns the mappings to Glslang client, client version, and SPIR-V version.
// Also indicates whether the input values were valid.
GlslangClientInfo GetGlslangClientInfo(
const std::string& error_tag, // Indicates source location, for errors.
shaderc_util::Compiler::TargetEnv env,
shaderc_util::Compiler::TargetEnvVersion env_version,
shaderc_util::Compiler::SpirvVersion spv_version,
bool spv_version_is_forced);
} // namespace shaderc_util
#endif // LIBSHADERC_UTIL_INC_COMPILER_H

View File

@ -0,0 +1,101 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_COUNTING_INCLUDER_H
#define LIBSHADERC_UTIL_COUNTING_INCLUDER_H
#include <atomic>
#include "glslang/Public/ShaderLang.h"
#include "libshaderc_util/mutex.h"
namespace shaderc_util {
// An Includer that counts how many #include directives it saw.
// Inclusions are internally serialized, but releasing a previous result
// can occur concurrently.
class CountingIncluder : public glslang::TShader::Includer {
public:
// Done as .store(0) instead of in the initializer list for the following
// reasons:
// Clang > 3.6 will complain about it if it is written as ({0}).
// VS2013 fails if it is written as {0}.
// G++-4.8 does not correctly support std::atomic_init.
CountingIncluder() {
num_include_directives_.store(0);
}
enum class IncludeType {
System, // Only do < > include search
Local, // Only do " " include search
};
// Resolves an include request for a source by name, type, and name of the
// requesting source. For the semantics of the result, see the base class.
// Also increments num_include_directives and returns the results of
// include_delegate(filename). Subclasses should override include_delegate()
// instead of this method. Inclusions are serialized.
glslang::TShader::Includer::IncludeResult* includeSystem(
const char* requested_source, const char* requesting_source,
size_t include_depth) final {
++num_include_directives_;
include_mutex_.lock();
auto result = include_delegate(requested_source, requesting_source,
IncludeType::System, include_depth);
include_mutex_.unlock();
return result;
}
// Like includeSystem, but for "local" include search.
glslang::TShader::Includer::IncludeResult* includeLocal(
const char* requested_source, const char* requesting_source,
size_t include_depth) final {
++num_include_directives_;
include_mutex_.lock();
auto result = include_delegate(requested_source, requesting_source,
IncludeType::Local, include_depth);
include_mutex_.unlock();
return result;
}
// Releases the given IncludeResult.
void releaseInclude(glslang::TShader::Includer::IncludeResult* result) final {
release_delegate(result);
}
int num_include_directives() const { return num_include_directives_.load(); }
private:
// Invoked by this class to provide results to
// glslang::TShader::Includer::include.
virtual glslang::TShader::Includer::IncludeResult* include_delegate(
const char* requested_source, const char* requesting_source,
IncludeType type, size_t include_depth) = 0;
// Release the given IncludeResult.
virtual void release_delegate(
glslang::TShader::Includer::IncludeResult* result) = 0;
// The number of #include directive encountered.
std::atomic_int num_include_directives_;
// A mutex to protect against concurrent inclusions. We can't trust
// our delegates to be safe for concurrent inclusions.
shaderc_util::mutex include_mutex_;
};
}
#endif // LIBSHADERC_UTIL_COUNTING_INCLUDER_H

View File

@ -0,0 +1,26 @@
// Copyright 2018 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_EXCEPTIONS_H_
#define LIBSHADERC_UTIL_EXCEPTIONS_H_
#if (defined(_MSC_VER) && !defined(_CPPUNWIND)) || !defined(__EXCEPTIONS)
#define TRY_IF_EXCEPTIONS_ENABLED
#define CATCH_IF_EXCEPTIONS_ENABLED(X) if (0)
#else
#define TRY_IF_EXCEPTIONS_ENABLED try
#define CATCH_IF_EXCEPTIONS_ENABLED(X) catch (X)
#endif
#endif // LIBSHADERC_UTIL_EXCEPTIONS_H_

View File

@ -0,0 +1,57 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_SRC_FILE_FINDER_H_
#define LIBSHADERC_UTIL_SRC_FILE_FINDER_H_
#include <string>
#include <vector>
namespace shaderc_util {
// Finds files within a search path.
class FileFinder {
public:
// Searches for a read-openable file based on filename, which must be
// non-empty. The search is attempted on filename prefixed by each element of
// search_path() in turn. The first hit is returned, or an empty string if
// there are no hits. Search attempts treat their argument the way
// std::fopen() treats its filename argument, ignoring whether the path is
// absolute or relative.
//
// If a search_path() element is non-empty and not ending in a slash, then a
// slash is inserted between it and filename before its search attempt. An
// empty string in search_path() means that the filename is tried as-is.
std::string FindReadableFilepath(const std::string& filename) const;
// Searches for a read-openable file based on filename, which must be
// non-empty. The search is first attempted as a path relative to
// the requesting_file parameter. If no file is found relative to the
// requesting_file then this acts as FindReadableFilepath does. If
// requesting_file does not contain a '/' or a '\' character then it is
// assumed to be a filename and the request will be relative to the
// current directory.
std::string FindRelativeReadableFilepath(const std::string& requesting_file,
const std::string& filename) const;
// Search path for Find(). Users may add/remove elements as desired.
std::vector<std::string>& search_path() { return search_path_; }
private:
std::vector<std::string> search_path_;
};
} // namespace shaderc_util
#endif // LIBSHADERC_UTIL_SRC_FILE_FINDER_H_

View File

@ -0,0 +1,36 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_FORMAT_H_
#define LIBSHADERC_UTIL_FORMAT_H_
#include <sstream>
namespace shaderc_util {
// Returns a string containing <prefix><key><infix><value><postfix> for every
// key-value entry in map.
template <typename Map>
std::string format(const Map& map, const std::string& prefix,
const std::string& infix, const std::string& postfix) {
std::stringstream s;
for (const auto& pair : map) {
s << prefix << pair.first << infix << pair.second << postfix;
}
return s.str();
}
} // namespace shaderc_util
#endif // LIBSHADERC_UTIL_FORMAT_H_

View File

@ -0,0 +1,69 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_IO_H_
#define LIBSHADERC_UTIL_IO_H_
#include <string>
#include <vector>
#include "string_piece.h"
namespace shaderc_util {
// Returns true if the given path is an absolute path.
bool IsAbsolutePath(const std::string& path);
// A helper function to return the base file name from either absolute path or
// relative path representation of a file. It keeps the component from the last
// '/' or '\' to the end of the given string. If the component is '..' or '.',
// returns an empty string. If '/' or '\' is the last char of the given string,
// also returns an empty string.
// e.g.: dir_a/dir_b/file_c.vert => file_c.vert
// dir_a/dir_b/.. => <empty string>
// dir_a/dir_b/. => <empty string>
// dir_a/dirb/c/ => <empty string>
// Note that this method doesn't check whether the given path is a valid one or
// not.
std::string GetBaseFileName(const std::string& file_path);
// Reads all of the characters in a given file into input_data. Outputs an
// error message to std::cerr if the file could not be read and returns false if
// there was an error. If the input_file is "-", then input is read from
// std::cin.
bool ReadFile(const std::string& input_file_name,
std::vector<char>* input_data);
// Returns and initializes the file_stream parameter if the output_filename
// refers to a file, or returns &std::cout if the output_filename is "-".
// Returns nullptr and emits an error message to err if the file could
// not be opened for writing. If the output refers to a file, and the open
// failed for writing, file_stream is left with its fail_bit set.
std::ostream* GetOutputStream(const string_piece& output_filename,
std::ofstream* file_stream, std::ostream* err);
// Writes output_data to a file, overwriting if it exists. If output_file_name
// is "-", writes to std::cout.
bool WriteFile(std::ostream* output_stream, const string_piece& output_data);
// Flush the standard output stream and set it to binary mode. Subsequent
// output will not translate newlines to carriage-return newline pairs.
void FlushAndSetBinaryModeOnStdout();
// Flush the standard output stream and set it to text mode. Subsequent
// output will translate newlines to carriage-return newline pairs.
void FlushAndSetTextModeOnStdout();
} // namespace shaderc_util
#endif // LIBSHADERC_UTIL_IO_H_

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.
#ifndef LIBSHADERC_UTIL_SRC_MESSAGE_H_
#define LIBSHADERC_UTIL_SRC_MESSAGE_H_
#include "libshaderc_util/string_piece.h"
namespace shaderc_util {
// TODO(antiagainst): document the differences of the following message types.
enum class MessageType {
Warning,
Error,
ErrorSummary,
WarningSummary,
GlobalWarning,
GlobalError,
Unknown,
Ignored
};
// Given a glslang warning/error message, processes it in the following way and
// returns its message type.
//
// * Places the source name into the source_name parameter, if found.
// Otherwise, clears the source_name parameter.
// * Places the line number into the line_number parameter, if found.
// Otherwise, clears the line_number parameter.
// * Places the rest of the message (the text past warning/error prefix, source
// name, and line number) into the rest parameter.
//
// If warnings_as_errors is set to true, then all warnings will be treated as
// errors.
// If suppress_warnings is set to true, then no warnings will be emitted. This
// takes precedence over warnings_as_errors.
//
// Examples:
// "ERROR: 0:2: Message"
// source_name="0", line_number="2", rest="Message"
// "Warning, Message"
// source_name="", line_number="", rest="Message"
// "ERROR: 2 errors found."
// source_name="2", line_number="", rest="errors found".
//
// Note that filenames can contain colons:
// "ERROR: foo:bar.comp.hlsl:2: 'a' : unknown variable"
MessageType ParseGlslangOutput(const shaderc_util::string_piece& message,
bool warnings_as_errors, bool suppress_warnings,
shaderc_util::string_piece* source_name,
shaderc_util::string_piece* line_number,
shaderc_util::string_piece* rest);
// Filters error_messages received from glslang, and outputs, to error_stream,
// any that are not ignored in a clang like format. If the warnings_as_errors
// boolean is set, then all warnings will be treated as errors. If the
// suppress_warnings boolean is set then any warning messages are ignored. This
// takes precedence over warnings_as_errors. Increments total_warnings and
// total_errors based on the message types.
// Returns true if no new errors were found when parsing the messages.
// "<command line>" will substitute "-1" appearing at the string name/number
// segment.
bool PrintFilteredErrors(const shaderc_util::string_piece& file_name,
std::ostream* error_stream, bool warnings_as_errors,
bool suppress_warnings, const char* error_list,
size_t* total_warnings, size_t* total_errors);
// Outputs, to error_stream, the number of warnings and errors if there are
// any.
void OutputMessages(std::ostream* error_stream, size_t total_warnings,
size_t total_errors);
} // namespace glslc
#endif // LIBSHADERC_UTIL_SRC_MESSAGE_H_

View File

@ -0,0 +1,107 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_INC_MUTEX_H
#define LIBSHADERC_UTIL_INC_MUTEX_H
// shaderc_util::mutex will be defined and specialized
// depending on the platform that is being compiled.
// It is more or less conformant to the C++11 specification of std::mutex.
// However it does not implement try_lock.
#ifdef _WIN32
// windows.h #defines min and max if we don't define this.
// this means things like std::min and std::max break
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
namespace shaderc_util {
// As the name suggests, this mutex class is for running on windows.
// It conforms to the c++11 mutex implementation, and should be a
// drop in replacement.
class windows_mutex {
public:
using native_handle_type = HANDLE;
windows_mutex() { mutex_ = CreateMutex(nullptr, false, nullptr); }
~windows_mutex() {
if (mutex_ != INVALID_HANDLE_VALUE) {
CloseHandle(mutex_);
}
}
windows_mutex(const windows_mutex&) = delete;
windows_mutex& operator=(const windows_mutex&) = delete;
// Locks this mutex, waiting until the mutex is unlocked if it is not already.
// It is not valid to lock a mutex that has already been locked.
void lock() { WaitForSingleObject(mutex_, INFINITE); }
// Unlocks this mutex. It is invalid to unlock a mutex that this thread
// has not already locked.
void unlock() { ReleaseMutex(mutex_); }
// Returns the native handle for this mutex. In this case a HANDLE object.
native_handle_type native_handle() { return mutex_; }
private:
HANDLE mutex_;
};
using mutex = windows_mutex;
}
#else
#include <pthread.h>
#include <memory>
namespace shaderc_util {
// As the name suggests, this mutex class is for running with pthreads.
// It conforms to the c++11 mutex implementation, and should be a
// drop in replacement.
class posix_mutex {
public:
using native_handle_type = pthread_mutex_t*;
posix_mutex() { pthread_mutex_init(&mutex_, nullptr); }
~posix_mutex() { pthread_mutex_destroy(&mutex_); }
posix_mutex(const posix_mutex&) = delete;
posix_mutex& operator=(const posix_mutex&) = delete;
// Locks this mutex, waiting until the mutex is unlocked if it is not already.
// It is not valid to lock a mutex that has already been locked.
void lock() { pthread_mutex_lock(&mutex_); }
// Unlocks this mutex. It is invalid to unlock a mutex that this thread
// has not already locked.
void unlock() { pthread_mutex_unlock(&mutex_); }
// Returns the native handle for this mutex. In this case a pthread_mutex_t*.
native_handle_type native_handle() { return &mutex_; }
private:
pthread_mutex_t mutex_;
};
using mutex = posix_mutex;
}
#endif
#endif // LIBSHADERC_UTIL_INC_MUTEX_H

View File

@ -0,0 +1,30 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_RESOURCES_H_
#define LIBSHADERC_UTIL_RESOURCES_H_
// We want TBuiltInResource
#include "glslang/Include/ResourceLimits.h"
namespace shaderc_util {
using TBuiltInResource = ::TBuiltInResource;
// A set of suitable defaults.
extern const TBuiltInResource kDefaultTBuiltInResource;
} // namespace shaderc_util
#endif // LIBSHADERC_UTIL_RESOURCES_H_

View File

@ -0,0 +1,107 @@
// Copyright 2016 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// These are the resource limits in a glslang::TBuiltInResource.
// The first field is the string name to be used in a configuration setting.
// The second field is the fieldname in TBuiltInResource.
// The third field is the enum name fragment for shaderc_limit.
//
// TODO(dneto): Consider using a single list of names, but use a Python script
// to generate *this* file. The original data file would have the first field,
// then generate the second field by lowering the case of the first letter, and
// generate the third field by taking the second field, and converting a
// lower-to-upper case transition into an underscore with lower-case.
RESOURCE(MaxLights,maxLights,max_lights)
RESOURCE(MaxClipPlanes,maxClipPlanes,max_clip_planes)
RESOURCE(MaxTextureUnits,maxTextureUnits,max_texture_units)
RESOURCE(MaxTextureCoords,maxTextureCoords,max_texture_coords)
RESOURCE(MaxVertexAttribs,maxVertexAttribs,max_vertex_attribs)
RESOURCE(MaxVertexUniformComponents,maxVertexUniformComponents,max_vertex_uniform_components)
RESOURCE(MaxVaryingFloats,maxVaryingFloats,max_varying_floats)
RESOURCE(MaxVertexTextureImageUnits,maxVertexTextureImageUnits,max_vertex_texture_image_units)
RESOURCE(MaxCombinedTextureImageUnits,maxCombinedTextureImageUnits,max_combined_texture_image_units)
RESOURCE(MaxTextureImageUnits,maxTextureImageUnits,max_texture_image_units)
RESOURCE(MaxFragmentUniformComponents,maxFragmentUniformComponents,max_fragment_uniform_components)
RESOURCE(MaxDrawBuffers,maxDrawBuffers,max_draw_buffers)
RESOURCE(MaxVertexUniformVectors,maxVertexUniformVectors,max_vertex_uniform_vectors)
RESOURCE(MaxVaryingVectors,maxVaryingVectors,max_varying_vectors)
RESOURCE(MaxFragmentUniformVectors,maxFragmentUniformVectors,max_fragment_uniform_vectors)
RESOURCE(MaxVertexOutputVectors,maxVertexOutputVectors,max_vertex_output_vectors)
RESOURCE(MaxFragmentInputVectors,maxFragmentInputVectors,max_fragment_input_vectors)
RESOURCE(MinProgramTexelOffset,minProgramTexelOffset,min_program_texel_offset)
RESOURCE(MaxProgramTexelOffset,maxProgramTexelOffset,max_program_texel_offset)
RESOURCE(MaxClipDistances,maxClipDistances,max_clip_distances)
RESOURCE(MaxComputeWorkGroupCountX,maxComputeWorkGroupCountX,max_compute_work_group_count_x)
RESOURCE(MaxComputeWorkGroupCountY,maxComputeWorkGroupCountY,max_compute_work_group_count_y)
RESOURCE(MaxComputeWorkGroupCountZ,maxComputeWorkGroupCountZ,max_compute_work_group_count_z)
RESOURCE(MaxComputeWorkGroupSizeX,maxComputeWorkGroupSizeX,max_compute_work_group_size_x)
RESOURCE(MaxComputeWorkGroupSizeY,maxComputeWorkGroupSizeY,max_compute_work_group_size_y)
RESOURCE(MaxComputeWorkGroupSizeZ,maxComputeWorkGroupSizeZ,max_compute_work_group_size_z)
RESOURCE(MaxComputeUniformComponents,maxComputeUniformComponents,max_compute_uniform_components)
RESOURCE(MaxComputeTextureImageUnits,maxComputeTextureImageUnits,max_compute_texture_image_units)
RESOURCE(MaxComputeImageUniforms,maxComputeImageUniforms,max_compute_image_uniforms)
RESOURCE(MaxComputeAtomicCounters,maxComputeAtomicCounters,max_compute_atomic_counters)
RESOURCE(MaxComputeAtomicCounterBuffers,maxComputeAtomicCounterBuffers,max_compute_atomic_counter_buffers)
RESOURCE(MaxVaryingComponents,maxVaryingComponents,max_varying_components)
RESOURCE(MaxVertexOutputComponents,maxVertexOutputComponents,max_vertex_output_components)
RESOURCE(MaxGeometryInputComponents,maxGeometryInputComponents,max_geometry_input_components)
RESOURCE(MaxGeometryOutputComponents,maxGeometryOutputComponents,max_geometry_output_components)
RESOURCE(MaxFragmentInputComponents,maxFragmentInputComponents,max_fragment_input_components)
RESOURCE(MaxImageUnits,maxImageUnits,max_image_units)
RESOURCE(MaxCombinedImageUnitsAndFragmentOutputs,maxCombinedImageUnitsAndFragmentOutputs,max_combined_image_units_and_fragment_outputs)
RESOURCE(MaxCombinedShaderOutputResources,maxCombinedShaderOutputResources,max_combined_shader_output_resources)
RESOURCE(MaxImageSamples,maxImageSamples,max_image_samples)
RESOURCE(MaxVertexImageUniforms,maxVertexImageUniforms,max_vertex_image_uniforms)
RESOURCE(MaxTessControlImageUniforms,maxTessControlImageUniforms,max_tess_control_image_uniforms)
RESOURCE(MaxTessEvaluationImageUniforms,maxTessEvaluationImageUniforms,max_tess_evaluation_image_uniforms)
RESOURCE(MaxGeometryImageUniforms,maxGeometryImageUniforms,max_geometry_image_uniforms)
RESOURCE(MaxFragmentImageUniforms,maxFragmentImageUniforms,max_fragment_image_uniforms)
RESOURCE(MaxCombinedImageUniforms,maxCombinedImageUniforms,max_combined_image_uniforms)
RESOURCE(MaxGeometryTextureImageUnits,maxGeometryTextureImageUnits,max_geometry_texture_image_units)
RESOURCE(MaxGeometryOutputVertices,maxGeometryOutputVertices,max_geometry_output_vertices)
RESOURCE(MaxGeometryTotalOutputComponents,maxGeometryTotalOutputComponents,max_geometry_total_output_components)
RESOURCE(MaxGeometryUniformComponents,maxGeometryUniformComponents,max_geometry_uniform_components)
RESOURCE(MaxGeometryVaryingComponents,maxGeometryVaryingComponents,max_geometry_varying_components)
RESOURCE(MaxTessControlInputComponents,maxTessControlInputComponents,max_tess_control_input_components)
RESOURCE(MaxTessControlOutputComponents,maxTessControlOutputComponents,max_tess_control_output_components)
RESOURCE(MaxTessControlTextureImageUnits,maxTessControlTextureImageUnits,max_tess_control_texture_image_units)
RESOURCE(MaxTessControlUniformComponents,maxTessControlUniformComponents,max_tess_control_uniform_components)
RESOURCE(MaxTessControlTotalOutputComponents,maxTessControlTotalOutputComponents,max_tess_control_total_output_components)
RESOURCE(MaxTessEvaluationInputComponents,maxTessEvaluationInputComponents,max_tess_evaluation_input_components)
RESOURCE(MaxTessEvaluationOutputComponents,maxTessEvaluationOutputComponents,max_tess_evaluation_output_components)
RESOURCE(MaxTessEvaluationTextureImageUnits,maxTessEvaluationTextureImageUnits,max_tess_evaluation_texture_image_units)
RESOURCE(MaxTessEvaluationUniformComponents,maxTessEvaluationUniformComponents,max_tess_evaluation_uniform_components)
RESOURCE(MaxTessPatchComponents,maxTessPatchComponents,max_tess_patch_components)
RESOURCE(MaxPatchVertices,maxPatchVertices,max_patch_vertices)
RESOURCE(MaxTessGenLevel,maxTessGenLevel,max_tess_gen_level)
RESOURCE(MaxViewports,maxViewports,max_viewports)
RESOURCE(MaxVertexAtomicCounters,maxVertexAtomicCounters,max_vertex_atomic_counters)
RESOURCE(MaxTessControlAtomicCounters,maxTessControlAtomicCounters,max_tess_control_atomic_counters)
RESOURCE(MaxTessEvaluationAtomicCounters,maxTessEvaluationAtomicCounters,max_tess_evaluation_atomic_counters)
RESOURCE(MaxGeometryAtomicCounters,maxGeometryAtomicCounters,max_geometry_atomic_counters)
RESOURCE(MaxFragmentAtomicCounters,maxFragmentAtomicCounters,max_fragment_atomic_counters)
RESOURCE(MaxCombinedAtomicCounters,maxCombinedAtomicCounters,max_combined_atomic_counters)
RESOURCE(MaxAtomicCounterBindings,maxAtomicCounterBindings,max_atomic_counter_bindings)
RESOURCE(MaxVertexAtomicCounterBuffers,maxVertexAtomicCounterBuffers,max_vertex_atomic_counter_buffers)
RESOURCE(MaxTessControlAtomicCounterBuffers,maxTessControlAtomicCounterBuffers,max_tess_control_atomic_counter_buffers)
RESOURCE(MaxTessEvaluationAtomicCounterBuffers,maxTessEvaluationAtomicCounterBuffers,max_tess_evaluation_atomic_counter_buffers)
RESOURCE(MaxGeometryAtomicCounterBuffers,maxGeometryAtomicCounterBuffers,max_geometry_atomic_counter_buffers)
RESOURCE(MaxFragmentAtomicCounterBuffers,maxFragmentAtomicCounterBuffers,max_fragment_atomic_counter_buffers)
RESOURCE(MaxCombinedAtomicCounterBuffers,maxCombinedAtomicCounterBuffers,max_combined_atomic_counter_buffers)
RESOURCE(MaxAtomicCounterBufferSize,maxAtomicCounterBufferSize,max_atomic_counter_buffer_size)
RESOURCE(MaxTransformFeedbackBuffers,maxTransformFeedbackBuffers,max_transform_feedback_buffers)
RESOURCE(MaxTransformFeedbackInterleavedComponents,maxTransformFeedbackInterleavedComponents,max_transform_feedback_interleaved_components)
RESOURCE(MaxCullDistances,maxCullDistances,max_cull_distances)
RESOURCE(MaxCombinedClipAndCullDistances,maxCombinedClipAndCullDistances,max_combined_clip_and_cull_distances)
RESOURCE(MaxSamples,maxSamples,max_samples)

View File

@ -0,0 +1,36 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_SHADER_STAGE_H_
#define LIBSHADERC_UTIL_SHADER_STAGE_H_
#include <ostream>
#include <string>
#include <utility>
#include <vector>
#include "glslang/Public/ShaderLang.h"
#include "libshaderc_util/string_piece.h"
namespace shaderc_util {
// Given a string representing a stage, returns the glslang EShLanguage for it.
// If the stage string is not recognized, returns EShLangCount.
EShLanguage MapStageNameToLanguage(
const shaderc_util::string_piece& stage_name);
} // namespace shaderc_util
#endif // LIBSHADERC_UTIL_SHADER_STAGE_H_

View File

@ -0,0 +1,67 @@
// Copyright 2016 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_INC_SPIRV_TOOLS_WRAPPER_H
#define LIBSHADERC_UTIL_INC_SPIRV_TOOLS_WRAPPER_H
#include <string>
#include <vector>
#include "spirv-tools/libspirv.hpp"
#include "libshaderc_util/compiler.h"
#include "libshaderc_util/string_piece.h"
namespace shaderc_util {
// Assembles the given assembly. On success, returns true, writes the assembled
// binary to *binary, and clears *errors. Otherwise, writes the error message
// into *errors.
bool SpirvToolsAssemble(Compiler::TargetEnv env,
Compiler::TargetEnvVersion version,
const string_piece assembly, spv_binary* binary,
std::string* errors);
// Disassembles the given binary. Returns true and writes the disassembled text
// to *text_or_error if successful. Otherwise, writes the error message to
// *text_or_error.
bool SpirvToolsDisassemble(Compiler::TargetEnv env,
Compiler::TargetEnvVersion version,
const std::vector<uint32_t>& binary,
std::string* text_or_error);
// The ids of a list of supported optimization passes.
enum class PassId {
// SPIRV-Tools standard recipes
kLegalizationPasses,
kPerformancePasses,
kSizePasses,
// SPIRV-Tools specific passes
kNullPass,
kStripDebugInfo,
kCompactIds,
};
// Optimizes the given binary. Passes are registered in the exact order as shown
// in enabled_passes, without de-duplication. Returns true and writes the
// optimized binary back to *binary if successful. Otherwise, writes errors to
// *errors and the content of binary may be in an invalid state.
bool SpirvToolsOptimize(Compiler::TargetEnv env,
Compiler::TargetEnvVersion version,
const std::vector<PassId>& enabled_passes,
std::vector<uint32_t>* binary, std::string* errors);
} // namespace shaderc_util
#endif // LIBSHADERC_UTIL_INC_SPIRV_TOOLS_WRAPPER_H

View File

@ -0,0 +1,357 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_STRING_PIECE_H_
#define LIBSHADERC_UTIL_STRING_PIECE_H_
#include <cassert>
#include <cstring>
#include <ostream>
#include <vector>
namespace shaderc_util {
// Provides a read-only view into a string (cstring or std::string).
// This must be created after the string in question, and cannot
// outlive the memory of the string in question.
// Any operations that may modify the location or size of the
// original data render the associated string_piece invalid.
class string_piece {
public:
typedef const char* iterator;
static const size_t npos = -1;
string_piece() {}
string_piece(const char* begin, const char* end) : begin_(begin), end_(end) {
assert((begin == nullptr) == (end == nullptr) &&
"either both begin and end must be nullptr or neither must be");
}
string_piece(const char* string) : begin_(string), end_(string) {
if (string) {
end_ += strlen(string);
}
}
string_piece(const std::string& str) {
if (!str.empty()) {
begin_ = &(str.front());
end_ = &(str.back()) + 1;
}
}
string_piece(const string_piece& other) {
begin_ = other.begin_;
end_ = other.end_;
}
string_piece& operator=(const string_piece& other) = default;
// Clears the string_piece removing any reference to the original string.
void clear() {
begin_ = nullptr;
end_ = nullptr;
}
// Returns a pointer to the data contained in the underlying string.
// If there is no underlying string, returns a nullptr.
const char* data() const { return begin_; }
// Returns an std::string copy of the internal data.
std::string str() const { return std::string(begin_, end_); }
// Returns a string_piece that points to a substring in the original string.
string_piece substr(size_t pos, size_t len = npos) const {
assert(len == npos || pos + len <= size());
return string_piece(begin_ + pos, len == npos ? end_ : begin_ + pos + len);
}
// Takes any function object predicate that takes a char and returns a
// boolean.
// Returns the index of the first element that does not return true for the
// predicate.
// Returns string_piece::npos if all elements match.
template <typename T>
size_t find_first_not_matching(T callee) {
for (auto it = begin_; it != end_; ++it) {
if (!callee(*it)) {
return it - begin_;
}
}
return npos;
}
// Returns the index of the first character that does not match any character
// in the input string_piece.
// The search only includes characters at or after position pos.
// Returns string_piece::npos if all match.
size_t find_first_not_of(const string_piece& to_search,
size_t pos = 0) const {
if (pos >= size()) {
return npos;
}
for (auto it = begin_ + pos; it != end_; ++it) {
if (to_search.find_first_of(*it) == npos) {
return it - begin_;
}
}
return npos;
}
// Returns find_first_not_of(str, pos) where str is a string_piece
// containing only to_search.
size_t find_first_not_of(char to_search, size_t pos = 0) const {
return find_first_not_of(string_piece(&to_search, &to_search + 1), pos);
}
// Returns the index of the first character that matches any character in the
// input string_piece.
// The search only includes characters at or after position pos.
// Returns string_piece::npos if there is no match.
size_t find_first_of(const string_piece& to_search, size_t pos = 0) const {
if (pos >= size()) {
return npos;
}
for (auto it = begin_ + pos; it != end_; ++it) {
for (char c : to_search) {
if (c == *it) {
return it - begin_;
}
}
}
return npos;
}
// Returns find_first_of(str, pos) where str is a string_piece
// containing only to_search.
size_t find_first_of(char to_search, size_t pos = 0) const {
return find_first_of(string_piece(&to_search, &to_search + 1), pos);
}
// Returns the index of the last character that matches any character in the
// input string_piece.
// The search only includes characters at or before position pos.
// Returns string_piece::npos if there is no match.
size_t find_last_of(const string_piece& to_search, size_t pos = npos) const {
if (empty()) return npos;
if (pos >= size()) {
pos = size();
}
auto it = begin_ + pos + 1;
do {
--it;
if (to_search.find_first_of(*it) != npos) {
return it - begin_;
}
} while (it != begin_);
return npos;
}
// Returns find_last_of(str, pos) where str is a string_piece
// containing only to_search.
size_t find_last_of(char to_search, size_t pos = npos) const {
return find_last_of(string_piece(&to_search, &to_search + 1), pos);
}
// Returns the index of the last character that does not match any character
// in the input string_piece.
// The search only includes characters at or before position pos.
// Returns string_piece::npos if there is no match.
size_t find_last_not_of(const string_piece& to_search,
size_t pos = npos) const {
if (empty()) return npos;
if (pos >= size()) {
pos = size();
}
auto it = begin_ + pos + 1;
do {
--it;
if (to_search.find_first_of(*it) == npos) {
return it - begin_;
}
} while (it != begin_);
return npos;
}
// Returns find_last_not_of(str, pos) where str is a string_piece
// containing only to_search.
size_t find_last_not_of(char to_search, size_t pos = 0) const {
return find_last_not_of(string_piece(&to_search, &to_search + 1), pos);
}
// Continuously removes characters appearing in chars_to_strip from the left.
string_piece lstrip(const string_piece& chars_to_strip) const {
iterator begin = begin_;
for (; begin < end_; ++begin)
if (chars_to_strip.find_first_of(*begin) == npos) break;
if (begin >= end_) return string_piece();
return string_piece(begin, end_);
}
// Continuously removes characters appearing in chars_to_strip from the right.
string_piece rstrip(const string_piece& chars_to_strip) const {
iterator end = end_;
for (; begin_ < end; --end)
if (chars_to_strip.find_first_of(*(end - 1)) == npos) break;
if (begin_ >= end) return string_piece();
return string_piece(begin_, end);
}
// Continuously removes characters appearing in chars_to_strip from both
// sides.
string_piece strip(const string_piece& chars_to_strip) const {
return lstrip(chars_to_strip).rstrip(chars_to_strip);
}
string_piece strip_whitespace() const { return strip(" \t\n\r\f\v"); }
// Returns the character at index i in the string_piece.
const char& operator[](size_t i) const { return *(begin_ + i); }
// Standard comparison operator.
bool operator==(const string_piece& other) const {
// Either end_ and _begin_ are nullptr or neither of them are.
assert(((end_ == nullptr) == (begin_ == nullptr)));
assert(((other.end_ == nullptr) == (other.begin_ == nullptr)));
if (size() != other.size()) {
return false;
}
return (memcmp(begin_, other.begin_, end_ - begin_) == 0);
}
bool operator!=(const string_piece& other) const {
return !operator==(other);
}
// Returns an iterator to the first element.
iterator begin() const { return begin_; }
// Returns an iterator to one past the last element.
iterator end() const { return end_; }
const char& front() const {
assert(!empty());
return *begin_;
}
const char& back() const {
assert(!empty());
return *(end_ - 1);
}
// Returns true is this string_piece starts with the same
// characters as other.
bool starts_with(const string_piece& other) const {
const char* iter = begin_;
const char* other_iter = other.begin();
while (iter != end_ && other_iter != other.end()) {
if (*iter++ != *other_iter++) {
return false;
}
}
return other_iter == other.end();
}
// Returns the index of the start of the first substring that matches
// the input string_piece.
// The search only includes substrings starting at or after position pos.
// Returns npos if the string cannot be found.
size_t find(const string_piece& substr, size_t pos = 0) const {
if (empty()) return npos;
if (pos >= size()) return npos;
if (substr.empty()) return 0;
for (auto it = begin_ + pos;
end() - it >= static_cast<decltype(end() - it)>(substr.size()); ++it) {
if (string_piece(it, end()).starts_with(substr)) return it - begin_;
}
return npos;
}
// Returns the index of the start of the first character that matches
// the input character.
// The search only includes substrings starting at or after position pos.
// Returns npos if the character cannot be found.
size_t find(char character, size_t pos = 0) const {
return find_first_of(character, pos);
}
// Returns true if the string_piece is empty.
bool empty() const { return begin_ == end_; }
// Returns the number of characters in the string_piece.
size_t size() const { return end_ - begin_; }
// Returns a vector of string_pieces representing delimiter delimited
// fields found. If the keep_delimiter parameter is true, then each
// delimiter character is kept with the string to its left.
std::vector<string_piece> get_fields(char delimiter,
bool keep_delimiter = false) const {
std::vector<string_piece> fields;
size_t first = 0;
size_t field_break = find_first_of(delimiter);
while (field_break != npos) {
fields.push_back(substr(first, field_break - first + keep_delimiter));
first = field_break + 1;
field_break = find_first_of(delimiter, first);
}
if (size() - first > 0) {
fields.push_back(substr(first, size() - first));
}
return fields;
}
friend std::ostream& operator<<(std::ostream& os, const string_piece& piece);
private:
// It is expected that begin_ and end_ will both be null or
// they will both point to valid pieces of memory, but it is invalid
// to have one of them being nullptr and the other not.
string_piece::iterator begin_ = nullptr;
string_piece::iterator end_ = nullptr;
};
inline std::ostream& operator<<(std::ostream& os, const string_piece& piece) {
// Either end_ and _begin_ are nullptr or neither of them are.
assert(((piece.end_ == nullptr) == (piece.begin_ == nullptr)));
if (piece.end_ != piece.begin_) {
os.write(piece.begin_, piece.end_ - piece.begin_);
}
return os;
}
inline bool operator==(const char* first, const string_piece second) {
return second == first;
}
inline bool operator!=(const char* first, const string_piece second) {
return !operator==(first, second);
}
}
namespace std {
template <>
struct hash<shaderc_util::string_piece> {
size_t operator()(const shaderc_util::string_piece& piece) const {
// djb2 algorithm.
size_t hash = 5381;
for (char c : piece) {
hash = ((hash << 5) + hash) + c;
}
return hash;
}
};
}
#endif // LIBSHADERC_UTIL_STRING_PIECE_H_

View File

@ -0,0 +1,32 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_UNIVERSAL_UNISTD_H_
#define LIBSHADERC_UTIL_UNIVERSAL_UNISTD_H_
#ifndef _MSC_VER
#include <unistd.h>
#else
// Minimal set of <unistd> needed to compile on windows.
#include <io.h>
#define access _access
// https://msdn.microsoft.com/en-us/library/1w06ktdy.aspx
// Defines these constants.
#define R_OK 4
#define W_OK 2
#endif //_MSC_VER
#endif // LIBSHADERC_UTIL_UNIVERSAL_UNISTD_H_

View File

@ -0,0 +1,61 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_INC_VERSION_PROFILE_H_
#define LIBSHADERC_UTIL_INC_VERSION_PROFILE_H_
#include <string>
#include "glslang/MachineIndependent/Versions.h"
namespace shaderc_util {
// Returns true if the given version is an accepted GLSL (ES) version.
inline bool IsKnownVersion(int version) {
switch (version) {
case 100:
case 110:
case 120:
case 130:
case 140:
case 150:
case 300:
case 310:
case 320:
case 330:
case 400:
case 410:
case 420:
case 430:
case 440:
case 450:
case 460:
return true;
default:
break;
}
return false;
}
// Given a string version_profile containing both version and profile, decodes
// it and puts the decoded version in version, decoded profile in profile.
// Returns true if decoding is successful and version and profile are accepted.
// This does not validate the version number against the profile. For example,
// "460es" doesn't make sense (yet), but is still accepted.
bool ParseVersionProfile(const std::string& version_profile, int* version,
EProfile* profile);
} // namespace shaderc_util
#endif // LIBSHADERC_UTIL_INC_VERSION_PROFILE_H_

View File

@ -0,0 +1,62 @@
// Copyright 2019 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/args.h"
#include <iomanip>
#include <sstream>
namespace shaderc_util {
bool GetOptionArgument(int argc, char** argv, int* index,
const std::string& option,
string_piece* option_argument) {
const string_piece arg = argv[*index];
assert(arg.starts_with(option));
if (arg.size() != option.size()) {
*option_argument = arg.substr(option.size());
return true;
}
if (option.back() == '=') {
*option_argument = "";
return true;
}
if (++(*index) >= argc) return false;
*option_argument = argv[*index];
return true;
}
bool ParseUint32(const std::string& str, uint32_t* value) {
std::istringstream iss(str);
iss >> std::setbase(0);
iss >> *value;
// We should have read something.
bool ok = !str.empty() && !iss.bad();
// It should have been all the text.
ok = ok && iss.eof();
// It should have been in range.
ok = ok && !iss.fail();
// Work around a bugs in various C++ standard libraries.
// Count any negative number as an error, including "-0".
ok = ok && (str[0] != '-');
return ok;
}
} // namespace shaderc_util

View File

@ -0,0 +1,785 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/compiler.h"
#include <cstdint>
#include <iomanip>
#include <sstream>
#include <thread>
#include <tuple>
#include "SPIRV/GlslangToSpv.h"
#include "libshaderc_util/format.h"
#include "libshaderc_util/io_shaderc.h"
#include "libshaderc_util/message.h"
#include "libshaderc_util/resources.h"
#include "libshaderc_util/shader_stage.h"
#include "libshaderc_util/spirv_tools_wrapper.h"
#include "libshaderc_util/string_piece.h"
#include "libshaderc_util/version_profile.h"
namespace {
using shaderc_util::string_piece;
// For use with glslang parsing calls.
const bool kNotForwardCompatible = false;
// Returns true if #line directive sets the line number for the next line in the
// given version and profile.
inline bool LineDirectiveIsForNextLine(int version, EProfile profile) {
return profile == EEsProfile || version >= 330;
}
// Returns a #line directive whose arguments are line and filename.
inline std::string GetLineDirective(int line, const string_piece& filename) {
return "#line " + std::to_string(line) + " \"" + filename.str() + "\"\n";
}
// Given a canonicalized #line directive (starting exactly with "#line", using
// single spaces to separate different components, and having an optional
// newline at the end), returns the line number and string name/number. If no
// string name/number is provided, the second element in the returned pair is an
// empty string_piece. Behavior is undefined if the directive parameter is not a
// canonicalized #line directive.
std::pair<int, string_piece> DecodeLineDirective(string_piece directive) {
const string_piece kLineDirective = "#line ";
assert(directive.starts_with(kLineDirective));
directive = directive.substr(kLineDirective.size());
const int line = std::atoi(directive.data());
const size_t space_loc = directive.find_first_of(' ');
if (space_loc == string_piece::npos) return std::make_pair(line, "");
directive = directive.substr(space_loc);
directive = directive.strip("\" \n");
return std::make_pair(line, directive);
}
// Returns the Glslang message rules for the given target environment,
// source language, and whether we want HLSL offset rules. We assume
// only valid combinations are used.
EShMessages GetMessageRules(shaderc_util::Compiler::TargetEnv env,
shaderc_util::Compiler::SourceLanguage lang,
bool hlsl_offsets, bool debug_info) {
using shaderc_util::Compiler;
EShMessages result = EShMsgCascadingErrors;
if (lang == Compiler::SourceLanguage::HLSL) {
result = static_cast<EShMessages>(result | EShMsgReadHlsl);
}
switch (env) {
case Compiler::TargetEnv::OpenGLCompat:
// The compiler will have already errored out before now.
// But we need to handle this enum.
break;
case Compiler::TargetEnv::OpenGL:
result = static_cast<EShMessages>(result | EShMsgSpvRules);
break;
case Compiler::TargetEnv::Vulkan:
result =
static_cast<EShMessages>(result | EShMsgSpvRules | EShMsgVulkanRules);
break;
}
if (hlsl_offsets) {
result = static_cast<EShMessages>(result | EShMsgHlslOffsets);
}
if (debug_info) {
result = static_cast<EShMessages>(result | EShMsgDebugInfo);
}
return result;
}
} // anonymous namespace
namespace shaderc_util {
unsigned int GlslangInitializer::initialize_count_ = 0;
std::mutex* GlslangInitializer::glslang_mutex_ = nullptr;
GlslangInitializer::GlslangInitializer() {
static std::mutex first_call_mutex;
// If this is the first call, glslang_mutex_ needs to be created, but in
// thread safe manner.
{
const std::lock_guard<std::mutex> first_call_lock(first_call_mutex);
if (glslang_mutex_ == nullptr) {
glslang_mutex_ = new std::mutex();
}
}
const std::lock_guard<std::mutex> glslang_lock(*glslang_mutex_);
if (initialize_count_ == 0) {
glslang::InitializeProcess();
}
initialize_count_++;
}
GlslangInitializer::~GlslangInitializer() {
const std::lock_guard<std::mutex> glslang_lock(*glslang_mutex_);
initialize_count_--;
if (initialize_count_ == 0) {
glslang::FinalizeProcess();
// There is no delete for glslang_mutex_ here, because we cannot guarantee
// there isn't a caller waiting for glslang_mutex_ in GlslangInitializer().
//
// This means that this class does leak one std::mutex worth of memory after
// the final instance is destroyed, but this allows us to defer allocating
// and constructing until we are sure we need to.
}
}
void Compiler::SetLimit(Compiler::Limit limit, int value) {
switch (limit) {
#define RESOURCE(NAME, FIELD, CNAME) \
case Limit::NAME: \
limits_.FIELD = value; \
break;
#include "libshaderc_util/resources.inc"
#undef RESOURCE
}
}
int Compiler::GetLimit(Compiler::Limit limit) const {
switch (limit) {
#define RESOURCE(NAME, FIELD, CNAME) \
case Limit::NAME: \
return limits_.FIELD;
#include "libshaderc_util/resources.inc"
#undef RESOURCE
}
return 0; // Unreachable
}
std::tuple<bool, std::vector<uint32_t>, size_t> Compiler::Compile(
const string_piece& input_source_string, EShLanguage forced_shader_stage,
const std::string& error_tag, const char* entry_point_name,
const std::function<EShLanguage(std::ostream* error_stream,
const string_piece& error_tag)>&
stage_callback,
CountingIncluder& includer, OutputType output_type,
std::ostream* error_stream, size_t* total_warnings, size_t* total_errors) const {
// Compilation results to be returned:
// Initialize the result tuple as a failed compilation. In error cases, we
// should return result_tuple directly without setting its members.
auto result_tuple =
std::make_tuple(false, std::vector<uint32_t>(), (size_t)0u);
// Get the reference of the members of the result tuple. We should set their
// values for succeeded compilation before returning the result tuple.
bool& succeeded = std::get<0>(result_tuple);
std::vector<uint32_t>& compilation_output_data = std::get<1>(result_tuple);
size_t& compilation_output_data_size_in_bytes = std::get<2>(result_tuple);
// Check target environment.
const auto target_client_info = GetGlslangClientInfo(
error_tag, target_env_, target_env_version_,
target_spirv_version_, target_spirv_version_is_forced_);
if (!target_client_info.error.empty()) {
*error_stream << target_client_info.error;
*total_warnings = 0;
*total_errors = 1;
return result_tuple;
}
EShLanguage used_shader_stage = forced_shader_stage;
const std::string macro_definitions =
shaderc_util::format(predefined_macros_, "#define ", " ", "\n");
const std::string pound_extension =
"#extension GL_GOOGLE_include_directive : enable\n";
const std::string preamble = macro_definitions + pound_extension;
std::string preprocessed_shader;
// If only preprocessing, we definitely need to preprocess. Otherwise, if
// we don't know the stage until now, we need the preprocessed shader to
// deduce the shader stage.
if (output_type == OutputType::PreprocessedText ||
used_shader_stage == EShLangCount) {
bool success;
std::string glslang_errors;
std::tie(success, preprocessed_shader, glslang_errors) =
PreprocessShader(error_tag, input_source_string, preamble, includer);
success &= PrintFilteredErrors(error_tag, error_stream, warnings_as_errors_,
/* suppress_warnings = */ true,
glslang_errors.c_str(), total_warnings,
total_errors);
if (!success) return result_tuple;
// Because of the behavior change of the #line directive, the #line
// directive introducing each file's content must use the syntax for the
// specified version. So we need to probe this shader's version and
// profile.
int version;
EProfile profile;
std::tie(version, profile) = DeduceVersionProfile(preprocessed_shader);
const bool is_for_next_line = LineDirectiveIsForNextLine(version, profile);
preprocessed_shader =
CleanupPreamble(preprocessed_shader, error_tag, pound_extension,
includer.num_include_directives(), is_for_next_line);
if (output_type == OutputType::PreprocessedText) {
// Set the values of the result tuple.
succeeded = true;
compilation_output_data = ConvertStringToVector(preprocessed_shader);
compilation_output_data_size_in_bytes = preprocessed_shader.size();
return result_tuple;
} else if (used_shader_stage == EShLangCount) {
std::string errors;
std::tie(used_shader_stage, errors) =
GetShaderStageFromSourceCode(error_tag, preprocessed_shader);
if (!errors.empty()) {
*error_stream << errors;
return result_tuple;
}
if (used_shader_stage == EShLangCount) {
if ((used_shader_stage = stage_callback(error_stream, error_tag)) ==
EShLangCount) {
return result_tuple;
}
}
}
}
// Parsing requires its own Glslang symbol tables.
glslang::TShader shader(used_shader_stage);
const char* shader_strings = input_source_string.data();
const int shader_lengths = static_cast<int>(input_source_string.size());
const char* string_names = error_tag.c_str();
shader.setStringsWithLengthsAndNames(&shader_strings, &shader_lengths,
&string_names, 1);
shader.setPreamble(preamble.c_str());
shader.setEntryPoint(entry_point_name);
shader.setAutoMapBindings(auto_bind_uniforms_);
if (auto_combined_image_sampler_) {
shader.setTextureSamplerTransformMode(EShTexSampTransUpgradeTextureRemoveSampler);
}
shader.setAutoMapLocations(auto_map_locations_);
const auto& bases = auto_binding_base_[static_cast<int>(used_shader_stage)];
shader.setShiftImageBinding(bases[static_cast<int>(UniformKind::Image)]);
shader.setShiftSamplerBinding(bases[static_cast<int>(UniformKind::Sampler)]);
shader.setShiftTextureBinding(bases[static_cast<int>(UniformKind::Texture)]);
shader.setShiftUboBinding(bases[static_cast<int>(UniformKind::Buffer)]);
shader.setShiftSsboBinding(
bases[static_cast<int>(UniformKind::StorageBuffer)]);
shader.setShiftUavBinding(
bases[static_cast<int>(UniformKind::UnorderedAccessView)]);
shader.setHlslIoMapping(hlsl_iomap_);
shader.setResourceSetBinding(
hlsl_explicit_bindings_[static_cast<int>(used_shader_stage)]);
shader.setEnvClient(target_client_info.client,
target_client_info.client_version);
shader.setEnvTarget(target_client_info.target_language,
target_client_info.target_language_version);
if (hlsl_functionality1_enabled_) {
shader.setEnvTargetHlslFunctionality1();
}
shader.setInvertY(invert_y_enabled_);
shader.setNanMinMaxClamp(nan_clamp_);
const EShMessages rules =
GetMessageRules(target_env_, source_language_, hlsl_offsets_,
generate_debug_info_);
bool success = shader.parse(&limits_, default_version_, default_profile_,
force_version_profile_, kNotForwardCompatible,
rules, includer);
success &= PrintFilteredErrors(error_tag, error_stream, warnings_as_errors_,
suppress_warnings_, shader.getInfoLog(),
total_warnings, total_errors);
if (!success) return result_tuple;
glslang::TProgram program;
program.addShader(&shader);
success = program.link(EShMsgDefault) && program.mapIO();
success &= PrintFilteredErrors(error_tag, error_stream, warnings_as_errors_,
suppress_warnings_, program.getInfoLog(),
total_warnings, total_errors);
if (!success) return result_tuple;
// 'spirv' is an alias for the compilation_output_data. This alias is added
// to serve as an input for the call to DissassemblyBinary.
std::vector<uint32_t>& spirv = compilation_output_data;
glslang::SpvOptions options;
options.generateDebugInfo = generate_debug_info_;
options.disableOptimizer = true;
options.optimizeSize = false;
// Note the call to GlslangToSpv also populates compilation_output_data.
glslang::GlslangToSpv(*program.getIntermediate(used_shader_stage), spirv,
&options);
// Set the tool field (the top 16-bits) in the generator word to
// 'Shaderc over Glslang'.
const uint32_t shaderc_generator_word = 13; // From SPIR-V XML Registry
const uint32_t generator_word_index = 2; // SPIR-V 2.3: Physical layout
assert(spirv.size() > generator_word_index);
spirv[generator_word_index] =
(spirv[generator_word_index] & 0xffff) | (shaderc_generator_word << 16);
std::vector<PassId> opt_passes;
if (hlsl_legalization_enabled_ && source_language_ == SourceLanguage::HLSL) {
// If from HLSL, run this passes to "legalize" the SPIR-V for Vulkan
// eg. forward and remove memory writes of opaque types.
opt_passes.push_back(PassId::kLegalizationPasses);
}
opt_passes.insert(opt_passes.end(), enabled_opt_passes_.begin(),
enabled_opt_passes_.end());
if (!opt_passes.empty()) {
std::string opt_errors;
if (!SpirvToolsOptimize(target_env_, target_env_version_,
opt_passes, &spirv, &opt_errors)) {
*error_stream << "shaderc: internal error: compilation succeeded but "
"failed to optimize: "
<< opt_errors << "\n";
return result_tuple;
}
}
if (output_type == OutputType::SpirvAssemblyText) {
std::string text_or_error;
if (!SpirvToolsDisassemble(target_env_, target_env_version_, spirv,
&text_or_error)) {
*error_stream << "shaderc: internal error: compilation succeeded but "
"failed to disassemble: "
<< text_or_error << "\n";
return result_tuple;
}
succeeded = true;
compilation_output_data = ConvertStringToVector(text_or_error);
compilation_output_data_size_in_bytes = text_or_error.size();
return result_tuple;
} else {
succeeded = true;
// Note compilation_output_data is already populated in GlslangToSpv().
compilation_output_data_size_in_bytes = spirv.size() * sizeof(spirv[0]);
return result_tuple;
}
}
void Compiler::AddMacroDefinition(const char* macro, size_t macro_length,
const char* definition,
size_t definition_length) {
predefined_macros_[std::string(macro, macro_length)] =
definition ? std::string(definition, definition_length) : "";
}
void Compiler::SetTargetEnv(Compiler::TargetEnv env,
Compiler::TargetEnvVersion version) {
target_env_ = env;
target_env_version_ = version;
}
void Compiler::SetTargetSpirv(Compiler::SpirvVersion version) {
target_spirv_version_ = version;
target_spirv_version_is_forced_ = true;
}
void Compiler::SetSourceLanguage(Compiler::SourceLanguage lang) {
source_language_ = lang;
}
void Compiler::SetForcedVersionProfile(int version, EProfile profile) {
default_version_ = version;
default_profile_ = profile;
force_version_profile_ = true;
}
void Compiler::SetWarningsAsErrors() { warnings_as_errors_ = true; }
void Compiler::SetGenerateDebugInfo() {
generate_debug_info_ = true;
for (size_t i = 0; i < enabled_opt_passes_.size(); ++i) {
if (enabled_opt_passes_[i] == PassId::kStripDebugInfo) {
enabled_opt_passes_[i] = PassId::kNullPass;
}
}
}
void Compiler::SetOptimizationLevel(Compiler::OptimizationLevel level) {
// Clear previous settings first.
enabled_opt_passes_.clear();
switch (level) {
case OptimizationLevel::Size:
if (!generate_debug_info_) {
enabled_opt_passes_.push_back(PassId::kStripDebugInfo);
}
enabled_opt_passes_.push_back(PassId::kSizePasses);
break;
case OptimizationLevel::Performance:
if (!generate_debug_info_) {
enabled_opt_passes_.push_back(PassId::kStripDebugInfo);
}
enabled_opt_passes_.push_back(PassId::kPerformancePasses);
break;
default:
break;
}
}
void Compiler::EnableHlslLegalization(bool hlsl_legalization_enabled) {
hlsl_legalization_enabled_ = hlsl_legalization_enabled;
}
void Compiler::EnableHlslFunctionality1(bool enable) {
hlsl_functionality1_enabled_ = enable;
}
void Compiler::EnableInvertY(bool enable) { invert_y_enabled_ = enable; }
void Compiler::SetNanClamp(bool enable) { nan_clamp_ = enable; }
void Compiler::SetSuppressWarnings() { suppress_warnings_ = true; }
std::tuple<bool, std::string, std::string> Compiler::PreprocessShader(
const std::string& error_tag, const string_piece& shader_source,
const string_piece& shader_preamble, CountingIncluder& includer) const {
// The stage does not matter for preprocessing.
glslang::TShader shader(EShLangVertex);
const char* shader_strings = shader_source.data();
const int shader_lengths = static_cast<int>(shader_source.size());
const char* string_names = error_tag.c_str();
shader.setStringsWithLengthsAndNames(&shader_strings, &shader_lengths,
&string_names, 1);
shader.setPreamble(shader_preamble.data());
auto target_client_info = GetGlslangClientInfo(
error_tag, target_env_, target_env_version_,
target_spirv_version_, target_spirv_version_is_forced_);
if (!target_client_info.error.empty()) {
return std::make_tuple(false, "", target_client_info.error);
}
shader.setEnvClient(target_client_info.client,
target_client_info.client_version);
if (hlsl_functionality1_enabled_) {
shader.setEnvTargetHlslFunctionality1();
}
shader.setInvertY(invert_y_enabled_);
shader.setNanMinMaxClamp(nan_clamp_);
// The preprocessor might be sensitive to the target environment.
// So combine the existing rules with the just-give-me-preprocessor-output
// flag.
const auto rules = static_cast<EShMessages>(
EShMsgOnlyPreprocessor |
GetMessageRules(target_env_, source_language_, hlsl_offsets_,
false));
std::string preprocessed_shader;
const bool success = shader.preprocess(
&limits_, default_version_, default_profile_, force_version_profile_,
kNotForwardCompatible, rules, &preprocessed_shader, includer);
if (success) {
return std::make_tuple(true, preprocessed_shader, shader.getInfoLog());
}
return std::make_tuple(false, "", shader.getInfoLog());
}
std::string Compiler::CleanupPreamble(const string_piece& preprocessed_shader,
const string_piece& error_tag,
const string_piece& pound_extension,
int num_include_directives,
bool is_for_next_line) const {
// Those #define directives in preamble will become empty lines after
// preprocessing. We also injected an #extension directive to turn on #include
// directive support. In the original preprocessing output from glslang, it
// appears before the user source string. We need to do proper adjustment:
// * Remove empty lines generated from #define directives in preamble.
// * If there is no #include directive in the source code, we do not need to
// output the injected #extension directive. Otherwise,
// * If there exists a #version directive in the source code, it should be
// placed at the first line. Its original line will be filled with an empty
// line as placeholder to maintain the code structure.
const std::vector<string_piece> lines =
preprocessed_shader.get_fields('\n', /* keep_delimiter = */ true);
std::ostringstream output_stream;
size_t pound_extension_index = lines.size();
size_t pound_version_index = lines.size();
for (size_t i = 0; i < lines.size(); ++i) {
if (lines[i] == pound_extension) {
pound_extension_index = std::min(i, pound_extension_index);
} else if (lines[i].starts_with("#version")) {
// In a preprocessed shader, directives are in a canonical format, so we
// can confidently compare to '#version' verbatim, without worrying about
// whitespace.
pound_version_index = i;
if (num_include_directives > 0) output_stream << lines[i];
break;
}
}
// We know that #extension directive exists and appears before #version
// directive (if any).
assert(pound_extension_index < lines.size());
for (size_t i = 0; i < pound_extension_index; ++i) {
// All empty lines before the #line directive we injected are generated by
// preprocessing preamble. Do not output them.
if (lines[i].strip_whitespace().empty()) continue;
output_stream << lines[i];
}
if (num_include_directives > 0) {
output_stream << pound_extension;
// Also output a #line directive for the main file.
output_stream << GetLineDirective(is_for_next_line, error_tag);
}
for (size_t i = pound_extension_index + 1; i < lines.size(); ++i) {
if (i == pound_version_index) {
if (num_include_directives > 0) {
output_stream << "\n";
} else {
output_stream << lines[i];
}
} else {
output_stream << lines[i];
}
}
return output_stream.str();
}
std::pair<EShLanguage, std::string> Compiler::GetShaderStageFromSourceCode(
string_piece filename, const std::string& preprocessed_shader) const {
const string_piece kPragmaShaderStageDirective = "#pragma shader_stage";
const string_piece kLineDirective = "#line";
int version;
EProfile profile;
std::tie(version, profile) = DeduceVersionProfile(preprocessed_shader);
const bool is_for_next_line = LineDirectiveIsForNextLine(version, profile);
std::vector<string_piece> lines =
string_piece(preprocessed_shader).get_fields('\n');
// The filename, logical line number (which starts from 1 and is sensitive to
// #line directives), and stage value for #pragma shader_stage() directives.
std::vector<std::tuple<string_piece, size_t, string_piece>> stages;
// The physical line numbers of the first #pragma shader_stage() line and
// first non-preprocessing line in the preprocessed shader text.
size_t first_pragma_physical_line = lines.size() + 1;
size_t first_non_pp_line = lines.size() + 1;
for (size_t i = 0, logical_line_no = 1; i < lines.size(); ++i) {
const string_piece current_line = lines[i].strip_whitespace();
if (current_line.starts_with(kPragmaShaderStageDirective)) {
const string_piece stage_value =
current_line.substr(kPragmaShaderStageDirective.size()).strip("()");
stages.emplace_back(filename, logical_line_no, stage_value);
first_pragma_physical_line = std::min(first_pragma_physical_line, i + 1);
} else if (!current_line.empty() && !current_line.starts_with("#")) {
first_non_pp_line = std::min(first_non_pp_line, i + 1);
}
// Update logical line number for the next line.
if (current_line.starts_with(kLineDirective)) {
string_piece name;
std::tie(logical_line_no, name) = DecodeLineDirective(current_line);
if (!name.empty()) filename = name;
// Note that for core profile, the meaning of #line changed since version
// 330. The line number given by #line used to mean the logical line
// number of the #line line. Now it means the logical line number of the
// next line after the #line line.
if (!is_for_next_line) ++logical_line_no;
} else {
++logical_line_no;
}
}
if (stages.empty()) return std::make_pair(EShLangCount, "");
std::string error_message;
const string_piece& first_pragma_filename = std::get<0>(stages[0]);
const std::string first_pragma_line = std::to_string(std::get<1>(stages[0]));
const string_piece& first_pragma_stage = std::get<2>(stages[0]);
if (first_pragma_physical_line > first_non_pp_line) {
error_message += first_pragma_filename.str() + ":" + first_pragma_line +
": error: '#pragma': the first 'shader_stage' #pragma "
"must appear before any non-preprocessing code\n";
}
EShLanguage stage = MapStageNameToLanguage(first_pragma_stage);
if (stage == EShLangCount) {
error_message +=
first_pragma_filename.str() + ":" + first_pragma_line +
": error: '#pragma': invalid stage for 'shader_stage' #pragma: '" +
first_pragma_stage.str() + "'\n";
}
for (size_t i = 1; i < stages.size(); ++i) {
const string_piece& current_stage = std::get<2>(stages[i]);
if (current_stage != first_pragma_stage) {
const string_piece& current_filename = std::get<0>(stages[i]);
const std::string current_line = std::to_string(std::get<1>(stages[i]));
error_message += current_filename.str() + ":" + current_line +
": error: '#pragma': conflicting stages for "
"'shader_stage' #pragma: '" +
current_stage.str() + "' (was '" +
first_pragma_stage.str() + "' at " +
first_pragma_filename.str() + ":" + first_pragma_line +
")\n";
}
}
return std::make_pair(error_message.empty() ? stage : EShLangCount,
error_message);
}
std::pair<int, EProfile> Compiler::DeduceVersionProfile(
const std::string& preprocessed_shader) const {
int version = default_version_;
EProfile profile = default_profile_;
if (!force_version_profile_) {
std::tie(version, profile) =
GetVersionProfileFromSourceCode(preprocessed_shader);
if (version == 0 && profile == ENoProfile) {
version = default_version_;
profile = default_profile_;
}
}
return std::make_pair(version, profile);
}
std::pair<int, EProfile> Compiler::GetVersionProfileFromSourceCode(
const std::string& preprocessed_shader) const {
string_piece pound_version = preprocessed_shader;
const size_t pound_version_loc = pound_version.find("#version");
if (pound_version_loc == string_piece::npos) {
return std::make_pair(0, ENoProfile);
}
pound_version =
pound_version.substr(pound_version_loc + std::strlen("#version"));
pound_version = pound_version.substr(0, pound_version.find_first_of("\n"));
std::string version_profile;
for (const auto character : pound_version) {
if (character != ' ') version_profile += character;
}
int version;
EProfile profile;
if (!ParseVersionProfile(version_profile, &version, &profile)) {
return std::make_pair(0, ENoProfile);
}
return std::make_pair(version, profile);
}
// Converts a string to a vector of uint32_t by copying the content of a given
// string to a vector<uint32_t> and returns it. Appends '\0' at the end if extra
// bytes are required to complete the last element.
std::vector<uint32_t> ConvertStringToVector(const std::string& str) {
size_t num_bytes_str = str.size() + 1u;
size_t vector_length =
(num_bytes_str + sizeof(uint32_t) - 1) / sizeof(uint32_t);
std::vector<uint32_t> result_vec(vector_length, 0);
std::strncpy(reinterpret_cast<char*>(result_vec.data()), str.c_str(),
str.size());
return result_vec;
}
GlslangClientInfo GetGlslangClientInfo(
const std::string& error_tag, shaderc_util::Compiler::TargetEnv env,
shaderc_util::Compiler::TargetEnvVersion env_version,
shaderc_util::Compiler::SpirvVersion spv_version,
bool spv_version_is_forced) {
GlslangClientInfo result;
std::ostringstream errs;
using shaderc_util::Compiler;
switch (env) {
case Compiler::TargetEnv::Vulkan:
result.client = glslang::EShClientVulkan;
if (env_version == Compiler::TargetEnvVersion::Default ||
env_version == Compiler::TargetEnvVersion::Vulkan_1_0) {
result.client_version = glslang::EShTargetVulkan_1_0;
} else if (env_version == Compiler::TargetEnvVersion::Vulkan_1_1) {
result.client_version = glslang::EShTargetVulkan_1_1;
result.target_language_version = glslang::EShTargetSpv_1_3;
} else if (env_version == Compiler::TargetEnvVersion::Vulkan_1_2) {
result.client_version = glslang::EShTargetVulkan_1_2;
result.target_language_version = glslang::EShTargetSpv_1_5;
} else if (env_version == Compiler::TargetEnvVersion::Vulkan_1_3) {
result.client_version = glslang::EShTargetVulkan_1_3;
result.target_language_version = glslang::EShTargetSpv_1_6;
} else {
errs << "error:" << error_tag << ": Invalid target client version "
<< static_cast<uint32_t>(env_version) << " for Vulkan environment "
<< int(env);
}
break;
case Compiler::TargetEnv::OpenGLCompat:
errs << "error: OpenGL compatibility profile is not supported";
break;
case Compiler::TargetEnv::OpenGL:
result.client = glslang::EShClientOpenGL;
if (env_version == Compiler::TargetEnvVersion::Default ||
env_version == Compiler::TargetEnvVersion::OpenGL_4_5) {
result.client_version = glslang::EShTargetOpenGL_450;
} else {
errs << "error:" << error_tag << ": Invalid target client version "
<< static_cast<uint32_t>(env_version) << " for OpenGL environment "
<< int(env);
}
break;
default:
errs << "error:" << error_tag << ": Invalid target client environment "
<< int(env);
break;
}
if (spv_version_is_forced && errs.str().empty()) {
switch (spv_version) {
case Compiler::SpirvVersion::v1_0:
result.target_language_version = glslang::EShTargetSpv_1_0;
break;
case Compiler::SpirvVersion::v1_1:
result.target_language_version = glslang::EShTargetSpv_1_1;
break;
case Compiler::SpirvVersion::v1_2:
result.target_language_version = glslang::EShTargetSpv_1_2;
break;
case Compiler::SpirvVersion::v1_3:
result.target_language_version = glslang::EShTargetSpv_1_3;
break;
case Compiler::SpirvVersion::v1_4:
result.target_language_version = glslang::EShTargetSpv_1_4;
break;
case Compiler::SpirvVersion::v1_5:
result.target_language_version = glslang::EShTargetSpv_1_5;
break;
case Compiler::SpirvVersion::v1_6:
result.target_language_version = glslang::EShTargetSpv_1_6;
break;
default:
errs << "error:" << error_tag << ": Unknown SPIR-V version " << std::hex
<< uint32_t(spv_version);
break;
}
}
result.error = errs.str();
return result;
}
} // namespace shaderc_util

View File

@ -0,0 +1,950 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/compiler.h"
#include <sstream>
#include <gmock/gmock.h>
#include "death_test.h"
#include "libshaderc_util/counting_includer.h"
#include "libshaderc_util/spirv_tools_wrapper.h"
namespace {
using shaderc_util::Compiler;
using shaderc_util::GlslangClientInfo;
using ::testing::Eq;
using ::testing::HasSubstr;
using ::testing::Not;
// A trivial vertex shader
const char kVertexShader[] =
"#version 140\n"
"void main() {}";
// A shader that parses under OpenGL compatibility profile rules.
// It does not compile because Glslang does not support SPIR-V
// code generation for OpenGL compatibility profile.
const char kOpenGLCompatibilityFragShader[] =
R"(#version 140
uniform highp sampler2D tex;
void main() {
gl_FragColor = texture2D(tex, vec2(0.0,0.0));
})";
// A shader that compiles under OpenGL core profile rules.
const char kOpenGLVertexShader[] =
R"(#version 330
void main() { int t = gl_VertexID; })";
// A shader that compiles under OpenGL core profile rules, even when
// deducing the stage.
const char kOpenGLVertexShaderDeducibleStage[] =
R"(#version 330
#pragma shader_stage(vertex)
void main() { int t = gl_VertexID; })";
// A shader that compiles under Vulkan rules.
// See the GL_KHR_vuklan_glsl extension to GLSL.
const char kVulkanVertexShader[] =
R"(#version 310 es
void main() { int t = gl_VertexIndex; })";
// A shader that needs valueless macro predefinition E, to be compiled
// successfully.
const std::string kValuelessPredefinitionShader =
"#version 140\n"
"#ifdef E\n"
"void main(){}\n"
"#else\n"
"#error\n"
"#endif";
// An HLSL vertex shader.
const char kHlslVertexShader[] =
R"(float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION
{ return float4(1.0, 2.0, 3.0, 4.0); })";
// A GLSL fragment shader without bindings for its uniforms.
// This also can be compiled as a vertex or compute shader.
const char kGlslFragShaderNoExplicitBinding[] =
R"(#version 450
#extension GL_ARB_sparse_texture2: enable
uniform texture2D my_tex;
uniform sampler my_sam;
layout(rgba32f) uniform image2D my_img;
layout(rgba32f) uniform imageBuffer my_imbuf;
uniform block { float x; float y; } my_ubo;
void main() {
texture(sampler2D(my_tex,my_sam),vec2(1.0));
vec4 t = vec4(1.0);
sparseImageLoadARB(my_img,ivec2(0),t);
imageLoad(my_imbuf,2);
float x = my_ubo.x;
})";
// A GLSL vertex shader with the location defined for its non-opaque uniform
// variable.
const char kGlslVertShaderExplicitLocation[] =
R"(#version 450
layout(location = 10) uniform mat4 my_mat;
layout(location = 0) in vec4 my_vec;
void main(void) {
gl_Position = my_mat * my_vec;
})";
// A GLSL vertex shader without the location defined for its non-opaque uniform
// variable.
const char kGlslVertShaderNoExplicitLocation[] =
R"(#version 450
uniform mat4 my_mat;
layout(location = 0) in vec4 my_vec;
void main(void) {
gl_Position = my_mat * my_vec;
})";
// A GLSL vertex shader with a weirdly packed block.
const char kGlslShaderWeirdPacking[] =
R"(#version 450
layout(set = 0, binding = 0)
buffer B { float x; vec3 foo; } my_ssbo;
void main() { my_ssbo.x = 1.0; })";
const char kHlslShaderForLegalizationTest[] = R"(
struct CombinedTextureSampler {
Texture2D tex;
SamplerState sampl;
};
float4 sampleTexture(CombinedTextureSampler c, float2 loc) {
return c.tex.Sample(c.sampl, loc);
};
[[vk::binding(0,0)]]
Texture2D gTex;
[[vk::binding(0,1)]]
SamplerState gSampler;
float4 main(float2 loc: A) : SV_Target {
CombinedTextureSampler cts;
cts.tex = gTex;
cts.sampl = gSampler;
return sampleTexture(cts, loc);
})";
const char kHlslShaderWithCounterBuffer[] = R"(
[[vk::binding(0,0)]]
RWStructuredBuffer<float4> Ainc;
float4 main() : SV_Target0 {
return float4(Ainc.IncrementCounter(), 0, 0, 0);
}
)";
const char kGlslShaderWithClamp[] = R"(#version 450
layout(location=0) in vec4 i;
layout(location=0) out vec4 o;
void main() { o = clamp(i, vec4(0.5), vec4(1.0)); }
)";
// Returns the disassembly of the given SPIR-V binary, as a string.
// Assumes the disassembly will be successful when targeting Vulkan.
std::string Disassemble(const std::vector<uint32_t> binary) {
std::string result;
shaderc_util::SpirvToolsDisassemble(Compiler::TargetEnv::Vulkan,
Compiler::TargetEnvVersion::Vulkan_1_3,
binary, &result);
return result;
}
// A CountingIncluder that never returns valid content for a requested
// file inclusion.
class DummyCountingIncluder : public shaderc_util::CountingIncluder {
private:
// Returns a pair of empty strings.
virtual glslang::TShader::Includer::IncludeResult* include_delegate(
const char*, const char*, IncludeType, size_t) override {
return nullptr;
}
virtual void release_delegate(
glslang::TShader::Includer::IncludeResult*) override {}
};
// A test fixture for compiling GLSL shaders.
class CompilerTest : public testing::Test {
public:
// Returns true if the given compiler successfully compiles the given shader
// source for the given shader stage to the specified output type. No
// includes are permitted, and shader stage deduction falls back to an invalid
// shader stage.
bool SimpleCompilationSucceedsForOutputType(
std::string source, EShLanguage stage, Compiler::OutputType output_type) {
shaderc_util::GlslangInitializer initializer;
std::stringstream errors;
size_t total_warnings = 0;
size_t total_errors = 0;
bool result = false;
DummyCountingIncluder dummy_includer;
std::tie(result, std::ignore, std::ignore) = compiler_.Compile(
source, stage, "shader", "main", dummy_stage_callback_, dummy_includer,
Compiler::OutputType::SpirvBinary, &errors, &total_warnings,
&total_errors);
errors_ = errors.str();
return result;
}
// Returns the result of SimpleCompilationSucceedsForOutputType, where
// the output type is a SPIR-V binary module.
bool SimpleCompilationSucceeds(std::string source, EShLanguage stage) {
return SimpleCompilationSucceedsForOutputType(
source, stage, Compiler::OutputType::SpirvBinary);
}
// Returns the SPIR-V binary for a successful compilation of a shader.
std::vector<uint32_t> SimpleCompilationBinary(std::string source,
EShLanguage stage) {
shaderc_util::GlslangInitializer initializer;
std::stringstream errors;
size_t total_warnings = 0;
size_t total_errors = 0;
bool result = false;
DummyCountingIncluder dummy_includer;
std::vector<uint32_t> words;
std::tie(result, words, std::ignore) = compiler_.Compile(
source, stage, "shader", "main", dummy_stage_callback_, dummy_includer,
Compiler::OutputType::SpirvBinary, &errors, &total_warnings,
&total_errors);
errors_ = errors.str();
EXPECT_TRUE(result) << errors_;
return words;
}
protected:
Compiler compiler_;
// The error string from the most recent compilation.
std::string errors_;
std::function<EShLanguage(std::ostream*, const shaderc_util::string_piece&)>
dummy_stage_callback_ =
[](std::ostream*, const shaderc_util::string_piece&) {
return EShLangCount;
};
};
TEST_F(CompilerTest, SimpleVertexShaderCompilesSuccessfullyToBinary) {
EXPECT_TRUE(SimpleCompilationSucceeds(kVertexShader, EShLangVertex));
}
TEST_F(CompilerTest, SimpleVertexShaderCompilesSuccessfullyToAssembly) {
EXPECT_TRUE(SimpleCompilationSucceedsForOutputType(
kVertexShader, EShLangVertex, Compiler::OutputType::SpirvAssemblyText));
}
TEST_F(CompilerTest, SimpleVertexShaderPreprocessesSuccessfully) {
EXPECT_TRUE(SimpleCompilationSucceedsForOutputType(
kVertexShader, EShLangVertex, Compiler::OutputType::PreprocessedText));
}
TEST_F(CompilerTest, BadVertexShaderFailsCompilation) {
EXPECT_FALSE(SimpleCompilationSucceeds(" bogus ", EShLangVertex));
}
TEST_F(CompilerTest, SimpleVulkanShaderCompilesWithDefaultCompilerSettings) {
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
}
TEST_F(CompilerTest, OpenGLCompatibilityProfileNotSupported) {
const EShLanguage stage = EShLangVertex;
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat);
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, stage));
EXPECT_EQ(errors_, "error: OpenGL compatibility profile is not supported");
}
TEST_F(CompilerTest, RespectTargetEnvOnOpenGLShaderForOpenGLShader) {
const EShLanguage stage = EShLangVertex;
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
EXPECT_TRUE(SimpleCompilationSucceeds(kOpenGLVertexShader, stage));
}
TEST_F(CompilerTest, RespectTargetEnvOnOpenGLShaderWhenDeducingStage) {
const EShLanguage stage = EShLangVertex;
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
EXPECT_TRUE(
SimpleCompilationSucceeds(kOpenGLVertexShaderDeducibleStage, stage));
}
TEST_F(CompilerTest, RespectTargetEnvOnVulkanShader) {
compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan);
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
}
TEST_F(CompilerTest, VulkanSpecificShaderFailsUnderOpenGLCompatibilityRules) {
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat);
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
}
TEST_F(CompilerTest, VulkanSpecificShaderFailsUnderOpenGLRules) {
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
}
TEST_F(CompilerTest, OpenGLSpecificShaderFailsUnderDefaultRules) {
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, EShLangVertex));
}
TEST_F(CompilerTest,
OpenGLCompatibilitySpecificShaderFailsUnderOpenGLCompatibilityRules) {
// OpenGLCompat mode now errors out. It's been deprecated for a long time.
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat);
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader,
EShLangFragment));
}
TEST_F(CompilerTest, OpenGLCompatibilitySpecificShaderFailsUnderOpenGLRules) {
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader,
EShLangFragment));
}
TEST_F(CompilerTest, OpenGLCompatibilitySpecificShaderFailsUnderVulkanRules) {
compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan);
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader,
EShLangFragment));
}
TEST_F(CompilerTest, OpenGLSpecificShaderFailsUnderVulkanRules) {
compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan);
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, EShLangVertex));
}
TEST_F(CompilerTest, BadTargetEnvFails) {
compiler_.SetTargetEnv(static_cast<Compiler::TargetEnv>(32767));
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
EXPECT_THAT(errors_, HasSubstr("Invalid target client environment 32767"));
}
TEST_F(CompilerTest, BadTargetEnvVulkanVersionFails) {
compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan,
static_cast<Compiler::TargetEnvVersion>(123));
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
EXPECT_THAT(errors_,
HasSubstr("Invalid target client version 123 for Vulkan environment 0"));
}
TEST_F(CompilerTest, BadTargetEnvOpenGLVersionFails) {
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL,
static_cast<Compiler::TargetEnvVersion>(123));
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
EXPECT_THAT(errors_,
HasSubstr("Invalid target client version 123 for OpenGL environment 1"));
}
TEST_F(CompilerTest, SpirvTargetVersion1_0Succeeds) {
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_0);
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
EXPECT_THAT(errors_, Eq(""));
}
TEST_F(CompilerTest, SpirvTargetVersion1_1Succeeds) {
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_1);
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
EXPECT_THAT(errors_, Eq(""));
}
TEST_F(CompilerTest, SpirvTargetVersion1_2Succeeds) {
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_2);
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
EXPECT_THAT(errors_, Eq(""));
}
TEST_F(CompilerTest, SpirvTargetVersion1_3Succeeds) {
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_3);
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
EXPECT_THAT(errors_, Eq(""));
}
TEST_F(CompilerTest, SpirvTargetVersion1_4Succeeds) {
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_4);
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
EXPECT_THAT(errors_, Eq(""));
}
TEST_F(CompilerTest, SpirvTargetVersion1_5Succeeds) {
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_5);
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
EXPECT_THAT(errors_, Eq(""));
}
TEST_F(CompilerTest, SpirvTargetVersion1_6Succeeds) {
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_6);
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
EXPECT_THAT(errors_, Eq(""));
}
TEST_F(CompilerTest, SpirvTargetBadVersionFails) {
compiler_.SetTargetSpirv(static_cast<Compiler::SpirvVersion>(0x090900));
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
EXPECT_THAT(errors_, HasSubstr(": Unknown SPIR-V version 90900"));
}
TEST_F(CompilerTest, AddMacroDefinition) {
const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}";
compiler_.AddMacroDefinition("E", 1u, "main", 4u);
EXPECT_TRUE(SimpleCompilationSucceeds(kMinimalExpandedShader, EShLangVertex));
}
TEST_F(CompilerTest, AddValuelessMacroDefinitionNullPointer) {
compiler_.AddMacroDefinition("E", 1u, nullptr, 100u);
EXPECT_TRUE(
SimpleCompilationSucceeds(kValuelessPredefinitionShader, EShLangVertex));
}
TEST_F(CompilerTest, AddValuelessMacroDefinitionZeroLength) {
compiler_.AddMacroDefinition("E", 1u, "something", 0u);
EXPECT_TRUE(
SimpleCompilationSucceeds(kValuelessPredefinitionShader, EShLangVertex));
}
TEST_F(CompilerTest, AddMacroDefinitionNotNullTerminated) {
const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}";
compiler_.AddMacroDefinition("EFGH", 1u, "mainnnnnn", 4u);
EXPECT_TRUE(SimpleCompilationSucceeds(kMinimalExpandedShader, EShLangVertex));
}
// A convert-string-to-vector test case consists of 1) an input string; 2) an
// expected vector after the conversion.
struct ConvertStringToVectorTestCase {
std::string input_str;
std::vector<uint32_t> expected_output_vec;
};
// Test the shaderc_util::ConvertStringToVector() function. The content of the
// input string, including the null terminator, should be packed into uint32_t
// cells and stored in the returned vector of uint32_t. In case extra bytes are
// required to complete the ending uint32_t element, bytes with value 0x00
// should be used to fill the space.
using ConvertStringToVectorTestFixture =
testing::TestWithParam<ConvertStringToVectorTestCase>;
TEST_P(ConvertStringToVectorTestFixture, VariousStringSize) {
const ConvertStringToVectorTestCase& test_case = GetParam();
EXPECT_EQ(test_case.expected_output_vec,
shaderc_util::ConvertStringToVector(test_case.input_str))
<< "test_case.input_str: " << test_case.input_str << std::endl;
}
INSTANTIATE_TEST_SUITE_P(
ConvertStringToVectorTest, ConvertStringToVectorTestFixture,
testing::ValuesIn(std::vector<ConvertStringToVectorTestCase>{
{"", {0x00000000}},
{"1", {0x00000031}},
{"12", {0x00003231}},
{"123", {0x00333231}},
{"1234", {0x34333231, 0x00000000}},
{"12345", {0x34333231, 0x00000035}},
{"123456", {0x34333231, 0x00003635}},
{"1234567", {0x34333231, 0x00373635}},
{"12345678", {0x34333231, 0x38373635, 0x00000000}},
{"123456789", {0x34333231, 0x38373635, 0x00000039}},
}));
TEST_F(CompilerTest, SetSourceLanguageToGLSLSucceeds) {
compiler_.SetSourceLanguage(Compiler::SourceLanguage::GLSL);
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
}
TEST_F(CompilerTest, SetSourceLanguageToGLSLFailsOnHLSL) {
compiler_.SetSourceLanguage(Compiler::SourceLanguage::GLSL);
EXPECT_FALSE(SimpleCompilationSucceeds(kHlslVertexShader, EShLangVertex));
}
TEST_F(CompilerTest, SetSourceLanguageToHLSLSucceeds) {
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
EXPECT_TRUE(SimpleCompilationSucceeds(kHlslVertexShader, EShLangVertex))
<< errors_;
}
TEST_F(CompilerTest, SetSourceLanguageToHLSLFailsOnGLSL) {
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
}
TEST_F(CompilerTest, EntryPointParameterTakesEffectForHLSL) {
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
std::stringstream errors;
size_t total_warnings = 0;
size_t total_errors = 0;
shaderc_util::GlslangInitializer initializer;
bool result = false;
DummyCountingIncluder dummy_includer;
std::vector<uint32_t> words;
std::tie(result, words, std::ignore) =
compiler_.Compile(kHlslVertexShader, EShLangVertex, "shader",
"EntryPoint", dummy_stage_callback_, dummy_includer,
Compiler::OutputType::SpirvAssemblyText, &errors,
&total_warnings, &total_errors);
EXPECT_TRUE(result);
std::string assembly(reinterpret_cast<char*>(words.data()));
EXPECT_THAT(assembly,
HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""))
<< assembly;
}
// A test case for setting resource limits.
struct SetLimitCase {
Compiler::Limit limit;
int default_value;
int value;
};
using LimitTest = testing::TestWithParam<SetLimitCase>;
TEST_P(LimitTest, Sample) {
Compiler compiler;
EXPECT_THAT(compiler.GetLimit(GetParam().limit),
Eq(GetParam().default_value));
compiler.SetLimit(GetParam().limit, GetParam().value);
EXPECT_THAT(compiler.GetLimit(GetParam().limit), Eq(GetParam().value));
}
#define CASE(LIMIT, DEFAULT, NEW) \
{ Compiler::Limit::LIMIT, DEFAULT, NEW }
INSTANTIATE_TEST_SUITE_P(
CompilerTest, LimitTest,
// See resources.cc for the defaults.
testing::ValuesIn(std::vector<SetLimitCase>{
// clang-format off
// This is just a sampling of the possible values.
CASE(MaxLights, 8, 99),
CASE(MaxClipPlanes, 6, 10929),
CASE(MaxTessControlAtomicCounters, 0, 72),
CASE(MaxSamples, 4, 8),
// clang-format on
}));
#undef CASE
// Returns a fragment shader accessing a texture with the given
// offset.
std::string ShaderWithTexOffset(int offset) {
std::ostringstream oss;
oss << "#version 450\n"
"layout (binding=0) uniform sampler1D tex;\n"
"void main() { vec4 x = textureOffset(tex, 1.0, "
<< offset << "); }\n";
return oss.str();
}
// Ensure compilation is sensitive to limit setting. Sample just
// two particular limits. The default minimum texel offset is -8,
// and the default maximum texel offset is 7.
TEST_F(CompilerTest, TexelOffsetDefaults) {
const EShLanguage stage = EShLangFragment;
EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(-9), stage));
EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(-8), stage));
EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(7), stage));
EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(8), stage));
}
TEST_F(CompilerTest, TexelOffsetLowerTheMinimum) {
const EShLanguage stage = EShLangFragment;
compiler_.SetLimit(Compiler::Limit::MinProgramTexelOffset, -99);
EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(-100), stage));
EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(-99), stage));
}
TEST_F(CompilerTest, TexelOffsetRaiseTheMaximum) {
const EShLanguage stage = EShLangFragment;
compiler_.SetLimit(Compiler::Limit::MaxProgramTexelOffset, 100);
EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(100), stage));
EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(101), stage));
}
TEST_F(CompilerTest, GeneratorWordIsShadercOverGlslang) {
const auto words = SimpleCompilationBinary(kVertexShader, EShLangVertex);
const uint32_t shaderc_over_glslang = 13; // From SPIR-V XML Registry
const uint32_t generator_word_index = 2; // From SPIR-V binary layout
EXPECT_EQ(shaderc_over_glslang, words[generator_word_index] >> 16u);
}
TEST_F(CompilerTest, NoBindingsAndNoAutoMapBindingsFailsCompile) {
compiler_.SetAutoBindUniforms(false);
EXPECT_FALSE(SimpleCompilationSucceeds(kGlslFragShaderNoExplicitBinding,
EShLangFragment));
EXPECT_THAT(errors_,
HasSubstr("sampler/texture/image requires layout(binding=X)"));
}
TEST_F(CompilerTest, AutoMapBindingsSetsBindings) {
compiler_.SetAutoBindUniforms(true);
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
EShLangFragment);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
<< disassembly;
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 2"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 3"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 4"));
}
TEST_F(CompilerTest, SetBindingBaseForTextureAdjustsTextureBindingsOnly) {
compiler_.SetAutoBindUniforms(true);
compiler_.SetAutoBindingBase(Compiler::UniformKind::Texture, 42);
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
EShLangFragment);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 42"))
<< disassembly;
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 0"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 1"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 2"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 3"));
}
TEST_F(CompilerTest, SetBindingBaseForSamplersAdjustsSamplerBindingsOnly) {
compiler_.SetAutoBindUniforms(true);
compiler_.SetAutoBindingBase(Compiler::UniformKind::Sampler, 42);
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
EShLangFragment);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
<< disassembly;
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 42"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 1"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 2"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 3"));
}
TEST_F(CompilerTest, SetBindingBaseForImagesAdjustsImageBindingsOnly) {
compiler_.SetAutoBindUniforms(true);
compiler_.SetAutoBindingBase(Compiler::UniformKind::Image, 42);
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
EShLangFragment);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
<< disassembly;
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 42"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 43"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 2"));
}
TEST_F(CompilerTest, SetBindingBaseForBufferAdjustsBufferBindingsOnly) {
compiler_.SetAutoBindUniforms(true);
compiler_.SetAutoBindingBase(Compiler::UniformKind::Buffer, 42);
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
EShLangFragment);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
<< disassembly;
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 2"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 3"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 42"));
}
TEST_F(CompilerTest,
AutoMapBindingsSetsBindingsSetFragTextureBindingBaseCompiledAsFrag) {
compiler_.SetAutoBindUniforms(true);
compiler_.SetAutoBindingBaseForStage(Compiler::Stage::Fragment,
Compiler::UniformKind::Texture, 100);
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
EShLangFragment);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 100"))
<< disassembly;
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 0"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 1"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 2"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 3"));
}
TEST_F(CompilerTest,
AutoMapBindingsSetsBindingsSetFragImageBindingBaseCompiledAsVert) {
compiler_.SetAutoBindUniforms(true);
// This is ignored because we're compiling the shader as a vertex shader, not
// as a fragment shader.
compiler_.SetAutoBindingBaseForStage(Compiler::Stage::Fragment,
Compiler::UniformKind::Image, 100);
const auto words =
SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding, EShLangVertex);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
<< disassembly;
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 2"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 3"));
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 4"));
}
TEST_F(CompilerTest, NoAutoMapLocationsFailsCompilationOnOpenGLShader) {
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
compiler_.SetAutoMapLocations(false);
const auto words =
SimpleCompilationBinary(kGlslVertShaderExplicitLocation, EShLangVertex);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_mat Location 10"))
<< disassembly;
EXPECT_FALSE(SimpleCompilationSucceeds(kGlslVertShaderNoExplicitLocation,
EShLangVertex));
}
TEST_F(CompilerTest, AutoMapLocationsSetsLocationsOnOpenGLShader) {
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
compiler_.SetAutoMapLocations(true);
const auto words_no_auto =
SimpleCompilationBinary(kGlslVertShaderExplicitLocation, EShLangVertex);
const auto disassembly_no_auto = Disassemble(words_no_auto);
EXPECT_THAT(disassembly_no_auto, HasSubstr("OpDecorate %my_mat Location 10"))
<< disassembly_no_auto;
const auto words_auto =
SimpleCompilationBinary(kGlslVertShaderNoExplicitLocation, EShLangVertex);
const auto disassembly_auto = Disassemble(words_auto);
EXPECT_THAT(disassembly_auto, HasSubstr("OpDecorate %my_mat Location 0"))
<< disassembly_auto;
}
TEST_F(CompilerTest, EmitMessageTextOnlyOnce) {
// Emit a warning by compiling a shader without a default entry point name.
// The warning should only be emitted once even though we do parsing, linking,
// and IO mapping.
Compiler c;
std::stringstream errors;
size_t total_warnings = 0;
size_t total_errors = 0;
shaderc_util::GlslangInitializer initializer;
bool result = false;
DummyCountingIncluder dummy_includer;
std::tie(result, std::ignore, std::ignore) = c.Compile(
"#version 150\nvoid MyEntryPoint(){}", EShLangVertex, "shader", "",
dummy_stage_callback_, dummy_includer, Compiler::OutputType::SpirvBinary,
&errors, &total_warnings, &total_errors);
const std::string errs = errors.str();
EXPECT_THAT(errs, Eq("shader: error: Linking vertex stage: Missing entry "
"point: Each stage requires one entry point\n"))
<< errs;
}
TEST_F(CompilerTest, GlslDefaultPackingUsed) {
const auto words =
SimpleCompilationBinary(kGlslShaderWeirdPacking, EShLangVertex);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpMemberDecorate %B 1 Offset 16"))
<< disassembly;
}
TEST_F(CompilerTest, HlslOffsetsOptionDisableRespected) {
compiler_.SetHlslOffsets(false);
const auto words =
SimpleCompilationBinary(kGlslShaderWeirdPacking, EShLangVertex);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpMemberDecorate %B 1 Offset 16"))
<< disassembly;
}
TEST_F(CompilerTest, HlslOffsetsOptionEnableRespected) {
compiler_.SetHlslOffsets(true);
const auto words =
SimpleCompilationBinary(kGlslShaderWeirdPacking, EShLangVertex);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpMemberDecorate %B 1 Offset 4"))
<< disassembly;
}
TEST_F(CompilerTest, HlslLegalizationEnabledNoSizeOpt) {
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
const auto words =
SimpleCompilationBinary(kHlslShaderForLegalizationTest, EShLangFragment);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, Not(HasSubstr("OpFunctionCall"))) << disassembly;
EXPECT_THAT(disassembly, HasSubstr("OpName")) << disassembly;
}
TEST_F(CompilerTest, HlslLegalizationEnabledWithSizeOpt) {
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
compiler_.SetOptimizationLevel(Compiler::OptimizationLevel::Size);
const auto words =
SimpleCompilationBinary(kHlslShaderForLegalizationTest, EShLangFragment);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, Not(HasSubstr("OpFunctionCall"))) << disassembly;
EXPECT_THAT(disassembly, Not(HasSubstr("OpName"))) << disassembly;
}
TEST_F(CompilerTest, HlslLegalizationDisabled) {
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
compiler_.EnableHlslLegalization(false);
const auto words =
SimpleCompilationBinary(kHlslShaderForLegalizationTest, EShLangFragment);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpFunctionCall")) << disassembly;
}
TEST_F(CompilerTest, HlslFunctionality1Enabled) {
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
compiler_.EnableHlslFunctionality1(true);
compiler_.SetAutoBindUniforms(true); // Counter variable needs a binding.
const auto words =
SimpleCompilationBinary(kHlslShaderWithCounterBuffer, EShLangFragment);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly,
HasSubstr("OpExtension \"SPV_GOOGLE_hlsl_functionality1\""))
<< disassembly;
EXPECT_THAT(disassembly,
HasSubstr("OpDecorateString %_entryPointOutput "
"UserSemantic \"SV_TARGET0\""))
<< disassembly;
}
TEST_F(CompilerTest, ClampMapsToFClampByDefault) {
const auto words =
SimpleCompilationBinary(kGlslShaderWithClamp, EShLangFragment);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpExtInst %v4float %1 FClamp"))
<< disassembly;
}
TEST_F(CompilerTest, ClampMapsToFClampWithNanClamp) {
compiler_.SetNanClamp(true);
const auto words =
SimpleCompilationBinary(kGlslShaderWithClamp, EShLangFragment);
const auto disassembly = Disassemble(words);
EXPECT_THAT(disassembly, HasSubstr("OpExtInst %v4float %1 NClamp"))
<< disassembly;
}
// A test coase for Glslang
// expected vector after the conversion.
struct GetGlslangClientInfoCase {
std::string prefix;
Compiler::TargetEnv env;
Compiler::TargetEnvVersion env_version;
Compiler::SpirvVersion spv_version;
bool spv_forced;
// Expected results. The error field is matched as a substring.
GlslangClientInfo expected;
};
// Test the shaderc_util::GetGlslangClientInfo function.
using GetGlslangClientInfoTest =
testing::TestWithParam<GetGlslangClientInfoCase>;
TEST_P(GetGlslangClientInfoTest, Sample) {
const auto& c = GetParam();
const auto& expected = c.expected;
auto result = shaderc_util::GetGlslangClientInfo(
c.prefix, c.env, c.env_version, c.spv_version, c.spv_forced);
EXPECT_THAT(result.error.empty(), Eq(expected.error.empty()));
if (result.error.empty()) {
EXPECT_THAT(result.client, Eq(expected.client));
EXPECT_THAT(result.client_version, Eq(expected.client_version));
EXPECT_THAT(result.target_language, Eq(expected.target_language));
EXPECT_THAT(result.target_language_version,
Eq(expected.target_language_version));
} else {
EXPECT_THAT(result.error, HasSubstr(expected.error));
}
}
#define CASE_VK(VKVER, SPVVER) \
"", Compiler::TargetEnv::Vulkan, Compiler::TargetEnvVersion::Vulkan_##VKVER, \
Compiler::SpirvVersion::v##SPVVER
#define BADCASE_VK(STR, VKVER, SPVVER) \
STR, Compiler::TargetEnv::Vulkan, \
static_cast<Compiler::TargetEnvVersion>(VKVER), \
static_cast<Compiler::SpirvVersion>(SPVVER)
#define CASE_GL(GLVER, SPVVER) \
"", Compiler::TargetEnv::OpenGL, Compiler::TargetEnvVersion::OpenGL_##GLVER, \
Compiler::SpirvVersion::v##SPVVER
#define BADCASE_GL(STR, GLVER, SPVVER) \
STR, Compiler::TargetEnv::OpenGL, \
static_cast<Compiler::TargetEnvVersion>(GLVER), \
static_cast<Compiler::SpirvVersion>(SPVVER)
#define GCASE_VK(STR, VKVER, SPVVER) \
shaderc_util::GlslangClientInfo { \
std::string(STR), glslang::EShClientVulkan, \
glslang::EShTargetVulkan_##VKVER, glslang::EShTargetSpv, \
glslang::EShTargetSpv_##SPVVER \
}
#define GCASE_GL(STR, GLVER, SPVVER) \
shaderc_util::GlslangClientInfo { \
std::string(STR), glslang::EShClientOpenGL, \
glslang::EShTargetOpenGL_##GLVER, glslang::EShTargetSpv, \
glslang::EShTargetSpv_##SPVVER \
}
INSTANTIATE_TEST_SUITE_P(
UnforcedSpirvSuccess, GetGlslangClientInfoTest,
testing::ValuesIn(std::vector<GetGlslangClientInfoCase>{
// Unforced SPIR-V version. Success cases.
{CASE_VK(1_0, 1_4), false, GCASE_VK("", 1_0, 1_0)},
{CASE_VK(1_1, 1_4), false, GCASE_VK("", 1_1, 1_3)},
{CASE_GL(4_5, 1_4), false, GCASE_GL("", 450, 1_0)},
}));
INSTANTIATE_TEST_SUITE_P(
ForcedSpirvSuccess, GetGlslangClientInfoTest,
testing::ValuesIn(std::vector<GetGlslangClientInfoCase>{
// Forced SPIR-V version. Success cases.
{CASE_VK(1_0, 1_0), true, GCASE_VK("", 1_0, 1_0)},
{CASE_VK(1_0, 1_1), true, GCASE_VK("", 1_0, 1_1)},
{CASE_VK(1_0, 1_2), true, GCASE_VK("", 1_0, 1_2)},
{CASE_VK(1_0, 1_3), true, GCASE_VK("", 1_0, 1_3)},
{CASE_VK(1_1, 1_0), true, GCASE_VK("", 1_1, 1_0)},
{CASE_VK(1_1, 1_1), true, GCASE_VK("", 1_1, 1_1)},
{CASE_VK(1_1, 1_2), true, GCASE_VK("", 1_1, 1_2)},
{CASE_VK(1_1, 1_3), true, GCASE_VK("", 1_1, 1_3)},
{CASE_GL(4_5, 1_0), true, GCASE_GL("", 450, 1_0)},
{CASE_GL(4_5, 1_1), true, GCASE_GL("", 450, 1_1)},
{CASE_GL(4_5, 1_2), true, GCASE_GL("", 450, 1_2)},
}));
INSTANTIATE_TEST_SUITE_P(
Failure, GetGlslangClientInfoTest,
testing::ValuesIn(std::vector<GetGlslangClientInfoCase>{
// Failure cases.
{BADCASE_VK("foo", 999, Compiler::SpirvVersion::v1_0), false,
GCASE_VK("error:foo: Invalid target client version 999 for Vulkan "
"environment 0",
1_0, 1_0)},
{BADCASE_GL("foo", 999, Compiler::SpirvVersion::v1_0), false,
GCASE_GL("error:foo: Invalid target client version 999 for OpenGL "
"environment 1",
450, 1_0)},
// For bad SPIR-V versions, have to force=true to make it pay attention.
{BADCASE_VK("foo", Compiler::TargetEnvVersion::Vulkan_1_0, 999), true,
GCASE_VK("error:foo: Unknown SPIR-V version 3e7", 1_0, 1_0)},
{BADCASE_GL("foo", Compiler::TargetEnvVersion::OpenGL_4_5, 999), true,
GCASE_GL("error:foo: Unknown SPIR-V version 3e7", 450, 1_0)},
}));
#undef CASE_VK
#undef CASE_GL
#undef BADCASE_VK
#undef BADCASE_GL
#undef GCASE_VK
#undef GCASE_GL
} // anonymous namespace

View File

@ -0,0 +1,93 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/counting_includer.h"
#include <thread>
#include <vector>
#include <gmock/gmock.h>
namespace {
// A trivial implementation of CountingIncluder's virtual methods, so tests can
// instantiate.
class ConcreteCountingIncluder : public shaderc_util::CountingIncluder {
public:
using IncludeResult = glslang::TShader::Includer::IncludeResult;
~ConcreteCountingIncluder() {
// Avoid leaks.
for (auto result : results_) {
release_delegate(result);
}
}
virtual IncludeResult* include_delegate(
const char* requested, const char* requestor, IncludeType,
size_t) override {
const char kError[] = "Unexpected #include";
results_.push_back(new IncludeResult{"", kError, strlen(kError), nullptr});
return results_.back();
}
virtual void release_delegate(IncludeResult* include_result) override {
delete include_result;
}
private:
// All the results we've returned so far.
std::vector<IncludeResult*> results_;
};
TEST(CountingIncluderTest, InitialCount) {
EXPECT_EQ(0, ConcreteCountingIncluder().num_include_directives());
}
TEST(CountingIncluderTest, OneIncludeLocal) {
ConcreteCountingIncluder includer;
includer.includeLocal("random file name", "from me", 0);
EXPECT_EQ(1, includer.num_include_directives());
}
TEST(CountingIncluderTest, TwoIncludesAnyIncludeType) {
ConcreteCountingIncluder includer;
includer.includeSystem("name1", "from me", 0);
includer.includeLocal("name2", "me", 0);
EXPECT_EQ(2, includer.num_include_directives());
}
TEST(CountingIncluderTest, ManyIncludes) {
ConcreteCountingIncluder includer;
for (int i = 0; i < 100; ++i) {
includer.includeLocal("filename", "from me", i);
includer.includeSystem("filename", "from me", i);
}
EXPECT_EQ(200, includer.num_include_directives());
}
#ifndef SHADERC_DISABLE_THREADED_TESTS
TEST(CountingIncluderTest, ThreadedIncludes) {
ConcreteCountingIncluder includer;
std::thread t1(
[&includer]() { includer.includeLocal("name1", "me", 0); });
std::thread t2(
[&includer]() { includer.includeSystem("name2", "me", 1); });
std::thread t3(
[&includer]() { includer.includeLocal("name3", "me", 2); });
t1.join();
t2.join();
t3.join();
EXPECT_EQ(3, includer.num_include_directives());
}
#endif // SHADERC_DISABLE_THREADED_TESTS
} // anonymous namespace

View File

@ -0,0 +1,25 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSHADERC_UTIL_SRC_DEATH_TEST_H
#define LIBSHADERC_UTIL_SRC_DEATH_TEST_H
#ifdef NDEBUG
#define EXPECT_DEBUG_DEATH_IF_SUPPORTED(statement, regexp)
#else
#define EXPECT_DEBUG_DEATH_IF_SUPPORTED(statement, regexp) \
EXPECT_DEATH_IF_SUPPORTED(statement, regexp)
#endif
#endif // LIBSHADERC_UTIL_SRC_DEATH_TEST_H

View File

@ -0,0 +1,71 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/file_finder.h"
#include "libshaderc_util/string_piece.h"
#include <cassert>
#include <fstream>
#include <ios>
namespace {
// Returns "" if path is empty or ends in '/'. Otherwise, returns "/".
std::string MaybeSlash(const shaderc_util::string_piece& path) {
return (path.empty() || path.back() == '/') ? "" : "/";
}
} // anonymous namespace
namespace shaderc_util {
std::string FileFinder::FindReadableFilepath(
const std::string& filename) const {
assert(!filename.empty());
static const auto for_reading = std::ios_base::in;
std::filebuf opener;
for (const auto& prefix : search_path_) {
const std::string prefixed_filename =
prefix + MaybeSlash(prefix) + filename;
if (opener.open(prefixed_filename, for_reading)) return prefixed_filename;
}
return "";
}
std::string FileFinder::FindRelativeReadableFilepath(
const std::string& requesting_file, const std::string& filename) const {
assert(!filename.empty());
string_piece dir_name(requesting_file);
size_t last_slash = requesting_file.find_last_of("/\\");
if (last_slash != std::string::npos) {
dir_name = string_piece(requesting_file.c_str(),
requesting_file.c_str() + last_slash);
}
if (dir_name.size() == requesting_file.size()) {
dir_name.clear();
}
static const auto for_reading = std::ios_base::in;
std::filebuf opener;
const std::string relative_filename =
dir_name.str() + MaybeSlash(dir_name) + filename;
if (opener.open(relative_filename, for_reading)) return relative_filename;
return FindReadableFilepath(filename);
}
} // namespace shaderc_util

View File

@ -0,0 +1,146 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/file_finder.h"
#include <gtest/gtest.h>
// We need getcwd
#if WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif
#include "death_test.h"
namespace {
using shaderc_util::FileFinder;
// Returns the absolute path of the current working directory.
std::string GetCurrentDir() {
// Provide generous space to write the path.
char buf[1000];
#if WIN32
return _getcwd(buf, sizeof(buf));
#else
return getcwd(buf, sizeof(buf));
#endif
}
class FileFinderTest : public testing::Test {
protected:
FileFinder finder;
// Absolute path of the current working directory.
const std::string current_dir = GetCurrentDir();
};
TEST_F(FileFinderTest, PathStartsEmpty) {
EXPECT_TRUE(FileFinder().search_path().empty());
}
TEST_F(FileFinderTest, EmptyPath) {
finder.search_path().clear();
EXPECT_EQ("", finder.FindReadableFilepath("include_file.1"));
}
TEST_F(FileFinderTest, EmptyStringInPath) {
finder.search_path() = {""};
EXPECT_EQ("include_file.1", finder.FindReadableFilepath("include_file.1"));
EXPECT_EQ("dir/subdir/include_file.2",
finder.FindReadableFilepath("dir/subdir/include_file.2"));
}
TEST_F(FileFinderTest, SimplePath) {
finder.search_path() = {"dir"};
EXPECT_EQ("dir/subdir/include_file.2",
finder.FindReadableFilepath("subdir/include_file.2"));
}
TEST_F(FileFinderTest, PathEndsInSlash) {
finder.search_path() = {"dir/"};
EXPECT_EQ("dir/subdir/include_file.2",
finder.FindReadableFilepath("subdir/include_file.2"));
}
TEST_F(FileFinderTest, ParentDir) {
finder.search_path() = {"dir"};
EXPECT_EQ("dir/../include_file.1",
finder.FindReadableFilepath("../include_file.1"));
}
TEST_F(FileFinderTest, EntirePathIsActive) {
finder.search_path() = {"", "dir/subdir/"};
EXPECT_EQ("include_file.1", finder.FindReadableFilepath("include_file.1"));
EXPECT_EQ("dir/subdir/include_file.2",
finder.FindReadableFilepath("include_file.2"));
}
TEST_F(FileFinderTest, NonExistingFile) {
finder.search_path() = {"", "dir/subdir/"};
EXPECT_EQ("", finder.FindReadableFilepath("garbage.xyxyxyxyxyxz"));
}
TEST_F(FileFinderTest, FirstHitReturned) {
finder.search_path() = {".", "", "dir/../"};
EXPECT_EQ("./include_file.1", finder.FindReadableFilepath("include_file.1"));
}
TEST_F(FileFinderTest, IrrelevantPaths) {
finder.search_path() = {".", "garbage.xyxyxyxyxyz", "dir/../"};
EXPECT_EQ("", finder.FindReadableFilepath("include_file.2"));
finder.search_path().push_back("dir/subdir");
EXPECT_EQ("dir/subdir/include_file.2",
finder.FindReadableFilepath("include_file.2"));
}
TEST_F(FileFinderTest, CurrentDirectory) {
ASSERT_GE(current_dir.size(), 0u);
// Either the directory should start with / (if we are on Linux),
// Or it should beither X:/ or X:\ or // (if we are on Windows).
ASSERT_TRUE(current_dir.front() == '\\' || current_dir.front() == '/' ||
(current_dir.size() >= 3u && current_dir[1] == ':' &&
(current_dir[2] == '\\' || current_dir[2] == '/')));
}
TEST_F(FileFinderTest, AbsolutePath) {
ASSERT_NE('/', current_dir.back());
finder.search_path() = {current_dir};
EXPECT_EQ(current_dir + "/include_file.1",
finder.FindReadableFilepath("include_file.1"));
EXPECT_EQ(current_dir + "/dir/subdir/include_file.2",
finder.FindReadableFilepath("dir/subdir/include_file.2"));
}
TEST_F(FileFinderTest, AbsoluteFilename) {
ASSERT_NE('/', current_dir.back());
finder.search_path() = {""};
const std::string absolute_file1 = current_dir + "/include_file.1";
EXPECT_EQ(absolute_file1, finder.FindReadableFilepath(absolute_file1));
EXPECT_EQ("", finder.FindReadableFilepath("/dir/subdir/include_file.2"));
finder.search_path().push_back(".");
EXPECT_EQ(".//dir/subdir/include_file.2",
finder.FindReadableFilepath("/dir/subdir/include_file.2"));
}
TEST(FileFinderDeathTest, EmptyFilename) {
EXPECT_DEBUG_DEATH_IF_SUPPORTED(FileFinder().FindReadableFilepath(""),
"Assertion");
}
} // anonymous namespace

View File

@ -0,0 +1,105 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/format.h"
#include <gmock/gmock.h>
#include <map>
#include <string>
#include <unordered_map>
namespace {
using testing::AllOf;
using testing::HasSubstr;
using testing::IsEmpty;
class FormatMap : public testing::Test {
public:
FormatMap()
: map1({{"one", 1}}),
umap1({map1.begin(), map1.end()}),
map8({{1, "one"},
{2, "two"},
{3, "three"},
{4, "four"},
{5, "five"},
{6, "six"},
{7, "seven"},
{8, "eight"}}),
umap8({map8.begin(), map8.end()}),
mmap({{1, 100}, {1, 200}, {2, 100}, {2, 200}}),
ummap({mmap.begin(), mmap.end()}) {}
protected:
std::map<int, int> empty_map;
std::unordered_map<int, int> empty_umap;
std::map<std::string, int> map1;
std::unordered_map<std::string, int> umap1;
std::map<int, std::string> map8;
std::unordered_map<int, std::string> umap8;
std::multimap<int, int> mmap;
std::unordered_multimap<int, int> ummap;
};
TEST_F(FormatMap, EmptyMap) {
EXPECT_THAT(shaderc_util::format(empty_map, "pre", "in", "post"), IsEmpty());
EXPECT_THAT(shaderc_util::format(empty_umap, "pre", "in", "post"), IsEmpty());
}
TEST_F(FormatMap, SingleEntry) {
EXPECT_EQ("PREoneIN1POST", shaderc_util::format(map1, "PRE", "IN", "POST"));
EXPECT_EQ("PREoneIN1POST", shaderc_util::format(umap1, "PRE", "IN", "POST"));
}
TEST_F(FormatMap, EmptyPrefix) {
EXPECT_EQ("oneIN1POST", shaderc_util::format(map1, "", "IN", "POST"));
EXPECT_EQ("oneIN1POST", shaderc_util::format(umap1, "", "IN", "POST"));
}
TEST_F(FormatMap, EmptyInfix) {
EXPECT_EQ("PREone1POST", shaderc_util::format(map1, "PRE", "", "POST"));
EXPECT_EQ("PREone1POST", shaderc_util::format(umap1, "PRE", "", "POST"));
}
TEST_F(FormatMap, EmptyPostfix) {
EXPECT_EQ("PREoneIN1", shaderc_util::format(map1, "PRE", "IN", ""));
EXPECT_EQ("PREoneIN1", shaderc_util::format(umap1, "PRE", "IN", ""));
}
TEST_F(FormatMap, LargerMap) {
const std::string result = shaderc_util::format(map8, "", "", "\n"),
uresult = shaderc_util::format(umap8, "", "", "\n");
auto has_all =
AllOf(HasSubstr("1one\n"), HasSubstr("2two\n"), HasSubstr("3three\n"),
HasSubstr("4four\n"), HasSubstr("5five\n"), HasSubstr("6six\n"),
HasSubstr("7seven\n"), HasSubstr("8eight\n"));
EXPECT_THAT(result, has_all);
EXPECT_EQ(48u, result.size());
EXPECT_THAT(uresult, has_all);
EXPECT_EQ(48u, uresult.size());
}
TEST_F(FormatMap, Multimap) {
const std::string result = shaderc_util::format(mmap, " ", "&", ""),
uresult = shaderc_util::format(ummap, " ", "&", "");
auto has_all = AllOf(HasSubstr(" 1&100"), HasSubstr(" 1&200"),
HasSubstr(" 2&100"), HasSubstr(" 2&200"));
EXPECT_THAT(result, has_all);
EXPECT_EQ(4 * 6u, result.size());
EXPECT_THAT(uresult, has_all);
EXPECT_EQ(4 * 6u, uresult.size());
}
} // anonymous namespace

View File

@ -0,0 +1,146 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/io_shaderc.h"
#include "libshaderc_util/universal_unistd.h"
#if _WIN32
// Need _fileno from stdio.h
// Need _O_BINARY and _O_TEXT from fcntl.h
#include <fcntl.h>
#include <stdio.h>
#endif
#include <errno.h>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
namespace {
// Outputs a descriptive message for errno_value to cerr.
// This may be truncated to 1023 bytes on certain platforms.
void OutputFileErrorMessage(int errno_value) {
#ifdef _MSC_VER
// If the error message is more than 1023 bytes it will be truncated.
char buffer[1024];
strerror_s(buffer, errno_value);
std::cerr << ": " << buffer << std::endl;
#else
std::cerr << ": " << strerror(errno_value) << std::endl;
#endif
}
} // anonymous namespace
namespace shaderc_util {
bool IsAbsolutePath(const std::string& path) {
if (path.empty()) return false;
// Unix-like OS: /path/to/file
if (path.front() == '/') return true;
// Windows: \\server\user\file
if (path.size() > 1 && path[0] == '\\' && path[1] == '\\') {
return true;
}
// Windows: X:\path\to\file
if (path.size() > 2 && ::isalpha(path[0]) && path[1] == ':' &&
path[2] == '\\') {
return true;
}
return false;
}
std::string GetBaseFileName(const std::string& file_path) {
size_t loc_slash = file_path.find_last_of("/\\");
std::string base_name =
file_path.substr((loc_slash == std::string::npos ? -1 : loc_slash) + 1);
if (base_name == ".." || base_name == ".") {
base_name = "";
}
return base_name;
}
bool ReadFile(const std::string& input_file_name,
std::vector<char>* input_data) {
std::istream* stream = &std::cin;
std::ifstream input_file;
if (input_file_name != "-") {
input_file.open(input_file_name, std::ios_base::binary);
stream = &input_file;
if (input_file.fail()) {
std::cerr << "glslc: error: cannot open input file: '" << input_file_name
<< "'";
if (access(input_file_name.c_str(), R_OK) != 0) {
OutputFileErrorMessage(errno);
return false;
}
std::cerr << std::endl;
return false;
}
}
*input_data = std::vector<char>((std::istreambuf_iterator<char>(*stream)),
std::istreambuf_iterator<char>());
return true;
}
std::ostream* GetOutputStream(const string_piece& output_filename,
std::ofstream* file_stream, std::ostream* err) {
std::ostream* stream = &std::cout;
if (output_filename != "-") {
file_stream->open(output_filename.str(), std::ios_base::binary);
stream = file_stream;
if (file_stream->fail()) {
*err << "glslc: error: cannot open output file: '" << output_filename
<< "'";
if (access(output_filename.str().c_str(), W_OK) != 0) {
OutputFileErrorMessage(errno);
return nullptr;
}
std::cerr << std::endl;
return nullptr;
}
}
return stream;
}
bool WriteFile(std::ostream* stream, const string_piece& output_data) {
if (output_data.size() > 0) {
stream->write(output_data.data(), output_data.size());
if (!stream->good()) {
return false;
}
}
stream->flush();
return true;
}
void FlushAndSetBinaryModeOnStdout() {
std::fflush(stdout);
#if _WIN32
_setmode(_fileno(stdout), _O_BINARY);
#endif
}
void FlushAndSetTextModeOnStdout() {
std::fflush(stdout);
#if _WIN32
_setmode(_fileno(stdout), _O_TEXT);
#endif
}
} // namespace shaderc_util

View File

@ -0,0 +1,139 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/io_shaderc.h"
#include <gmock/gmock.h>
#include <fstream>
namespace {
using shaderc_util::GetBaseFileName;
using shaderc_util::GetOutputStream;
using shaderc_util::IsAbsolutePath;
using shaderc_util::ReadFile;
using shaderc_util::WriteFile;
using testing::Eq;
using testing::HasSubstr;
std::string ToString(const std::vector<char>& v) {
return std::string(v.data(), v.size());
}
class ReadFileTest : public testing::Test {
protected:
// A vector to pass to ReadFile.
std::vector<char> read_data;
};
TEST(IsAbsolutePathTest, Linux) {
EXPECT_FALSE(IsAbsolutePath(""));
EXPECT_TRUE(IsAbsolutePath("/"));
EXPECT_FALSE(IsAbsolutePath("."));
EXPECT_FALSE(IsAbsolutePath(".."));
EXPECT_TRUE(IsAbsolutePath("/bin/echo"));
EXPECT_TRUE(IsAbsolutePath("//etc/shadow"));
EXPECT_TRUE(IsAbsolutePath("/../../../lib"));
EXPECT_FALSE(IsAbsolutePath("./something"));
EXPECT_FALSE(IsAbsolutePath("input"));
EXPECT_FALSE(IsAbsolutePath("../test"));
EXPECT_FALSE(IsAbsolutePath(" /abc"));
EXPECT_TRUE(IsAbsolutePath("/abc def/ttt"));
}
TEST(IsAbsolutePathTest, Windows) {
EXPECT_TRUE(IsAbsolutePath(R"(\\Server1000\superuser\file)"));
EXPECT_TRUE(IsAbsolutePath(R"(\\zzzz 1000\user with space\file with space)"));
EXPECT_TRUE(
IsAbsolutePath(R"(C:\Program Files (x86)\Windows Folder\shader.glsl)"));
EXPECT_FALSE(IsAbsolutePath(R"(third_party\gmock)"));
EXPECT_FALSE(IsAbsolutePath(R"(C:..\File.txt)"));
}
TEST(GetBaseFileName, Linux) {
EXPECT_EQ("", GetBaseFileName(""));
EXPECT_EQ("", GetBaseFileName("/"));
EXPECT_EQ("", GetBaseFileName("."));
EXPECT_EQ("", GetBaseFileName(".."));
EXPECT_EQ("echo", GetBaseFileName("/bin/echo"));
EXPECT_EQ("shadow", GetBaseFileName("//etc/shadow"));
EXPECT_EQ("lib", GetBaseFileName("/../../../lib"));
EXPECT_EQ("something", GetBaseFileName("./something"));
EXPECT_EQ("input", GetBaseFileName("input"));
EXPECT_EQ("test", GetBaseFileName("../test"));
EXPECT_EQ("abc", GetBaseFileName(" /abc"));
EXPECT_EQ("ttt", GetBaseFileName("/abc def/ttt"));
}
TEST(GetBaseFileName, Windows) {
EXPECT_EQ("file", GetBaseFileName(R"(\\Server1000\superuser\file)"));
EXPECT_EQ("file with space",
GetBaseFileName(R"(\\zzzz 1000\user with space\file with space)"));
EXPECT_EQ(
"shader.glsl",
GetBaseFileName(R"(C:\Program Files (x86)\Windows Folder\shader.glsl)"));
EXPECT_EQ("gmock", GetBaseFileName(R"(third_party\gmock)"));
EXPECT_EQ("File.txt", GetBaseFileName(R"(C:..\File.txt)"));
}
TEST_F(ReadFileTest, CorrectContent) {
ASSERT_TRUE(ReadFile("include_file.1", &read_data));
EXPECT_EQ("The quick brown fox jumps over a lazy dog.", ToString(read_data));
}
TEST_F(ReadFileTest, EmptyContent) {
ASSERT_TRUE(ReadFile("dir/subdir/include_file.2", &read_data));
EXPECT_TRUE(read_data.empty());
}
TEST_F(ReadFileTest, FileNotFound) {
EXPECT_FALSE(ReadFile("garbage garbage vjoiarhiupo hrfewi", &read_data));
}
TEST_F(ReadFileTest, EmptyFilename) { EXPECT_FALSE(ReadFile("", &read_data)); }
TEST(WriteFiletest, BadStream) {
std::ofstream fstream;
std::ostringstream err;
std::ostream* output_stream = GetOutputStream(
"/this/should/not/be/writable/asdfasdfasdfasdf", &fstream, &err);
EXPECT_EQ(nullptr, output_stream);
EXPECT_TRUE(fstream.fail());
EXPECT_EQ(nullptr, output_stream);
EXPECT_THAT(err.str(), HasSubstr("cannot open output file"));
}
TEST(WriteFileTest, Roundtrip) {
const std::string content = "random content 12345";
const std::string filename = "WriteFileTestOutput.tmp";
std::ofstream fstream;
std::ostringstream err;
std::ostream* output_stream = GetOutputStream(filename, &fstream, &err);
ASSERT_EQ(output_stream, &fstream);
EXPECT_THAT(err.str(), Eq(""));
ASSERT_TRUE(WriteFile(output_stream, content));
std::vector<char> read_data;
ASSERT_TRUE(ReadFile(filename, &read_data));
EXPECT_EQ(content, ToString(read_data));
}
TEST(OutputStreamTest, Stdout) {
std::ofstream fstream;
std::ostringstream err;
std::ostream* output_stream = GetOutputStream("-", &fstream, &err);
EXPECT_EQ(&std::cout, output_stream);
EXPECT_THAT(err.str(), Eq(""));
}
} // anonymous namespace

View File

@ -0,0 +1,293 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/message.h"
#include <algorithm>
#include <cstring>
#include <iostream>
#include <iterator>
namespace shaderc_util {
namespace {
// Given a message, deduces and returns its type. If the message type is
// recognized, advances *message past the prefix indicating the type. Otherwise,
// leaves *message unchanged and returns MessageType::Unknown.
MessageType DeduceMessageType(string_piece* message) {
static const char kErrorMessage[] = "ERROR: ";
static const char kWarningMessage[] = "WARNING: ";
static const char kGlobalWarningMessage[] = "Warning, ";
if (message->starts_with(kErrorMessage)) {
*message = message->substr(::strlen(kErrorMessage));
return MessageType::Error;
} else if (message->starts_with(kWarningMessage)) {
*message = message->substr(::strlen(kWarningMessage));
return MessageType::Warning;
} else if (message->starts_with(kGlobalWarningMessage)) {
*message = message->substr(::strlen(kGlobalWarningMessage));
return MessageType::GlobalWarning;
}
return MessageType::Unknown;
}
// Deduces a location specification from the given message. A location
// specification is of the form "<source-name>:<line-number>:" and a trailing
// space. If the deduction is successful, returns true and updates source_name
// and line_number to the deduced source name and line numer respectively. The
// prefix standing for the location specification in message is skipped.
// Otherwise, returns false and keeps all parameters untouched.
bool DeduceLocationSpec(string_piece* message, string_piece* source_name,
string_piece* line_number) {
if (!message || message->empty()) {
return false;
}
// When we find a pattern like this:
// colon
// digits
// colon
// space
// Then deduce that the source_name is the text before the first colon,
// the line number is the digits, and the message is the text after the
// second colon.
const size_t size = message->size();
if (size <= 4) {
// A valid message must have a colon, a digit, a colon, and a space.
return false;
}
// The last possible position of the first colon.
const size_t first_colon_cutoff = size - 4;
// The last possible position of the second colon.
const size_t next_colon_cutoff = size - 2;
for (size_t first_colon_pos = message->find_first_of(':'), next_colon_pos = 0;
// There is a first colon, and it's not too close to the end
(first_colon_pos != string_piece::npos) &&
(first_colon_pos <= first_colon_cutoff);
// Try the next pair of colons.
first_colon_pos = next_colon_pos) {
// We're guaranteed to have at least 3 more characters.
// Guarantee progress toward the end of the string.
next_colon_pos = message->find_first_of(':', first_colon_pos + 1);
if ((next_colon_pos == string_piece::npos) ||
(next_colon_pos > next_colon_cutoff)) {
// No valid solution.
return false;
}
if (first_colon_pos + 1 == next_colon_pos) {
// There is no room for digits.
continue;
}
if ((message->data()[next_colon_pos + 1] != ' ')) {
// There is no space character after the second colon.
continue;
}
if (message->find_first_not_of("0123456789", first_colon_pos + 1) ==
next_colon_pos) {
// We found the first solution.
*source_name = message->substr(0, first_colon_pos);
*line_number = message->substr(first_colon_pos + 1,
next_colon_pos - 1 - first_colon_pos);
*message = message->substr(next_colon_pos + 2);
return true;
}
}
return false;
}
// Returns true if the given message is a summary message.
bool IsSummaryMessage(const string_piece& message) {
const size_t space_loc = message.find_first_of(' ');
if (space_loc == string_piece::npos) return false;
const string_piece number = message.substr(0, space_loc);
const string_piece rest = message.substr(space_loc + 1);
if (!std::all_of(number.begin(), number.end(), ::isdigit)) return false;
if (!rest.starts_with("compilation errors.")) return false;
return true;
}
} // anonymous namespace
MessageType ParseGlslangOutput(const string_piece& message,
bool warnings_as_errors, bool suppress_warnings,
string_piece* source_name,
string_piece* line_number, string_piece* rest) {
string_piece rest_of_message(message);
source_name->clear();
line_number->clear();
rest->clear();
// The glslang warning/error messages are typically of the following form:
// <message-type> <location-specification> <message-body>
//
// <message-type> can be "WARNING:", "ERROR:", or "Warning, ". "WARNING:"
// means a warning message for a certain line, while "Warning, " means a
// global one.
//
// <location-specification> is of the form:
// <filename-or-string-number>:<line-number>:
// It doesn't exist if the warning/error message is a global one.
//
// See Glslang's TInfoSink class implementation for details.
bool is_error = false;
// Handle <message-type>.
switch (DeduceMessageType(&rest_of_message)) {
case MessageType::Warning:
if (suppress_warnings) return MessageType::Ignored;
break;
case MessageType::Error:
is_error = true;
break;
case MessageType::GlobalWarning:
if (suppress_warnings) return MessageType::Ignored;
*rest = rest_of_message;
return warnings_as_errors ? MessageType::GlobalError
: MessageType::GlobalWarning;
case MessageType::Unknown:
*rest = rest_of_message;
return MessageType::Unknown;
default:
break;
}
rest_of_message = rest_of_message.strip_whitespace();
if (rest_of_message.empty()) return MessageType::Unknown;
// Now we have stripped the <message-type>. Try to see if we can find
// a <location-specification>.
if (DeduceLocationSpec(&rest_of_message, source_name, line_number)) {
*rest = rest_of_message;
return (is_error || warnings_as_errors) ? MessageType::Error
: MessageType::Warning;
} else {
// No <location-specification>. This is a global warning/error message.
// A special kind of global message is summary message, which should
// start with a number.
*rest = rest_of_message;
if (IsSummaryMessage(rest_of_message)) {
return (is_error || warnings_as_errors) ? MessageType::ErrorSummary
: MessageType::WarningSummary;
}
return (is_error || warnings_as_errors) ? MessageType::GlobalError
: MessageType::GlobalWarning;
}
return MessageType::Unknown;
}
bool PrintFilteredErrors(const string_piece& file_name,
std::ostream* error_stream, bool warnings_as_errors,
bool suppress_warnings, const char* error_list,
size_t* total_warnings, size_t* total_errors) {
const char* ignored_error_strings[] = {
"Warning, version 310 is not yet complete; most version-specific "
"features are present, but some are missing.",
"Warning, version 400 is not yet complete; most version-specific "
"features are present, but some are missing.",
"Warning, version 410 is not yet complete; most version-specific "
"features are present, but some are missing.",
"Warning, version 420 is not yet complete; most version-specific "
"features are present, but some are missing.",
"Warning, version 430 is not yet complete; most version-specific "
"features are present, but some are missing.",
"Warning, version 440 is not yet complete; most version-specific "
"features are present, but some are missing.",
"Warning, version 450 is not yet complete; most version-specific "
"features are present, but some are missing.",
"Linked vertex stage:", "Linked fragment stage:",
"Linked tessellation control stage:",
"Linked tessellation evaluation stage:", "Linked geometry stage:",
"Linked compute stage:", ""};
size_t existing_total_errors = *total_errors;
string_piece error_messages(error_list);
for (const string_piece& message : error_messages.get_fields('\n')) {
if (std::find(std::begin(ignored_error_strings),
std::end(ignored_error_strings),
message) == std::end(ignored_error_strings)) {
string_piece source_name;
string_piece line_number;
string_piece rest;
const MessageType type =
ParseGlslangOutput(message, warnings_as_errors, suppress_warnings,
&source_name, &line_number, &rest);
string_piece name = file_name;
if (!source_name.empty()) {
// -1 is the string number for the preamble injected by us.
name = source_name == "-1" ? "<command line>" : source_name;
}
switch (type) {
case MessageType::Error:
case MessageType::Warning:
assert(!name.empty() && !line_number.empty() && !rest.empty());
*error_stream << name << ":" << line_number << ": "
<< (type == MessageType::Error ? "error: "
: "warning: ")
<< rest.strip_whitespace() << std::endl;
*total_errors += type == MessageType::Error;
*total_warnings += type == MessageType::Warning;
break;
case MessageType::ErrorSummary:
case MessageType::WarningSummary:
break;
case MessageType::GlobalError:
case MessageType::GlobalWarning:
assert(!rest.empty());
*total_errors += type == MessageType::GlobalError;
*total_warnings += type == MessageType::GlobalWarning;
*error_stream << name << ": "
<< (type == MessageType::GlobalError ? "error"
: "warning")
<< ": " << rest.strip_whitespace() << std::endl;
break;
case MessageType::Unknown:
*error_stream << name << ":";
*error_stream << " " << message << std::endl;
break;
case MessageType::Ignored:
break;
}
}
}
return (existing_total_errors == *total_errors);
}
// Outputs the number of warnings and errors if there are any.
void OutputMessages(std::ostream* error_stream, size_t total_warnings,
size_t total_errors) {
if (total_warnings > 0 || total_errors > 0) {
if (total_warnings > 0 && total_errors > 0) {
*error_stream << total_warnings << " warning"
<< (total_warnings > 1 ? "s" : "") << " and "
<< total_errors << " error" << (total_errors > 1 ? "s" : "")
<< " generated." << std::endl;
} else if (total_warnings > 0) {
*error_stream << total_warnings << " warning"
<< (total_warnings > 1 ? "s" : "") << " generated."
<< std::endl;
} else if (total_errors > 0) {
*error_stream << total_errors << " error" << (total_errors > 1 ? "s" : "")
<< " generated." << std::endl;
}
}
}
} // namespace glslc

View File

@ -0,0 +1,281 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Some of the tests here check code paths that are not checked by
// integration tests.
// Generally, these would be conditions not generated by the Glslang
// compiler. It's easier to write these unit tests than to inject
// a dependency on a fake compiler.
#include "libshaderc_util/message.h"
#include <gtest/gtest.h>
using shaderc_util::MessageType;
using shaderc_util::ParseGlslangOutput;
using shaderc_util::string_piece;
namespace {
TEST(ParseGlslangOutputTest, EmptyMessageBody) {
string_piece segment_number;
string_piece line_number;
string_piece rest;
EXPECT_EQ(MessageType::Unknown,
ParseGlslangOutput("WARNING: ", false, false, &segment_number,
&line_number, &rest));
EXPECT_EQ(MessageType::Unknown,
ParseGlslangOutput("ERROR: ", false, false, &segment_number,
&line_number, &rest));
}
TEST(ParseGlslangOutputTest, GlobalError) {
string_piece segment_number;
string_piece line_number;
string_piece rest;
EXPECT_EQ(
MessageType::GlobalError,
ParseGlslangOutput("ERROR: too many functions: got 1666473 of them",
false, false, &segment_number, &line_number, &rest));
EXPECT_EQ("too many functions: got 1666473 of them", rest.str());
EXPECT_EQ(
MessageType::GlobalError,
ParseGlslangOutput(
"ERROR: #version: versions before 150 do not allow a profile token",
false, false, &segment_number, &line_number, &rest));
EXPECT_EQ("#version: versions before 150 do not allow a profile token",
rest.str());
}
TEST(ParseGlslangOutputTest, GlobalWarning) {
string_piece segment_number;
string_piece line_number;
string_piece rest;
EXPECT_EQ(MessageType::GlobalWarning,
ParseGlslangOutput("Warning, version 1000 is unknown.", false,
false, &segment_number, &line_number, &rest));
EXPECT_EQ("version 1000 is unknown.", rest.str());
}
TEST(ParseGlslangOutputTest, InvalidSuffixAfterSegmentNumber) {
string_piece segment_number;
string_piece line_number;
string_piece rest;
EXPECT_EQ(MessageType::GlobalWarning,
ParseGlslangOutput("WARNING: 12a", false, false, &segment_number,
&line_number, &rest));
EXPECT_EQ(MessageType::GlobalError,
ParseGlslangOutput("WARNING: 12a", true, false, &segment_number,
&line_number, &rest));
EXPECT_EQ(MessageType::GlobalError,
ParseGlslangOutput("ERROR: 42!", false, false, &segment_number,
&line_number, &rest));
}
TEST(ParseGlslangOutputTest, OnlyANumber) {
string_piece source_name;
string_piece line_number;
string_piece rest;
EXPECT_EQ(MessageType::GlobalWarning,
ParseGlslangOutput("WARNING: 12", false, false, &source_name,
&line_number, &rest));
EXPECT_TRUE(source_name.empty());
EXPECT_TRUE(line_number.empty());
EXPECT_EQ("12", rest.str());
EXPECT_EQ(MessageType::GlobalError,
ParseGlslangOutput("WARNING: 12", true, false, &source_name,
&line_number, &rest));
EXPECT_TRUE(source_name.empty());
EXPECT_TRUE(line_number.empty());
EXPECT_EQ("12", rest.str());
EXPECT_EQ(MessageType::GlobalError,
ParseGlslangOutput("ERROR: 42", false, false, &source_name,
&line_number, &rest));
EXPECT_TRUE(source_name.empty());
EXPECT_TRUE(line_number.empty());
EXPECT_EQ("42", rest.str());
}
TEST(ParseGlslangOutputTest, InvalidSuffixAfterSegmentNumberColon) {
string_piece segment_number;
string_piece line_number;
string_piece rest;
EXPECT_EQ(MessageType::GlobalWarning,
ParseGlslangOutput("WARNING: 12:0", false, false, &segment_number,
&line_number, &rest));
EXPECT_EQ(MessageType::GlobalError,
ParseGlslangOutput("ERROR: 42:1234", false, false, &segment_number,
&line_number, &rest));
}
TEST(ParseGlslangOutputTest, CompletelyUnrecognized) {
string_piece segment_number;
string_piece line_number;
string_piece rest;
EXPECT_EQ(MessageType::Unknown,
ParseGlslangOutput("hello world!", false, false, &segment_number,
&line_number, &rest));
}
TEST(ParseGlslangOutputTest, LocationSpecification) {
string_piece segment_number;
string_piece line_number;
string_piece rest;
// Glslang reading from strings can give string segment numbers as
// the filename part.
EXPECT_EQ(
MessageType::Error,
ParseGlslangOutput("ERROR: 0:2: '#' : invalid directive: foo", false,
false, &segment_number, &line_number, &rest));
EXPECT_EQ("0", segment_number.str());
EXPECT_EQ("2", line_number.str());
EXPECT_EQ("'#' : invalid directive: foo", rest.str());
EXPECT_EQ(
MessageType::Warning,
ParseGlslangOutput("WARNING: 15:36: The following extension must be "
"enabled to use this feature:",
false, false, &segment_number, &line_number, &rest));
EXPECT_EQ("15", segment_number.str());
EXPECT_EQ("36", line_number.str());
EXPECT_EQ("The following extension must be enabled to use this feature:",
rest.str());
}
TEST(ParseGlslangOutputTest, FileName_BaseAndExtension) {
string_piece source_name;
string_piece line_number;
string_piece rest;
EXPECT_EQ(MessageType::Error,
ParseGlslangOutput("ERROR: shader.vert:5: something wrong", false,
false, &source_name, &line_number, &rest));
EXPECT_EQ("shader.vert", source_name.str());
EXPECT_EQ("5", line_number.str());
EXPECT_EQ("something wrong", rest.str());
}
TEST(ParseGlslangOutputTest, FileName_BaseOnly) {
string_piece source_name;
string_piece line_number;
string_piece rest;
EXPECT_EQ(MessageType::Warning,
ParseGlslangOutput("WARNING: file:42: something wrong", false,
false, &source_name, &line_number, &rest));
EXPECT_EQ("file", source_name.str());
EXPECT_EQ("42", line_number.str());
EXPECT_EQ("something wrong", rest.str());
}
TEST(ParseGlslangOutputTest, FileName_HexNumber) {
string_piece source_name;
string_piece line_number;
string_piece rest;
EXPECT_EQ(MessageType::Warning,
ParseGlslangOutput("WARNING: 0xdeedbeef:0: wa:ha:ha", false, false,
&source_name, &line_number, &rest));
EXPECT_EQ("0xdeedbeef", source_name.str());
EXPECT_EQ("0", line_number.str());
EXPECT_EQ("wa:ha:ha", rest.str());
}
TEST(ParseGlslangOutputTest, FileName_ContainsColons) {
string_piece source_name;
string_piece line_number;
string_piece rest;
EXPECT_EQ(MessageType::Warning,
ParseGlslangOutput("WARNING: foo:bar:0: wa:ha:ha", false, false,
&source_name, &line_number, &rest));
EXPECT_EQ("foo:bar", source_name.str());
EXPECT_EQ("0", line_number.str());
EXPECT_EQ("wa:ha:ha", rest.str());
}
TEST(ParseGlslangOutputTest, NoFile) {
string_piece source_name;
string_piece line_number;
string_piece rest;
EXPECT_EQ(MessageType::Warning,
ParseGlslangOutput("WARNING: :12: abc", false, false, &source_name,
&line_number, &rest));
EXPECT_EQ("", source_name.str());
EXPECT_EQ("12", line_number.str());
EXPECT_EQ("abc", rest.str());
}
TEST(ParseGlslangOutputTest, NoLineNumber_InferredAsGlobalNoLocation) {
string_piece source_name;
string_piece line_number;
string_piece rest;
// No solution since there is no room for digits.
EXPECT_EQ(MessageType::GlobalWarning,
ParseGlslangOutput("WARNING: foo:: abc", false, false,
&source_name, &line_number, &rest));
EXPECT_EQ("", source_name.str());
EXPECT_EQ("", line_number.str());
EXPECT_EQ("foo:: abc", rest.str());
}
TEST(ParseGlslangOutputTest, NoSpaceAfterColon_InferredAsGlobalNoLocation) {
string_piece source_name;
string_piece line_number;
string_piece rest;
// No solution since there is no space after the line-number-and-colon.
EXPECT_EQ(MessageType::GlobalWarning,
ParseGlslangOutput("WARNING: foo:12:abc", false, false,
&source_name, &line_number, &rest));
EXPECT_EQ("", source_name.str());
EXPECT_EQ("", line_number.str());
EXPECT_EQ("foo:12:abc", rest.str());
}
TEST(ParseGlslangOutputTest, WindowsPath) {
string_piece source_name;
string_piece line_number;
string_piece rest;
EXPECT_EQ(
MessageType::Error,
ParseGlslangOutput(R"(ERROR: C:\path\to\shader.glsl:5: something wrong)",
false, false, &source_name, &line_number, &rest));
EXPECT_EQ(R"(C:\path\to\shader.glsl)", source_name.str());
EXPECT_EQ("5", line_number.str());
EXPECT_EQ("something wrong", rest.str());
EXPECT_EQ(
MessageType::Warning,
ParseGlslangOutput(R"(WARNING: \\path\without\drive.vert:42: BOOM!)",
false, false, &source_name, &line_number, &rest));
EXPECT_EQ(R"(\\path\without\drive.vert)", source_name.str());
EXPECT_EQ("42", line_number.str());
EXPECT_EQ("BOOM!", rest.str());
EXPECT_EQ(MessageType::Warning,
ParseGlslangOutput(R"(WARNING: X:\123.456\789:0: wa:ha:ha)", false,
false, &source_name, &line_number, &rest));
EXPECT_EQ(R"(X:\123.456\789)", source_name.str());
EXPECT_EQ("0", line_number.str());
EXPECT_EQ("wa:ha:ha", rest.str());
}
} // anonymous namespace

View File

@ -0,0 +1,51 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/mutex.h"
#include <gmock/gmock.h>
#include <thread>
namespace {
TEST(MutexTest, CanCreateMutex) {
shaderc_util::mutex mutex;
mutex.lock();
mutex.unlock();
}
#ifndef SHADERC_DISABLE_THREADED_TESTS
void increment_by_1000(shaderc_util::mutex& mut, int& i) {
for(size_t j = 0; j < 1000; ++j) {
mut.lock();
i = i + 1;
mut.unlock();
}
}
TEST(MutexTest, MutexLocks) {
shaderc_util::mutex mutex;
int i = 0;
std::thread t1([&mutex, &i]() { increment_by_1000(mutex, i); });
std::thread t2([&mutex, &i]() { increment_by_1000(mutex, i); });
std::thread t3([&mutex, &i]() { increment_by_1000(mutex, i); });
t1.join();
t2.join();
t3.join();
EXPECT_EQ(3000, i);
}
#endif // SHADERC_DISABLE_THREADED_TESTS
} // anonymous namespace

View File

@ -0,0 +1,144 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/resources.h"
#include "glslang/Include/ResourceLimits.h"
namespace shaderc_util {
// These numbers come from the OpenGL 4.4 core profile specification Chapter 23
// unless otherwise specified.
const TBuiltInResource kDefaultTBuiltInResource = {
/*.maxLights = */ 8, // From OpenGL 3.0 table 6.46.
/*.maxClipPlanes = */ 6, // From OpenGL 3.0 table 6.46.
/*.maxTextureUnits = */ 2, // From OpenGL 3.0 table 6.50.
/*.maxTextureCoords = */ 8, // From OpenGL 3.0 table 6.50.
/*.maxVertexAttribs = */ 16,
/*.maxVertexUniformComponents = */ 4096,
/*.maxVaryingFloats = */ 60, // From OpenGLES 3.1 table 6.44.
/*.maxVertexTextureImageUnits = */ 16,
/*.maxCombinedTextureImageUnits = */ 80,
/*.maxTextureImageUnits = */ 16,
/*.maxFragmentUniformComponents = */ 1024,
// glslang has 32 maxDrawBuffers.
// Pixel phone Vulkan driver in Android N has 8
// maxFragmentOutputAttachments.
/*.maxDrawBuffers = */ 8,
/*.maxVertexUniformVectors = */ 256,
/*.maxVaryingVectors = */ 15, // From OpenGLES 3.1 table 6.44.
/*.maxFragmentUniformVectors = */ 256,
/*.maxVertexOutputVectors = */ 16, // maxVertexOutputComponents / 4
/*.maxFragmentInputVectors = */ 15, // maxFragmentInputComponents / 4
/*.minProgramTexelOffset = */ -8,
/*.maxProgramTexelOffset = */ 7,
/*.maxClipDistances = */ 8,
/*.maxComputeWorkGroupCountX = */ 65535,
/*.maxComputeWorkGroupCountY = */ 65535,
/*.maxComputeWorkGroupCountZ = */ 65535,
/*.maxComputeWorkGroupSizeX = */ 1024,
/*.maxComputeWorkGroupSizeX = */ 1024,
/*.maxComputeWorkGroupSizeZ = */ 64,
/*.maxComputeUniformComponents = */ 512,
/*.maxComputeTextureImageUnits = */ 16,
/*.maxComputeImageUniforms = */ 8,
/*.maxComputeAtomicCounters = */ 8,
/*.maxComputeAtomicCounterBuffers = */ 1, // From OpenGLES 3.1 Table 6.43
/*.maxVaryingComponents = */ 60,
/*.maxVertexOutputComponents = */ 64,
/*.maxGeometryInputComponents = */ 64,
/*.maxGeometryOutputComponents = */ 128,
/*.maxFragmentInputComponents = */ 128,
/*.maxImageUnits = */ 8, // This does not seem to be defined anywhere,
// set to ImageUnits.
/*.maxCombinedImageUnitsAndFragmentOutputs = */ 8,
/*.maxCombinedShaderOutputResources = */ 8,
/*.maxImageSamples = */ 0,
/*.maxVertexImageUniforms = */ 0,
/*.maxTessControlImageUniforms = */ 0,
/*.maxTessEvaluationImageUniforms = */ 0,
/*.maxGeometryImageUniforms = */ 0,
/*.maxFragmentImageUniforms = */ 8,
/*.maxCombinedImageUniforms = */ 8,
/*.maxGeometryTextureImageUnits = */ 16,
/*.maxGeometryOutputVertices = */ 256,
/*.maxGeometryTotalOutputComponents = */ 1024,
/*.maxGeometryUniformComponents = */ 512,
/*.maxGeometryVaryingComponents = */ 60, // Does not seem to be defined
// anywhere, set equal to
// maxVaryingComponents.
/*.maxTessControlInputComponents = */ 128,
/*.maxTessControlOutputComponents = */ 128,
/*.maxTessControlTextureImageUnits = */ 16,
/*.maxTessControlUniformComponents = */ 1024,
/*.maxTessControlTotalOutputComponents = */ 4096,
/*.maxTessEvaluationInputComponents = */ 128,
/*.maxTessEvaluationOutputComponents = */ 128,
/*.maxTessEvaluationTextureImageUnits = */ 16,
/*.maxTessEvaluationUniformComponents = */ 1024,
/*.maxTessPatchComponents = */ 120,
/*.maxPatchVertices = */ 32,
/*.maxTessGenLevel = */ 64,
/*.maxViewports = */ 16,
/*.maxVertexAtomicCounters = */ 0,
/*.maxTessControlAtomicCounters = */ 0,
/*.maxTessEvaluationAtomicCounters = */ 0,
/*.maxGeometryAtomicCounters = */ 0,
/*.maxFragmentAtomicCounters = */ 8,
/*.maxCombinedAtomicCounters = */ 8,
/*.maxAtomicCounterBindings = */ 1,
/*.maxVertexAtomicCounterBuffers = */ 0, // From OpenGLES 3.1 Table 6.41.
// ARB_shader_atomic_counters.
/*.maxTessControlAtomicCounterBuffers = */ 0,
/*.maxTessEvaluationAtomicCounterBuffers = */ 0,
/*.maxGeometryAtomicCounterBuffers = */ 0,
// /ARB_shader_atomic_counters.
/*.maxFragmentAtomicCounterBuffers = */ 0, // From OpenGLES 3.1 Table 6.43.
/*.maxCombinedAtomicCounterBuffers = */ 1,
/*.maxAtomicCounterBufferSize = */ 32,
/*.maxTransformFeedbackBuffers = */ 4,
/*.maxTransformFeedbackInterleavedComponents = */ 64,
/*.maxCullDistances = */ 8, // ARB_cull_distance.
/*.maxCombinedClipAndCullDistances = */ 8, // ARB_cull_distance.
/*.maxSamples = */ 4,
/* .maxMeshOutputVerticesNV = */ 256,
/* .maxMeshOutputPrimitivesNV = */ 512,
/* .maxMeshWorkGroupSizeX_NV = */ 32,
/* .maxMeshWorkGroupSizeY_NV = */ 1,
/* .maxMeshWorkGroupSizeZ_NV = */ 1,
/* .maxTaskWorkGroupSizeX_NV = */ 32,
/* .maxTaskWorkGroupSizeY_NV = */ 1,
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
/* .maxMeshViewCountNV = */ 4,
/* .maxDualSourceDrawBuffersEXT = */ 1,
// This is the glslang TLimits structure.
// It defines whether or not the following features are enabled.
// We want them to all be enabled.
/*.limits = */ {
/*.nonInductiveForLoops = */ 1,
/*.whileLoops = */ 1,
/*.doWhileLoops = */ 1,
/*.generalUniformIndexing = */ 1,
/*.generalAttributeMatrixVectorIndexing = */ 1,
/*.generalVaryingIndexing = */ 1,
/*.generalSamplerIndexing = */ 1,
/*.generalVariableIndexing = */ 1,
/*.generalConstantMatrixVectorIndexing = */ 1,
}};
} // namespace shaderc_util

View File

@ -0,0 +1,53 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/shader_stage.h"
namespace {
// Maps an identifier to a language.
struct LanguageMapping {
const char* id;
EShLanguage language;
};
} // anonymous namespace
namespace shaderc_util {
EShLanguage MapStageNameToLanguage(const string_piece& stage_name) {
const LanguageMapping string_to_stage[] = {
{"vertex", EShLangVertex},
{"fragment", EShLangFragment},
{"tesscontrol", EShLangTessControl},
{"tesseval", EShLangTessEvaluation},
{"geometry", EShLangGeometry},
{"compute", EShLangCompute},
{"raygen", EShLangRayGenNV},
{"intersect", EShLangIntersectNV},
{"anyhit", EShLangAnyHitNV},
{"closest", EShLangClosestHitNV},
{"miss", EShLangMissNV},
{"callable", EShLangCallableNV},
{"task", EShLangTaskNV},
{"mesh", EShLangMeshNV},
};
for (const auto& entry : string_to_stage) {
if (stage_name == entry.id) return entry.language;
}
return EShLangCount;
}
} // namespace shaderc_util

View File

@ -0,0 +1,169 @@
// Copyright 2016 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/spirv_tools_wrapper.h"
#include <algorithm>
#include <sstream>
#include "spirv-tools/optimizer.hpp"
namespace shaderc_util {
namespace {
// Gets the corresponding target environment used in SPIRV-Tools.
spv_target_env GetSpirvToolsTargetEnv(Compiler::TargetEnv env,
Compiler::TargetEnvVersion version) {
switch (env) {
case Compiler::TargetEnv::Vulkan:
switch (version) {
case Compiler::TargetEnvVersion::Default:
return SPV_ENV_VULKAN_1_0;
case Compiler::TargetEnvVersion::Vulkan_1_0:
return SPV_ENV_VULKAN_1_0;
case Compiler::TargetEnvVersion::Vulkan_1_1:
return SPV_ENV_VULKAN_1_1;
case Compiler::TargetEnvVersion::Vulkan_1_2:
return SPV_ENV_VULKAN_1_2;
case Compiler::TargetEnvVersion::Vulkan_1_3:
return SPV_ENV_VULKAN_1_3;
default:
break;
}
break;
case Compiler::TargetEnv::OpenGL:
return SPV_ENV_OPENGL_4_5;
case Compiler::TargetEnv::OpenGLCompat:
// Errors out before getting here. But the compiler wants us to handle
// enum anyway.
return SPV_ENV_OPENGL_4_5;
}
assert(false && "unexpected target environment or version");
return SPV_ENV_VULKAN_1_0;
}
} // anonymous namespace
bool SpirvToolsDisassemble(Compiler::TargetEnv env,
Compiler::TargetEnvVersion version,
const std::vector<uint32_t>& binary,
std::string* text_or_error) {
spvtools::SpirvTools tools(GetSpirvToolsTargetEnv(env, version));
std::ostringstream oss;
tools.SetMessageConsumer([&oss](spv_message_level_t, const char*,
const spv_position_t& position,
const char* message) {
oss << position.index << ": " << message;
});
const bool success =
tools.Disassemble(binary, text_or_error,
SPV_BINARY_TO_TEXT_OPTION_INDENT |
SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
if (!success) {
*text_or_error = oss.str();
}
return success;
}
bool SpirvToolsAssemble(Compiler::TargetEnv env,
Compiler::TargetEnvVersion version,
const string_piece assembly, spv_binary* binary,
std::string* errors) {
auto spvtools_context =
spvContextCreate(GetSpirvToolsTargetEnv(env, version));
spv_diagnostic spvtools_diagnostic = nullptr;
*binary = nullptr;
errors->clear();
const bool success =
spvTextToBinary(spvtools_context, assembly.data(), assembly.size(),
binary, &spvtools_diagnostic) == SPV_SUCCESS;
if (!success) {
std::ostringstream oss;
oss << spvtools_diagnostic->position.line + 1 << ":"
<< spvtools_diagnostic->position.column + 1 << ": "
<< spvtools_diagnostic->error;
*errors = oss.str();
}
spvDiagnosticDestroy(spvtools_diagnostic);
spvContextDestroy(spvtools_context);
return success;
}
bool SpirvToolsOptimize(Compiler::TargetEnv env,
Compiler::TargetEnvVersion version,
const std::vector<PassId>& enabled_passes,
std::vector<uint32_t>* binary, std::string* errors) {
errors->clear();
if (enabled_passes.empty()) return true;
if (std::all_of(
enabled_passes.cbegin(), enabled_passes.cend(),
[](const PassId& pass) { return pass == PassId::kNullPass; })) {
return true;
}
spvtools::ValidatorOptions val_opts;
// This allows flexible memory layout for HLSL.
val_opts.SetSkipBlockLayout(true);
// This allows HLSL legalization regarding resources.
val_opts.SetRelaxLogicalPointer(true);
// This uses relaxed rules for pre-legalized HLSL.
val_opts.SetBeforeHlslLegalization(true);
spvtools::OptimizerOptions opt_opts;
opt_opts.set_validator_options(val_opts);
opt_opts.set_run_validator(true);
spvtools::Optimizer optimizer(GetSpirvToolsTargetEnv(env, version));
std::ostringstream oss;
optimizer.SetMessageConsumer(
[&oss](spv_message_level_t, const char*, const spv_position_t&,
const char* message) { oss << message << "\n"; });
for (const auto& pass : enabled_passes) {
switch (pass) {
case PassId::kLegalizationPasses:
optimizer.RegisterLegalizationPasses();
break;
case PassId::kPerformancePasses:
optimizer.RegisterPerformancePasses();
break;
case PassId::kSizePasses:
optimizer.RegisterSizePasses();
break;
case PassId::kNullPass:
// We actually don't need to do anything for null pass.
break;
case PassId::kStripDebugInfo:
optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
break;
case PassId::kCompactIds:
optimizer.RegisterPass(spvtools::CreateCompactIdsPass());
break;
}
}
if (!optimizer.Run(binary->data(), binary->size(), binary, opt_opts)) {
*errors = oss.str();
return false;
}
return true;
}
} // namespace shaderc_util

View File

@ -0,0 +1,437 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/string_piece.h"
#include <gtest/gtest.h>
#include <sstream>
#include <unordered_map>
#include "death_test.h"
namespace {
using shaderc_util::string_piece;
TEST(string_piece, creation) {
std::string my_string("std::string");
const char* my_c_string = "c::string";
string_piece my_string_piece(my_string);
string_piece my_c_string_piece(my_c_string);
string_piece my_partial_c_string_piece(my_c_string, my_c_string + 3);
string_piece my_string_piece_string_piece(my_string_piece);
EXPECT_EQ("std::string", my_string_piece);
EXPECT_EQ("c::string", my_c_string_piece);
EXPECT_EQ("c::", my_partial_c_string_piece);
EXPECT_EQ("std::string", my_string_piece_string_piece);
}
TEST(string_piece, creation_with_empty_data) {
string_piece my_string_piece(nullptr, nullptr);
EXPECT_EQ("", my_string_piece);
}
TEST(string_piece, creation_with_nullptr) {
string_piece my_string_piece(nullptr);
EXPECT_EQ("", my_string_piece);
}
TEST(string_pieceDeathTest, creation_causing_assert) {
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece("my_cstring", nullptr), ".*");
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr, "my_cstring"), ".*");
}
TEST(string_pieceDeathTest, front) {
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr).front(), "Assertion");
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr, nullptr).front(),
"Assertion");
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece("").front(), "Assertion");
string_piece s("nonempty");
s.clear();
EXPECT_DEBUG_DEATH_IF_SUPPORTED(s.front(), "Assertion");
}
TEST(string_pieceDeathTest, back) {
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr).back(), "Assertion");
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr, nullptr).back(),
"Assertion");
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece("").back(), "Assertion");
string_piece s("nonempty");
s.clear();
EXPECT_DEBUG_DEATH_IF_SUPPORTED(s.back(), "Assertion");
}
TEST(string_piece, substr) {
string_piece my_string("my really long string");
EXPECT_EQ("my really long string", my_string.substr(0, string_piece::npos));
EXPECT_EQ("my really long string", my_string.substr(0));
EXPECT_EQ("really long string", my_string.substr(3, string_piece::npos));
EXPECT_EQ("really long string", my_string.substr(3));
EXPECT_EQ("really", my_string.substr(3, 6));
}
TEST(string_piece, length) {
EXPECT_EQ(0u, string_piece().size());
EXPECT_TRUE(string_piece().empty());
EXPECT_EQ(10u, string_piece("0123456789").size());
std::string my_string("std::string");
EXPECT_EQ(my_string.size(), string_piece(my_string).size());
}
TEST(string_piece, clear) {
string_piece my_string("my really long string");
EXPECT_EQ("my really long string", my_string);
string_piece other_string(my_string);
EXPECT_EQ("my really long string", other_string);
my_string.clear();
EXPECT_EQ("", my_string);
EXPECT_EQ("my really long string", other_string);
}
TEST(string_piece, str) {
std::string test_string;
{
std::string temporary_string("my really long string");
string_piece my_stringpiece(temporary_string);
string_piece my_substring = my_stringpiece.substr(3, 6);
EXPECT_EQ("really", my_substring);
test_string = my_substring.str();
}
EXPECT_EQ("really", test_string);
}
template <char C>
bool find_char(char c) {
return c == C;
}
TEST(string_piece, find_first_not_matching) {
string_piece my_string("aaaaaaa b");
EXPECT_EQ(7u, my_string.find_first_not_matching(find_char<'a'>));
EXPECT_EQ(0u, my_string.find_first_not_matching(find_char<'b'>));
EXPECT_EQ(0u, string_piece(" ").find_first_not_matching(::isdigit));
size_t npos = string_piece::npos;
EXPECT_EQ(npos, string_piece("").find_first_not_matching(::isdigit));
EXPECT_EQ(npos, string_piece("123").find_first_not_matching(::isdigit));
EXPECT_EQ(3u, string_piece("123 ").find_first_not_matching(::isdigit));
}
TEST(string_piece, find_first_not_of) {
size_t npos = string_piece::npos;
string_piece my_string("aaaaaaa b");
EXPECT_EQ(7u, my_string.find_first_not_of("a"));
EXPECT_EQ(0u, my_string.find_first_not_of("b"));
EXPECT_EQ(7u, my_string.find_first_not_of('a'));
EXPECT_EQ(0u, my_string.find_first_not_of('b'));
EXPECT_EQ(0u, string_piece(" ").find_first_not_of("0123456789"));
EXPECT_EQ(7u, my_string.find_first_not_of("a", 2));
EXPECT_EQ(2u, my_string.find_first_not_of("b", 2));
EXPECT_EQ(7u, my_string.find_first_not_of('a', 2));
EXPECT_EQ(4u, my_string.find_first_not_of('b', 4));
EXPECT_EQ(0u, string_piece(" ").find_first_not_of("0123456789"));
EXPECT_EQ(npos, string_piece(" ").find_first_not_of("0123456789", 5));
EXPECT_EQ(npos, string_piece("").find_first_not_of("012345689"));
EXPECT_EQ(npos, string_piece("").find_first_not_of("012345689", 1));
EXPECT_EQ(npos, string_piece("123").find_first_not_of("0123456789"));
EXPECT_EQ(npos, string_piece("123").find_first_not_of("0123456789", 1));
EXPECT_EQ(3u, string_piece("123 ").find_first_not_of("0123456789", 2));
EXPECT_EQ(npos, string_piece("123 ").find_first_not_of("0123456789", 4));
EXPECT_EQ(npos, string_piece("").find_first_not_of("1"));
EXPECT_EQ(npos, string_piece("111").find_first_not_of('1'));
}
TEST(string_piece, find_first_of_char) {
const size_t npos = string_piece::npos;
string_piece my_string("my really long string");
EXPECT_EQ(0u, my_string.find_first_of('m'));
EXPECT_EQ(3u, my_string.find_first_of('r'));
EXPECT_EQ(npos, my_string.find_first_of('z'));
size_t pos = my_string.find_first_of('l');
EXPECT_EQ(6u, pos);
// If pos points to a 'l' then we should just find that one
EXPECT_EQ(6u, my_string.find_first_of('l', pos));
EXPECT_EQ(7u, my_string.find_first_of('l', pos + 1));
EXPECT_EQ(10u, my_string.find_first_of('l', pos + 2));
EXPECT_EQ(npos, my_string.find_first_of('l', pos + 5));
EXPECT_EQ(npos, my_string.find_first_of('z', 0));
EXPECT_EQ(npos, my_string.find_first_of('z', npos));
my_string.clear();
EXPECT_EQ(npos, my_string.find_first_of('a'));
EXPECT_EQ(npos, my_string.find_first_of('a', 0));
}
TEST(string_piece, find_first_of) {
string_piece my_string("aaaaaa b");
EXPECT_EQ(0u, my_string.find_first_of("a"));
EXPECT_EQ(7u, my_string.find_first_of("b"));
EXPECT_EQ(6u, my_string.find_first_of(" "));
size_t npos = string_piece::npos;
EXPECT_EQ(npos, my_string.find_first_of("xh"));
EXPECT_EQ(6u, my_string.find_first_of(" x"));
EXPECT_EQ(6u, my_string.find_first_of(" b"));
EXPECT_EQ(0u, my_string.find_first_of("ab"));
EXPECT_EQ(6u, my_string.find_first_of(" x", 2));
EXPECT_EQ(6u, my_string.find_first_of(" b", 2));
EXPECT_EQ(2u, my_string.find_first_of("ab", 2));
EXPECT_EQ(npos, my_string.find_first_of("ab", 10));
EXPECT_EQ(npos, my_string.find_first_of("c"));
EXPECT_EQ(npos, my_string.find_first_of("c", 1));
EXPECT_EQ(npos, string_piece(" ").find_first_of("a"));
EXPECT_EQ(npos, string_piece(" ").find_first_of("a", 10));
EXPECT_EQ(npos, string_piece("aa").find_first_of(""));
EXPECT_EQ(npos, string_piece("aa").find_first_of("", 1));
EXPECT_EQ(npos, string_piece("").find_first_of(""));
EXPECT_EQ(npos, string_piece("").find_first_of("", 1));
EXPECT_EQ(npos, string_piece("").find_first_of("a"));
EXPECT_EQ(npos, string_piece("").find_first_of("ae"));
EXPECT_EQ(npos, string_piece("").find_first_of("ae", 32));
}
TEST(string_piece, find_last_of) {
string_piece my_string("aaaaaa b");
EXPECT_EQ(5u, my_string.find_last_of('a'));
EXPECT_EQ(7u, my_string.find_last_of('b'));
EXPECT_EQ(6u, my_string.find_last_of(' '));
EXPECT_EQ(5u, my_string.find_last_of("a"));
EXPECT_EQ(7u, my_string.find_last_of("b"));
EXPECT_EQ(6u, my_string.find_last_of(" "));
size_t npos = string_piece::npos;
EXPECT_EQ(npos, my_string.find_last_of("xh"));
EXPECT_EQ(6u, my_string.find_last_of(" x"));
EXPECT_EQ(7u, my_string.find_last_of(" b"));
EXPECT_EQ(7u, my_string.find_last_of("ab"));
EXPECT_EQ(4u, my_string.find_last_of('a', 4));
EXPECT_EQ(5u, my_string.find_last_of('a', 6));
EXPECT_EQ(0u, string_piece("abbbaa").find_last_of('a', 3));
EXPECT_EQ(4u, string_piece("abbbaa").find_last_of('a', 4));
EXPECT_EQ(5u, string_piece("abbbaa").find_last_of('a', 5));
EXPECT_EQ(5u, string_piece("abbbaa").find_last_of('a', 6));
EXPECT_EQ(npos, string_piece("abbbaa").find_last_of('c', 2));
EXPECT_EQ(npos, my_string.find_last_of("c"));
EXPECT_EQ(npos, string_piece(" ").find_last_of("a"));
EXPECT_EQ(npos, string_piece("aa").find_last_of(""));
EXPECT_EQ(npos, string_piece("").find_last_of(""));
EXPECT_EQ(npos, string_piece("").find_last_of("a"));
EXPECT_EQ(npos, my_string.find_last_of('c'));
EXPECT_EQ(npos, string_piece(" ").find_last_of('a'));
EXPECT_EQ(npos, string_piece("").find_last_of('a'));
EXPECT_EQ(npos, string_piece("").find_last_of("ae"));
}
TEST(string_piece, begin_end) {
const char* my_string = "my really long string";
string_piece p(my_string);
size_t pos = 0;
for (auto it = p.begin(); it != p.end(); ++it) {
EXPECT_EQ(my_string[pos++], *it);
}
pos = 0;
for (auto c : p) {
EXPECT_EQ(my_string[pos++], c);
}
}
TEST(string_piece, front_back) {
// EXPECT_TRUE() is used here because gtest will think we are comparing
// between pointer and integer here if EXPECT_EQ() is used.
const string_piece one_char("a");
EXPECT_TRUE(one_char.front() == 'a');
EXPECT_TRUE(one_char.back() == 'a');
const string_piece two_chars("bc");
EXPECT_TRUE(two_chars.front() == 'b');
EXPECT_TRUE(two_chars.back() == 'c');
const string_piece multi_chars("w vm g gg t\t");
EXPECT_TRUE(multi_chars.front() == 'w');
EXPECT_TRUE(multi_chars.back() == '\t');
}
TEST(string_piece, starts_with) {
EXPECT_TRUE(string_piece("my string").starts_with("my"));
EXPECT_TRUE(string_piece("my string").starts_with("my s"));
EXPECT_TRUE(string_piece("my string").starts_with("m"));
EXPECT_TRUE(string_piece("my string").starts_with(""));
EXPECT_TRUE(string_piece("my string").starts_with("my string"));
EXPECT_TRUE(string_piece("").starts_with(""));
EXPECT_FALSE(string_piece("").starts_with("a"));
EXPECT_FALSE(string_piece("my string").starts_with(" "));
EXPECT_FALSE(string_piece("my string").starts_with("my stq"));
EXPECT_FALSE(string_piece("my string").starts_with("a"));
EXPECT_FALSE(string_piece("my string").starts_with("my strings"));
}
TEST(string_piece, find) {
const size_t npos = string_piece::npos;
string_piece my_string("gooogle gooogle");
EXPECT_EQ(0u, my_string.find(""));
EXPECT_EQ(0u, my_string.find("g"));
EXPECT_EQ(4u, my_string.find("g", 1));
EXPECT_EQ(0u, my_string.find("go"));
EXPECT_EQ(8u, my_string.find("go", 1));
EXPECT_EQ(1u, my_string.find("oo"));
EXPECT_EQ(1u, my_string.find("oo", 1));
EXPECT_EQ(2u, my_string.find("oo", 2));
EXPECT_EQ(9u, my_string.find("oo", 3));
EXPECT_EQ(4u, my_string.find("gle"));
EXPECT_EQ(12u, my_string.find("gle", 5));
EXPECT_EQ(npos, my_string.find("0"));
EXPECT_EQ(npos, my_string.find("does-not-exist"));
EXPECT_EQ(npos, my_string.find("longer than gooogle gooogle"));
EXPECT_EQ(npos, my_string.find("", npos));
EXPECT_EQ(npos, my_string.find("gle", npos));
}
TEST(string_piece, get_fields) {
string_piece input;
std::vector<string_piece> expected_lines;
EXPECT_EQ(expected_lines, input.get_fields('\n'));
EXPECT_EQ(expected_lines, input.get_fields('\n', true));
input = "first line";
expected_lines = {"first line"};
EXPECT_EQ(expected_lines, input.get_fields('\n'));
EXPECT_EQ(expected_lines, input.get_fields('\n', true));
input = "first line\n";
expected_lines = {"first line"};
EXPECT_EQ(expected_lines, input.get_fields('\n'));
expected_lines = {"first line\n"};
EXPECT_EQ(expected_lines, input.get_fields('\n', true));
input = "\nfirst line";
expected_lines = {"", "first line"};
EXPECT_EQ(expected_lines, input.get_fields('\n'));
expected_lines = {"\n", "first line"};
EXPECT_EQ(expected_lines, input.get_fields('\n', true));
input = "first line\nsecond line\nthird line\n";
expected_lines = {"first line", "second line", "third line"};
EXPECT_EQ(expected_lines, input.get_fields('\n'));
expected_lines = {"first line\n", "second line\n", "third line\n"};
EXPECT_EQ(expected_lines, input.get_fields('\n', true));
input = "first line\n\nsecond line\n\nthird line\n\n";
expected_lines = {"first line", "", "second line", "", "third line", ""};
EXPECT_EQ(expected_lines, input.get_fields('\n'));
expected_lines = {"first line\n", "\n", "second line\n",
"\n", "third line\n", "\n"};
EXPECT_EQ(expected_lines, input.get_fields('\n', true));
}
TEST(string_piece, operator_stream_out) {
std::stringstream stream;
string_piece my_string("my really long string");
stream << my_string;
EXPECT_EQ("my really long string", stream.str());
stream.str("");
stream << my_string.substr(3, 6);
EXPECT_EQ("really", stream.str());
stream.str("");
stream << string_piece();
EXPECT_EQ("", stream.str());
}
TEST(string_piece, lrstrip) {
string_piece nothing_to_remove("abcdefg");
EXPECT_EQ("abcdefg", nothing_to_remove.lstrip("hijklmn"));
EXPECT_EQ("abcdefg", nothing_to_remove.rstrip("hijklmn"));
EXPECT_EQ("abcdefg", nothing_to_remove.strip("hijklmn"));
string_piece empty_string("");
EXPECT_EQ(0u, empty_string.lstrip("google").size());
EXPECT_EQ(0u, empty_string.rstrip("google").size());
EXPECT_EQ(0u, empty_string.strip("google").size());
string_piece remove_nothing("asdfghjkl");
EXPECT_EQ("asdfghjkl", remove_nothing.lstrip(""));
EXPECT_EQ("asdfghjkl", remove_nothing.rstrip(""));
EXPECT_EQ("asdfghjkl", remove_nothing.strip(""));
string_piece strip_numbers("0123g4o5o6g7l8e9");
EXPECT_EQ("g4o5o6g7l8e9", strip_numbers.lstrip("0123456789"));
EXPECT_EQ("0123g4o5o6g7l8e", strip_numbers.rstrip("0123456789"));
EXPECT_EQ("g4o5o6g7l8e", strip_numbers.strip("0123456789"));
}
TEST(string_piece, strip_whitespace) {
string_piece lots_of_space(" b i n g o ");
EXPECT_EQ("b i n g o", lots_of_space.strip_whitespace());
string_piece whitespaces("\v\t\f\n\rleft\r\t\f\n\vright\f\n\t\v\r");
EXPECT_EQ("left\r\t\f\n\vright", whitespaces.strip_whitespace());
string_piece remove_all(" \t ");
EXPECT_EQ(0u, remove_all.strip_whitespace().size());
}
TEST(string_piece, not_equal) {
EXPECT_FALSE(string_piece() != string_piece());
EXPECT_FALSE(string_piece("") != string_piece());
EXPECT_TRUE(string_piece() != string_piece(" "));
EXPECT_FALSE(string_piece("abc") != string_piece("abc"));
EXPECT_TRUE(string_piece("abc") != string_piece("abc "));
EXPECT_TRUE(string_piece("abc") != string_piece("abd"));
EXPECT_FALSE("" != string_piece());
EXPECT_FALSE("" != string_piece(""));
EXPECT_TRUE(" " != string_piece(""));
EXPECT_FALSE("abc" != string_piece("abc"));
EXPECT_TRUE(" abc" != string_piece("abc"));
EXPECT_TRUE("abd" != string_piece("abc"));
}
TEST(string_piece, data) {
EXPECT_EQ(nullptr, string_piece().data());
const char* empty = "";
EXPECT_EQ(empty, string_piece(empty).data());
const char* space = " ";
EXPECT_EQ(space, string_piece(space).data());
const char* a = "a";
EXPECT_EQ(a, string_piece(a).data());
const char* abc = "abc";
EXPECT_EQ(abc, string_piece(abc).data());
EXPECT_EQ(abc + 1, string_piece(abc).substr(1).data());
EXPECT_EQ(abc + 3, string_piece(abc).substr(3).data());
}
TEST(string_piece, unordered_map) {
std::unordered_map<string_piece, int> dict;
dict["abc"] = 123;
EXPECT_EQ(123, dict["abc"]);
}
} // anonymous namespace

View File

@ -0,0 +1,59 @@
// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/version_profile.h"
#include <cctype>
#include <sstream>
namespace {
const int kVersionNumberLength = 3;
const int kMaxProfileLength = 13; // strlen(compatibility)
const int kMaxVersionProfileLength = kVersionNumberLength + kMaxProfileLength;
const int kMinVersionProfileLength = kVersionNumberLength;
} // anonymous namespace
namespace shaderc_util {
bool ParseVersionProfile(const std::string& version_profile, int* version,
EProfile* profile) {
if (version_profile.size() < kMinVersionProfileLength ||
version_profile.size() > kMaxVersionProfileLength ||
!::isdigit(version_profile.front()))
return false;
std::string profile_string;
std::istringstream(version_profile) >> *version >> profile_string;
if (!IsKnownVersion(*version)) {
return false;
}
if (profile_string.empty()) {
*profile = ENoProfile;
} else if (profile_string == "core") {
*profile = ECoreProfile;
} else if (profile_string == "es") {
*profile = EEsProfile;
} else if (profile_string == "compatibility") {
*profile = ECompatibilityProfile;
} else {
return false;
}
return true;
}
} // namespace shaderc_util

View File

@ -0,0 +1,133 @@
// Copyright 2017 The Shaderc Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libshaderc_util/version_profile.h"
#include "gmock/gmock.h"
namespace {
using shaderc_util::IsKnownVersion;
using shaderc_util::ParseVersionProfile;
using ::testing::Eq;
using ::testing::ValuesIn;
TEST(IsKnownVersionTest, Samples) {
EXPECT_TRUE(IsKnownVersion(100));
EXPECT_TRUE(IsKnownVersion(110));
EXPECT_TRUE(IsKnownVersion(120));
EXPECT_TRUE(IsKnownVersion(130));
EXPECT_TRUE(IsKnownVersion(140));
EXPECT_TRUE(IsKnownVersion(150));
EXPECT_TRUE(IsKnownVersion(300));
EXPECT_TRUE(IsKnownVersion(330));
EXPECT_TRUE(IsKnownVersion(310));
EXPECT_TRUE(IsKnownVersion(400));
EXPECT_TRUE(IsKnownVersion(410));
EXPECT_TRUE(IsKnownVersion(420));
EXPECT_TRUE(IsKnownVersion(430));
EXPECT_TRUE(IsKnownVersion(440));
EXPECT_TRUE(IsKnownVersion(450));
EXPECT_TRUE(IsKnownVersion(460));
EXPECT_FALSE(IsKnownVersion(101));
EXPECT_FALSE(IsKnownVersion(470));
}
struct ParseVersionProfileCase {
std::string input;
bool success;
// The following are only used when success is true.
int expected_version;
EProfile expected_profile;
};
using ParseVersionProfileTest = ::testing::TestWithParam<ParseVersionProfileCase>;
TEST_P(ParseVersionProfileTest, Sample) {
int version = 0;
EProfile profile = EBadProfile;
const bool result = ParseVersionProfile(GetParam().input, &version, &profile);
EXPECT_THAT(result, GetParam().success);
if (result) {
EXPECT_THAT(version, GetParam().expected_version);
EXPECT_THAT(profile, GetParam().expected_profile);
}
}
// For OpenGL ES GLSL (ESSL) versions, see
// https://www.khronos.org/registry/OpenGL/index_e.php
INSTANTIATE_TEST_SUITE_P(OpenGLESCases, ParseVersionProfileTest,
ValuesIn(std::vector<ParseVersionProfileCase>{
{"100es", true, 100, EEsProfile},
{"300es", true, 300, EEsProfile},
{"310es", true, 310, EEsProfile},
{"320es", true, 320, EEsProfile},
{"99es", false, 0, EBadProfile},
{"500es", false, 0, EBadProfile},
}));
// For OpenGL GLSL versions, see
// https://www.khronos.org/registry/OpenGL/index_gl.php
INSTANTIATE_TEST_SUITE_P(OpenGLBlankCases, ParseVersionProfileTest,
ValuesIn(std::vector<ParseVersionProfileCase>{
{"110", true, 110, ENoProfile},
{"120", true, 120, ENoProfile},
{"130", true, 130, ENoProfile},
{"140", true, 140, ENoProfile},
{"150", true, 150, ENoProfile},
{"330", true, 330, ENoProfile},
{"400", true, 400, ENoProfile},
{"410", true, 410, ENoProfile},
{"420", true, 420, ENoProfile},
{"430", true, 430, ENoProfile},
{"440", true, 440, ENoProfile},
{"450", true, 450, ENoProfile},
{"460", true, 460, ENoProfile},
{"99", false, 0, EBadProfile},
{"500", false, 0, EBadProfile},
}));
INSTANTIATE_TEST_SUITE_P(OpenGLCoreCases, ParseVersionProfileTest,
ValuesIn(std::vector<ParseVersionProfileCase>{
{"320core", true, 320, ECoreProfile},
{"330core", true, 330, ECoreProfile},
{"400core", true, 400, ECoreProfile},
{"410core", true, 410, ECoreProfile},
{"420core", true, 420, ECoreProfile},
{"430core", true, 430, ECoreProfile},
{"440core", true, 440, ECoreProfile},
{"450core", true, 450, ECoreProfile},
{"460core", true, 460, ECoreProfile},
}));
INSTANTIATE_TEST_SUITE_P(
OpenGLCompatibilityCases, ParseVersionProfileTest,
ValuesIn(std::vector<ParseVersionProfileCase>{
{"320compatibility", true, 320, ECompatibilityProfile},
{"330compatibility", true, 330, ECompatibilityProfile},
{"400compatibility", true, 400, ECompatibilityProfile},
{"410compatibility", true, 410, ECompatibilityProfile},
{"420compatibility", true, 420, ECompatibilityProfile},
{"430compatibility", true, 430, ECompatibilityProfile},
{"440compatibility", true, 440, ECompatibilityProfile},
{"450compatibility", true, 450, ECompatibilityProfile},
{"460compatibility", true, 460, ECompatibilityProfile},
}));
} // anonymous namespace

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.
file(GLOB all_files ${CMAKE_CURRENT_LIST_DIR}/*)
file(COPY ${all_files} DESTINATION .)

View File

@ -0,0 +1 @@
The quick brown fox jumps over a lazy dog.

View File

@ -0,0 +1,36 @@
[
{
"licenses": [ "Apache-2.0" ],
"paths": [
{
"exclude": [
"**.md",
"**.png",
"**/README.asciidoc",
".*",
"AUTHORS",
"CHANGES",
"CONTRIBUTORS",
"DEPS",
"LICENSE",
"cmake/*.pc.in",
"libshaderc_util/testdata/dir/subdir/include_file.2",
"libshaderc_util/testdata/include_file.1",
"utils/git-sync-deps",
"third_party/**"
]
}
]
},
{
"licenses": [ "BSD-3-Clause" ],
"paths": [
{ "exclude": [ "**" ] },
{ "include": [ "utils/git-sync-deps" ] }
]
}
]

35
lib/shaderc/third_party/Android.mk vendored Normal file
View File

@ -0,0 +1,35 @@
THIRD_PARTY_PATH := $(call my-dir)
# Set the location of glslang
ifeq ($(GLSLANG_LOCAL_PATH),)
GLSLANG_LOCAL_PATH:=$(THIRD_PARTY_PATH)/glslang
endif
include $(GLSLANG_LOCAL_PATH)/Android.mk
# Set the location of SPIRV-Tools.
# Allow the user to override it, but default it to under our third_party directory.
ifeq ($(SPVTOOLS_LOCAL_PATH),)
SPVTOOLS_LOCAL_PATH:=$(THIRD_PARTY_PATH)/spirv-tools
endif
ifeq ($(SPVHEADERS_LOCAL_PATH),)
# Use the third party dir if it exists.
ifneq ($(wildcard $(THIRD_PARTY_PATH)/spirv-headers/include/spirv/spir-v.xml),)
SPVHEADERS_LOCAL_PATH:=$(THIRD_PARTY_PATH)/spirv-headers
else
# Let SPIRV-Tools find its own headers and hope for the best.
endif
endif
# Now include the SPIRV-Tools dependency
include $(SPVTOOLS_LOCAL_PATH)/Android.mk
ifeq ($(SHADERC_ENABLE_SPVC),1)
# Set the location of SPIRV-Cross.
# Allow the user to override it, but default it to under our third_party directory.
ifeq ($(SPVCROSS_LOCAL_PATH),)
SPVCROSS_LOCAL_PATH:=$(THIRD_PARTY_PATH)/spirv-cross
endif
# Now include the SPIRV-Cross dependency
include $(SPVCROSS_LOCAL_PATH)/jni/Android.mk
endif

100
lib/shaderc/third_party/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,100 @@
# Suppress all warnings from third-party projects.
set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS -w)
set(SHADERC_THIRD_PARTY_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE STRING
"Root location of all third_party projects")
set(SHADERC_GOOGLE_TEST_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/googletest" CACHE STRING
"Location of googletest source")
set(SHADERC_SPIRV_TOOLS_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/spirv-tools" CACHE STRING
"Location of spirv-tools source")
set(SHADERC_SPIRV_HEADERS_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/spirv-headers" CACHE STRING
"Location of spirv-headers source")
set(SHADERC_GLSLANG_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/glslang" CACHE STRING
"Location of glslang source")
set(SHADERC_EFFCEE_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/effcee" CACHE STRING
"Location of effcee source")
set(SHADERC_RE2_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/re2" CACHE STRING
"Location of re2 source")
set(SHADERC_TINT_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/tint" CACHE STRING
"Location of tint source")
set( SKIP_GLSLANG_INSTALL ${SHADERC_SKIP_INSTALL} )
set( SKIP_SPIRV_TOOLS_INSTALL ${SHADERC_SKIP_INSTALL} )
set( SKIP_GOOGLETEST_INSTALL ${SHADERC_SKIP_INSTALL} )
# Configure third party projects.
if(${SHADERC_ENABLE_TESTS})
if (IS_DIRECTORY ${SHADERC_GOOGLE_TEST_DIR})
add_subdirectory(${SHADERC_GOOGLE_TEST_DIR} googletest)
endif()
if (NOT TARGET gmock)
message(FATAL_ERROR "gmock was not found - required for tests")
endif()
endif()
set(OLD_PLATFORM_TOOLSET ${CMAKE_GENERATOR_TOOLSET})
check_cxx_compiler_flag(-fPIC COMPILER_SUPPORTS_PIC)
if (IS_DIRECTORY ${SHADERC_SPIRV_HEADERS_DIR})
set(SPIRV_HEADERS_SKIP_EXAMPLES ON)
add_subdirectory(${SHADERC_SPIRV_HEADERS_DIR} spirv-headers)
endif()
if (NOT TARGET SPIRV-Tools)
# Check SPIRV-Tools before glslang so that it is linked into glslang.
# we control optimizations via glslang API calls directly.
if (IS_DIRECTORY ${SHADERC_SPIRV_TOOLS_DIR})
if ("${SHADERC_SKIP_TESTS}")
# Also skip building tests in SPIRV-Tools.
set(SPIRV_SKIP_TESTS ON CACHE BOOL "Skip building SPIRV-Tools tests")
elseif(NOT "${SPIRV_SKIP_TESTS}")
# SPIRV-Tools requires effcee and re2 to build tests.
# re2 tests take a long time and do not add much value, since re2 is a
# dependency of a dependency, so not running them.
set(RE2_BUILD_TESTING OFF CACHE STRING "Run RE2 Tests")
add_subdirectory(${SHADERC_RE2_DIR} re2)
add_subdirectory(${SHADERC_EFFCEE_DIR} effcee)
endif()
add_subdirectory(${SHADERC_SPIRV_TOOLS_DIR} spirv-tools)
endif()
if (NOT TARGET SPIRV-Tools)
message(FATAL_ERROR "SPIRV-Tools was not found - required for compilation")
endif()
endif()
if (NOT TARGET glslang)
if (IS_DIRECTORY ${SHADERC_GLSLANG_DIR})
add_subdirectory(${SHADERC_GLSLANG_DIR} glslang)
endif()
if (NOT TARGET glslang)
message(FATAL_ERROR "glslang was not found - required for compilation")
endif()
if(WIN32)
# This is unfortunate but glslang forces our
# platform toolset to be v110, which we may not even have
# installed, undo anything glslang has done to it.
set(CMAKE_GENERATOR_TOOLSET "${OLD_PLATFORM_TOOLSET}" CACHE STRING
"Platform Toolset" FORCE)
endif()
endif()
if (SHADERC_ENABLE_WGSL_OUTPUT)
# Use Google Tint for WGSL output.
if (NOT TARGET libtint)
if (IS_DIRECTORY ${SHADERC_TINT_DIR})
if (NOT IS_DIRECTORY ${SHADERC_TINT_DIR}/out/docs)
# The Tint Doxygen configuration assumes it can write to the out/docs
# source directory.
message(STATUS "Tint source directory out/docs does not exist. Disabling doc generation")
set(TINT_BUILD_DOCS OFF)
endif()
set(TINT_BUILD_SPV_READER ON CACHE BOOL "Built Tint SPIR-V reader" FORCE)
set(TINT_BUILD_WGSL_WRITER ON CACHE BOOL "Build Tint WGSL writer" FORCE)
add_subdirectory(${SHADERC_TINT_DIR} tint)
endif()
endif()
if (NOT TARGET libtint)
message(FATAL_ERROR "Tint was not found - required for WGSL output")
endif()
endif (SHADERC_ENABLE_WGSL_OUTPUT)

172
lib/shaderc/third_party/LICENSE.glslang vendored Normal file
View File

@ -0,0 +1,172 @@
-----
Most code has one of the following copyrights:
Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
Copyright (C) 2012-2014 LunarG, Inc.
Copyright (C) 2002-2010 The ANGLE Project Authors.
Copyright (C) 2015-2016 Google, Inc.
and is covered under the following license (BSD):
//
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditionsA
//are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
-----
Files under glslang/MachineIndependent/preprocessor used under
the following license (BSD-like):
/****************************************************************************\
Copyright (c) 2002, NVIDIA Corporation.
NVIDIA Corporation("NVIDIA") supplies this software to you in
consideration of your agreement to the following terms, and your use,
installation, modification or redistribution of this NVIDIA software
constitutes acceptance of these terms. If you do not agree with these
terms, please do not use, install, modify or redistribute this NVIDIA
software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, NVIDIA grants you a personal, non-exclusive
license, under NVIDIA's copyrights in this original NVIDIA software (the
"NVIDIA Software"), to use, reproduce, modify and redistribute the
NVIDIA Software, with or without modifications, in source and/or binary
forms; provided that if you redistribute the NVIDIA Software, you must
retain the copyright notice of NVIDIA, this notice and the following
text and disclaimers in all such redistributions of the NVIDIA Software.
Neither the name, trademarks, service marks nor logos of NVIDIA
Corporation may be used to endorse or promote products derived from the
NVIDIA Software without specific prior written permission from NVIDIA.
Except as expressly stated in this notice, no other rights or licenses
express or implied, are granted by NVIDIA herein, including but not
limited to any patent rights that may be infringed by your derivative
works or by other works in which the NVIDIA Software may be
incorporated. No hardware is licensed hereunder.
THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
PRODUCTS.
IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\****************************************************************************/
-----
The file glslang/MachineIndependent/gl_types.h has the following
license (MIT):
/*
** Copyright (c) 2013 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
-----
The files glslang/SPIRV/GLSL.std.450.h and
glslang/SPIRV/spirv.hpp have the following license.
/*
** Copyright (c) 2014-2016 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and/or associated documentation files (the "Materials"),
** to deal in the Materials without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
** and/or sell copies of the Materials, and to permit persons to whom the
** Materials are furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Materials.
**
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
** IN THE MATERIALS.
*/
-----
Files under tools/data contain portions of GNU Bison, and are used under
the following license (GPL v3), with an exception as described at
at http://www.gnu.org/software/bison/manual/bison.html#Conditions.
In particular, when parsers are generated from the template files, an
exception clause is inserted into the generated source files which allows
their use in non-free programs.
# Copyright (C) 1984, 1989-1990, 1999-2012 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

View File

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

View File

@ -0,0 +1,108 @@
# Windows Build Configuration for AppVeyor
# http://www.appveyor.com/docs/appveyor-yml
# build version format
version: "{build}"
os: Visual Studio 2015
platform:
- x64
configuration:
- Debug
- Release
branches:
only:
- master
# changes to these files don't need to trigger testing
skip_commits:
files:
- README.md
- README-spirv-remap.txt
- LICENSE.txt
- CODE_OF_CONDUCT.md
- BUILD.*
- WORKSPACE
- kokoro/*
- make-revision
- Android.mk
- _config.yml
# Travis advances the master-tot tag to current top of the tree after
# each push into the master branch, because it relies on that tag to
# upload build artifacts to the master-tot release. This will cause
# double testing for each push on Appveyor: one for the push, one for
# the tag advance. Disable testing tags.
skip_tags: true
clone_depth: 5
matrix:
fast_finish: true # Show final status immediately if a test fails.
# scripts that run after cloning repository
install:
- C:/Python27/python.exe update_glslang_sources.py
- set PATH=C:\ninja;C:\Python36;%PATH%
- git clone https://github.com/google/googletest.git External/googletest
build:
parallel: true # enable MSBuild parallel builds
verbosity: minimal
build_script:
- mkdir build && cd build
- cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_INSTALL_PREFIX=install ..
- cmake --build . --config %CONFIGURATION% --target install
test_script:
- ctest -C %CONFIGURATION% --output-on-failure
- cd ../Test && bash runtests
- cd ../build
after_test:
# For debug build, the generated dll has a postfix "d" in its name.
- ps: >-
If ($env:configuration -Match "Debug") {
$env:SUFFIX="d"
} Else {
$env:SUFFIX=""
}
- cd install
# Zip all glslang artifacts for uploading and deploying
- 7z a glslang-master-windows-"%PLATFORM%"-"%CONFIGURATION%".zip
bin\glslangValidator.exe
bin\spirv-remap.exe
include\glslang\*
lib\GenericCodeGen%SUFFIX%.lib
lib\glslang%SUFFIX%.lib
lib\glslang-default-resource-limits%SUFFIX%.lib
lib\HLSL%SUFFIX%.lib
lib\MachineIndependent%SUFFIX%.lib
lib\OGLCompiler%SUFFIX%.lib
lib\OSDependent%SUFFIX%.lib
lib\SPIRV%SUFFIX%.lib
lib\SPVRemapper%SUFFIX%.lib
lib\SPIRV-Tools%SUFFIX%.lib
lib\SPIRV-Tools-opt%SUFFIX%.lib
artifacts:
- path: build\install\*.zip
name: artifacts-zip
deploy:
- provider: GitHub
auth_token:
secure: YglcSYdl0TylEa59H4K6lylBEDr586NAt2EMgZquSo+iuPrwgZQuJLPCoihSm9y6
release: master-tot
description: "Continuous build of the latest master branch by Appveyor and Travis CI"
artifact: artifacts-zip
draft: false
prerelease: false
force_update: true
on:
branch: master
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015

View File

@ -0,0 +1,13 @@
Language: Cpp
IndentWidth: 4
PointerAlignment: Left
BreakBeforeBraces: Custom
BraceWrapping: { AfterFunction: true, AfterControlStatement: false }
IndentCaseLabels: false
ReflowComments: false
ColumnLimit: 120
AccessModifierOffset: -4
AlignTrailingComments: true
AllowShortBlocksOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false

View File

@ -0,0 +1,17 @@
# test files have a mix of lf/crlf, and that's a good thing, for testing, don't mess with it
# bash scripts need lines ending with lf, and that's correct for Windows too, e.g., under Cygwin
# (scripts often don't have a suffix)
* -text
*.sh text eof=lf
# txt files should be native and normalized
*.txt text
# source code can be native and normalized, but simpler if lf everywhere; will try that way
*.h text eol=lf
*.c text eol=lf
*.cpp text eol=lf
*.y text eol=lf
*.out text eol=lf
*.conf text eol=lf
*.err text eol=lf

View File

@ -0,0 +1,168 @@
# NOTE: This workflow was ported from Travis.
# Travis was using Ubuntu 14.04. Ubuntu 14.04 is not supportted by GitHub workflows. Ubuntu 20.04 is recommended.
# Travis was using Clang 3.6. The earliest version support by Ubuntu 20.04 is Clang 6.0.
# Travis was caching the clang package. APT package caching is not natively supported by GitHub actions/cache.
# Travis was using Mac OS X 10.13.6 / Xcode 9.4.1 / LLVM 9.1.0
# NOTE: The following documentation may be useful to maintainers of this workflow.
# Github actions: https://docs.github.com/en/actions
# Github github-script action: https://github.com/actions/github-script
# GitHub REST API: https://docs.github.com/en/rest
# Octokit front-end to the GitHub REST API: https://octokit.github.io/rest.js/v18
# Octokit endpoint methods: https://github.com/octokit/plugin-rest-endpoint-methods.js/tree/master/docs/repos
# TODO: Use actions/upload-artifact and actions/download-artifact to simplify deployment.
# TODO: Use composite actions to refactor redundant code.
name: Continuous Deployment
on:
workflow_dispatch:
push:
branches:
- master
jobs:
linux:
runs-on: ${{matrix.os.genus}}
strategy:
fail-fast: false
matrix:
os: [{genus: ubuntu-20.04, family: linux}]
compiler: [{cc: clang, cxx: clang++}, {cc: gcc, cxx: g++}]
cmake_build_type: [Debug, Release]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.7'
- name: Install Ubuntu Package Dependencies
run: |
sudo apt-get -qq update
sudo apt-get install -y clang-6.0
- name: Install GoogleTest
run: |
# check out pre-breakage version of googletest; can be deleted when
# issue 3128 is fixed
# git clone --depth=1 https://github.com/google/googletest.git External/googletest
mkdir -p External/googletest
cd External/googletest
git init
git remote add origin https://github.com/google/googletest.git
git fetch --depth 1 origin 0c400f67fcf305869c5fb113dd296eca266c9725
git reset --hard FETCH_HEAD
cd ../..
- name: Update Glslang Sources
run: |
./update_glslang_sources.py
- name: Build
env:
CC: ${{matrix.compiler.cc}}
CXX: ${{matrix.compiler.cxx}}
run: |
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=${{matrix.cmake_build_type}} -DCMAKE_INSTALL_PREFIX=`pwd`/install ..
make -j4 install
- name: Test
run: |
cd build
ctest --output-on-failure &&
cd ../Test && ./runtests
- name: Zip
if: ${{ matrix.compiler.cc == 'clang' }}
env:
ARCHIVE: glslang-master-${{matrix.os.family}}-${{matrix.cmake_build_type}}.zip
run: |
cd build/install
zip ${ARCHIVE} \
bin/glslangValidator \
include/glslang/* \
lib/libGenericCodeGen${SUFFIX}.a \
lib/libglslang${SUFFIX}.a \
lib/libglslang-default-resource-limits${SUFFIX}.a \
lib/libHLSL${SUFFIX}.a \
lib/libMachineIndependent${SUFFIX}.a \
lib/libOGLCompiler${SUFFIX}.a \
lib/libOSDependent${SUFFIX}.a \
lib/libSPIRV${SUFFIX}.a \
lib/libSPVRemapper${SUFFIX}.a \
lib/libSPIRV-Tools${SUFFIX}.a \
lib/libSPIRV-Tools-opt${SUFFIX}.a
- name: Deploy
if: ${{ matrix.compiler.cc == 'clang' }}
env:
ARCHIVE: glslang-master-${{matrix.os.family}}-${{matrix.cmake_build_type}}.zip
uses: actions/github-script@v5
with:
script: |
const script = require('.github/workflows/deploy.js')
await script({github, context, core})
macos:
runs-on: ${{matrix.os.genus}}
strategy:
fail-fast: false
matrix:
os: [{genus: macos-10.15, family: osx}]
compiler: [{cc: clang, cxx: clang++}]
cmake_build_type: [Debug, Release]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.7'
- name: Install GoogleTest
run: |
# check out pre-breakage version of googletest; can be deleted when
# issue 3128 is fixed
# git clone --depth=1 https://github.com/google/googletest.git External/googletest
mkdir -p External/googletest
cd External/googletest
git init
git remote add origin https://github.com/google/googletest.git
git fetch --depth 1 origin 0c400f67fcf305869c5fb113dd296eca266c9725
git reset --hard FETCH_HEAD
cd ../..
- name: Update Glslang Sources
run: |
./update_glslang_sources.py
- name: Build
env:
CC: ${{matrix.compiler.cc}}
CXX: ${{matrix.compiler.cxx}}
run: |
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=${{matrix.cmake_build_type}} -DCMAKE_INSTALL_PREFIX=`pwd`/install ..
make -j4 install
- name: Test
run: |
cd build
ctest --output-on-failure &&
cd ../Test && ./runtests
- name: Zip
env:
ARCHIVE: glslang-master-${{matrix.os.family}}-${{matrix.cmake_build_type}}.zip
run: |
cd build/install
zip ${ARCHIVE} \
bin/glslangValidator \
include/glslang/* \
lib/libGenericCodeGen${SUFFIX}.a \
lib/libglslang${SUFFIX}.a \
lib/libglslang-default-resource-limits${SUFFIX}.a \
lib/libHLSL${SUFFIX}.a \
lib/libMachineIndependent${SUFFIX}.a \
lib/libOGLCompiler${SUFFIX}.a \
lib/libOSDependent${SUFFIX}.a \
lib/libSPIRV${SUFFIX}.a \
lib/libSPVRemapper${SUFFIX}.a \
lib/libSPIRV-Tools${SUFFIX}.a \
lib/libSPIRV-Tools-opt${SUFFIX}.a
- name: Deploy
env:
ARCHIVE: glslang-master-${{matrix.os.family}}-${{matrix.cmake_build_type}}.zip
uses: actions/github-script@v5
with:
script: |
const script = require('.github/workflows/deploy.js')
await script({github, context, core})

View File

@ -0,0 +1,157 @@
# NOTE: This workflow was ported from Travis.
# Travis was using Ubuntu 14.04. Ubuntu 14.04 is not supportted by GitHub workflows. Ubuntu 20.04 is recommended.
# Travis was using Clang 3.6. The earliest version support by Ubuntu 20.04 is Clang 6.0.
# Travis was caching the clang package. APT package caching is not natively supported by GitHub actions/cache.
# Travis was using Mac OS X 10.13.6 / Xcode 9.4.1 / LLVM 9.1.0
#
name: Continuous Integration
on:
workflow_dispatch:
pull_request:
branches:
- master
jobs:
linux:
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04]
compiler: [{cc: clang, cxx: clang++}, {cc: gcc, cxx: g++}]
cmake_build_type: [Debug, Release]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.7'
- name: Install Ubuntu Package Dependencies
run: |
sudo apt-get -qq update
sudo apt-get install -y clang-6.0
- name: Install GoogleTest
run: |
# check out pre-breakage version of googletest; can be deleted when
# issue 3128 is fixed
# git clone --depth=1 https://github.com/google/googletest.git External/googletest
mkdir -p External/googletest
cd External/googletest
git init
git remote add origin https://github.com/google/googletest.git
git fetch --depth 1 origin 0c400f67fcf305869c5fb113dd296eca266c9725
git reset --hard FETCH_HEAD
cd ../..
- name: Update Glslang Sources
run: |
./update_glslang_sources.py
- name: Build
env:
CC: ${{matrix.compiler.cc}}
CXX: ${{matrix.compiler.cxx}}
run: |
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=${{matrix.cmake_build_type}} -DCMAKE_INSTALL_PREFIX=`pwd`/install ..
make -j4 install
- name: Test
run: |
cd build
ctest --output-on-failure &&
cd ../Test && ./runtests
macos:
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
matrix:
os: [macos-10.15]
compiler: [{cc: clang, cxx: clang++}]
cmake_build_type: [Debug, Release]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.7'
- name: Install GoogleTest
run: |
# check out pre-breakage version of googletest; can be deleted when
# issue 3128 is fixed
# git clone --depth=1 https://github.com/google/googletest.git External/googletest
mkdir -p External/googletest
cd External/googletest
git init
git remote add origin https://github.com/google/googletest.git
git fetch --depth 1 origin 0c400f67fcf305869c5fb113dd296eca266c9725
git reset --hard FETCH_HEAD
cd ../..
- name: Update Glslang Sources
run: |
./update_glslang_sources.py
- name: Build
env:
CC: ${{matrix.compiler.cc}}
CXX: ${{matrix.compiler.cxx}}
run: |
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=${{matrix.cmake_build_type}} -DCMAKE_INSTALL_PREFIX=`pwd`/install ..
make -j4 install
- name: Test
run: |
cd build
ctest --output-on-failure &&
cd ../Test && ./runtests
android:
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04]
compiler: [{cc: clang, cxx: clang++}]
cmake_build_type: [Release]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.7'
- name: Install Ubuntu Package Dependencies
if: ${{matrix.os == 'ubuntu-20.04'}}
run: |
sudo apt-get -qq update
sudo apt-get install -y clang-6.0
- name: Install Android NDK
run: |
export ANDROID_NDK=$HOME/android-ndk
git init $ANDROID_NDK
pushd $ANDROID_NDK
git remote add dneto0 https://github.com/dneto0/android-ndk.git
git fetch --depth=1 dneto0 r17b-strip
git checkout FETCH_HEAD
popd
- name: Install GoogleTest
run: |
# check out pre-breakage version of googletest; can be deleted when
# issue 3128 is fixed
# git clone --depth=1 https://github.com/google/googletest.git External/googletest
mkdir -p External/googletest
cd External/googletest
git init
git remote add origin https://github.com/google/googletest.git
git fetch --depth 1 origin 0c400f67fcf305869c5fb113dd296eca266c9725
git reset --hard FETCH_HEAD
cd ../..
- name: Update Glslang Sources
run: |
./update_glslang_sources.py
- name: Build
env:
CC: ${{matrix.compiler.cc}}
CXX: ${{matrix.compiler.cxx}}
run: |
export ANDROID_NDK=$HOME/android-ndk
export TOOLCHAIN_PATH=$ANDROID_NDK/build/cmake/android.toolchain.cmake
echo $ANDROID_NDK
echo $TOOLCHAIN_PATH
mkdir build && cd build
cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_PATH} -DANDROID_NATIVE_API_LEVEL=android-14 -DCMAKE_BUILD_TYPE=${{matrix.cmake_build_type}} -DANDROID_ABI="armeabi-v7a with NEON" -DBUILD_TESTING=OFF ..
make -j4

View File

@ -0,0 +1,73 @@
module.exports = async ({github, context, core}) => {
try {
await github.rest.git.updateRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: 'tags/master-tot',
sha: context.sha
})
} catch (error) {
core.setFailed(`upload master-tot tag; ${error.name}; ${error.message}`)
}
let release
try {
release = await github.rest.repos.getReleaseByTag({
owner: context.repo.owner,
repo: context.repo.repo,
tag: 'master-tot'
})
} catch (error) {
core.setFailed(`get the master release; ${error.name}; ${error.message}`)
}
try {
await github.rest.repos.updateRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: release.data.id
})
} catch (error) {
core.setFailed(`update the master release; ${error.name}; ${error.message}`)
}
let release_assets
try {
release_assets = await github.rest.repos.listReleaseAssets({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: release.data.id
})
} catch (error) {
core.setFailed(`list release assets; ${error.name}; ${error.message}`)
}
const { ARCHIVE } = process.env
for (const release_asset of release_assets.data) {
if (release_asset.name === `${ ARCHIVE }`) {
try {
await github.rest.repos.deleteReleaseAsset({
owner: context.repo.owner,
repo: context.repo.repo,
asset_id: release_asset.id
})
} catch (error) {
core.setFailed(`delete ${ ARCHIVE }; ${error.name}; ${error.message}`)
}
}
}
try {
const asset_path = `./build/install/${ ARCHIVE }`
const fs = require("fs")
await github.rest.repos.uploadReleaseAsset({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: release.data.id,
name: `${ ARCHIVE }`,
data: fs.readFileSync(asset_path)
})
} catch (error) {
core.setFailed(`upload ${ ARCHIVE }; ${error.name}; ${error.message}`)
}
}

39
lib/shaderc/third_party/glslang/.gn vendored Normal file
View File

@ -0,0 +1,39 @@
# Copyright (C) 2020 The Khronos Group Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# Neither the name of The Khronos Group Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
buildconfig = "//build/config/BUILDCONFIG.gn"
default_args = {
clang_use_chrome_plugins = false
use_custom_libcxx = false
}

View File

@ -0,0 +1,166 @@
# Copyright (C) 2020 The Khronos Group Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# Neither the name of The Khronos Group Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
LOCAL_PATH := $(call my-dir)
# Generate glslang/build_info.h
GLSLANG_GENERATED_INCLUDEDIR:=$(TARGET_OUT)/include
GLSLANG_BUILD_INFO_H:=$(GLSLANG_GENERATED_INCLUDEDIR)/glslang/build_info.h
define gen_glslang_build_info_h
$(call generate-file-dir,$(GLSLANG_GENERATED_INCLUDEDIR)/dummy_filename)
$(GLSLANG_BUILD_INFO_H): \
$(LOCAL_PATH)/build_info.py \
$(LOCAL_PATH)/build_info.h.tmpl \
$(LOCAL_PATH)/CHANGES.md
@$(HOST_PYTHON) $(LOCAL_PATH)/build_info.py \
$(LOCAL_PATH) \
-i $(LOCAL_PATH)/build_info.h.tmpl \
-o $(GLSLANG_BUILD_INFO_H)
@echo "[$(TARGET_ARCH_ABI)] Generate : $(GLSLANG_BUILD_INFO_H) <= CHANGES.md"
endef
$(eval $(call gen_glslang_build_info_h))
GLSLANG_OS_FLAGS := -DGLSLANG_OSINCLUDE_UNIX
# AMD and NV extensions are turned on by default in upstream Glslang.
GLSLANG_DEFINES:= -DAMD_EXTENSIONS -DNV_EXTENSIONS -DENABLE_HLSL $(GLSLANG_OS_FLAGS)
include $(CLEAR_VARS)
LOCAL_MODULE:=OSDependent
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES)
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)
LOCAL_SRC_FILES:=glslang/OSDependent/Unix/ossource.cpp
LOCAL_C_INCLUDES:=$(LOCAL_PATH) $(LOCAL_PATH)/glslang/OSDependent/Unix/
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/glslang/OSDependent/Unix/
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:=OGLCompiler
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES)
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)
LOCAL_SRC_FILES:=OGLCompilersDLL/InitializeDll.cpp
LOCAL_C_INCLUDES:=$(LOCAL_PATH)/OGLCompiler
LOCAL_STATIC_LIBRARIES:=OSDependent
include $(BUILD_STATIC_LIBRARY)
# Build the stubbed HLSL library.
# The HLSL source is now directly referenced by the glslang static library
# instead.
include $(CLEAR_VARS)
LOCAL_MODULE:=HLSL
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES)
LOCAL_SRC_FILES:= \
hlsl/stub.cpp
LOCAL_C_INCLUDES:=$(LOCAL_PATH) \
$(LOCAL_PATH)/glslang/HLSL
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
GLSLANG_OUT_PATH=$(if $(call host-path-is-absolute,$(TARGET_OUT)),$(TARGET_OUT),$(abspath $(TARGET_OUT)))
# ShaderLang.cpp depends on the generated build_info.h
$(LOCAL_PATH)/glslang/MachineIndependent/ShaderLang.cpp: \
$(GLSLANG_BUILD_INFO_H)
LOCAL_MODULE:=glslang
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES)
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)
LOCAL_SRC_FILES:= \
glslang/GenericCodeGen/CodeGen.cpp \
glslang/GenericCodeGen/Link.cpp \
glslang/HLSL/hlslAttributes.cpp \
glslang/HLSL/hlslGrammar.cpp \
glslang/HLSL/hlslOpMap.cpp \
glslang/HLSL/hlslParseables.cpp \
glslang/HLSL/hlslParseHelper.cpp \
glslang/HLSL/hlslScanContext.cpp \
glslang/HLSL/hlslTokenStream.cpp \
glslang/MachineIndependent/attribute.cpp \
glslang/MachineIndependent/Constant.cpp \
glslang/MachineIndependent/glslang_tab.cpp \
glslang/MachineIndependent/InfoSink.cpp \
glslang/MachineIndependent/Initialize.cpp \
glslang/MachineIndependent/Intermediate.cpp \
glslang/MachineIndependent/intermOut.cpp \
glslang/MachineIndependent/IntermTraverse.cpp \
glslang/MachineIndependent/iomapper.cpp \
glslang/MachineIndependent/limits.cpp \
glslang/MachineIndependent/linkValidate.cpp \
glslang/MachineIndependent/parseConst.cpp \
glslang/MachineIndependent/ParseContextBase.cpp \
glslang/MachineIndependent/ParseHelper.cpp \
glslang/MachineIndependent/PoolAlloc.cpp \
glslang/MachineIndependent/propagateNoContraction.cpp \
glslang/MachineIndependent/reflection.cpp \
glslang/MachineIndependent/RemoveTree.cpp \
glslang/MachineIndependent/Scan.cpp \
glslang/MachineIndependent/ShaderLang.cpp \
glslang/MachineIndependent/SpirvIntrinsics.cpp \
glslang/MachineIndependent/SymbolTable.cpp \
glslang/MachineIndependent/Versions.cpp \
glslang/MachineIndependent/preprocessor/PpAtom.cpp \
glslang/MachineIndependent/preprocessor/PpContext.cpp \
glslang/MachineIndependent/preprocessor/Pp.cpp \
glslang/MachineIndependent/preprocessor/PpScanner.cpp \
glslang/MachineIndependent/preprocessor/PpTokens.cpp
LOCAL_C_INCLUDES:=$(LOCAL_PATH) \
$(LOCAL_PATH)/glslang/MachineIndependent \
$(GLSLANG_GENERATED_INCLUDEDIR) \
$(GLSLANG_OUT_PATH)
LOCAL_STATIC_LIBRARIES:=OSDependent OGLCompiler HLSL
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
# GlslangToSpv.cpp depends on the generated build_info.h
$(LOCAL_PATH)/SPIRV/GlslangToSpv.cpp: \
$(GLSLANG_BUILD_INFO_H)
LOCAL_MODULE:=SPIRV
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -Werror $(GLSLANG_DEFINES)
LOCAL_SRC_FILES:= \
SPIRV/GlslangToSpv.cpp \
SPIRV/InReadableOrder.cpp \
SPIRV/Logger.cpp \
SPIRV/SPVRemapper.cpp \
SPIRV/SpvBuilder.cpp \
SPIRV/SpvPostProcess.cpp \
SPIRV/SpvTools.cpp \
SPIRV/disassemble.cpp \
SPIRV/doc.cpp
LOCAL_C_INCLUDES:=$(LOCAL_PATH) \
$(LOCAL_PATH)/glslang/SPIRV \
$(GLSLANG_GENERATED_INCLUDEDIR)
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/glslang/SPIRV
LOCAL_STATIC_LIBRARIES:=glslang
include $(BUILD_STATIC_LIBRARY)

View File

@ -0,0 +1,309 @@
# Copyright (C) 2020 The Khronos Group Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# Neither the name of The Khronos Group Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
package(
default_visibility = ["//visibility:public"],
)
# Description:
#
# Khronos reference front-end for GLSL and ESSL, and sample SPIR-V generator.
licenses(["notice"])
exports_files(["LICENSE"])
# Build information generation script
py_binary(
name = "build_info",
srcs = ["build_info.py"],
)
py_binary(
name = "gen_extension_headers",
srcs = ["gen_extension_headers.py"],
)
genrule(
name = "gen_build_info_h",
srcs = ["CHANGES.md", "build_info.h.tmpl"],
outs = ["glslang/build_info.h"],
cmd_bash = "$(location build_info) $$(dirname $(location CHANGES.md)) -i $(location build_info.h.tmpl) -o $(location glslang/build_info.h)",
cmd_bat = "for %F in ($(location CHANGES.md)) do $(location build_info) %~dpF -i $(location build_info.h.tmpl) -o $(location glslang/build_info.h)",
tools = [":build_info"],
)
genrule(
name = "gen_extension_headers_h",
srcs = ["glslang/ExtensionHeaders", "gen_extension_headers.py"],
outs = ["glslang/glsl_intrinsic_header.h"],
cmd_bash = "$(location gen_extension_headers) -i $(location glslang/ExtensionHeaders) -o $(location glslang/glsl_intrinsic_header.h)",
tools = [":gen_extension_headers"],
)
COMMON_COPTS = select({
"@bazel_tools//src/conditions:windows": [""],
"//conditions:default": [
"-Wall",
"-Wuninitialized",
"-Wunused",
"-Wunused-local-typedefs",
"-Wunused-parameter",
"-Wunused-value",
"-Wunused-variable",
"-Wno-reorder",
"-std=c++11",
"-fvisibility=hidden",
"-fvisibility-inlines-hidden",
"-fno-exceptions",
"-fno-rtti",
],
})
cc_library(
name = "glslang",
srcs = glob(
[
"glslang/GenericCodeGen/*.cpp",
"glslang/HLSL/*.cpp",
"glslang/MachineIndependent/*.cpp",
"glslang/MachineIndependent/preprocessor/*.cpp",
],
exclude = [
"glslang/HLSL/pch.h",
"glslang/MachineIndependent/pch.h",
],
) + [
"OGLCompilersDLL/InitializeDll.cpp",
] + select({
"@bazel_tools//src/conditions:windows":
["glslang/OSDependent/Windows/ossource.cpp"],
"//conditions:default":
["glslang/OSDependent/Unix/ossource.cpp"],
}),
hdrs = glob([
"glslang/HLSL/*.h",
"glslang/Include/*.h",
"glslang/MachineIndependent/*.h",
"glslang/MachineIndependent/preprocessor/*.h",
]) + [
"OGLCompilersDLL/InitializeDll.h",
"StandAlone/DirStackFileIncluder.h",
"glslang/OSDependent/osinclude.h",
"glslang/Public/ShaderLang.h",
":gen_build_info_h",
],
copts = COMMON_COPTS,
defines = [
"AMD_EXTENSIONS",
"ENABLE_HLSL=0",
"ENABLE_OPT=0",
"NV_EXTENSIONS",
],
linkopts = select({
"@bazel_tools//src/conditions:windows": [""],
"//conditions:default": ["-lm", "-lpthread"],
}),
linkstatic = 1,
)
genrule(
name = "export_spirv_headers",
srcs = [
"SPIRV/GLSL.ext.AMD.h",
"SPIRV/GLSL.ext.EXT.h",
"SPIRV/GLSL.ext.KHR.h",
"SPIRV/GLSL.ext.NV.h",
"SPIRV/GLSL.std.450.h",
"SPIRV/NonSemanticDebugPrintf.h",
"SPIRV/spirv.hpp",
],
outs = [
"include/SPIRV/GLSL.ext.AMD.h",
"include/SPIRV/GLSL.ext.EXT.h",
"include/SPIRV/GLSL.ext.KHR.h",
"include/SPIRV/GLSL.ext.NV.h",
"include/SPIRV/GLSL.std.450.h",
"include/SPIRV/NonSemanticDebugPrintf.h",
"include/SPIRV/spirv.hpp",
],
cmd_bash = "mkdir -p $(@D)/include/SPIRV && cp $(SRCS) $(@D)/include/SPIRV/",
cmd_bat = "(if not exist $(@D)\\include\\SPIRV mkdir $(@D)\\include\\SPIRV) && (for %S in ($(SRCS)) do @xcopy /q %S $(@D)\\include\\SPIRV\\ >NUL)",
)
cc_library(
name = "SPIRV_headers",
hdrs = [":export_spirv_headers"],
copts = COMMON_COPTS,
includes = [
"include",
"include/SPIRV",
],
linkstatic = 1,
)
cc_library(
name = "SPIRV",
srcs = glob(
["SPIRV/*.cpp"],
exclude = [
"SPIRV/SpvTools.cpp",
],
),
hdrs = [
"SPIRV/GlslangToSpv.h",
"SPIRV/Logger.h",
"SPIRV/SPVRemapper.h",
"SPIRV/SpvBuilder.h",
"SPIRV/SpvTools.h",
"SPIRV/bitutils.h",
"SPIRV/disassemble.h",
"SPIRV/doc.h",
"SPIRV/hex_float.h",
"SPIRV/spvIR.h",
],
copts = COMMON_COPTS,
includes = ["SPIRV"],
linkopts = select({
"@bazel_tools//src/conditions:windows": [""],
"//conditions:default": ["-lm"],
}),
linkstatic = 1,
deps = [
":SPIRV_headers",
":glslang",
],
)
cc_library(
name = "glslang-default-resource-limits",
srcs = ["StandAlone/ResourceLimits.cpp"],
hdrs = ["StandAlone/ResourceLimits.h"],
copts = COMMON_COPTS,
linkstatic = 1,
deps = [":glslang"],
)
cc_binary(
name = "glslangValidator",
srcs = [
"StandAlone/StandAlone.cpp",
"StandAlone/Worklist.h",
":glslang/glsl_intrinsic_header.h"
],
copts = COMMON_COPTS,
deps = [
":SPIRV",
":glslang",
":glslang-default-resource-limits",
],
)
cc_binary(
name = "spirv-remap",
srcs = ["StandAlone/spirv-remap.cpp"],
copts = COMMON_COPTS,
deps = [
":SPIRV",
":glslang",
":glslang-default-resource-limits",
],
)
filegroup(
name = "test_files",
srcs = glob(
["Test/**"],
exclude = [
"Test/bump",
"Test/glslangValidator",
"Test/runtests",
],
),
)
cc_library(
name = "glslang_test_lib",
testonly = 1,
srcs = [
"gtests/HexFloat.cpp",
"gtests/Initializer.h",
"gtests/Settings.cpp",
"gtests/Settings.h",
"gtests/TestFixture.cpp",
"gtests/TestFixture.h",
"gtests/main.cpp",
],
copts = COMMON_COPTS,
data = [":test_files"],
defines = select({
# Unfortunately we can't use $(location) in cc_library at the moment.
# See https://github.com/bazelbuild/bazel/issues/1023
# So we'll specify the path manually.
"@bazel_tools//src/conditions:windows":
["GLSLANG_TEST_DIRECTORY='\"../../../../../Test\"'"],
"//conditions:default":
["GLSLANG_TEST_DIRECTORY='\"Test\"'"],
}),
linkstatic = 1,
deps = [
":SPIRV",
":glslang",
":glslang-default-resource-limits",
"@com_google_googletest//:gtest",
],
)
GLSLANG_TESTS = glob(
["gtests/*.FromFile.cpp"],
# Since we are not building the SPIRV-Tools dependency, the following tests
# cannot be performed.
exclude = [
"gtests/Hlsl.FromFile.cpp",
"gtests/Spv.FromFile.cpp",
],
)
[cc_test(
name = test_file.replace("gtests/", "").replace(".FromFile.cpp", "") + "_test",
srcs = [test_file],
copts = COMMON_COPTS,
data = [
":test_files",
],
deps = [
":SPIRV",
":glslang",
":glslang_test_lib",
],
) for test_file in GLSLANG_TESTS]

353
lib/shaderc/third_party/glslang/BUILD.gn vendored Normal file
View File

@ -0,0 +1,353 @@
# Copyright (C) 2018 Google, Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import("//build_overrides/glslang.gni")
# Both Chromium and Fuchsia use by default a set of warning errors
# that is far too strict to compile this project. These are also
# typically appended after |cflags|, overriding target-specific
# definitions. To work around this, determine which configs to
# add and remove in order to succesfully build the project.
if (defined(is_fuchsia_tree) && is_fuchsia_tree) {
_configs_to_remove = [ "//build/config:default_warnings" ]
_configs_to_add = []
} else {
_configs_to_remove = [ "//build/config/compiler:chromium_code" ]
_configs_to_add = [ "//build/config/compiler:no_chromium_code" ]
}
action("glslang_build_info") {
script = "build_info.py"
src_dir = "."
changes_file = "CHANGES.md"
template_file = "build_info.h.tmpl"
out_file = "${target_gen_dir}/include/glslang/build_info.h"
inputs = [
changes_file,
script,
template_file,
]
outputs = [ out_file ]
args = [
rebase_path(src_dir, root_build_dir),
"-i",
rebase_path(template_file, root_build_dir),
"-o",
rebase_path(out_file, root_build_dir),
]
}
action("glslang_extension_headers") {
script = "gen_extension_headers.py"
out_file = "${target_gen_dir}/include/glslang/glsl_intrinsic_header.h"
# Fuchsia GN build rules require all GN actions to be hermetic and they
# should correctly and fully state their inputs and outpus (see
# https://fuchsia.dev/fuchsia-src/development/build/hermetic_actions
# for details). All input files of the script should be added to the
# |sources| list.
sources = [
"glslang/ExtensionHeaders/GL_EXT_shader_realtime_clock.glsl",
]
inputs = [
script
]
outputs = [ out_file ]
args = [
"-i",
rebase_path("glslang/ExtensionHeaders", root_build_dir),
"-o",
rebase_path(out_file, root_build_dir),
]
}
spirv_tools_dir = glslang_spirv_tools_dir
if (!defined(glslang_angle)) {
glslang_angle = false
}
config("glslang_public") {
include_dirs = [ "." ]
if (!is_win || is_clang) {
cflags = [ "-Wno-conversion" ]
}
}
config("glslang_hlsl") {
defines = [ "ENABLE_HLSL=1" ]
}
template("glslang_sources_common") {
source_set(target_name) {
public_configs = [ ":glslang_public" ]
if (invoker.enable_hlsl) {
public_configs += [ ":glslang_hlsl" ]
}
sources = [
"OGLCompilersDLL/InitializeDll.cpp",
"OGLCompilersDLL/InitializeDll.h",
"SPIRV/GLSL.ext.AMD.h",
"SPIRV/GLSL.ext.EXT.h",
"SPIRV/GLSL.ext.KHR.h",
"SPIRV/GLSL.ext.NV.h",
"SPIRV/GLSL.std.450.h",
"SPIRV/GlslangToSpv.cpp",
"SPIRV/GlslangToSpv.h",
"SPIRV/InReadableOrder.cpp",
"SPIRV/Logger.cpp",
"SPIRV/Logger.h",
"SPIRV/NonSemanticDebugPrintf.h",
"SPIRV/SPVRemapper.cpp",
"SPIRV/SPVRemapper.h",
"SPIRV/SpvBuilder.cpp",
"SPIRV/SpvBuilder.h",
"SPIRV/SpvPostProcess.cpp",
"SPIRV/SpvTools.h",
"SPIRV/bitutils.h",
"SPIRV/disassemble.cpp",
"SPIRV/disassemble.h",
"SPIRV/doc.cpp",
"SPIRV/doc.h",
"SPIRV/hex_float.h",
"SPIRV/spirv.hpp",
"SPIRV/spvIR.h",
"glslang/GenericCodeGen/CodeGen.cpp",
"glslang/GenericCodeGen/Link.cpp",
"glslang/Include/BaseTypes.h",
"glslang/Include/Common.h",
"glslang/Include/ConstantUnion.h",
"glslang/Include/InfoSink.h",
"glslang/Include/InitializeGlobals.h",
"glslang/Include/PoolAlloc.h",
"glslang/Include/ResourceLimits.h",
"glslang/Include/ShHandle.h",
"glslang/Include/SpirvIntrinsics.h",
"glslang/Include/Types.h",
"glslang/Include/arrays.h",
"glslang/Include/intermediate.h",
"glslang/MachineIndependent/Constant.cpp",
"glslang/MachineIndependent/InfoSink.cpp",
"glslang/MachineIndependent/Initialize.cpp",
"glslang/MachineIndependent/Initialize.h",
"glslang/MachineIndependent/IntermTraverse.cpp",
"glslang/MachineIndependent/Intermediate.cpp",
"glslang/MachineIndependent/LiveTraverser.h",
"glslang/MachineIndependent/ParseContextBase.cpp",
"glslang/MachineIndependent/ParseHelper.cpp",
"glslang/MachineIndependent/ParseHelper.h",
"glslang/MachineIndependent/PoolAlloc.cpp",
"glslang/MachineIndependent/RemoveTree.cpp",
"glslang/MachineIndependent/RemoveTree.h",
"glslang/MachineIndependent/Scan.cpp",
"glslang/MachineIndependent/Scan.h",
"glslang/MachineIndependent/ScanContext.h",
"glslang/MachineIndependent/ShaderLang.cpp",
"glslang/MachineIndependent/SpirvIntrinsics.cpp",
"glslang/MachineIndependent/SymbolTable.cpp",
"glslang/MachineIndependent/SymbolTable.h",
"glslang/MachineIndependent/Versions.cpp",
"glslang/MachineIndependent/Versions.h",
"glslang/MachineIndependent/attribute.cpp",
"glslang/MachineIndependent/attribute.h",
"glslang/MachineIndependent/gl_types.h",
"glslang/MachineIndependent/glslang_tab.cpp",
"glslang/MachineIndependent/glslang_tab.cpp.h",
"glslang/MachineIndependent/intermOut.cpp",
"glslang/MachineIndependent/iomapper.cpp",
"glslang/MachineIndependent/iomapper.h",
"glslang/MachineIndependent/limits.cpp",
"glslang/MachineIndependent/linkValidate.cpp",
"glslang/MachineIndependent/localintermediate.h",
"glslang/MachineIndependent/parseConst.cpp",
"glslang/MachineIndependent/parseVersions.h",
"glslang/MachineIndependent/preprocessor/Pp.cpp",
"glslang/MachineIndependent/preprocessor/PpAtom.cpp",
"glslang/MachineIndependent/preprocessor/PpContext.cpp",
"glslang/MachineIndependent/preprocessor/PpContext.h",
"glslang/MachineIndependent/preprocessor/PpScanner.cpp",
"glslang/MachineIndependent/preprocessor/PpTokens.cpp",
"glslang/MachineIndependent/preprocessor/PpTokens.h",
"glslang/MachineIndependent/propagateNoContraction.cpp",
"glslang/MachineIndependent/propagateNoContraction.h",
"glslang/MachineIndependent/reflection.cpp",
"glslang/MachineIndependent/reflection.h",
"glslang/OSDependent/osinclude.h",
"glslang/Public/ShaderLang.h",
]
# Workaround gn issue complaining about these not being allowed even though GLSLANG_HLSL is not
# defined.
sources += [
"glslang/HLSL/hlslParseHelper.h",
"glslang/HLSL/hlslParseables.h",
"glslang/HLSL/hlslScanContext.h",
"glslang/HLSL/hlslTokens.h",
]
if (invoker.enable_hlsl) {
sources += [
"glslang/HLSL/hlslAttributes.cpp",
"glslang/HLSL/hlslAttributes.h",
"glslang/HLSL/hlslGrammar.cpp",
"glslang/HLSL/hlslGrammar.h",
"glslang/HLSL/hlslOpMap.cpp",
"glslang/HLSL/hlslOpMap.h",
"glslang/HLSL/hlslParseHelper.cpp",
"glslang/HLSL/hlslParseables.cpp",
"glslang/HLSL/hlslScanContext.cpp",
"glslang/HLSL/hlslTokenStream.cpp",
"glslang/HLSL/hlslTokenStream.h",
]
}
defines = []
if (invoker.enable_opt) {
sources += [ "SPIRV/SpvTools.cpp" ]
defines += [ "ENABLE_OPT=1" ]
}
if (invoker.is_angle) {
defines += [ "GLSLANG_ANGLE" ]
}
if (is_win) {
sources += [ "glslang/OSDependent/Windows/ossource.cpp" ]
defines += [ "GLSLANG_OSINCLUDE_WIN32" ]
} else {
sources += [ "glslang/OSDependent/Unix/ossource.cpp" ]
defines += [ "GLSLANG_OSINCLUDE_UNIX" ]
}
if (is_clang) {
cflags = [
"-Wno-extra-semi",
"-Wno-ignored-qualifiers",
"-Wno-implicit-fallthrough",
"-Wno-inconsistent-missing-override",
"-Wno-missing-field-initializers",
"-Wno-newline-eof",
"-Wno-sign-compare",
"-Wno-suggest-destructor-override",
"-Wno-suggest-override",
"-Wno-unused-variable",
]
}
if (is_win && !is_clang) {
cflags = [
"/wd4018", # signed/unsigned mismatch
"/wd4189", # local variable is initialized but not referenced
]
}
include_dirs = [ "${target_gen_dir}/include" ]
deps = [ ":glslang_build_info" ]
if (invoker.enable_opt) {
deps += [
"${spirv_tools_dir}:spvtools_opt",
"${spirv_tools_dir}:spvtools_val",
]
include_dirs += [ "${spirv_tools_dir}/include" ]
}
configs -= _configs_to_remove
configs += _configs_to_add
}
}
glslang_sources_common("glslang_lib_sources") {
enable_opt = !glslang_angle
enable_hlsl = !glslang_angle
is_angle = glslang_angle
}
glslang_sources_common("glslang_sources") {
enable_opt = true
enable_hlsl = true
is_angle = false
}
source_set("glslang_default_resource_limits_sources") {
sources = [
"StandAlone/ResourceLimits.cpp",
"StandAlone/ResourceLimits.h",
"glslang/Include/ResourceLimits.h",
]
public_configs = [ ":glslang_public" ]
configs -= _configs_to_remove
configs += _configs_to_add
}
executable("glslang_validator") {
sources = [
"StandAlone/DirStackFileIncluder.h",
"StandAlone/StandAlone.cpp",
]
if (!is_win) {
cflags = [ "-Woverflow" ]
}
defines = [ "ENABLE_OPT=1" ]
deps = [
":glslang_build_info",
":glslang_default_resource_limits_sources",
":glslang_sources",
":glslang_extension_headers",
]
public_configs = [ ":glslang_hlsl" ]
include_dirs = [
"${target_gen_dir}/include",
"${spirv_tools_dir}/include",
]
configs -= _configs_to_remove
configs += _configs_to_add
}
executable("spirv-remap") {
sources = [ "StandAlone/spirv-remap.cpp" ]
defines = [ "ENABLE_OPT=1" ]
deps = [ ":glslang_sources" ]
include_dirs = [ "${spirv_tools_dir}/include" ]
configs -= _configs_to_remove
configs += _configs_to_add
}

View File

@ -0,0 +1,96 @@
# Revision history for `glslang`
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/).
## 11.8.0 2022-01-27
### Other changes
* Add support for SPIR-V 1.6
* Add support for Vulkan 1.3
* Add --hlsl-dx-position-w option
## 11.7.0 2021-11-11
### Other changes
* Add support for targeting Vulkan 1.2 in the C API
## 11.6.0 2021-08-25
### Other changes
* Atomic memory function only for shader storage block member or shared variable
* Add support for gl_MaxVaryingVectors for ogl
* Fix loading bool arrays from interface blocks
* Generate separate stores for partially swizzled memory stores
* Allow layout(std430) uniform with GL_EXT_scalar_block_layout
* Support for pragma STDGL invariant(all)
* Support for GL_NV_ray_tracing_motion_blur
## 11.5.0 2021-06-23
### Other changes
* Implement GLSL_EXT_shader_atomic_float2
* Implement GL_EXT_spirv_intrinsics
* Fixed SPIR-V remapper not remapping OpExtInst instruction set IDs
* only declare compatibility gl_ variables in compatibility mode
* Add support for float spec const vector initialization
* Implement GL_EXT_subgroup_uniform_control_flow.
* Fix arrays dimensioned with spec constant sized gl_WorkGroupSize
* Add support for 64bit integer scalar and vector types to bitCount() builtin
## 11.4.0 2021-04-22
### Other changes
* Fix to keep source compatible with CMake 3.10.2
## 11.3.0 2021-04-21
### Other changes
* Added --depfile
* Added --auto-sampled-textures
* Now supports InterpolateAt-based functions
* Supports cross-stage automatic IO mapping
* Supports GL_EXT_vulkan_glsl_relaxed (-R option)
## 11.2.0 2021-02-18
### Other changes
* Removed Python requirement when not building with spirv-tools
* Add support for GL_EXT_shared_memory_block
* Implement GL_EXT_null_initializer
* Add CMake support for Fuschia
## 11.1.0 2020-12-07
### Other changes
* Added ray-tracing extension support
## 11.0.0 2020-07-20
### Breaking changes
#### Visual Studio 2013 is no longer supported
[As scheduled](https://github.com/KhronosGroup/glslang/blob/9eef54b2513ca6b40b47b07d24f453848b65c0df/README.md#planned-deprecationsremovals),
Microsoft Visual Studio 2013 is no longer officially supported. Please upgrade
to at least Visual Studio 2015.
## 10.15.3847 2020-07-20
### Breaking changes
* The following files have been removed:
* `glslang/include/revision.h`
* `glslang/include/revision.template`
The `GLSLANG_MINOR_VERSION` and `GLSLANG_PATCH_LEVEL` defines have been removed
from the public headers. \
Instead each build script now uses the new `build_info.py`
script along with the `build_info.h.tmpl` and this `CHANGES.md` file to generate
the glslang build-time generated header `glslang/build_info.h`.
The new public API to obtain the `glslang` version is `glslang::GetVersion()`.
### Other changes
* `glslang` shared objects produced by CMake are now `SONAME` versioned using
[Semantic Versioning 2.0.0](https://semver.org/).

View File

@ -0,0 +1,365 @@
# Copyright (C) 2020 The Khronos Group Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# Neither the name of The Khronos Group Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# increase to 3.1 once all major distributions
# include a version of CMake >= 3.1
cmake_minimum_required(VERSION 2.8.12)
if (POLICY CMP0048)
cmake_policy(SET CMP0048 NEW)
endif()
if(POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()
project(glslang LANGUAGES CXX)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Enable compile commands database
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Adhere to GNU filesystem layout conventions
include(GNUInstallDirs)
# Needed for CMAKE_DEPENDENT_OPTION macro
include(CMakeDependentOption)
option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
option(BUILD_EXTERNAL "Build external dependencies in /External" ON)
set(LIB_TYPE STATIC)
if(BUILD_SHARED_LIBS)
set(LIB_TYPE SHARED)
endif()
if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
# This logic inside SPIRV-Tools, which can upset build target dependencies
# if changed after targets are already defined. To prevent these issues,
# ensure CMAKE_BUILD_TYPE is assigned early and at the glslang root scope.
message(STATUS "No build type selected, default to Debug")
set(CMAKE_BUILD_TYPE "Debug")
endif()
option(SKIP_GLSLANG_INSTALL "Skip installation" ${SKIP_GLSLANG_INSTALL})
if(NOT ${SKIP_GLSLANG_INSTALL})
set(ENABLE_GLSLANG_INSTALL ON)
endif()
option(ENABLE_SPVREMAPPER "Enables building of SPVRemapper" ON)
option(ENABLE_GLSLANG_BINARIES "Builds glslangValidator and spirv-remap" ON)
option(ENABLE_GLSLANG_JS
"If using Emscripten, build glslang.js. Otherwise, builds a sample executable for binary-size testing." OFF)
CMAKE_DEPENDENT_OPTION(ENABLE_GLSLANG_WEBMIN
"Reduces glslang to minimum needed for web use"
OFF "ENABLE_GLSLANG_JS"
OFF)
CMAKE_DEPENDENT_OPTION(ENABLE_GLSLANG_WEBMIN_DEVEL
"For ENABLE_GLSLANG_WEBMIN builds, enables compilation error messages"
OFF "ENABLE_GLSLANG_WEBMIN"
OFF)
CMAKE_DEPENDENT_OPTION(ENABLE_EMSCRIPTEN_SINGLE_FILE
"If using Emscripten, enables SINGLE_FILE build"
OFF "ENABLE_GLSLANG_JS AND EMSCRIPTEN"
OFF)
CMAKE_DEPENDENT_OPTION(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE
"If using Emscripten, builds to run on Node instead of Web"
OFF "ENABLE_GLSLANG_JS AND EMSCRIPTEN"
OFF)
CMAKE_DEPENDENT_OPTION(ENABLE_HLSL
"Enables HLSL input support"
ON "NOT ENABLE_GLSLANG_WEBMIN"
OFF)
option(ENABLE_RTTI "Enables RTTI" OFF)
option(ENABLE_EXCEPTIONS "Enables Exceptions" OFF)
option(ENABLE_OPT "Enables spirv-opt capability if present" ON)
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND ${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
# Workaround for CMake behavior on Mac OS with gcc, cmake generates -Xarch_* arguments
# which gcc rejects
option(ENABLE_PCH "Enables Precompiled header" OFF)
else()
option(ENABLE_PCH "Enables Precompiled header" ON)
endif()
option(ENABLE_CTEST "Enables testing" ON)
if(ENABLE_GLSLANG_INSTALL AND CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND WIN32)
set(CMAKE_INSTALL_PREFIX "install" CACHE STRING "..." FORCE)
endif()
option(USE_CCACHE "Use ccache" OFF)
if(USE_CCACHE)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
endif()
endif()
if(ENABLE_CTEST)
include(CTest)
endif()
if(ENABLE_HLSL)
add_definitions(-DENABLE_HLSL)
endif()
if(ENABLE_GLSLANG_WEBMIN)
add_definitions(-DGLSLANG_WEB)
if(ENABLE_GLSLANG_WEBMIN_DEVEL)
add_definitions(-DGLSLANG_WEB_DEVEL)
endif()
endif()
if(WIN32)
set(CMAKE_DEBUG_POSTFIX "d")
option(OVERRIDE_MSVCCRT "Overrides runtime of MSVC " ON)
if(MSVC AND OVERRIDE_MSVCCRT)
include(ChooseMSVCCRT.cmake)
endif()
add_definitions(-DGLSLANG_OSINCLUDE_WIN32)
elseif(UNIX)
add_definitions(-DGLSLANG_OSINCLUDE_UNIX)
else()
message("unknown platform")
endif()
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
add_compile_options(-Wall -Wmaybe-uninitialized -Wuninitialized -Wunused -Wunused-local-typedefs
-Wunused-parameter -Wunused-value -Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable -fno-exceptions)
add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over.
if(NOT ENABLE_RTTI)
add_compile_options(-fno-rtti)
endif()
if(NOT ENABLE_EXCEPTIONS)
add_compile_options(-fno-exceptions)
endif()
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0.0")
add_compile_options(-Werror=deprecated-copy)
endif()
if(NOT CMAKE_VERSION VERSION_LESS "3.13" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# Error if there's symbols that are not found at link time.
# add_link_options() was added in CMake 3.13 - if using an earlier
# version don't set this - it should be caught by presubmits anyway.
add_link_options("-Wl,--no-undefined")
endif()
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND NOT MSVC)
add_compile_options(-Wall -Wuninitialized -Wunused -Wunused-local-typedefs
-Wunused-parameter -Wunused-value -Wunused-variable)
add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over.
if(NOT ENABLE_RTTI)
add_compile_options(-fno-rtti)
endif()
if(NOT ENABLE_EXCEPTIONS)
add_compile_options(-fno-exceptions)
endif()
if(NOT CMAKE_VERSION VERSION_LESS "3.13")
# Error if there's symbols that are not found at link time.
# add_link_options() was added in CMake 3.13 - if using an earlier
# version don't set this - it should be caught by presubmits anyway.
add_link_options("-Wl,-undefined,error")
endif()
elseif(MSVC)
if(NOT ENABLE_RTTI)
string(FIND "${CMAKE_CXX_FLAGS}" "/GR" MSVC_HAS_GR)
if(MSVC_HAS_GR)
string(REGEX REPLACE "/GR" "/GR-" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
add_compile_options(/GR-) # Disable RTTI
endif()
endif()
if(ENABLE_EXCEPTIONS)
add_compile_options(/EHsc) # Enable Exceptions
else()
string(REGEX REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") # Try to remove default /EHsc cxx_flag
add_compile_options(/D_HAS_EXCEPTIONS=0)
endif()
endif()
if(ENABLE_GLSLANG_JS)
if(MSVC)
add_compile_options(/Os /GR-)
else()
add_compile_options(-Os -fno-rtti -fno-exceptions)
if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND NOT MSVC)
add_compile_options(-Wno-unused-parameter)
add_compile_options(-Wno-unused-variable -Wno-unused-const-variable)
endif()
endif()
endif()
# Request C++11
if(${CMAKE_VERSION} VERSION_LESS 3.1)
# CMake versions before 3.1 do not understand CMAKE_CXX_STANDARD
# remove this block once CMake >=3.1 has fixated in the ecosystem
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
else()
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
endif()
function(glslang_set_link_args TARGET)
# For MinGW compiles, statically link against the GCC and C++ runtimes.
# This avoids the need to ship those runtimes as DLLs.
if(WIN32 AND ${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
set_target_properties(${TARGET} PROPERTIES
LINK_FLAGS "-static -static-libgcc -static-libstdc++")
endif()
endfunction(glslang_set_link_args)
if(NOT COMMAND find_host_package)
macro(find_host_package)
find_package(${ARGN})
endmacro()
endif()
# Root directory for build-time generated include files
set(GLSLANG_GENERATED_INCLUDEDIR "${CMAKE_BINARY_DIR}/include")
################################################################################
# Build version information generation
################################################################################
include(parse_version.cmake)
set(GLSLANG_CHANGES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CHANGES.md")
set(GLSLANG_BUILD_INFO_H_TMPL "${CMAKE_CURRENT_SOURCE_DIR}/build_info.h.tmpl")
set(GLSLANG_BUILD_INFO_H "${GLSLANG_GENERATED_INCLUDEDIR}/glslang/build_info.h")
parse_version(${GLSLANG_CHANGES_FILE} GLSLANG)
function(configurate_version)
set(major ${GLSLANG_VERSION_MAJOR})
set(minor ${GLSLANG_VERSION_MINOR})
set(patch ${GLSLANG_VERSION_PATCH})
set(flavor ${GLSLANG_VERSION_FLAVOR})
configure_file(${GLSLANG_BUILD_INFO_H_TMPL} ${GLSLANG_BUILD_INFO_H} @ONLY)
endfunction()
configurate_version()
# glslang_add_build_info_dependency() adds the glslang-build-info dependency and
# generated include directories to target.
function(glslang_add_build_info_dependency target)
target_include_directories(${target} PUBLIC $<BUILD_INTERFACE:${GLSLANG_GENERATED_INCLUDEDIR}>)
endfunction()
# glslang_only_export_explicit_symbols() makes the symbol visibility hidden by
# default for <target> when building shared libraries, and sets the
# GLSLANG_IS_SHARED_LIBRARY define, and GLSLANG_EXPORTING to 1 when specifically
# building <target>.
function(glslang_only_export_explicit_symbols target)
if(BUILD_SHARED_LIBS)
target_compile_definitions(${target} PUBLIC "GLSLANG_IS_SHARED_LIBRARY=1")
if(WIN32)
target_compile_definitions(${target} PRIVATE "GLSLANG_EXPORTING=1")
else()
target_compile_options(${target} PRIVATE "-fvisibility=hidden")
endif()
endif()
endfunction()
# glslang_pch() adds precompiled header rules to <target> for the pre-compiled
# header file <pch>. As target_precompile_headers() was added in CMake 3.16,
# this is a no-op if called on earlier versions of CMake.
if(NOT CMAKE_VERSION VERSION_LESS "3.16" AND ENABLE_PCH)
function(glslang_pch target pch)
target_precompile_headers(${target} PRIVATE ${pch})
endfunction()
else()
function(glslang_pch target pch)
endfunction()
if(ENABLE_PCH)
message("Your CMake version is ${CMAKE_VERSION}. Update to at least 3.16 to enable precompiled headers to speed up incremental builds")
endif()
endif()
if(BUILD_EXTERNAL AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/External)
find_host_package(PythonInterp 3 REQUIRED)
# We depend on these for later projects, so they should come first.
add_subdirectory(External)
endif()
if(NOT TARGET SPIRV-Tools-opt)
set(ENABLE_OPT OFF)
endif()
if(ENABLE_OPT)
message(STATUS "optimizer enabled")
add_definitions(-DENABLE_OPT=1)
else()
if(ENABLE_HLSL)
message(STATUS "spirv-tools not linked - illegal SPIRV may be generated for HLSL")
endif()
add_definitions(-DENABLE_OPT=0)
endif()
add_subdirectory(glslang)
add_subdirectory(OGLCompilersDLL)
if(ENABLE_GLSLANG_BINARIES)
add_subdirectory(StandAlone)
endif()
add_subdirectory(SPIRV)
if(ENABLE_HLSL)
add_subdirectory(hlsl)
endif()
if(ENABLE_CTEST)
add_subdirectory(gtests)
endif()
if(ENABLE_CTEST AND BUILD_TESTING)
# glslang-testsuite runs a bash script on Windows.
# Make sure to use '-o igncr' flag to ignore carriage returns (\r).
set(IGNORE_CR_FLAG "")
if(WIN32)
set(IGNORE_CR_FLAG -o igncr)
endif()
if (CMAKE_CONFIGURATION_TYPES)
set(RESULTS_PATH ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>/localResults)
set(VALIDATOR_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/$<CONFIGURATION>/glslangValidator)
set(REMAP_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/$<CONFIGURATION>/spirv-remap)
else()
set(RESULTS_PATH ${CMAKE_CURRENT_BINARY_DIR}/localResults)
set(VALIDATOR_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/glslangValidator)
set(REMAP_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/spirv-remap)
endif()
add_test(NAME glslang-testsuite
COMMAND bash ${IGNORE_CR_FLAG} runtests ${RESULTS_PATH} ${VALIDATOR_PATH} ${REMAP_PATH}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Test/)
endif()

View File

@ -0,0 +1 @@
A reminder that this issue tracker is managed by the Khronos Group. Interactions here should follow the Khronos Code of Conduct (https://www.khronos.org/developers/code-of-conduct), which prohibits aggressive or derogatory language. Please keep the discussion friendly and civil.

View File

@ -0,0 +1,138 @@
# Copyright (C) 2020 The Khronos Group Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# Neither the name of The Khronos Group Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# The macro choose_msvc_crt() takes a list of possible
# C runtimes to choose from, in the form of compiler flags,
# to present to the user. (MTd for /MTd, etc)
#
# The macro is invoked at the end of the file.
#
# CMake already sets CRT flags in the CMAKE_CXX_FLAGS_* and
# CMAKE_C_FLAGS_* variables by default. To let the user
# override that for each build type:
# 1. Detect which CRT is already selected, and reflect this in
# LLVM_USE_CRT_* so the user can have a better idea of what
# changes they're making.
# 2. Replace the flags in both variables with the new flag via a regex.
# 3. set() the variables back into the cache so the changes
# are user-visible.
### Helper macros: ###
macro(make_crt_regex regex crts)
set(${regex} "")
foreach(crt ${${crts}})
# Trying to match the beginning or end of the string with stuff
# like [ ^]+ didn't work, so use a bunch of parentheses instead.
set(${regex} "${${regex}}|(^| +)/${crt}($| +)")
endforeach(crt)
string(REGEX REPLACE "^\\|" "" ${regex} "${${regex}}")
endmacro(make_crt_regex)
macro(get_current_crt crt_current regex flagsvar)
# Find the selected-by-CMake CRT for each build type, if any.
# Strip off the leading slash and any whitespace.
string(REGEX MATCH "${${regex}}" ${crt_current} "${${flagsvar}}")
string(REPLACE "/" " " ${crt_current} "${${crt_current}}")
string(STRIP "${${crt_current}}" ${crt_current})
endmacro(get_current_crt)
# Replaces or adds a flag to a variable.
# Expects 'flag' to be padded with spaces.
macro(set_flag_in_var flagsvar regex flag)
string(REGEX MATCH "${${regex}}" current_flag "${${flagsvar}}")
if("${current_flag}" STREQUAL "")
set(${flagsvar} "${${flagsvar}}${${flag}}")
else()
string(REGEX REPLACE "${${regex}}" "${${flag}}" ${flagsvar} "${${flagsvar}}")
endif()
string(STRIP "${${flagsvar}}" ${flagsvar})
# Make sure this change gets reflected in the cache/gui.
# CMake requires the docstring parameter whenever set() touches the cache,
# so get the existing docstring and re-use that.
get_property(flagsvar_docs CACHE ${flagsvar} PROPERTY HELPSTRING)
set(${flagsvar} "${${flagsvar}}" CACHE STRING "${flagsvar_docs}" FORCE)
endmacro(set_flag_in_var)
macro(choose_msvc_crt MSVC_CRT)
if(LLVM_USE_CRT)
message(FATAL_ERROR
"LLVM_USE_CRT is deprecated. Use the CMAKE_BUILD_TYPE-specific
variables (LLVM_USE_CRT_DEBUG, etc) instead.")
endif()
make_crt_regex(MSVC_CRT_REGEX ${MSVC_CRT})
foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE})
string(TOUPPER "${build_type}" build)
if (NOT LLVM_USE_CRT_${build})
get_current_crt(LLVM_USE_CRT_${build}
MSVC_CRT_REGEX
CMAKE_CXX_FLAGS_${build})
set(LLVM_USE_CRT_${build}
"${LLVM_USE_CRT_${build}}"
CACHE STRING "Specify VC++ CRT to use for ${build_type} configurations."
FORCE)
set_property(CACHE LLVM_USE_CRT_${build}
PROPERTY STRINGS ;${${MSVC_CRT}})
endif(NOT LLVM_USE_CRT_${build})
endforeach(build_type)
foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE})
string(TOUPPER "${build_type}" build)
if ("${LLVM_USE_CRT_${build}}" STREQUAL "")
set(flag_string " ")
else()
set(flag_string " /${LLVM_USE_CRT_${build}} ")
list(FIND ${MSVC_CRT} ${LLVM_USE_CRT_${build}} idx)
if (idx LESS 0)
message(FATAL_ERROR
"Invalid value for LLVM_USE_CRT_${build}: ${LLVM_USE_CRT_${build}}. Valid options are one of: ${${MSVC_CRT}}")
endif (idx LESS 0)
message(STATUS "Using ${build_type} VC++ CRT: ${LLVM_USE_CRT_${build}}")
endif()
foreach(lang C CXX)
set_flag_in_var(CMAKE_${lang}_FLAGS_${build} MSVC_CRT_REGEX flag_string)
endforeach(lang)
endforeach(build_type)
endmacro(choose_msvc_crt MSVC_CRT)
# List of valid CRTs for MSVC
set(MSVC_CRT
MD
MDd
MT
MTd)
choose_msvc_crt(MSVC_CRT)

82
lib/shaderc/third_party/glslang/DEPS vendored Normal file
View File

@ -0,0 +1,82 @@
# Copyright (C) 2020 The Khronos Group Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# Neither the name of The Khronos Group Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
use_relative_paths = True
gclient_gn_args_file = 'build/config/gclient_args.gni'
vars = {
'chromium_git': 'https://chromium.googlesource.com',
'build_with_chromium': False,
}
deps = {
'./build': {
'url': '{chromium_git}/chromium/src/build.git@85ee3b7692e5284f08bd3c9459fb5685eed7b838',
'condition': 'not build_with_chromium',
},
'./buildtools': {
'url': '{chromium_git}/chromium/src/buildtools.git@4be464e050b3d05060471788f926b34c641db9fd',
'condition': 'not build_with_chromium',
},
'./tools/clang': {
'url': '{chromium_git}/chromium/src/tools/clang.git@3a982adabb720aa8f3e3885d40bf3fe506990157',
'condition': 'not build_with_chromium',
},
}
hooks = [
{
'name': 'sysroot_x64',
'pattern': '.',
'condition': 'checkout_linux and (checkout_x64 and not build_with_chromium)',
'action': ['python', './build/linux/sysroot_scripts/install-sysroot.py',
'--arch=x64'],
},
{
# Note: On Win, this should run after win_toolchain, as it may use it.
'name': 'clang',
'pattern': '.',
'action': ['python', './tools/clang/scripts/update.py'],
'condition': 'not build_with_chromium',
},
]
recursedeps = [
# buildtools provides clang_format, libc++, and libc++abi
'buildtools',
]

View File

@ -0,0 +1,77 @@
# Copyright (C) 2020 The Khronos Group Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# Neither the name of The Khronos Group Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# Suppress all warnings from external projects.
set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS -w)
if(BUILD_TESTING)
if(TARGET gmock)
message(STATUS "Google Mock already configured - use it")
elseif(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/googletest)
# We need to make sure Google Test does not mess up with the
# global CRT settings on Windows.
if(WIN32)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
endif(WIN32)
# EXCLUDE_FROM_ALL keeps the install target from installing GTEST files.
add_subdirectory(googletest EXCLUDE_FROM_ALL)
set(GTEST_TARGETS
gtest
gtest_main
gmock
gmock_main)
foreach(target ${GTEST_TARGETS})
set_property(TARGET ${target} PROPERTY FOLDER gtest)
endforeach()
mark_as_advanced(gmock_build_tests
BUILD_GMOCK
BUILD_GTEST
BUILD_SHARED_LIBS
gtest_build_samples
gtest_build_tests
gtest_disable_pthreads
gtest_force_shared_crt
gtest_hide_internal_symbols)
else()
message(STATUS
"Google Mock was not found - tests based on that will not build")
endif()
endif()
if(ENABLE_OPT AND NOT TARGET SPIRV-Tools-opt)
if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/spirv-tools)
set(SPIRV_SKIP_TESTS ON CACHE BOOL "Skip building SPIRV-Tools tests")
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/spirv-tools spirv-tools)
endif()
endif()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
# Copyright (C) 2020 The Khronos Group Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# Neither the name of The Khronos Group Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
set(SOURCES InitializeDll.cpp InitializeDll.h)
add_library(OGLCompiler STATIC ${SOURCES})
set_property(TARGET OGLCompiler PROPERTY FOLDER glslang)
set_property(TARGET OGLCompiler PROPERTY POSITION_INDEPENDENT_CODE ON)
if(WIN32)
source_group("Source" FILES ${SOURCES})
endif(WIN32)
if(ENABLE_GLSLANG_INSTALL)
install(TARGETS OGLCompiler EXPORT OGLCompilerTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(EXPORT OGLCompilerTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
endif(ENABLE_GLSLANG_INSTALL)

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