diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-02-13 15:05:36 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-02-14 10:33:47 +0000 |
commit | e684a3455bcc29a6e3e66a004e352dea4e1141e7 (patch) | |
tree | d55b4003bde34d7d05f558f02cfd82b2a66a7aac /chromium/third_party/shaderc | |
parent | 2b94bfe47ccb6c08047959d1c26e392919550e86 (diff) | |
download | qtwebengine-chromium-e684a3455bcc29a6e3e66a004e352dea4e1141e7.tar.gz |
BASELINE: Update Chromium to 72.0.3626.110 and Ninja to 1.9.0
Change-Id: Ic57220b00ecc929a893c91f5cc552f5d3e99e922
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/third_party/shaderc')
157 files changed, 18655 insertions, 0 deletions
diff --git a/chromium/third_party/shaderc/OWNERS b/chromium/third_party/shaderc/OWNERS new file mode 100644 index 00000000000..e9c1789a69c --- /dev/null +++ b/chromium/third_party/shaderc/OWNERS @@ -0,0 +1,4 @@ +cwallez@chromium.org +dsinclair@chromium.org + +# COMPONENT: Internals>GPU>Internals diff --git a/chromium/third_party/shaderc/README.chromium b/chromium/third_party/shaderc/README.chromium new file mode 100644 index 00000000000..70616b0697b --- /dev/null +++ b/chromium/third_party/shaderc/README.chromium @@ -0,0 +1,10 @@ +Name: Shaderc +Short Name: shaderc +URL: https://github.com/google/shaderc +Version: Unknown +Security Critical: yes +License: Apache 2.0 +License File: src/LICENSE + +Description: +A collection of SPIR-V related tools/libraries. diff --git a/chromium/third_party/shaderc/src/AUTHORS b/chromium/third_party/shaderc/src/AUTHORS new file mode 100644 index 00000000000..9bd9eaa7b5f --- /dev/null +++ b/chromium/third_party/shaderc/src/AUTHORS @@ -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. diff --git a/chromium/third_party/shaderc/src/Android.mk b/chromium/third_party/shaderc/src/Android.mk new file mode 100644 index 00000000000..e23b77aaf15 --- /dev/null +++ b/chromium/third_party/shaderc/src/Android.mk @@ -0,0 +1,59 @@ +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 + +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) && $(2)ar -M < combine.ar && cd $(ROOT_SHADERC_PATH) + @$(2)objcopy --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 +$(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.hpp: \ + $(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/shaderc.hpp + $(call host-mkdir,$(NDK_APP_LIBS_OUT)/../include/shaderc) + $(call host-cp,$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/shaderc.hpp \ + ,$(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.hpp) + +$(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.h: \ + $(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/shaderc.h + $(call host-mkdir,$(NDK_APP_LIBS_OUT)/../include/shaderc) + $(call host-cp,$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/shaderc.h \ + ,$(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.h) +endif + +libshaderc_combined: \ + $(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a + +endef +libshaderc_combined: $(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.hpp \ + $(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.h + +$(eval $(call gen_libshaderc,$(TARGET_OUT),$(TOOLCHAIN_PREFIX))) diff --git a/chromium/third_party/shaderc/src/BUILD.gn b/chromium/third_party/shaderc/src/BUILD.gn new file mode 100644 index 00000000000..f9d52b15f32 --- /dev/null +++ b/chromium/third_party/shaderc/src/BUILD.gn @@ -0,0 +1,106 @@ +# 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/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/file_finder.h", + "libshaderc_util/include/libshaderc_util/format.h", + "libshaderc_util/include/libshaderc_util/io.h", + "libshaderc_util/include/libshaderc_util/message.h", + "libshaderc_util/include/libshaderc_util/mutex.h", + "libshaderc_util/include/libshaderc_util/resources.h", + "libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h", + "libshaderc_util/include/libshaderc_util/string_piece.h", + "libshaderc_util/include/libshaderc_util/universal_unistd.h", + "libshaderc_util/include/libshaderc_util/version_profile.h", + "libshaderc_util/src/compiler.cc", + "libshaderc_util/src/file_finder.cc", + "libshaderc_util/src/io.cc", + "libshaderc_util/src/message.cc", + "libshaderc_util/src/resources.cc", + "libshaderc_util/src/shader_stage.cc", + "libshaderc_util/src/spirv_tools_wrapper.cc", + "libshaderc_util/src/version_profile.cc", + ] + + public_configs = [ ":shaderc_util_public" ] + + deps = [ + "${glslang_dir}:glslang_sources", + "${spirv_tools_dir}:spvtools", + ] +} + +config("shaderc_public") { + include_dirs = [ "libshaderc/include" ] + defines = [ "SHADERC_SHAREDLIB" ] + + # Executable needs an rpath to find our shared libraries on OSX + if (is_mac) { + ldflags = [ + "-rpath", + "@executable_path/", + ] + } +} + +source_set("libshaderc_sources") { + defines = [ "SHADERC_IMPLEMENTATION" ] + + sources = [ + "libshaderc/include/shaderc/shaderc.h", + "libshaderc/include/shaderc/shaderc.hpp", + "libshaderc/src/shaderc.cc", + "libshaderc/src/shaderc_private.h", + ] + + public_configs = [ ":shaderc_public" ] + + deps = [ + ":shaderc_util_sources", + "${spirv_tools_dir}:spvtools", + "${spirv_tools_dir}:spvtools_val", + "${glslang_dir}:glslang_sources", + ] +} + +shared_library("libshaderc") { + public_configs = [ ":shaderc_public" ] + + deps = [ + ":libshaderc_sources", + ] + + # Tell dependents where to find this shared library + if (is_mac) { + ldflags = [ + "-install_name", + "@rpath/${target_name}.dylib", + ] + } + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] +} + diff --git a/chromium/third_party/shaderc/src/CHANGES b/chromium/third_party/shaderc/src/CHANGES new file mode 100644 index 00000000000..002dfee4618 --- /dev/null +++ b/chromium/third_party/shaderc/src/CHANGES @@ -0,0 +1,91 @@ +Revision history for Shaderc + +v2018.1-dev 2018-10-01 + - Start v2018.1 development + +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 diff --git a/chromium/third_party/shaderc/src/CMakeLists.txt b/chromium/third_party/shaderc/src/CMakeLists.txt new file mode 100644 index 00000000000..b982eabfa27 --- /dev/null +++ b/chromium/third_party/shaderc/src/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 2.8.12) +project(shaderc) +enable_testing() + +message(STATUS "Shaderc: build type is \"${CMAKE_BUILD_TYPE}\".") + +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() + +set (CMAKE_CXX_STANDARD 11) + +option(SHADERC_ENABLE_NV_EXTENSIONS "Enables support of Nvidia-specific extensions" ON) + +include(GNUInstallDirs) +include(cmake/setup_build.cmake) +include(cmake/utils.cmake) + + +if(SHADERC_ENABLE_NV_EXTENSIONS) + add_definitions(-DNV_EXTENSIONS) +endif(SHADERC_ENABLE_NV_EXTENSIONS) + +add_custom_target(check-copyright ALL + ${PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/utils/add_copyright.py + --check + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Check copyright") + +add_custom_target(add-copyright + ${PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/utils/add_copyright.py + 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) +add_subdirectory(glslc) +add_subdirectory(examples) + +add_custom_target(build-version + ${PYTHON_EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/utils/update_build_version.py + ${shaderc_SOURCE_DIR} ${spirv-tools_SOURCE_DIR} ${glslang_SOURCE_DIR} + COMMENT "Update build-version.inc in the Shaderc build directory (if necessary).") diff --git a/chromium/third_party/shaderc/src/CONTRIBUTING.md b/chromium/third_party/shaderc/src/CONTRIBUTING.md new file mode 100644 index 00000000000..24ff04c4b62 --- /dev/null +++ b/chromium/third_party/shaderc/src/CONTRIBUTING.md @@ -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. diff --git a/chromium/third_party/shaderc/src/CONTRIBUTORS b/chromium/third_party/shaderc/src/CONTRIBUTORS new file mode 100644 index 00000000000..503b32d050a --- /dev/null +++ b/chromium/third_party/shaderc/src/CONTRIBUTORS @@ -0,0 +1,23 @@ +# 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> diff --git a/chromium/third_party/shaderc/src/DEVELOPMENT.howto.md b/chromium/third_party/shaderc/src/DEVELOPMENT.howto.md new file mode 100644 index 00000000000..0abb40598aa --- /dev/null +++ b/chromium/third_party/shaderc/src/DEVELOPMENT.howto.md @@ -0,0 +1,90 @@ +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. But 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") | + + +## glslang + +Some Shaderc changes require concomitant changes to glslang. It is our policy +to upstream such work to glslang by following the official glslang project's +procedures. At the same time, we would like to have those changes available to +all Shaderc developers immediately upon passing our code review. Currently this +is best done by maintaining +[our own GitHub fork](https://github.com/google/glslang) of glslang, landing +Shaderc-supporting changes there<sup>\*</sup>, building Shaderc against it, and +generating pull requests from there to the glslang's original GitHub repository. +Although a separate repository, this should be treated as essentially a part of +Shaderc: the Shaderc master should always<sup>\**</sup> build against our +glslang fork's master. + +Changes made to glslang in the course of Shaderc development must build and test +correctly on their own, independently of Shaderc code, so they don't break other +users of glslang when sent upstream. We will periodically upstream the content +of our fork's `master` branch to the official glslang `master` branch, so all +the contributions we accept will find their way to glslang. + +We aim to keep our fork up to date with the official glslang by pulling their +changes frequently and merging them into our `master` branch. + +<hr><small> + +\*: Please note that GitHub uses the term "fork" as a routine part of +[contributing to another project](https://help.github.com/articles/using-pull-requests/#types-of-collaborative-development-models), +_not_ in the sense of scary open-source schism. This is why you'll hear us +speak of "our fork" and see "forked from KhronosGroup/glslang" atop the +[google/glslang](https://github.com/google/glslang) GitHub page. It does _not_ +mean that we're divorcing our glslang development from the original -- quite the +opposite. As stated above, we intend to upstream all our work to the original +glslang repository. + +\*\*: with one small exception: if a Shaderc and glslang pull requests need each +other and are simultaneously cherry-picked, then a `HEAD`s inconsistency will be +tolerated for the short moment that one has landed while the other hasn't. diff --git a/chromium/third_party/shaderc/src/Dockerfile b/chromium/third_party/shaderc/src/Dockerfile new file mode 100644 index 00000000000..7e7b1e03a7b --- /dev/null +++ b/chromium/third_party/shaderc/src/Dockerfile @@ -0,0 +1,52 @@ +# 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 \ + python \ + py-pip \ + && rm -rf /var/cache/apk/* + +WORKDIR /root +RUN git clone https://github.com/google/shaderc +WORKDIR shaderc +RUN git clone https://github.com/google/googletest.git third_party/googletest +RUN git clone https://github.com/google/glslang.git third_party/glslang +RUN git clone https://github.com/KhronosGroup/SPIRV-Tools.git third_party/spirv-tools +RUN git clone https://github.com/KhronosGroup/SPIRV-Headers.git third_party/spirv-tools/external/spirv-headers + +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"] diff --git a/chromium/third_party/shaderc/src/LICENSE b/chromium/third_party/shaderc/src/LICENSE new file mode 100644 index 00000000000..261eeb9e9f8 --- /dev/null +++ b/chromium/third_party/shaderc/src/LICENSE @@ -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. diff --git a/chromium/third_party/shaderc/src/README.md b/chromium/third_party/shaderc/src/README.md new file mode 100644 index 00000000000..b6d5e903426 --- /dev/null +++ b/chromium/third_party/shaderc/src/README.md @@ -0,0 +1,245 @@ +# Shaderc + +<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_release.svg) +<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_release.svg) +<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_release.svg) + +A collection of tools, libraries and tests for shader compilation. +At the moment it includes: + +- [`glslc`](glslc), a command line compiler for GLSL/HLSL to SPIR-V, and +- [`libshaderc`](libshaderc), a library API for doing the same. + +Shaderc wraps around core functionality in [glslang][khr-glslang] +and [SPIRV-Tools][spirv-tools]. Shaderc 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 + +## 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.) + +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. +Sometimes a change updates both Shaderc and glslang. In that case the +glslang change will appear in [google/glslang][google-glslang] +before it appears upstream in [KhronosGroup/glslang][khr-glslang] +We intend to upstream all changes to glslang. We maintain the separate +copy only to stage those changes for review, and to provide something for +Shaderc to build against in the meantime. Please see +[DEVELOPMENT.howto.md](DEVELOPMENT.howto.md) for more details. + +Shaderc depends on [SPIRV-Tools][spirv-tools] for assembling, disassembling, +and transforming SPIR-V binaries. + +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 + +**Experimental:** On Windows, instead of building from source, you can get the +artifacts built by [Appveyor][appveyor] for the top of the tree of the master +branch under the "Artifacts" tab of a certain job. + +1) Check out the source code: + +```sh +git clone https://github.com/google/shaderc $SOURCE_DIR +cd $SOURCE_DIR/third_party +git clone https://github.com/google/googletest.git +git clone https://github.com/google/glslang.git +git clone https://github.com/KhronosGroup/SPIRV-Tools.git spirv-tools +git clone https://github.com/KhronosGroup/SPIRV-Headers.git spirv-headers +cd $SOURCE_DIR/ +``` + +**Note:** The [known-good](https://github.com/google/shaderc/tree/known-good) +branch of the repository contains a +[known_good.json](https://github.com/google/shaderc/blob/known-good/known_good.json) +file describing a set of repo URLs and specific commits that have been +tested together. This information is updated periodically, and typically +matches the latest update of these sources in the development branch +of the Android NDK. +The `known-good` branch also contains a +[update_shaderc.py](https://github.com/google/shaderc/blob/known-good/update_shaderc_sources.py) +script that will read the JSON file and checkout those specific commits for you. + +2) Ensure you have the requisite tools -- see the tools subsection below. + +3) Decide where to place the build output. In the following steps, we'll call it + `$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](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 Micrsoft C runtime libraries. + +On Windows, the following tools should be installed and available on your path: + +- Visual Studio 2013 Update 4 or later. Previous versions of Visual Studio + will likely work but are untested. +- 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. + - [`nosetests`](https://nose.readthedocs.io): for testing the Python code. + +### 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] + +[khr-glslang]: https://github.com/KhronosGroup/glslang +[google-glslang]: https://github.com/google/glslang +[spirv-tools]: https://github.com/KhronosGroup/SPIRV-Tools +[pyshaderc]: https://github.com/realitix/pyshaderc +[shaderc-rs]: https://github.com/google/shaderc-rs +[appveyor]: https://ci.appveyor.com/project/dneto0/shaderc diff --git a/chromium/third_party/shaderc/src/android_test/Android.mk b/chromium/third_party/shaderc/src/android_test/Android.mk new file mode 100644 index 00000000000..4959331bc3f --- /dev/null +++ b/chromium/third_party/shaderc/src/android_test/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_CPP_EXTENSION := .cc .cpp .cxx +LOCAL_SRC_FILES:=test.cpp +LOCAL_MODULE:=shaderc_test +LOCAL_LDLIBS:=-landroid +LOCAL_STATIC_LIBRARIES=shaderc android_native_app_glue +include $(BUILD_SHARED_LIBRARY) + +include $(LOCAL_PATH)/../Android.mk +$(call import-module,android/native_app_glue) diff --git a/chromium/third_party/shaderc/src/android_test/jni/Android.mk b/chromium/third_party/shaderc/src/android_test/jni/Android.mk new file mode 100644 index 00000000000..8a362595e73 --- /dev/null +++ b/chromium/third_party/shaderc/src/android_test/jni/Android.mk @@ -0,0 +1,2 @@ +LOCAL_PATH := $(call my-dir) +include $(LOCAL_PATH)/../Android.mk diff --git a/chromium/third_party/shaderc/src/android_test/jni/Application.mk b/chromium/third_party/shaderc/src/android_test/jni/Application.mk new file mode 100644 index 00000000000..1f3808bcada --- /dev/null +++ b/chromium/third_party/shaderc/src/android_test/jni/Application.mk @@ -0,0 +1,4 @@ +APP_ABI := all +APP_BUILD_SCRIPT := Android.mk +APP_STL := gnustl_static +APP_PLATFORM := android-9 diff --git a/chromium/third_party/shaderc/src/android_test/test.cpp b/chromium/third_party/shaderc/src/android_test/test.cpp new file mode 100644 index 00000000000..23df9b8e372 --- /dev/null +++ b/chromium/third_party/shaderc/src/android_test/test.cpp @@ -0,0 +1,24 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "shaderc/shaderc.hpp" +#include <android_native_app_glue.h> + +void android_main(struct android_app* state) { + app_dummy(); + shaderc::Compiler compiler; + const char* test_program = "void main() {}"; + compiler.CompileGlslToSpv(test_program, strlen(test_program), + shaderc_glsl_vertex_shader, "shader"); +} diff --git a/chromium/third_party/shaderc/src/build_overrides/shaderc.gni b/chromium/third_party/shaderc/src/build_overrides/shaderc.gni new file mode 100644 index 00000000000..da034220b92 --- /dev/null +++ b/chromium/third_party/shaderc/src/build_overrides/shaderc.gni @@ -0,0 +1,19 @@ +# Copyright 2018 The Shaderc Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# These are variables that are overridable by projects that include shaderc. + +# The path to shaderc dependencies. +shaderc_glslang_dir = "//third_party/glslang" +shaderc_spirv_tools_dir = "//third_party/spirv-tools" diff --git a/chromium/third_party/shaderc/src/cmake/linux-mingw-toolchain.cmake b/chromium/third_party/shaderc/src/cmake/linux-mingw-toolchain.cmake new file mode 100644 index 00000000000..400b9a0b2d6 --- /dev/null +++ b/chromium/third_party/shaderc/src/cmake/linux-mingw-toolchain.cmake @@ -0,0 +1,21 @@ +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) +find_program(CMAKE_CXX_COMPILER NAMES ${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) diff --git a/chromium/third_party/shaderc/src/cmake/setup_build.cmake b/chromium/third_party/shaderc/src/cmake/setup_build.cmake new file mode 100644 index 00000000000..9d15428477a --- /dev/null +++ b/chromium/third_party/shaderc/src/cmake/setup_build.cmake @@ -0,0 +1,137 @@ +# Find nosetests; see shaderc_add_nosetests() from utils.cmake for opting in to +# nosetests in a specific directory. + +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_program(NOSETESTS_EXE NAMES nosetests PATHS $ENV{PYTHON_PACKAGE_PATH}) +if (NOT NOSETESTS_EXE) + message(STATUS "nosetests was not found - python code will not be tested") +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. +find_host_package(PythonInterp) +find_host_package(BISON) +endif() + +foreach(PROGRAM echo python) + string(TOUPPER ${PROGRAM} PROG_UC) + if (ANDROID) + find_host_program(${PROG_UC}_EXE ${PROGRAM} REQUIRED) + else() + find_program(${PROG_UC}_EXE ${PROGRAM} REQUIRED) + endif() +endforeach(PROGRAM) + +option(ENABLE_CODE_COVERAGE "Enable collecting code coverage." OFF) +if (ENABLE_CODE_COVERAGE) + 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_EXE} + ${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) diff --git a/chromium/third_party/shaderc/src/cmake/utils.cmake b/chromium/third_party/shaderc/src/cmake/utils.cmake new file mode 100644 index 00000000000..ed3c7333605 --- /dev/null +++ b/chromium/third_party/shaderc/src/cmake/utils.cmake @@ -0,0 +1,213 @@ +# 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}") + target_compile_options(${TARGET} PRIVATE -Wall -Werror -fvisibility=hidden) + if (NOT "${MINGW}") + 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() + +# Run nosetests on file ${PREFIX}_nosetest.py. Nosetests will look for classes +# and functions whose names start with "nosetest". The test name will be +# ${PREFIX}_nosetests. +function(shaderc_add_nosetests PREFIX) + if("${SHADERC_ENABLE_TESTS}" AND NOSETESTS_EXE) + add_test( + NAME ${PREFIX}_nosetests + COMMAND ${NOSETESTS_EXE} -m "^[Nn]ose[Tt]est" -v + ${CMAKE_CURRENT_SOURCE_DIR}/${PREFIX}_nosetest.py) + endif() +endfunction() + +# Adds a set of tests. +# This function accepts the following parameters: +# TEST_PREFIX: a prefix for each test target name +# 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") + list(INSERT ${out_list} 0 "${target}") + 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_STATIC_LIBRARY_PREFIX}${new_target}${CMAKE_STATIC_LIBRARY_SUFFIX}) + + if (CMAKE_CONFIGURATION_TYPES) + list(LENGTH CMAKE_CONFIGURATION_TYPES num_configurations) + if (${num_configurations} GREATER 1) + set(libname + ${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${new_target}${CMAKE_STATIC_LIBRARY_SUFFIX}) + endif() + endif() + + 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() diff --git a/chromium/third_party/shaderc/src/examples/CMakeLists.txt b/chromium/third_party/shaderc/src/examples/CMakeLists.txt new file mode 100644 index 00000000000..176c40b4c47 --- /dev/null +++ b/chromium/third_party/shaderc/src/examples/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(online-compile) diff --git a/chromium/third_party/shaderc/src/examples/online-compile/CMakeLists.txt b/chromium/third_party/shaderc/src/examples/online-compile/CMakeLists.txt new file mode 100644 index 00000000000..e4541e0c0e3 --- /dev/null +++ b/chromium/third_party/shaderc/src/examples/online-compile/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(shaderc-online-compile main.cc) +shaderc_default_compile_options(shaderc-online-compile) +target_link_libraries(shaderc-online-compile PRIVATE shaderc) diff --git a/chromium/third_party/shaderc/src/examples/online-compile/main.cc b/chromium/third_party/shaderc/src/examples/online-compile/main.cc new file mode 100644 index 00000000000..9e1ca5b6da3 --- /dev/null +++ b/chromium/third_party/shaderc/src/examples/online-compile/main.cc @@ -0,0 +1,171 @@ +// Copyright 2016 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The program demonstrates basic shader compilation using the Shaderc C++ API. +// For clarity, each method is deliberately self-contained. +// +// Techniques demonstrated: +// - Preprocessing GLSL source text +// - Compiling a shader to SPIR-V assembly text +// - Compliing a shader to a SPIR-V binary module +// - Performing optimization with compilation +// - Setting basic options: setting a preprocessor symbol. +// - Checking compilation status and extracting an error message. + +#include <cstring> +#include <iostream> +#include <string> +#include <vector> + +#include <shaderc/shaderc.hpp> + +// Returns GLSL shader source text after preprocessing. +std::string preprocess_shader(const std::string& source_name, + shaderc_shader_kind kind, + const std::string& source) { + shaderc::Compiler compiler; + shaderc::CompileOptions options; + + // Like -DMY_DEFINE=1 + options.AddMacroDefinition("MY_DEFINE", "1"); + + shaderc::PreprocessedSourceCompilationResult result = + compiler.PreprocessGlsl(source, kind, source_name.c_str(), options); + + if (result.GetCompilationStatus() != shaderc_compilation_status_success) { + std::cerr << result.GetErrorMessage(); + return ""; + } + + return {result.cbegin(), result.cend()}; +} + +// Compiles a shader to SPIR-V assembly. Returns the assembly text +// as a string. +std::string compile_file_to_assembly(const std::string& source_name, + shaderc_shader_kind kind, + const std::string& source, + bool optimize = false) { + shaderc::Compiler compiler; + shaderc::CompileOptions options; + + // Like -DMY_DEFINE=1 + options.AddMacroDefinition("MY_DEFINE", "1"); + if (optimize) options.SetOptimizationLevel(shaderc_optimization_level_size); + + shaderc::AssemblyCompilationResult result = compiler.CompileGlslToSpvAssembly( + source, kind, source_name.c_str(), options); + + if (result.GetCompilationStatus() != shaderc_compilation_status_success) { + std::cerr << result.GetErrorMessage(); + return ""; + } + + return {result.cbegin(), result.cend()}; +} + +// Compiles a shader to a SPIR-V binary. Returns the binary as +// a vector of 32-bit words. +std::vector<uint32_t> compile_file(const std::string& source_name, + shaderc_shader_kind kind, + const std::string& source, + bool optimize = false) { + shaderc::Compiler compiler; + shaderc::CompileOptions options; + + // Like -DMY_DEFINE=1 + options.AddMacroDefinition("MY_DEFINE", "1"); + if (optimize) options.SetOptimizationLevel(shaderc_optimization_level_size); + + shaderc::SpvCompilationResult module = + compiler.CompileGlslToSpv(source, kind, source_name.c_str(), options); + + if (module.GetCompilationStatus() != shaderc_compilation_status_success) { + std::cerr << module.GetErrorMessage(); + return std::vector<uint32_t>(); + } + + return {module.cbegin(), module.cend()}; +} + +int main() { + const char kShaderSource[] = + "#version 310 es\n" + "void main() { int x = MY_DEFINE; }\n"; + + { // Preprocessing + auto preprocessed = preprocess_shader( + "shader_src", shaderc_glsl_vertex_shader, kShaderSource); + std::cout << "Compiled a vertex shader resulting in preprocessed text:" + << std::endl + << preprocessed << std::endl; + } + + { // Compiling + auto assembly = compile_file_to_assembly( + "shader_src", shaderc_glsl_vertex_shader, kShaderSource); + std::cout << "SPIR-V assembly:" << std::endl << assembly << std::endl; + + auto spirv = + compile_file("shader_src", shaderc_glsl_vertex_shader, kShaderSource); + std::cout << "Compiled to a binary module with " << spirv.size() + << " words." << std::endl; + } + + { // Compiling with optimizing + auto assembly = + compile_file_to_assembly("shader_src", shaderc_glsl_vertex_shader, + kShaderSource, /* optimize = */ true); + std::cout << "Optimized SPIR-V assembly:" << std::endl + << assembly << std::endl; + + auto spirv = compile_file("shader_src", shaderc_glsl_vertex_shader, + kShaderSource, /* optimize = */ true); + std::cout << "Compiled to an optimized binary module with " << spirv.size() + << " words." << std::endl; + } + + { // Error case + const char kBadShaderSource[] = + "#version 310 es\nint main() { int main_should_be_void; }\n"; + + std::cout << std::endl << "Compiling a bad shader:" << std::endl; + compile_file("bad_src", shaderc_glsl_vertex_shader, kBadShaderSource); + } + + { // Compile using the C API. + std::cout << "\n\nCompiling with the C API" << std::endl; + + // The first example has a compilation problem. The second does not. + const char source[2][80] = {"void main() {}", "#version 450\nvoid main() {}"}; + + shaderc_compiler_t compiler = shaderc_compiler_initialize(); + for (int i = 0; i < 2; ++i) { + std::cout << " Source is:\n---\n" << source[i] << "\n---\n"; + shaderc_compilation_result_t result = shaderc_compile_into_spv( + compiler, source[i], std::strlen(source[i]), shaderc_glsl_vertex_shader, + "main.vert", "main", nullptr); + auto status = shaderc_result_get_compilation_status(result); + std::cout << " Result code " << int(status) << std::endl; + if (status != shaderc_compilation_status_success) { + std::cout << "error: " << shaderc_result_get_error_message(result) + << std::endl; + } + shaderc_result_release(result); + } + shaderc_compiler_release(compiler); + } + + return 0; +} diff --git a/chromium/third_party/shaderc/src/glslc/.clang-format b/chromium/third_party/shaderc/src/glslc/.clang-format new file mode 100644 index 00000000000..e209e8cb803 --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/.clang-format @@ -0,0 +1,5 @@ +--- +# Use Google code formatting rules. +Language: Cpp +BasedOnStyle: Google +... diff --git a/chromium/third_party/shaderc/src/glslc/CMakeLists.txt b/chromium/third_party/shaderc/src/glslc/CMakeLists.txt new file mode 100644 index 00000000000..acf6fb0b262 --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/CMakeLists.txt @@ -0,0 +1,46 @@ +find_package(Threads) + +add_library(glslc STATIC + src/file_compiler.cc + src/file_compiler.h + src/file.cc + src/file.h + src/file_includer.cc + src/file_includer.h + src/resource_parse.h + src/resource_parse.cc + src/shader_stage.cc + src/shader_stage.h + src/dependency_info.cc + src/dependency_info.h +) + +shaderc_default_compile_options(glslc) +target_include_directories(glslc PUBLIC ${glslang_SOURCE_DIR}) +target_link_libraries(glslc PRIVATE glslang OSDependent OGLCompiler + HLSL glslang SPIRV ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(glslc PRIVATE shaderc_util shaderc) + +add_executable(glslc_exe src/main.cc) +shaderc_default_compile_options(glslc_exe) +target_include_directories(glslc_exe PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/.. ${spirv-tools_SOURCE_DIR}/include) +set_target_properties(glslc_exe PROPERTIES OUTPUT_NAME glslc) +target_link_libraries(glslc_exe PRIVATE glslc shaderc_util shaderc) +add_dependencies(glslc_exe build-version) + +shaderc_add_tests( + TEST_PREFIX glslc + LINK_LIBS glslc shaderc_util shaderc + TEST_NAMES + file + resource_parse + stage) + +shaderc_add_asciidoc(glslc_doc_README README) + +if(SHADERC_ENABLE_INSTALL) + install(TARGETS glslc_exe + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif(SHADERC_ENABLE_INSTALL) + +add_subdirectory(test) diff --git a/chromium/third_party/shaderc/src/glslc/README.asciidoc b/chromium/third_party/shaderc/src/glslc/README.asciidoc new file mode 100644 index 00000000000..0716be95ab8 --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/README.asciidoc @@ -0,0 +1,691 @@ += glslc Manual +:toc: +:toclevels: 3 +:numbered: +:source-highlighter: pygments + +== Name + +`glslc` - A command-line GLSL/HLSL to SPIR-V compiler with +Clang-compatible arguments. + +== Synopsis + +---- +glslc [--help] + +glslc [--show-limits] + +glslc [-c|-S|-E] + [-x ...] [-std=standard] + [ ... options for resource bindings ... ] + [-fhlsl-offsets] + [-fhlsl-functionality1] + [-fentry-point=<name>] + [-fauto-map-locations] + [-flimit=...] + [-flimit-file <resource-limits-file>] + [-fshader-stage=...] + [--target-env=...] + [-g] + [-O0|-Os] + [-Idirectory...] + [-Dmacroname[=value]...] + [-w] [-Werror] + [-o outfile] + shader... +---- + +== Description + +=== Input file languages + +glslc accepts both GLSL/HLSL source and SPIR-V assembly files as inputs. + +==== Shader stage specification + +glslc provides three ways to specify the shader stage of a GLSL source file: +`-fshader-stage=<stage>`, `#pragma shader_stage(<stage>)`, and file extension. +The `-fshader-stage=` option overrides `#pragma shader_stage()`, which overrides +the file extension. + +Shader stages can be specified by naming a file with an appropriate extension +as shown in the following table. `-fshader-stage=` and `#pragma shader_stage()`, +on the other hand, enable you to specify shader stages from the command line +and within the source file. Possible ``stage``s for them are also listed in +the following table. Details about `-fshader-stage=` can be found in +<<option-fshader-stage,its own section>>. + +[[shader-stage-selection]] +.Shader Stage Selection +|=== +|Shader Stage |Shader File Extension |`<stage>` + +|vertex |`.vert` |`vertex` +|fragment |`.frag` |`fragment` +|tesselation control |`.tesc` |`tesscontrol` +|tesselation evaluation |`.tese` |`tesseval` +|geometry |`.geom` |`geometry` +|compute |`.comp` |`compute` +|=== + +`#pragma shader_stage()` relies on the `#pragma` preprocessor directive; thus, +the token inside `shader_stage()` is not subject to preprocessor macro +expansion. It must be exactly one of the ``stage``s in the above table. + +`#pragma shader_stage()` behaves as follows: + +* The first `#pragma shader_stage()` directive in a translation unit must + precede any non-preprocessor tokens. +* If there is more than one `#pragma shader_stage()` directive in the same + translation unit, all the ``stage``s specified must be the same. Otherwise, + glslc will issue an error. + +==== SPIR-V assembly files + +SPIR-V assembly input files should follow the +https://github.com/KhronosGroup/SPIRV-Tools/blob/master/syntax.md[syntax] +defined in the https://github.com/KhronosGroup/SPIRV-Tools[SPIRV-Tools] +project and have the `.spvasm` extension. Command line options treat SPIR-V +assembly files differently; some may ignore them, e.g., `<<option-cap-e,-E>>`, +`<<option-cap-s,-S>>`, and some may even treat them not as SPIR-V assembly +files, e.g., `<<shader-stage-with-spirv-assembly,-fshader-stage\=>>`. + +[[output-file-naming]] +=== Output file naming + +If a name is specified via `-o`, the output file will be given that name. +Otherwise, + +* If a compilation stage selection option is given (`-S` or `-c`), there will + be one output file generated per input shader file. The generated output file + will end with a file extension that matches the compilation stage, which is + `.spvasm` for `-S` and `.spv` for `-c`. The name will depend on the original + file's name and extension. +** If the input file has a <<shader-stage-selection,shader stage selection + extension>>, the output file will be named as by appending the file extension + for the compilation stage to the input file's name. E.g., `glslc -c foo.vert` + will generate `foo.vert.spv`, and `glslc -s bar.frag` will generate + `bar.frag.spvasm`. +** Otherwise, the output file will be named as by replacing the input file's + file extension, if any, with the file extension for the compilation stage. + E.g., `glslc -c foo` will generate `foo.spv`, and `glslc -s bar.glsl` will + generate `bar.spvasm`. +* If no compilation stage is selected, the output file will be named `a.spv`. + +== Command Line Options + +=== Overall Options + +==== `--help` + +`--help` tells the glslc compiler to display all available options and exit. + +==== `--show-limits` + +`--show-limits` shows default resource limits for shader compilation. The syntax +is the same as accepted by `-flimit=` and for the contents of the file specified +by `-flimit-file`. + +==== `-o` + +`-o` lets you specify the output file's name. It cannot be used when there are +multiple files generated. A filename of `-` represents standard output. + +=== Language and Mode Selection Options + +[[option-flimit]] +==== `-flimit=` + +`-flimit=<resource-limits>` lets you specify resource limits. +The argument should be a sequence of limit name, integer value pairs. Tokens +should be separated by whitespace. If the same limit is specified several +times, only the last setting takes effect. + +Use `--show-limits` to show the default values, and example syntax. + +This option affects all compiled shaders. + +[[option-flimit-file]] +==== `-flimit-file` + +`-flimit-file <resource-limits-file>` lets you specify resource limits in a file. +The syntax of the file contents is the same as the argument to `-flimit=` and +the output of `--show-limits`. This option accepts Glslang resource configuration +files, e.g. as emitted by `glslangValidator -c`. + +This option affects all compiled shaders. + +[[option-fshader-stage]] +==== `-fshader-stage=` + +`-fshader-stage=<stage>` lets you specify the shader stage for one or more +inputs from the command line. + +Possible values for ``<stage>`` are listed in the <<shader-stage-selection, +Shader Stage Selection>> table. + +`-fshader-stage=` behaves as follows: + +* `-fshader-stage=` sets the shader stage for subsequent input files. It does + not affect the stages of any preceding inputs on the command line. +* When supplying more than one `-fshader-stage=` argument, the most recent + argument preceding an input file applies. +* A shader file not ending with <<shader-stage-selection,known shader file + extensions>> must have a `-fshader-stage=` argument ahead of it to specify + its stage. +* If there is a `-fshader-stage=` before a file in which there is a `#pragma + shader_stage()` directive, the directive is ignored and the `-fshader-stage=` + argument is used instead. +* If there is a `-fshader-stage=` before a file with a known shader file + extension, the file extension is ignored and the `-fshader-stage=` argument + is used instead. + +[[shader-stage-with-spirv-assembly]] +CAUTION: `-fshader-stage=` overrides file extension; that means it should not +be used together with SPIR-V assembly files because glslc will treat the given +SPIR-V assembly files as GLSL source code of the given shader stage. If you +need to supply both SPIR-V assembly files and `-fshader-stage=` on the same +command line, please put SPIR-V assembly files ahead of the first +`-fshader-stage=`, since `-fshader-stage=` only affects the treatment of +subsequent files. + +==== `-std=` + +`-std=<value>` lets you specify a shader version and profile on the command +line. ``<value>`` can be any valid concatenation of a GLSL version number and +profile, e.g., `310es`, `450core`, etc. The profile can be omitted as allowed by +GLSL, e.g., `450`. + +`-std=` behaves as follows: + +* `-std=` affects the version of all GLSL inputs passed to `glslc`. +* `-std=` is ignored for HLSL inputs. +* `-std=` overwrites `#version` directives in all input shaders, including those + preceding the argument. +* If a `-std=` argument specifies a different version from a `#version` + directive in an input file, `glslc` will issue a warning. +* If multiple `-std=` arguments are specified on the command line, only the last + one takes effect. + +CAUTION: `-std=` does not affect the `#version` directive in the preprocessed +output. That is, when `-std=` specifies a version different from the shader +source code, the `#version` directive in preprocessed output will still be the +one in the source code. But `-std=` does affect the behavior of `#line` +directives in the preprocessed output. Behavior of `#line` directives will +follow the version specified by `-std=`. + +==== `--target-env=` + +`--target-env=<value>` lets you specify a target environment on the command line. +This affects the generation of warnings and errors. The ``<value>`` can be one of +the following: + +* `vulkan`: create SPIR-V under Vulkan 1.0 semantics. +* `vulkan1.0`: create SPIR-V under Vulkan 1.0 semantics. +* `vulkan1.1`: create SPIR-V under Vulkan 1.1 semantics. +* `opengl`: create SPIR-V under OpenGL 4.5 semantics. +* `opengl4.5`: create SPIR-V under OpenGL 4.5 semantics. +* `opengl_compat`: create SPIR-V under OpenGL semantics, including compatibility + profile functions. + +Generated code uses SPIR-V 1.0, except that code compiled for Vulkan 1.1 uses SPIR-V 1.3. + +If this option is not specified, a default of `vulkan1.0` is used. + +==== `-x` + +`-x` lets you specify the language of the input shader files. Valid languages +are `glsl` and `hlsl`. If the file extension is `hlsl` then the default language +is HLSL. Otherwise the default is 'glsl'. + +Note: HLSL compilation will use HLSL packing (offset) rules for variables +that are vertex shader outputs, and inputs and outputs of both geometry +and pixel shaders. + +[[compilation-stage-selection-options]] +=== Compilation Stage Selection Options + +==== `-c` + +`-c` tells the glslc compiler to run the preprocessing and compiling stage. +Each input shader file results in a SPIR-V binary file; these SPIR-V binary +files are named by the rules in the <<output-file-naming,Output File Naming>> +section. + +[[option-cap-e]] +==== `-E` + +`-E` tells the glslc compiler to run only the preprocessing stage. It overrides +`-c` and `-S`. Preprocessed output is written to standard output, while +preprocessing errors are written to standard error. If multiple input shader +files are given, their preprocessed output are all written to standard output, +in the order specified on the command line. + +glslc will do nothing for SPIR-V assembly files with this option. + +[[option-cap-s]] +==== `-S` + +`-S` tells the glslc compiler to run the preprocessing, compiling, and then +disassembling stage. It overrides `-c`. Each input shader file results in a +SPIR-V assembly file; these SPIR-V assembly files are named by the rules in the +<<output-file-naming,Output File Naming>> section. + +glslc will do nothing for SPIR-V assembly files with this option. + +==== No Compilation Stage Selection + +If none of the above options is given, the glslc compiler will run +preprocessing, compiling, and linking stages. + +WARNING: Linking of multiple input shader files are not supported yet. + +=== Preprocessor Options + +==== `-D` + +`-Dmacroname[=[value]]` lets you define a preprocessor macro before input shader +files are preprocessed. If `value` is omitted, the macro is defined with an +empty value. + +==== `-I` + +`-Idirectory` or `-I directory` adds the specified directory to the search path +for include files. The directory may be an absolute path or a relative path to +the current working directory. + +=== Code Generation Options + +==== `-g` + +Requests that the compiler place source-level debug information into the object +code, such as identifier names and line numbers. + +This option restrains `-O` from turning on the strip-debug-info optimization +pass. + +NOTE: Currently this option has no effect. Full functionality depends on +glslang support for generating debug info. + +==== `-O0`, `-Os` + +`-O` specifies which optimization level to use: + +* `-O0` means "no optimization". This level generates the most debuggable code. +* `-O` means the default optimization level for better performance. +* `-Os` enables optimizations to reduce code size. + +==== `-mfmt=<format>` + +`-mfmt=<format>` selects output format for compilation output in SPIR-V binary +code form. Supported options are listed in the +<<binary-output-format-options,binary output format options>> table. This +option is only valid to be used when the compilation output is SPIR-V binary +code. Specifying any options listed below when the output is not SPIR-V binary +code, like disassembly (with `-S` specified), text (with `-M`, `-MM` or `-E` +specified) will trigger an error. + +[[binary-output-format-options]] +.Binary Output Format Options +[cols="20%,80%"] +|=== +|Format option |Description + +|bin |Output SPIR-V binary code as a sequence of binary 32-bitwords + in host native endianness. This is the default format for + SPIR-V binary compilation output. +|num |Output SPIR-V binary code as a text file containing a list of + comma-separated hex numbers. + + Example: `glslc -c -mfmt=num main.vert -o output_file.txt` + + Content of the output_file.txt: + + 0x07230203,0x00010000,0x00080001,0x00000006... +|c |Output SPIR-V binary code as a text file containing C-style + + initializer list. + + This is just wrapping the output of `num` option with curly + brackets. + + Example: `glslc -c -mfmt=c main.vert -o output_file.txt` + + Content of output_file.txt: + + {0x07230203, 0x00010000, 0x00080001, 0x00000006...} +|=== + +[[option-fhlsl-offsets]] +==== `-fhlsl-offsets` + +Use HLSL packing rules instead of GLSL rules when determining offsets of +members of blocks. This option is always on when compiling for HLSL. + +[[option-fhlsl-functionality1]] +==== `-fhlsl-functionality1` + +Enable extension `SPV_GOOGLE_hlsl_functionality1`, and instructs the compiler +to: + +- Annotate HLSL semantic string decorations on interface objects +- Explicitly record the association of a UAV resource with its companion counter buffer. + +This option can also be spelled with an underscore: `-fhlsl_functionality1`. + +[[option-fentry-point]] +==== `-fentry-point=<name>` + +`-fentry-point=<name>` lets you specify the entry point name. This is only +significant for HLSL compilation. The default is "main". + +[[option-fauto-map-locations]] +==== `-fauto-map-locations` + +For GLSL compilation, option `-fauto-map-locations` directs the compiler to automatically +assign location numbers to user-defined stage input and output variables if not explicitly +specified by the shader source. + +For HLSL compilation, this option is on by default. + +Client APIs normally require adjacent stages to agree on their I/O interface. +The compiler only sees one stage at a time, so it is strongly recommended that +you avoid relying on this option to assign locations. + +Instead, an explicit binding number should be specified in the shader source, as follows: + +* In a GLSL shader, use a `location` layout qualifier: + +---- +layout(location = 1) in vec4 x; +---- + +* In an HLSL shader, use a `vk::location` attribute: + +---- +[[vk::location(1)]] float4 FooShader( + [[vk::location(0)]] float4 a, + [[vk::location(2)]] float4 b) : COLOR0 { + return a + b; +} +---- + +=== Warning and Error Options + +==== `-w` + +`-w` suppresses all warning output from `glslc`. Any warning that would have +been generated is silently ignored. + +==== `-Werror` + +`-Werror` forces any warning to be treated as an error in `glslc`. This means +that all `warning:` messages are shown as `error:` and any warnings will cause +a non-zero exit code from `glslc`. If `-w` is specified the warnings +generated are suppressed before they are converted to errors. + +=== Dependency Generation Options + +==== `-M` or `-MM` + +`-M` generates *make* dependencies. It outputs a rule suitable for *make* +describing the dependencies of the input file. Instead of outputting the result +of preprocessing, the preprocessor outputs one *make* rule containing the +SPIR-V object file name for that source file, a colon, and the names of all the +included files. + +Unless specified explicitly (with `-MT`), the SPIR-V object file name in the +generated *make* rules follows the rules of <<output-file-naming,Output File +Naming>> as in `-c` compilation stage. + +Specifying `-M` implies `-E`, and suppresses warnings with an implicit `-w`. +By default the output will be written to stdout, unless `-MF` or `-o` is +specified. + +The dependency info file name can be specified by `-o` and `-MF` options. When +both are specified, `-o` option is ignored. + +Specifying multiple input files is valid when the *make* rules are written to +stdout, which means neither `-MF` nor `-o` is specified. When `-o` or `-MF` is +specified, only one input file is allowed. + +`-MM` is an alias for `-M`. + +E.g., `glslc -M main.vert` will dump `main.vert.spv: main.vert <other included +files>` to stdout. More examples are listed in +<<dependency-generation-examples,Dependency Generation Examples>> + +==== `-MD` + +`-MD` tells the glslc compiler to both compile the source and generate *make* +dependencies. Dependencies are written to a file whose name is determined as +follows: If option `-MF` is specified, use its argument. Otherwise, use the +filename formed by appending *.d* to the name of the file containing +compilation results. + +Specifying multiple input files is valid when neither `-MF` nor `-o` is +specified. When `-o` or `-MF` is specified, only one input file is allowed. + +E.g., `glslc -c -MD main.vert` will generate `main.vert.spv` as the SPIR-V +object file and `main.vert.spv.d` as the dependency info file. More examples +are listed in <<dependency-generation-examples,Dependency Generation Examples>> + +==== `-MF` + +`-MF` lets you specify the dependency info file name when used with `-M` or +`-MD`. This option is invalid when used with multiple input files. + +E.g., `glslc -c -MD main.vert -MF dep_info` will generate `main.vert.spv` as +the SPIR-V object file and `dep_info` as the dependency info file. + +==== `-MT` + +`-MT` lets you specify the target of the rule emitted by dependency generation +when used with `-M` or `-MD`. This option is invalid when used with multiple +input files. + +E.g., `glslc -M main.vert -MT target` will dump following dependency info to +stdout: `target: main.vert <other dependent files>`. + +[[dependency-generation-examples]] +.Dependency Generation Examples +|=== +|Command Line Input|Compilation Output File|Dependency Output File|Dependency Info + +|glslc -M main.vert | <NA> | <Stdout> | main.vert.spv: main.vert +.2+|glslc -M a.vert b.vert | <NA> | <Stdout> | a.vert.spv: a.vert + | <NA> | <Stdout> | b.vert.spv: b.vert +|glslc -M main.vert -o dep_info | <NA> | dep_info | main.vert.spv: main.vert +|glslc -M main.vert -MF dep_info| <NA> | dep_info | main.vert.spv: main.vert +|glslc -M main.vert -MT target | <NA> | <Stdout> | target: main.vert +|glslc -MD main.vert |a.spv |main.vert.spv.d|main.vert.spv: main.vert +|glslc -c -MD main.vert |main.vert.spv|main.vert.spv.d|main.vert.spv: main.vert +.2+|glslc -c -MD a.vert b.vert | a.vert.spv | a.vert.spv.d | a.vert.spv: a.vert + | b.vert.spv | b.vert.spv.d | b.vert.spv: b.vert +|glslc -S -MD main.vert |main.vert.spvasm |main.vert.spvasm.d |main.vert.spvasm: main.vert +|glslc -c -MD main.vert -MF dep_info |main.vert.spv|dep_info|main.vert.spv: main.vert +|glslc -c -MD main.vert -o obj |obj |obj.d |obj: main.vert +|glslc -c -MD main.vert -o obj -MF dep_info -MT target|obj|dep_info|target: main.vert +|=== + +=== Resource Binding Options + +[[option-fauto-bind-uniforms]] +==== `-fauto-bind-uniforms` + +Option `-fauto-bind-uniforms` directs the compiler to automatically assign +binding numbers to uniform variables, when an explicit binding is not +specified in the shader source. + +An explicit binding number can be specified in the shader source by using +a `binding` layout qualifier. For example: + +---- +layout(binding = 12) uniform texture2D; +---- + +[[option-fhlsl-iomap]] +==== `-fhlsl-iomap` + +Option `-fhlsl-iomap` directs the compiler to use HLSL register +assignments as binding values. + +[[option-fimage-binding-base]] +==== `-fimage-binding-base` + +Option `-fimage-binding-base [stage] base` sets the lowest automatically +assigned binding for images. If a stage is specified, only affects the specified +stage. + +For HLSL, sets one less than the base. + +[[option-fsampler-binding-base]] +==== `-fsampler-binding-base` + +Option `-fsampler-binding-base [stage] base` sets the lowest automatically +assigned binding for samplers. If a stage is specified, only affects the specified +stage. + +For HLSL, sets one less than the base. + +[[option-ftexture-binding-base]] +==== `-ftexture-binding-base` + +Option `-ftexture-binding-base [stage] base` sets the lowest automatically +assigned binding for textures. If a stage is specified, only affects the specified +stage. + +For HLSL, sets one less than the base. + +[[option-fubo-binding-base]] +==== `-fubo-binding-base` + +Option `-fubo-binding-base [stage] base` sets the lowest automatically +assigned binding for Uniform Buffer Objects (GLSL) or Cbuffers (HLSL). +If a stage is specified, only affects the specified stage. + +For HLSL, sets one less than the base. + +[[option-fcbuffer-binding-base]] +==== `-fcbuffer-binding-base` + +Option `-fcbuffer-binding-base [stage] base` is the same as +`-fubo-binding-base [stage] base`. + +[[option-fssbo-binding-base]] +==== `-fssbo-binding-base` + +Option `-fssbo-binding-base [stage] base` sets the lowest automatically +assigned binding for Shader Storage Buffer Objects (GLSL). +If a stage is specified, only affects the specified stage. + +This only affects GLSL compilation. + +[[option-fuav-binding-base]] +==== `-fuav-binding-base` + +Option `-fuav-binding-base [stage] base` sets one less than the lowest +automatically assigned binding for Unordered Access Views (UAV). +If a stage is specified, only affects the specified stage. + +This only affects HLSL compilation. + +[[option-fregister-set-binding]] +==== `-fresource-set-binding` + +Option `-fresource-set-binding [stage] <reg0> <set0> <binding0>` sets +the descriptor set and binding for an HLSL resource, by register name. +To specify settings for more registers, append their triples consisting +of register name, descriptor set, and binding. + +Example: + +---- +# For a texture in register t1, use set 1 binding 0. +# For a texture in register t2, use set 1 binding 3 +glslc -x hlsl foo.frag -fresource-set-binding t1 1 0 t2 1 3 +---- + +If a stage is specified, only affects the specified stage. + +---- +# Same as the previous example, but the settings only apply +# to fragment (pixel) shaders. +glslc -x hlsl foo.frag -fresource-set-binding frag t1 1 0 t2 1 3 +---- + + +== Divergence from and extensions to GLSL specifications + +=== Source-filename-based `#line` and `\\__FILE__` + +This section describes how the glslc compiler extends the syntax for the `#line` +directive and the `\\__FILE__` macro. By default, the glslc compiler enables +the `GL_GOOGLE_cpp_style_line_directive` extension. It will generate this +extended syntax in the preprocessed output (obtained via the `-E` option). + +WARNING: This section is still evolving. Expect changes. + +GLSL specifications have a notion of source strings. + +[quote, Section 3.2 of both version 3.30 and 4.50] +____ +The source for a single shader is an array of strings of characters from the +character set. A single shader is made from the concatenation of these strings. +____ + +With the above notion, the second parameter to the `#line` directive should +be a constant integer expressions representing the source string number. Also +the `\\__FILE__` macro will "substitute a decimal integer constant that says +which source string number is currently being processed." + +The glslc compiler implements the standard `#line` and `\\__FILE__` syntax. It +also provides an extension, `GL_GOOGLE_cpp_style_line_directive`, to allow +source filenames to be used instead of integer source string indices. +Specifically, the `#line` directive can have, after macro substitution, one of +the following three forms: + +[source,glsl] +---- +#line line-number +#line line-number integer-source-string-index +#line line-number "source-filename" +---- + +where `source-filename` can be any combinations of characters except double +quotation marks. (Note that according to the GLSL specification, "there are +no escape sequences or other uses of the backslash beyond use as the +line-continuation character".) + +And if source-filename-based `#line` is used, the `\\__FILE__` macro expands to +a string whose contents are the filename quoted with double quotation marks. +The filename is dertermined as the last of + +* The filename given to the glslc compiler, +* The filename argument of the most recent `#line` directive, if any. + +[[include-directive]] +=== `#include` + +The glslc compiler extends GLSL with the include syntax by turning on the +`GL_GOOGLE_include_directive` extension. It will preprocess and substitute +`#include` directives properly with the following behaviors. + +WARNING: This section is still evolving. Expect changes. + +If `#include` directives are used in a shader, there will be an `#extension +GL_GOOGLE_include_directive : enable` line generated into the preprocessed +output. + +The `GL_GOOGLE_cpp_style_line_directive` extension is implicitly turned on by +the `GL_GOOGLE_include_directive` extension. + +The file argument to `#include` must be enclosed in double quotes. It must be a +relative path, using whatever path separator the OS supports. However, the last +path element -- the name of the file itself -- must not contain either '/' or +'\', regardless of which path separator is used. This will not be flagged as an +error but will instead trigger undefined behavior. For example, let's say there +is a file named `f\ilename.vert` on a Unix OS. It is not possible to craft a +`#include` that includes that file. + +Furthermore, it is not possible to escape any characters in a `#include` +directive, so the file argument cannot contain any special characters that need +escaping in C. + +The file argument is a relative path that is matched first against the including +file's own directory and then against all `-I` arguments in order of their +appearance on the command line. If the file cannot be found, `glslc` aborts +with an error. diff --git a/chromium/third_party/shaderc/src/glslc/src/dependency_info.cc b/chromium/third_party/shaderc/src/glslc/src/dependency_info.cc new file mode 100644 index 00000000000..26226291e96 --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/dependency_info.cc @@ -0,0 +1,104 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dependency_info.h" + +#include <fstream> +#include <iostream> +#include <sstream> + +#include "file.h" +#include "libshaderc_util/io.h" + +namespace glslc { + +DependencyInfoDumpingHandler::DependencyInfoDumpingHandler() : mode_(not_set) {} + +bool DependencyInfoDumpingHandler::DumpDependencyInfo( + std::string compilation_output_file_name, std::string source_file_name, + std::string* compilation_output_ptr, + const std::unordered_set<std::string>& dependent_files) { + std::string dep_target_label = GetTarget(compilation_output_file_name); + std::string dep_file_name = + GetDependencyFileName(compilation_output_file_name); + + // Dump everything to a string stream first, then dump its content to either + // a file or compilation output string, depends on current dumping mode. + std::stringstream dep_string_stream; + // dump target label and the source_file_name. + dep_string_stream << dep_target_label << ": " << source_file_name; + // dump the dependent file names. + for (auto& dependent_file_name : dependent_files) { + dep_string_stream << " " << dependent_file_name; + } + dep_string_stream << std::endl; + + if (mode_ == dump_as_compilation_output) { + compilation_output_ptr->assign(dep_string_stream.str()); + } else if (mode_ == dump_as_extra_file) { + std::ofstream potential_file_stream_for_dep_info_dump; + std::ostream* dep_file_stream = shaderc_util::GetOutputStream( + dep_file_name, &potential_file_stream_for_dep_info_dump, &std::cerr); + *dep_file_stream << dep_string_stream.str(); + if (dep_file_stream->fail()) { + std::cerr << "glslc: error: error writing dependent_files info to output " + "file: '" + << dep_file_name << "'" << std::endl; + return false; + } + } else { + // mode_ should not be 'not_set', we should never be here. + return false; + } + return true; +} + +std::string DependencyInfoDumpingHandler::GetTarget( + const std::string& compilation_output_file_name) { + if (!user_specified_dep_target_label_.empty()) { + return user_specified_dep_target_label_; + } + + return compilation_output_file_name; +} + +std::string DependencyInfoDumpingHandler::GetDependencyFileName( + const std::string& compilation_output_file_name) { + if (!user_specified_dep_file_name_.empty()) { + return user_specified_dep_file_name_; + } + + return compilation_output_file_name + ".d"; +} + +bool DependencyInfoDumpingHandler::IsValid(std::string* error_msg_ptr, + size_t num_files) { + if (DumpingModeNotSet()) { + *error_msg_ptr = + "to generate dependencies you must specify either -M (-MM) or -MD"; + return false; + } + + if (!user_specified_dep_file_name_.empty() || + !user_specified_dep_target_label_.empty()) { + if (num_files > 1) { + *error_msg_ptr = + "to specify dependency info file name or dependency info target, " + "only one input file is allowed."; + return false; + } + } + return true; +} +} diff --git a/chromium/third_party/shaderc/src/glslc/src/dependency_info.h b/chromium/third_party/shaderc/src/glslc/src/dependency_info.h new file mode 100644 index 00000000000..b0b47568b8e --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/dependency_info.h @@ -0,0 +1,136 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef GLSLC_DEPENDENCY_INFO_H +#define GLSLC_DEPENDENCY_INFO_H + +#include <unordered_set> +#include <string> +#include <string> + +namespace glslc { + +// An object to handle everything about dumping dependency info. Internally it +// has two valid dumping mode: 1) Dump to extra dependency info files, such as +// *.d files. This mode is used when we want to generate dependency info and +// also compile. 2) Overwrite the original compilation output and dump +// dependency info as compilation output. This mode is used when we do not want +// to compile the source code and want the dependency info only. +class DependencyInfoDumpingHandler { + public: + DependencyInfoDumpingHandler(); + + // Sets the dependency target explicitly. It's the same as the argument to + // -MT. + void SetTarget(const std::string& target_label) { + user_specified_dep_target_label_ = target_label; + } + + // Sets the name of the file where dependency info will be written. + void SetDependencyFileName(const std::string& dep_file_name) { + user_specified_dep_file_name_ = dep_file_name; + }; + + // Dump depdendency info to a) an extra dependency info file, b) an string + // which holds the compilation output. The choice depends on the dump + // mode of the handler. Returns true if dumping is succeeded, false otherwise. + // + // The dependency file name and target are deduced based on 1) user + // specified dependency file name and target name, 2) the output filename when + // the compiler is in 'does not need linking' and 'not preprocessing-only' + // mode. It is passed through compilation_output_file_name. + // + // When the handler is set to dump dependency info as extra dependency info + // files, this method will open a file with the dependency file name and write + // the dependency info to it. Error messages caused by writing to the file are + // emitted to stderr. + // + // When the handler is set to dump dependency info as compilation output, the + // compilation output string, which is passed through compilation_output_ptr, + // will be cleared and this method will write dependency info to it. Then the + // dependency info should be emitted as normal compilation output. + // + // If the dump mode is not set when this method is called, return false. + bool DumpDependencyInfo(std::string compilation_output_file_name, + std::string source_file_name, + std::string* compilation_output_ptr, + const std::unordered_set<std::string>& dependent_files); + + // Sets to always dump dependency info as an extra file, instead of the normal + // compilation output. This means the output name specified by -o options + // won't be used for the dependency info file. + void SetDumpToExtraDependencyInfoFiles() { mode_ = dump_as_extra_file; }; + + // Sets to dump dependency info as normal compilation output. The dependency + // info will be either saved in a file with -o option specified file, or, if + // no output file name specified, to stdout. + void SetDumpAsNormalCompilationOutput() { + mode_ = dump_as_compilation_output; + } + + // Returns true if the handler's dumping mode is set to dump dependency info + // as extra dependency info files. + bool DumpingToExtraDependencyInfoFiles() { + return mode_ == dump_as_extra_file; + } + + // Returns true if the handler's dumping mode is set to dump dependency info + // as normal compilation output. + bool DumpingAsCompilationOutput() { + return mode_ == dump_as_compilation_output; + } + + // Returns true if the handler's dumping mode is not set. + bool DumpingModeNotSet() { return mode_ == not_set; } + + // Returns true if the handler is at valid state for dumping dependency info. + bool IsValid(std::string* error_msg_ptr, size_t num_files); + + private: + typedef enum { + // not_set mode tells that the dumping mode is not set yet, so the handler + // is not ready for dumping dependency info. Calling DumpDependencyInfo when + // the handler is in this mode will cause failure. + not_set = 0, + // Dumping dependency info as normal compilation output mode. In this mode, + // the dependency info will be dumped as compilation output by overwriting + // the string which holds the compilation output. + dump_as_compilation_output, + // Dumping dependency info as extra dependency info files mode. In this + // mode, dependency info will be dumped to a user specified dependency info + // file or a *.d file. Compilation output will still be generated along with + // the dependency info. + dump_as_extra_file, + } dump_mode; + + // Returns the target file label to be used in depdendency info file. If -MT + // defined a label, use that string as the label. Otherwise returns the + // compilation output filename deduced in 'doesn't need linking' and 'not + // preprocessing-only' mode. + std::string GetTarget(const std::string& compilation_output_file_name); + + // Returns the dependency file name to be used. If -MF defined a file name + // before, use it. Othwise, returns a filename formed by appending .d to the + // output filename deduced in 'doesn't need linking' and 'no + // preprocessing-only' mode. + std::string GetDependencyFileName( + const std::string& compilation_output_file_name); + + std::string user_specified_dep_file_name_; + std::string user_specified_dep_target_label_; + dump_mode mode_; +}; +} + +#endif // GLSLC_DEPENDENCY_INFO_H diff --git a/chromium/third_party/shaderc/src/glslc/src/file.cc b/chromium/third_party/shaderc/src/glslc/src/file.cc new file mode 100644 index 00000000000..0d1b74aac01 --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/file.cc @@ -0,0 +1,26 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "file.h" + +namespace glslc { + +shaderc_util::string_piece GetFileExtension( + const shaderc_util::string_piece& filename) { + size_t dot_pos = filename.find_last_of("."); + if (dot_pos == shaderc_util::string_piece::npos) return ""; + return filename.substr(dot_pos + 1); +} + +} // namespace glslc diff --git a/chromium/third_party/shaderc/src/glslc/src/file.h b/chromium/third_party/shaderc/src/glslc/src/file.h new file mode 100644 index 00000000000..902b4cf7e3d --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/file.h @@ -0,0 +1,46 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef GLSLC_FILE_H_ +#define GLSLC_FILE_H_ + +#include "libshaderc_util/string_piece.h" + +namespace glslc { + +// Given a file name, returns its extension. If no extension exists, +// returns an empty string_piece. +shaderc_util::string_piece GetFileExtension( + const shaderc_util::string_piece& filename); + +// Returns true if the given file name ends with a known shader file extension. +inline bool IsStageFile(const shaderc_util::string_piece& filename) { + const shaderc_util::string_piece extension = + glslc::GetFileExtension(filename); + return extension == "vert" || extension == "frag" || extension == "tesc" || + extension == "tese" || extension == "geom" || extension == "comp"; +} + +// Returns the file extension if is either "glsl" or "hlsl", or an empty +// string otherwise. +inline std::string GetGlslOrHlslExtension( + const shaderc_util::string_piece& filename) { + auto extension = glslc::GetFileExtension(filename); + if ((extension == "glsl") || (extension == "hlsl")) return extension.str(); + return ""; +} + +} // namespace glslc + +#endif // GLSLC_FILE_H_ diff --git a/chromium/third_party/shaderc/src/glslc/src/file_compiler.cc b/chromium/third_party/shaderc/src/glslc/src/file_compiler.cc new file mode 100644 index 00000000000..839cc6eebcd --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/file_compiler.cc @@ -0,0 +1,398 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "file_compiler.h" + +#include <cassert> +#include <fstream> +#include <iomanip> +#include <iostream> +#include <sstream> + +#include "file.h" +#include "file_includer.h" +#include "shader_stage.h" + +#include "libshaderc_util/io.h" +#include "libshaderc_util/message.h" + +namespace { +using shaderc_util::string_piece; + +// A helper function to emit SPIR-V binary code as a list of hex numbers in +// text form. Returns true if a non-empty compilation result is emitted +// successfully. Return false if nothing should be emitted, either because the +// compilation result is empty, or the compilation output is not SPIR-V binary +// code. +template <typename CompilationResultType> +bool EmitSpirvBinaryAsCommaSeparatedNumbers(const CompilationResultType& result, + std::ostream* out) { + // Return early if the compilation output is not in SPIR-V binary code form. + if (!std::is_same<CompilationResultType, + shaderc::SpvCompilationResult>::value) + return false; + // Return early if the compilation result is empty. + if (result.cbegin() == result.cend()) return false; + std::ios::fmtflags output_stream_flag_cache(out->flags()); + *out << std::hex << std::setfill('0'); + auto RI = result.cbegin(); + *out << "0x" << std::setw(8) << *RI++; + for (size_t counter = 1; RI != result.cend(); RI++, counter++) { + *out << ","; + // Break line for every four words. + if (counter % 4 == 0) { + *out << std::endl; + } + *out << "0x" << std::setw(8) << *RI; + } + out->flags(output_stream_flag_cache); + return true; +} +} // anonymous namespace + +namespace glslc { +bool FileCompiler::CompileShaderFile(const InputFileSpec& input_file) { + std::vector<char> input_data; + std::string path = input_file.name; + if (!shaderc_util::ReadFile(path, &input_data)) { + return false; + } + + std::string output_file_name = GetOutputFileName(input_file.name); + string_piece error_file_name = input_file.name; + + if (error_file_name == "-") { + // If the input file was stdin, we want to output errors as <stdin>. + error_file_name = "<stdin>"; + } + + string_piece source_string = ""; + if (!input_data.empty()) { + source_string = {&input_data.front(), + &input_data.front() + input_data.size()}; + } + + std::unique_ptr<FileIncluder> includer( + new FileIncluder(&include_file_finder_)); + // Get a reference to the dependency trace before we pass the ownership to + // shaderc::CompileOptions. + const auto& used_source_files = includer->file_path_trace(); + options_.SetIncluder(std::move(includer)); + + if (input_file.stage == shaderc_spirv_assembly) { + // Only act if the requested target is SPIR-V binary. + if (output_type_ == OutputType::SpirvBinary) { + const auto result = + compiler_.AssembleToSpv(source_string.data(), source_string.size()); + return EmitCompiledResult(result, input_file.name, output_file_name, + error_file_name, used_source_files); + } else { + return true; + } + } + + // Set the language. Since we only use the options object in this + // method, then it's ok to always set it without resetting it after + // compilation. A subsequent compilation will set it again anyway. + options_.SetSourceLanguage(input_file.language); + + switch (output_type_) { + case OutputType::SpirvBinary: { + const auto result = compiler_.CompileGlslToSpv( + source_string.data(), source_string.size(), input_file.stage, + error_file_name.data(), input_file.entry_point_name.c_str(), + options_); + return EmitCompiledResult(result, input_file.name, output_file_name, + error_file_name, used_source_files); + } + case OutputType::SpirvAssemblyText: { + const auto result = compiler_.CompileGlslToSpvAssembly( + source_string.data(), source_string.size(), input_file.stage, + error_file_name.data(), input_file.entry_point_name.c_str(), + options_); + return EmitCompiledResult(result, input_file.name, output_file_name, + error_file_name, used_source_files); + } + case OutputType::PreprocessedText: { + const auto result = compiler_.PreprocessGlsl( + source_string.data(), source_string.size(), input_file.stage, + error_file_name.data(), options_); + return EmitCompiledResult(result, input_file.name, output_file_name, + error_file_name, used_source_files); + } + } + return false; +} + +template <typename CompilationResultType> +bool FileCompiler::EmitCompiledResult( + const CompilationResultType& result, const std::string& input_file, + const std::string& output_file_name, string_piece error_file_name, + const std::unordered_set<std::string>& used_source_files) { + total_errors_ += result.GetNumErrors(); + total_warnings_ += result.GetNumWarnings(); + + bool compilation_success = + result.GetCompilationStatus() == shaderc_compilation_status_success; + + // Handle the error message for failing to deduce the shader kind. + if (result.GetCompilationStatus() == + shaderc_compilation_status_invalid_stage) { + auto glsl_or_hlsl_extension = GetGlslOrHlslExtension(error_file_name); + if (glsl_or_hlsl_extension != "") { + std::cerr << "glslc: error: " + << "'" << error_file_name << "': " + << "." << glsl_or_hlsl_extension + << " file encountered but no -fshader-stage specified ahead"; + } else if (error_file_name == "<stdin>") { + std::cerr + << "glslc: error: '-': -fshader-stage required when input is from " + "standard " + "input \"-\""; + } else { + std::cerr << "glslc: error: " + << "'" << error_file_name << "': " + << "file not recognized: File format not recognized"; + } + std::cerr << "\n"; + + return false; + } + + // Get a string_piece which refers to the normal compilation output for now. + // This string_piece might be redirected to the dependency info to be dumped + // later, if the handler is instantiated to dump as normal compilation output, + // and the original compilation output should be blocked. Otherwise it won't + // be touched. The main output stream dumps this string_piece later. + string_piece compilation_output( + reinterpret_cast<const char*>(result.cbegin()), + reinterpret_cast<const char*>(result.cend())); + + // If we have dependency info dumping handler instantiated, we should dump + // dependency info first. This may redirect the compilation output + // string_piece to dependency info. + std::string potential_dependency_info_output; + if (dependency_info_dumping_handler_) { + if (!dependency_info_dumping_handler_->DumpDependencyInfo( + GetCandidateOutputFileName(input_file), error_file_name.data(), + &potential_dependency_info_output, used_source_files)) { + return false; + } + if (!potential_dependency_info_output.empty()) { + // If the potential_dependency_info_output string is not empty, it means + // we should dump dependency info as normal compilation output. Redirect + // the compilation output string_piece to the dependency info stored in + // potential_dependency_info_output to make it happen. + compilation_output = potential_dependency_info_output; + } + } + + std::ostream* out = nullptr; + std::ofstream potential_file_stream; + if (compilation_success) { + out = shaderc_util::GetOutputStream(output_file_name, + &potential_file_stream, &std::cerr); + if (!out || out->fail()) { + // An error message has already been emitted to the stderr stream. + return false; + } + + // Write compilation output to output file. If an output format for SPIR-V + // binary code is specified, it is handled here. + switch (binary_emission_format_) { + case SpirvBinaryEmissionFormat::Unspecified: + case SpirvBinaryEmissionFormat::Binary: + // The output format is unspecified or specified as binary output. + // On Windows, the output stream must be set to binary mode. By + // default the standard output stream is set to text mode, which + // translates newlines (\n) to carriage-return newline pairs + // (\r\n). + if (out == &std::cout) shaderc_util::FlushAndSetBinaryModeOnStdout(); + out->write(compilation_output.data(), compilation_output.size()); + if (out == &std::cout) shaderc_util::FlushAndSetTextModeOnStdout(); + break; + case SpirvBinaryEmissionFormat::Numbers: + // The output format is specified to be a list of hex numbers, the + // compilation output must be in SPIR-V binary code form. + assert(output_type_ == OutputType::SpirvBinary); + if (EmitSpirvBinaryAsCommaSeparatedNumbers(result, out)) { + // Only emits the end-of-line character when the emitted compilation + // result is not empty. + *out << std::endl; + } + break; + case SpirvBinaryEmissionFormat::CInitList: + // The output format is specified to be a C-style initializer list, the + // compilation output must be in SPIR-V binary code form. + assert(output_type_ == OutputType::SpirvBinary); + if (result.begin() != result.end()) { + // Only emits the '{' when the compilation result is not empty. + *out << "{"; + } + if (EmitSpirvBinaryAsCommaSeparatedNumbers(result, out)) { + // Only emits the end-of-line character when the emitted compilation + // result is not empty. + *out << "}" << std::endl; + } + break; + } + } + + // Write error message to std::cerr. + std::cerr << result.GetErrorMessage(); + if (out && out->fail()) { + // Something wrong happened on output. + if (out == &std::cout) { + std::cerr << "glslc: error: error writing to standard output" + << std::endl; + } else { + std::cerr << "glslc: error: error writing to output file: '" + << output_file_name_ << "'" << std::endl; + } + return false; + } + + return compilation_success; +} + +void FileCompiler::AddIncludeDirectory(const std::string& path) { + include_file_finder_.search_path().push_back(path); +} + +void FileCompiler::SetIndividualCompilationFlag() { + if (output_type_ != OutputType::SpirvAssemblyText) { + needs_linking_ = false; + file_extension_ = ".spv"; + } +} + +void FileCompiler::SetDisassemblyFlag() { + if (!PreprocessingOnly()) { + output_type_ = OutputType::SpirvAssemblyText; + needs_linking_ = false; + file_extension_ = ".spvasm"; + } +} + +void FileCompiler::SetPreprocessingOnlyFlag() { + output_type_ = OutputType::PreprocessedText; + needs_linking_ = false; + if (output_file_name_.empty()) { + output_file_name_ = "-"; + } +} + +bool FileCompiler::ValidateOptions(size_t num_files) { + if (num_files == 0) { + std::cerr << "glslc: error: no input files" << std::endl; + return false; + } + + if (num_files > 1 && needs_linking_) { + std::cerr << "glslc: error: linking multiple files is not supported yet. " + "Use -c to compile files individually." + << std::endl; + return false; + } + + // If we are outputting many object files, we cannot specify -o. Also + // if we are preprocessing multiple files they must be to stdout. + if (num_files > 1 && ((!PreprocessingOnly() && !needs_linking_ && + !output_file_name_.empty()) || + (PreprocessingOnly() && output_file_name_ != "-"))) { + std::cerr << "glslc: error: cannot specify -o when generating multiple" + " output files" + << std::endl; + return false; + } + + // If we have dependency info dumping handler instantiated, we should check + // its validity. + if (dependency_info_dumping_handler_) { + std::string dependency_info_dumping_hander_error_msg; + if (!dependency_info_dumping_handler_->IsValid( + &dependency_info_dumping_hander_error_msg, num_files)) { + std::cerr << "glslc: error: " << dependency_info_dumping_hander_error_msg + << std::endl; + return false; + } + } + + // If the output format is specified to be a binary, a list of hex numbers or + // a C-style initializer list, the output must be in SPIR-V binary code form. + if (binary_emission_format_ != SpirvBinaryEmissionFormat::Unspecified) { + if (output_type_ != OutputType::SpirvBinary) { + std::cerr << "glslc: error: cannot emit output as a "; + switch (binary_emission_format_) { + case SpirvBinaryEmissionFormat::Binary: + std::cerr << "binary"; + break; + case SpirvBinaryEmissionFormat::Numbers: + std::cerr << "list of hex numbers"; + break; + case SpirvBinaryEmissionFormat::CInitList: + std::cerr << "C-style initializer list"; + break; + case SpirvBinaryEmissionFormat::Unspecified: + // The compiler should never be here at runtime. This case is added to + // complete the switch cases. + break; + } + std::cerr << " when the output is not SPIR-V binary code" << std::endl; + return false; + } + if (dependency_info_dumping_handler_ && + dependency_info_dumping_handler_->DumpingAsCompilationOutput()) { + std::cerr << "glslc: error: cannot dump dependency info when specifying " + "any binary output format" + << std::endl; + } + } + + return true; +} + +void FileCompiler::OutputMessages() { + shaderc_util::OutputMessages(&std::cerr, total_warnings_, total_errors_); +} + +std::string FileCompiler::GetOutputFileName(std::string input_filename) { + if (output_file_name_.empty()) { + return needs_linking_ ? std::string("a.spv") + : GetCandidateOutputFileName(input_filename); + } else { + return output_file_name_.str(); + } +} + +std::string FileCompiler::GetCandidateOutputFileName( + std::string input_filename) { + if (!output_file_name_.empty() && !PreprocessingOnly()) { + return output_file_name_.str(); + } + + std::string extension = file_extension_; + if (PreprocessingOnly() || needs_linking_) { + extension = ".spv"; + } + + std::string candidate_output_file_name = + IsStageFile(input_filename) + ? shaderc_util::GetBaseFileName(input_filename) + extension + : shaderc_util::GetBaseFileName( + input_filename.substr(0, input_filename.find_last_of('.')) + + extension); + return candidate_output_file_name; +} +} // namesapce glslc diff --git a/chromium/third_party/shaderc/src/glslc/src/file_compiler.h b/chromium/third_party/shaderc/src/glslc/src/file_compiler.h new file mode 100644 index 00000000000..f00fac5e7ea --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/file_compiler.h @@ -0,0 +1,232 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef GLSLC_FILE_COMPILER_H +#define GLSLC_FILE_COMPILER_H + +#include <string> + +#include "libshaderc_util/file_finder.h" +#include "libshaderc_util/string_piece.h" +#include "shaderc/shaderc.hpp" + +#include "dependency_info.h" + +namespace glslc { + +// Describes an input file to be compiled. +struct InputFileSpec { + std::string name; + shaderc_shader_kind stage; + shaderc_source_language language; + std::string entry_point_name; +}; + +// Context for managing compilation of source GLSL files into destination +// SPIR-V files or preprocessed output. +class FileCompiler { + public: + enum class SpirvBinaryEmissionFormat { + Unspecified, // No binary output format specified, this is the only valid + // option when the compilation output is not in SPIR-V binary + // code form. + Binary, // Emits SPIR-V binary code directly. + Numbers, // Emits SPIR-V binary code as a list of hex numbers. + CInitList, // Emits SPIR-V bianry code as a C-style initializer list + // of hex numbers. + }; + + FileCompiler() + : output_type_(OutputType::SpirvBinary), + binary_emission_format_(SpirvBinaryEmissionFormat::Unspecified), + needs_linking_(true), + total_warnings_(0), + total_errors_(0) {} + + // Compiles a shader received as specified by input_file, returning true + // on success and false otherwise. If force_shader_stage is not + // shaderc_glsl_infer_source or any default shader stage then the given + // shader_stage will be used, otherwise it will be determined from the source + // or the file type. + // + // Places the compilation output into a new file whose name is derived from + // input_file according to the rules from glslc/README.asciidoc. + // + // If version/profile has been forced, the shader's version/profile is set to + // that value regardless of the #version directive in the source code. + // + // Any errors/warnings found in the shader source will be output to std::cerr + // and increment the counts reported by OutputMessages(). + bool CompileShaderFile(const InputFileSpec& input_file); + + // Adds a directory to be searched when processing #include directives. + // + // Best practice: if you add an empty string before any other path, that will + // correctly resolve both absolute paths and paths relative to the current + // working directory. + void AddIncludeDirectory(const std::string& path); + + // Sets the output filename. A name of "-" indicates standard output. + void SetOutputFileName(const shaderc_util::string_piece& file) { + output_file_name_ = file; + } + + // Sets the format for SPIR-V binary compilation output. + void SetSpirvBinaryOutputFormat(SpirvBinaryEmissionFormat format) { + binary_emission_format_ = format; + } + + // Returns false if any options are incompatible. The num_files parameter + // represents the number of files that will be compiled. + bool ValidateOptions(size_t num_files); + + // Outputs to std::cerr the number of warnings and errors if there are any. + void OutputMessages(); + + // Sets the flag to indicate individual compilation mode. In this mode, all + // files are compiled individually and written to separate output files + // instead of linked together. This method also disables linking and sets the + // output file extension to ".spv". Disassembly mode and preprocessing only + // mode override this mode and flags. + void SetIndividualCompilationFlag(); + + // Sets the flag to indicate disassembly mode. In this mode, the compiler + // emits disassembled textual output, instead of outputting object files. + // This method also sets the output file extension to ".spvasm" and disables + // linking. This mode overrides individual compilation mode, and preprocessing + // only mode overrides this mode. + void SetDisassemblyFlag(); + + // Sets the flag to indicate preprocessing only mode. In this mode, instead of + // outputting object files, the compiler emits the preprocessed source files. + // This method disables linking and sets the output file to stdout. This mode + // overrides disassembly mode and individual compilation mode. + void SetPreprocessingOnlyFlag(); + + // Gets the reference of the compiler options which reflects the command-line + // arguments. + shaderc::CompileOptions& options() { return options_; }; + + // Gets a pointer which points to the dependency info dumping hander. Creates + // such a handler if such one does not exist. + DependencyInfoDumpingHandler* GetDependencyDumpingHandler() { + if (!dependency_info_dumping_handler_) { + dependency_info_dumping_handler_.reset( + new DependencyInfoDumpingHandler()); + } + return dependency_info_dumping_handler_.get(); + }; + + private: + enum class OutputType { + SpirvBinary, // A binary module, as defined by the SPIR-V specification. + SpirvAssemblyText, // Assembly syntax defined by the SPIRV-Tools project. + PreprocessedText, // Preprocessed source code. + }; + + // Emits the compilation output from the given result to the given output + // file and returns true if the result represents a successful compilation + // step. Otherwise returns false, possibly emits messages to the standard + // error stream, and does not produce an output file. Accumulates error + // and warning counts for use by the OutputMessages() method. + template <typename CompilationResultType> + bool EmitCompiledResult( + const CompilationResultType& result, const std::string& input_file_name, + const std::string& output_file_name, + shaderc_util::string_piece error_file_name, + const std::unordered_set<std::string>& used_source_files); + + // Returns the final file name to be used for the output file. + // + // If an output file name is specified by the SetOutputFileName(), use that + // argument as the final output file name. + // + // If the user did not specify an output filename: + // If linking is not required, and the input filename has a + // standard stage extension (e.g. .vert) then returns the input filename + // without directory names but with the result extenstion (e.g. .spv or + // .spvasm) appended. + // + // If linking is not required, and the input file name does not have a + // standard stage extension, then also returns the directory-stripped input + // filename, but replaces its extension with the result extension. (If the + // resolved input filename does not have an extension, then appends the + // result extension.) + // + // If linking is required and output filename is not specified, returns + // "a.spv". + std::string GetOutputFileName(std::string input_filename); + + // Returns the candidate output file name deduced from input file name and + // user specified output file name. It is computed as follows: + // + // If the user did specify an output filename and the compiler is not in + // preprocessing-only mode, then returns that file name. + // + // If the user did not specify an output filename: + // If the input filename has a standard stage extension (e.g. .vert) then + // returns the input filename without directory names but with the result + // extenstion (e.g. .spv or .spvasm) appended. + // + // If the input file name does not have a standard stage extension, then also + // returns the directory-stripped input filename, but replaces its extension + // with the result extension. (If the resolved input filename does not have + // an extension, then appends the result extension.) + // + // When a resolved extension is not available because the compiler is in + // preprocessing-only mode or the compilation requires linking, use .spv as + // the extension. + std::string GetCandidateOutputFileName(std::string input_filename); + + // Returns true if the compiler's output is preprocessed text. + bool PreprocessingOnly() { + return output_type_ == OutputType::PreprocessedText; + } + + // Performs actual SPIR-V compilation on the contents of input files. + shaderc::Compiler compiler_; + + // Reflects the command-line arguments and goes into + // compiler_.CompileGlslToSpv(). + shaderc::CompileOptions options_; + + // What kind of output will be produced? + OutputType output_type_; + + // The Flag to indicate to which format the output SPIR-V binary code should + // be emitted. + SpirvBinaryEmissionFormat binary_emission_format_; + + // A FileFinder used to substitute #include directives in the source code. + shaderc_util::FileFinder include_file_finder_; + + // Indicates whether linking is needed to generate the final output. + bool needs_linking_; + + // The ownership of dependency dumping handler. + std::unique_ptr<DependencyInfoDumpingHandler> + dependency_info_dumping_handler_ = nullptr; + + // Reflects the type of file being generated. + std::string file_extension_; + // Name of the file where the compilation output will go. + shaderc_util::string_piece output_file_name_; + + // Counts warnings encountered in all compilations via this object. + size_t total_warnings_; + // Counts errors encountered in all compilations via this object. + size_t total_errors_; +}; +} // namespace glslc +#endif // GLSLC_FILE_COMPILER_H diff --git a/chromium/third_party/shaderc/src/glslc/src/file_includer.cc b/chromium/third_party/shaderc/src/glslc/src/file_includer.cc new file mode 100644 index 00000000000..448bfba5485 --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/file_includer.cc @@ -0,0 +1,66 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "file_includer.h" + +#include <mutex> +#include <utility> + +#include "libshaderc_util/io.h" + +namespace glslc { + +shaderc_include_result* MakeErrorIncludeResult(const char* message) { + return new shaderc_include_result{"", 0, message, strlen(message)}; +} + +FileIncluder::~FileIncluder() = default; + +shaderc_include_result* FileIncluder::GetInclude( + const char* requested_source, shaderc_include_type include_type, + const char* requesting_source, size_t) { + + const std::string full_path = + (include_type == shaderc_include_type_relative) + ? file_finder_.FindRelativeReadableFilepath(requesting_source, + requested_source) + : file_finder_.FindReadableFilepath(requested_source); + + if (full_path.empty()) + return MakeErrorIncludeResult("Cannot find or open include file."); + + // In principle, several threads could be resolving includes at the same + // time. Protect the included_files. + + // Read the file and save its full path and contents into stable addresses. + FileInfo* new_file_info = new FileInfo{full_path, {}}; + if (!shaderc_util::ReadFile(full_path, &(new_file_info->contents))) { + return MakeErrorIncludeResult("Cannot read file"); + } + + included_files_.insert(full_path); + + return new shaderc_include_result{ + new_file_info->full_path.data(), new_file_info->full_path.length(), + new_file_info->contents.data(), new_file_info->contents.size(), + new_file_info}; +} + +void FileIncluder::ReleaseInclude(shaderc_include_result* include_result) { + FileInfo* info = static_cast<FileInfo*>(include_result->user_data); + delete info; + delete include_result; +} + +} // namespace glslc diff --git a/chromium/third_party/shaderc/src/glslc/src/file_includer.h b/chromium/third_party/shaderc/src/glslc/src/file_includer.h new file mode 100644 index 00000000000..98fe28afbef --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/file_includer.h @@ -0,0 +1,74 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef GLSLC_FILE_INCLUDER_H_ +#define GLSLC_FILE_INCLUDER_H_ + +#include <mutex> +#include <string> +#include <unordered_map> +#include <unordered_set> +#include <utility> +#include <vector> +#include <unordered_set> + +#include "libshaderc_util/file_finder.h" +#include "shaderc/shaderc.hpp" + +namespace glslc { + +// An includer for files implementing shaderc's includer interface. It responds +// to the file including query from the compiler with the full path and content +// of the file to be included. In the case that the file is not found or cannot +// be opened, the full path field of in the response will point to an empty +// string, and error message will be passed to the content field. +// This class provides the basic thread-safety guarantee. +class FileIncluder : public shaderc::CompileOptions::IncluderInterface { + public: + explicit FileIncluder(const shaderc_util::FileFinder* file_finder) + : file_finder_(*file_finder) {} + + ~FileIncluder() override; + + // Resolves a requested source file of a given type from a requesting + // source into a shaderc_include_result whose contents will remain valid + // until it's released. + shaderc_include_result* GetInclude(const char* requested_source, + shaderc_include_type type, + const char* requesting_source, + size_t include_depth) override; + // Releases an include result. + void ReleaseInclude(shaderc_include_result* include_result) override; + + // Returns a reference to the member storing the set of included files. + const std::unordered_set<std::string>& file_path_trace() const { + return included_files_; + }; + + private: + // Used by GetInclude() to get the full filepath. + const shaderc_util::FileFinder& file_finder_; + // The full path and content of a source file. + struct FileInfo { + const std::string full_path; + std::vector<char> contents; + }; + + // The set of full paths of included files. + std::unordered_set<std::string> included_files_; +}; + +} // namespace glslc + +#endif // GLSLC_FILE_INCLUDER_H_ diff --git a/chromium/third_party/shaderc/src/glslc/src/file_test.cc b/chromium/third_party/shaderc/src/glslc/src/file_test.cc new file mode 100644 index 00000000000..d9e075b4732 --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/file_test.cc @@ -0,0 +1,96 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "file.h" + +#include <gmock/gmock.h> + +namespace { + +using glslc::GetFileExtension; +using glslc::IsStageFile; +using glslc::GetGlslOrHlslExtension; +using shaderc_util::string_piece; +using testing::Eq; + +class FileExtensionTest : public testing::Test { + protected: + string_piece empty = ""; + string_piece dot = "."; + string_piece no_ext = "shader"; + string_piece trailing_dot = "shader."; + string_piece vert_ext = "shader.vert"; + string_piece frag_ext = "shader.frag"; + string_piece tesc_ext = "shader.tesc"; + string_piece tese_ext = "shader.tese"; + string_piece geom_ext = "shader.geom"; + string_piece comp_ext = "shader.comp"; + string_piece glsl_ext = "shader.glsl"; + string_piece hlsl_ext = "shader.hlsl"; + string_piece multi_dot = "shader.some..ext"; + string_piece both_hg_ext = "shader.hlsl.glsl"; + string_piece both_gh_ext = "shader.glsl.hlsl"; +}; + +TEST_F(FileExtensionTest, GetFileExtension) { + EXPECT_EQ("", GetFileExtension(empty)); + EXPECT_EQ("", GetFileExtension(dot)); + EXPECT_EQ("", GetFileExtension(no_ext)); + EXPECT_EQ("", GetFileExtension(trailing_dot)); + EXPECT_EQ("vert", GetFileExtension(vert_ext)); + EXPECT_EQ("frag", GetFileExtension(frag_ext)); + EXPECT_EQ("tesc", GetFileExtension(tesc_ext)); + EXPECT_EQ("tese", GetFileExtension(tese_ext)); + EXPECT_EQ("geom", GetFileExtension(geom_ext)); + EXPECT_EQ("comp", GetFileExtension(comp_ext)); + EXPECT_EQ("glsl", GetFileExtension(glsl_ext)); + EXPECT_EQ("ext", GetFileExtension(multi_dot)); + EXPECT_EQ("glsl", GetFileExtension(both_hg_ext)); + EXPECT_EQ("hlsl", GetFileExtension(both_gh_ext)); +} + +TEST_F(FileExtensionTest, GetGlslOrHlslExtension) { + EXPECT_THAT(GetGlslOrHlslExtension(empty), Eq("")); + EXPECT_THAT(GetGlslOrHlslExtension(dot), Eq("")); + EXPECT_THAT(GetGlslOrHlslExtension(no_ext), Eq("")); + EXPECT_THAT(GetGlslOrHlslExtension(trailing_dot), Eq("")); + EXPECT_THAT(GetGlslOrHlslExtension(vert_ext), Eq("")); + EXPECT_THAT(GetGlslOrHlslExtension(frag_ext), Eq("")); + EXPECT_THAT(GetGlslOrHlslExtension(tesc_ext), Eq("")); + EXPECT_THAT(GetGlslOrHlslExtension(tese_ext), Eq("")); + EXPECT_THAT(GetGlslOrHlslExtension(geom_ext), Eq("")); + EXPECT_THAT(GetGlslOrHlslExtension(comp_ext), Eq("")); + EXPECT_THAT(GetGlslOrHlslExtension(glsl_ext), Eq("glsl")); + EXPECT_THAT(GetGlslOrHlslExtension(hlsl_ext), Eq("hlsl")); + EXPECT_THAT(GetGlslOrHlslExtension(multi_dot), Eq("")); + EXPECT_THAT(GetGlslOrHlslExtension(both_hg_ext), Eq("glsl")); + EXPECT_THAT(GetGlslOrHlslExtension(both_gh_ext), Eq("hlsl")); +} + +TEST_F(FileExtensionTest, IsStageFile) { + EXPECT_FALSE(IsStageFile(empty)); + EXPECT_FALSE(IsStageFile(dot)); + EXPECT_FALSE(IsStageFile(no_ext)); + EXPECT_FALSE(IsStageFile(trailing_dot)); + EXPECT_TRUE(IsStageFile(vert_ext)); + EXPECT_TRUE(IsStageFile(frag_ext)); + EXPECT_TRUE(IsStageFile(tesc_ext)); + EXPECT_TRUE(IsStageFile(tese_ext)); + EXPECT_TRUE(IsStageFile(geom_ext)); + EXPECT_TRUE(IsStageFile(comp_ext)); + EXPECT_FALSE(IsStageFile(glsl_ext)); + EXPECT_FALSE(IsStageFile(multi_dot)); +} + +} // anonymous namespace diff --git a/chromium/third_party/shaderc/src/glslc/src/main.cc b/chromium/third_party/shaderc/src/glslc/src/main.cc new file mode 100644 index 00000000000..c6ceaec85ff --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/main.cc @@ -0,0 +1,666 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <cassert> +#include <cctype> +#include <cstdint> +#include <cstring> +#include <iomanip> +#include <iostream> +#include <list> +#include <tuple> +#include <string> +#include <sstream> +#include <utility> + +#include "libshaderc_util/compiler.h" +#include "libshaderc_util/io.h" +#include "libshaderc_util/string_piece.h" +#include "shaderc/shaderc.h" +#include "spirv-tools/libspirv.h" + +#include "file.h" +#include "file_compiler.h" +#include "resource_parse.h" +#include "shader_stage.h" + +using shaderc_util::string_piece; + +namespace { + +// Prints the help message. +void PrintHelp(std::ostream* out) { + *out << R"(glslc - Compile shaders into SPIR-V + +Usage: glslc [options] file... + +An input file of - represents standard input. + +Options: + -c Only run preprocess, compile, and assemble steps. + -Dmacro[=defn] Add an implicit macro definition. + -E Outputs only the results of the preprocessing step. + Output defaults to standard output. + -fauto-bind-uniforms + Automatically assign bindings to uniform variables that + don't have an explicit 'binding' layout in the shader + source. + -fauto-map-locations + Automatically assign locations to uniform variables that + don't have an explicit 'location' layout in the shader + source. + -fentry-point=<name> + Specify the entry point name for HLSL compilation, for + all subsequent source files. Default is "main". + -fhlsl_functionality1, -fhlsl-functionality1 + Enable extension SPV_GOOGLE_hlsl_functionality1 for HLSL + compilation. + -fhlsl-iomap Use HLSL IO mappings for bindings. + -fhlsl-offsets Use HLSL offset rules for packing members of blocks. + Affects only GLSL. HLSL rules are always used for HLSL. + -flimit=<settings> + Specify resource limits. Each limit is specified by a limit + name followed by an integer value. Tokens should be + separated by whitespace. If the same limit is specified + several times, only the last setting takes effect. + -flimit-file <file> + Set limits as specified in the given file. + -fresource-set-binding [stage] <reg0> <set0> <binding0> + [<reg1> <set1> <binding1>...] + Explicitly sets the descriptor set and binding for + HLSL resources, by register name. Optionally restrict + it to a single stage. + -fcbuffer-binding-base [stage] <value> + Same as -fubo-binding-base. + -fimage-binding-base [stage] <value> + Sets the lowest automatically assigned binding number for + images. Optionally only set it for a single shader stage. + For HLSL, the resource register number is added to this + base. + -fsampler-binding-base [stage] <value> + Sets the lowest automatically assigned binding number for + samplers Optionally only set it for a single shader stage. + For HLSL, the resource register number is added to this + base. + -fssbo-binding-base [stage] <value> + Sets the lowest automatically assigned binding number for + shader storage buffer objects (SSBO). Optionally only set + it for a single shader stage. Only affects GLSL. + -ftexture-binding-base [stage] <value> + Sets the lowest automatically assigned binding number for + textures. Optionally only set it for a single shader stage. + For HLSL, the resource register number is added to this + base. + -fuav-binding-base [stage] <value> + For automatically assigned bindings for unordered access + views (UAV), the register number is added to this base to + determine the binding number. Optionally only set it for + a single shader stage. Only affects HLSL. + -fubo-binding-base [stage] <value> + Sets the lowest automatically assigned binding number for + uniform buffer objects (UBO). Optionally only set it for + a single shader stage. + For HLSL, the resource register number is added to this + base. + -fshader-stage=<stage> + Treat subsequent input files as having stage <stage>. + Valid stages are vertex, vert, fragment, frag, tesscontrol, + tesc, tesseval, tese, geometry, geom, compute, and comp. + -g Generate source-level debug information. + Currently this option has no effect. + --help Display available options. + -I <value> Add directory to include search path. + -mfmt=<format> Output SPIR-V binary code using the selected format. This + option may be specified only when the compilation output is + in SPIR-V binary code form. Available options include bin, c + and num. By default the binary output format is bin. + -M Generate make dependencies. Implies -E and -w. + -MM An alias for -M. + -MD Generate make dependencies and compile. + -MF <file> Write dependency output to the given file. + -MT <target> Specify the target of the rule emitted by dependency + generation. + -O Optimize the generated SPIR-V code for better performance. + -Os Optimize the generated SPIR-V code for smaller size. + -O0 Disable optimization. + -o <file> Write output to <file>. + A file name of '-' represents standard output. + -std=<value> Version and profile for GLSL input files. Possible values + are concatenations of version and profile, e.g. 310es, + 450core, etc. Ignored for HLSL files. + -S Only run preprocess and compilation steps. + --show-limits Display available limit names and their default values. + --target-env=<environment> + Set the target client environment, and the semantics + of warnings and errors. An optional suffix can specify + the client version. Values are: + vulkan1.0 # The default + vulkan1.1 + vulkan # Same as vulkan1.0 + opengl4.5 + opengl # Same as opengl4.5 + --version Display compiler version information. + -w Suppresses all warning messages. + -Werror Treat all warnings as errors. + -x <language> Treat subsequent input files as having type <language>. + Valid languages are: glsl, hlsl. + For files ending in .hlsl the default is hlsl. + Otherwise the default is glsl. +)"; +} + +// 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) { + const string_piece arg = argv[*index]; + assert(arg.starts_with(option)); + if (arg.size() != option.size()) { + *option_argument = arg.substr(option.size()); + return true; + } else { + if (option.back() == '=') { + *option_argument = ""; + return true; + } + if (++(*index) >= argc) return false; + *option_argument = argv[*index]; + return true; + } +} + +// Sets resource limits according to the given string. The string +// should be formated as required for ParseResourceSettings. +// Returns true on success. Otherwise returns false and sets err +// to a descriptive error message. +bool SetResourceLimits(const std::string& str, shaderc::CompileOptions* options, + std::string* err) { + std::vector<glslc::ResourceSetting> settings; + if (!ParseResourceSettings(str, &settings, err)) { + return false; + } + for (const auto& setting : settings) { + options->SetLimit(setting.limit, setting.value); + } + return true; +} + +const char kBuildVersion[] = +#include "build-version.inc" + ; + + +// 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) { + 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; +} + +// Gets an optional stage name followed by required offset argument. Returns +// false and emits a message to *errs if any errors occur. After calling this +// function, *index will be the index of the last command line argument +// consumed. If no stage name is provided, then *stage contains +// shaderc_glsl_infer_from_source. +bool GetOptionalStageThenOffsetArgument(const shaderc_util::string_piece option, + std::ostream* errs, int argc, + char** argv, int* index, + shaderc_shader_kind* shader_kind, + uint32_t* offset) { + int& argi = *index; + if (argi + 1 >= argc) { + *errs << "glslc: error: Option " << option + << " requires at least one argument" << std::endl; + return false; + } + auto stage = glslc::MapStageNameToForcedKind(argv[argi + 1]); + if (stage != shaderc_glsl_infer_from_source) { + ++argi; + if (argi + 1 >= argc) { + *errs << "glslc: error: Option " << option << " with stage " + << argv[argi - 1] << " requires an offset argument" << std::endl; + return false; + } + } + if (!ParseUint32(argv[argi + 1], offset)) { + *errs << "glslc: error: invalid offset value " << argv[argi + 1] << " for " + << option << std::endl; + return false; + } + ++argi; + *shader_kind = stage; + return true; +} + +} // anonymous namespace + +int main(int argc, char** argv) { + std::vector<glslc::InputFileSpec> input_files; + shaderc_shader_kind current_fshader_stage = shaderc_glsl_infer_from_source; + bool source_language_forced = false; + shaderc_source_language current_source_language = + shaderc_source_language_glsl; + std::string current_entry_point_name("main"); + glslc::FileCompiler compiler; + bool success = true; + bool has_stdin_input = false; + // Shader stage for a single option. + shaderc_shader_kind arg_stage = shaderc_glsl_infer_from_source; + // Binding base for a single option. + uint32_t arg_base = 0; + + // What kind of uniform variable are we setting the binding base for? + shaderc_uniform_kind u_kind = shaderc_uniform_kind_buffer; + + // Sets binding base for the given uniform kind. If stage is + // shader_glsl_infer_from_source then set it for all shader stages. + auto set_binding_base = [&compiler]( + shaderc_shader_kind stage, shaderc_uniform_kind kind, uint32_t base) { + if (stage == shaderc_glsl_infer_from_source) + compiler.options().SetBindingBase(kind, base); + else + compiler.options().SetBindingBaseForStage(stage, kind, base); + }; + + for (int i = 1; i < argc; ++i) { + const string_piece arg = argv[i]; + if (arg == "--help") { + ::PrintHelp(&std::cout); + return 0; + } else if (arg == "--show-limits") { + shaderc_util::Compiler default_compiler; +// The static cast here depends on us keeping the shaderc_limit enum in +// lockstep with the shaderc_util::Compiler::Limit enum. The risk of mismatch +// is low since both are generated from the same resources.inc file. +#define RESOURCE(NAME, FIELD, ENUM) \ + std::cout << #NAME << " " \ + << default_compiler.GetLimit( \ + static_cast<shaderc_util::Compiler::Limit>( \ + shaderc_limit_##ENUM)) \ + << std::endl; +#include "libshaderc_util/resources.inc" +#undef RESOURCE + return 0; + } else if (arg == "--version") { + std::cout << kBuildVersion << std::endl; + std::cout << "Target: " << spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0) + << std::endl; + return 0; + } else if (arg.starts_with("-o")) { + string_piece file_name; + if (!GetOptionArgument(argc, argv, &i, "-o", &file_name)) { + std::cerr + << "glslc: error: argument to '-o' is missing (expected 1 value)" + << std::endl; + return 1; + } + compiler.SetOutputFileName(file_name); + } else if (arg.starts_with("-fshader-stage=")) { + const string_piece stage = arg.substr(std::strlen("-fshader-stage=")); + current_fshader_stage = glslc::GetForcedShaderKindFromCmdLine(arg); + if (current_fshader_stage == shaderc_glsl_infer_from_source) { + std::cerr << "glslc: error: stage not recognized: '" << stage << "'" + << std::endl; + return 1; + } + } else if (arg == "-fauto-bind-uniforms") { + compiler.options().SetAutoBindUniforms(true); + } else if (arg == "-fauto-map-locations") { + compiler.options().SetAutoMapLocations(true); + } else if (arg == "-fhlsl-iomap") { + compiler.options().SetHlslIoMapping(true); + } else if (arg == "-fhlsl-offsets") { + compiler.options().SetHlslOffsets(true); + } else if (arg == "-fhlsl_functionality1" || arg == "-fhlsl-functionality1") { + compiler.options().SetHlslFunctionality1(true); + } else if (((u_kind = shaderc_uniform_kind_image), + (arg == "-fimage-binding-base")) || + ((u_kind = shaderc_uniform_kind_texture), + (arg == "-ftexture-binding-base")) || + ((u_kind = shaderc_uniform_kind_sampler), + (arg == "-fsampler-binding-base")) || + ((u_kind = shaderc_uniform_kind_buffer), + (arg == "-fubo-binding-base")) || + ((u_kind = shaderc_uniform_kind_buffer), + (arg == "-fcbuffer-binding-base")) || + ((u_kind = shaderc_uniform_kind_storage_buffer), + (arg == "-fssbo-binding-base")) || + ((u_kind = shaderc_uniform_kind_unordered_access_view), + (arg == "-fuav-binding-base"))) { + if (!GetOptionalStageThenOffsetArgument(arg, &std::cerr, argc, argv, &i, + &arg_stage, &arg_base)) + return 1; + set_binding_base(arg_stage, u_kind, arg_base); + } else if (arg == "-fresource-set-binding") { + auto need_three_args_err = []() { + std::cerr << "glsc: error: Option -fresource-set-binding" + << " requires at least 3 arguments" << std::endl; + return 1; + }; + if (i + 1 >= argc) return need_three_args_err(); + auto stage = glslc::MapStageNameToForcedKind(argv[i + 1]); + if (stage != shaderc_glsl_infer_from_source) { + ++i; + } + bool seen_triple = false; + while (i + 3 < argc && argv[i + 1][0] != '-' && argv[i + 2][0] != '-' && + argv[i + 3][0] != '-') { + seen_triple = true; + uint32_t set = 0; + if (!ParseUint32(argv[i + 2], &set)) { + std::cerr << "glslc: error: Invalid set number: " << argv[i + 2] + << std::endl; + return 1; + } + uint32_t binding = 0; + if (!ParseUint32(argv[i + 3], &binding)) { + std::cerr << "glslc: error: Invalid binding number: " << argv[i + 3] + << std::endl; + return 1; + } + if (stage == shaderc_glsl_infer_from_source) { + compiler.options().SetHlslRegisterSetAndBinding( + argv[i + 1], argv[i + 2], argv[i + 3]); + } else { + compiler.options().SetHlslRegisterSetAndBindingForStage( + stage, argv[i + 1], argv[i + 2], argv[i + 3]); + } + i += 3; + } + if (!seen_triple) return need_three_args_err(); + } else if (arg.starts_with("-fentry-point=")) { + current_entry_point_name = + arg.substr(std::strlen("-fentry-point=")).str(); + } else if (arg.starts_with("-flimit=")) { + std::string err; + if (!SetResourceLimits(arg.substr(std::strlen("-flimit=")).str(), + &compiler.options(), &err)) { + std::cerr << "glslc: error: -flimit error: " << err << std::endl; + return 1; + } + } else if (arg.starts_with("-flimit-file")) { + std::string err; + string_piece limits_file; + if (!GetOptionArgument(argc, argv, &i, "-flimit-file", &limits_file)) { + std::cerr << "glslc: error: argument to '-flimit-file' is missing" + << std::endl; + return 1; + } + std::vector<char> contents; + if (!shaderc_util::ReadFile(limits_file.str(), &contents)) { + std::cerr << "glslc: cannot read limits file: " << limits_file + << std::endl; + return 1; + } + if (!SetResourceLimits( + string_piece(contents.data(), contents.data() + contents.size()) + .str(), + &compiler.options(), &err)) { + std::cerr << "glslc: error: -flimit-file error: " << err << std::endl; + return 1; + } + } else if (arg.starts_with("-std=")) { + const string_piece standard = arg.substr(std::strlen("-std=")); + int version; + shaderc_profile profile; + if (!shaderc_parse_version_profile(standard.begin(), &version, + &profile)) { + std::cerr << "glslc: error: invalid value '" << standard + << "' in '-std=" << standard << "'" << std::endl; + return 1; + } + compiler.options().SetForcedVersionProfile(version, profile); + } else if (arg.starts_with("--target-env=")) { + shaderc_target_env target_env = shaderc_target_env_default; + const string_piece target_env_str = + arg.substr(std::strlen("--target-env=")); + uint32_t version = 0; // Will default appropriately. + if (target_env_str == "vulkan") { + target_env = shaderc_target_env_vulkan; + } else if (target_env_str == "vulkan1.0") { + target_env = shaderc_target_env_vulkan; + version = shaderc_env_version_vulkan_1_0; + } else if (target_env_str == "vulkan1.1") { + target_env = shaderc_target_env_vulkan; + version = shaderc_env_version_vulkan_1_1; + } else if (target_env_str == "opengl") { + target_env = shaderc_target_env_opengl; + } else if (target_env_str == "opengl4.5") { + target_env = shaderc_target_env_opengl; + version = shaderc_env_version_opengl_4_5; + } else if (target_env_str == "opengl_compat") { + target_env = shaderc_target_env_opengl_compat; + } else { + std::cerr << "glslc: error: invalid value '" << target_env_str + << "' in '--target-env=" << target_env_str << "'" + << std::endl; + return 1; + } + compiler.options().SetTargetEnvironment(target_env, version); + } else if (arg.starts_with("-mfmt=")) { + const string_piece binary_output_format = + arg.substr(std::strlen("-mfmt=")); + if (binary_output_format == "bin") { + compiler.SetSpirvBinaryOutputFormat( + glslc::FileCompiler::SpirvBinaryEmissionFormat::Binary); + } else if (binary_output_format == "num") { + compiler.SetSpirvBinaryOutputFormat( + glslc::FileCompiler::SpirvBinaryEmissionFormat::Numbers); + } else if (binary_output_format == "c") { + compiler.SetSpirvBinaryOutputFormat( + glslc::FileCompiler::SpirvBinaryEmissionFormat::CInitList); + } else { + std::cerr << "glslc: error: invalid value '" << binary_output_format + << "' in '-mfmt=" << binary_output_format << "'" << std::endl; + return 1; + } + } else if (arg.starts_with("-x")) { + string_piece option_arg; + if (!GetOptionArgument(argc, argv, &i, "-x", &option_arg)) { + std::cerr + << "glslc: error: argument to '-x' is missing (expected 1 value)" + << std::endl; + success = false; + } else { + if (option_arg == "glsl") { + current_source_language = shaderc_source_language_glsl; + } else if (option_arg == "hlsl") { + current_source_language = shaderc_source_language_hlsl; + } else { + std::cerr << "glslc: error: language not recognized: '" << option_arg + << "'" << std::endl; + return 1; + } + source_language_forced = true; + } + } else if (arg == "-c") { + compiler.SetIndividualCompilationFlag(); + } else if (arg == "-E") { + compiler.SetPreprocessingOnlyFlag(); + } else if (arg == "-M" || arg == "-MM") { + // -M implies -E and -w + compiler.SetPreprocessingOnlyFlag(); + compiler.options().SetSuppressWarnings(); + if (compiler.GetDependencyDumpingHandler()->DumpingModeNotSet()) { + compiler.GetDependencyDumpingHandler() + ->SetDumpAsNormalCompilationOutput(); + } else { + std::cerr << "glslc: error: both -M (or -MM) and -MD are specified. " + "Only one should be used at one time." + << std::endl; + return 1; + } + } else if (arg == "-MD") { + if (compiler.GetDependencyDumpingHandler()->DumpingModeNotSet()) { + compiler.GetDependencyDumpingHandler() + ->SetDumpToExtraDependencyInfoFiles(); + } else { + std::cerr << "glslc: error: both -M (or -MM) and -MD are specified. " + "Only one should be used at one time." + << std::endl; + return 1; + } + } else if (arg == "-MF") { + string_piece dep_file_name; + if (!GetOptionArgument(argc, argv, &i, "-MF", &dep_file_name)) { + std::cerr + << "glslc: error: missing dependency info filename after '-MF'" + << std::endl; + return 1; + } + compiler.GetDependencyDumpingHandler()->SetDependencyFileName( + std::string(dep_file_name.data(), dep_file_name.size())); + } else if (arg == "-MT") { + string_piece dep_file_name; + if (!GetOptionArgument(argc, argv, &i, "-MT", &dep_file_name)) { + std::cerr << "glslc: error: missing dependency info target after '-MT'" + << std::endl; + return 1; + } + compiler.GetDependencyDumpingHandler()->SetTarget( + std::string(dep_file_name.data(), dep_file_name.size())); + } else if (arg == "-S") { + compiler.SetDisassemblyFlag(); + } else if (arg.starts_with("-D")) { + const size_t length = arg.size(); + if (length <= 2) { + std::cerr << "glslc: error: argument to '-D' is missing" << std::endl; + } else { + const string_piece argument = arg.substr(2); + // Get the exact length of the macro string. + size_t equal_sign_loc = argument.find_first_of('='); + size_t name_length = equal_sign_loc != shaderc_util::string_piece::npos + ? equal_sign_loc + : argument.size(); + const string_piece name_piece = argument.substr(0, name_length); + if (name_piece.starts_with("GL_")) { + std::cerr + << "glslc: error: names beginning with 'GL_' cannot be defined: " + << arg << std::endl; + return 1; + } + if (name_piece.find("__") != string_piece::npos) { + std::cerr + << "glslc: warning: names containing consecutive underscores " + "are reserved: " + << arg << std::endl; + } + + const string_piece value_piece = + (equal_sign_loc == string_piece::npos || + equal_sign_loc == argument.size() - 1) + ? "" + : argument.substr(name_length + 1); + // TODO(deki): check arg for newlines. + compiler.options().AddMacroDefinition( + name_piece.data(), name_piece.size(), value_piece.data(), + value_piece.size()); + } + } else if (arg.starts_with("-I")) { + string_piece option_arg; + if (!GetOptionArgument(argc, argv, &i, "-I", &option_arg)) { + std::cerr + << "glslc: error: argument to '-I' is missing (expected 1 value)" + << std::endl; + success = false; + } else { + compiler.AddIncludeDirectory(option_arg.str()); + } + } else if (arg == "-g") { + compiler.options().SetGenerateDebugInfo(); + } else if (arg.starts_with("-O")) { + if (arg == "-O") { + compiler.options().SetOptimizationLevel( + shaderc_optimization_level_performance); + } else if (arg == "-Os") { + compiler.options().SetOptimizationLevel( + shaderc_optimization_level_size); + } else if (arg == "-O0") { + compiler.options().SetOptimizationLevel( + shaderc_optimization_level_zero); + } else { + std::cerr << "glslc: error: invalid value '" + << arg.substr(std::strlen("-O")) << "' in '" << arg << "'" + << std::endl; + return 1; + } + } else if (arg == "-w") { + compiler.options().SetSuppressWarnings(); + } else if (arg == "-Werror") { + compiler.options().SetWarningsAsErrors(); + } else if (!(arg == "-") && arg[0] == '-') { + std::cerr << "glslc: error: " + << (arg[1] == '-' ? "unsupported option" : "unknown argument") + << ": '" << arg << "'" << std::endl; + return 1; + } else { + if (arg == "-") { + if (has_stdin_input) { + std::cerr << "glslc: error: specifying standard input \"-\" as input " + << "more than once is not allowed." << std::endl; + return 1; + } + has_stdin_input = true; + } + + const auto language = source_language_forced + ? current_source_language + : ((glslc::GetFileExtension(arg) == "hlsl") + ? shaderc_source_language_hlsl + : shaderc_source_language_glsl); + + // If current_fshader_stage is shaderc_glsl_infer_from_source, that means + // we didn't set forced shader kinds (otherwise an error should have + // already been emitted before). So we should deduce the shader kind + // from the file name. If current_fshader_stage is specifed to one of + // the forced shader kinds, use that for the following compilation. + input_files.emplace_back(glslc::InputFileSpec{ + arg.str(), (current_fshader_stage == shaderc_glsl_infer_from_source + ? glslc::DeduceDefaultShaderKindFromFileName(arg) + : current_fshader_stage), + language, current_entry_point_name}); + } + } + + if (!compiler.ValidateOptions(input_files.size())) return 1; + + if (!success) return 1; + + for (const auto& input_file : input_files) { + success &= compiler.CompileShaderFile(input_file); + } + + compiler.OutputMessages(); + return success ? 0 : 1; +} diff --git a/chromium/third_party/shaderc/src/glslc/src/resource_parse.cc b/chromium/third_party/shaderc/src/glslc/src/resource_parse.cc new file mode 100644 index 00000000000..7109333f12b --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/resource_parse.cc @@ -0,0 +1,97 @@ +// Copyright 2016 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "resource_parse.h" + +#include <algorithm> +#include <cstring> +#include <iterator> +#include <sstream> +#include <vector> + +namespace { + +// Converts a limit string to a limit enum. Returns true on successful +// conversion. +bool StringToLimit(const std::string& str, shaderc_limit* limit) { + const char* cstr = str.c_str(); +#define RESOURCE(NAME, FIELD, ENUM) \ + if (0 == std::strcmp(#NAME, cstr)) { \ + *limit = shaderc_limit_##ENUM; \ + return true; \ + } +#include "libshaderc_util/resources.inc" +#undef RESOURCE + return false; +} + +// Returns true if we should ignore the setting. +bool IgnoreSetting(const std::string& str) { + const std::string ignore_list[] = { + "nonInductiveForLoops", + "whileLoops", + "doWhileLoops", + "generalUniformIndexing", + "generalAttributeMatrixVectorIndexing", + "generalVaryingIndexing", + "generalSamplerIndexing", + "generalVariableIndexing", + "generalConstantMatrixVectorIndexing", + }; + return std::find(std::begin(ignore_list), std::end(ignore_list), str) != + std::end(ignore_list); +} + +} // anonymous namespace + +namespace glslc { + +bool ParseResourceSettings(const std::string& input, + std::vector<ResourceSetting>* limits, + std::string* err) { + auto failure = [err, limits](std::string msg) { + *err = msg; + limits->clear(); + return false; + }; + std::istringstream input_stream(input); + std::istream_iterator<std::string> pos((input_stream)); + limits->clear(); + + while (pos != std::istream_iterator<std::string>()) { + const std::string limit_name = *pos++; + shaderc_limit limit = static_cast<shaderc_limit>(0); + bool ignore = IgnoreSetting(limit_name); + if (!ignore) { + if (!StringToLimit(limit_name, &limit)) + return failure(std::string("invalid resource limit: " + limit_name)); + } + + if (pos == std::istream_iterator<std::string>()) + return failure(std::string("missing value after limit: ") + limit_name); + + const std::string value_str = *pos; + int value; + std::istringstream value_stream(value_str); + value_stream >> value; + if (value_stream.bad() || !value_stream.eof() || value_stream.fail()) + return failure(std::string("invalid integer: ") + value_str); + + if (!ignore) limits->push_back({limit, value}); + ++pos; + } + + return true; +} +} // anonymous namespace diff --git a/chromium/third_party/shaderc/src/glslc/src/resource_parse.h b/chromium/third_party/shaderc/src/glslc/src/resource_parse.h new file mode 100644 index 00000000000..9794ce4f0c8 --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/resource_parse.h @@ -0,0 +1,60 @@ +// Copyright 2016 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef GLSLC_RESOURCE_PARSE_H +#define GLSLC_RESOURCE_PARSE_H + +#include <string> +#include <vector> + +#include "shaderc/shaderc.h" + +namespace glslc { + +// A resource limit setting. +struct ResourceSetting { + shaderc_limit limit; + int value; +}; + + +// Returns true when two resource setting structures are equal. +inline bool operator==(const ResourceSetting& lhs, const ResourceSetting& rhs) { + return (lhs.limit == rhs.limit) && (lhs.value == rhs.value); +} + + +// Parses a resource limit setting string. On success, returns true and populates +// the limits parameter. On failure returns failure and emits a message to err. +// The setting string should be a seqeuence of pairs, where each pair +// is a limit name followed by a decimal integer. Tokens should be separated +// by whitespace. In particular, this function accepts Glslang's configuration +// file syntax. If a limit is mentioned multiple times, then the last setting +// takes effect. Ignore settings for: +// nonInductiveForLoops +// whileLoops +// doWhileLoops +// generalUniformIndexing +// generalAttributeMatrixVectorIndexing +// generalVaryingIndexing +// generalSamplerIndexing +// generalVariableIndexing +// generalConstantMatrixVectorIndexing +bool ParseResourceSettings(const std::string& input, + std::vector<ResourceSetting>* limits, + std::string* err); +} // namespace glslc + + +#endif // GLSLC_FILE_H_ diff --git a/chromium/third_party/shaderc/src/glslc/src/resource_parse_test.cc b/chromium/third_party/shaderc/src/glslc/src/resource_parse_test.cc new file mode 100644 index 00000000000..42c877b9a34 --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/resource_parse_test.cc @@ -0,0 +1,75 @@ +// Copyright 2017 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "resource_parse.h" + +#include <gmock/gmock.h> + +namespace { + +using glslc::ParseResourceSettings; +using glslc::ResourceSetting; +using testing::Eq; + +struct ResourceSettingsCase { + std::string input; + bool success; + std::vector<ResourceSetting> settings; + std::string message; +}; + +using ParseResourceSettingsTest = ::testing::TestWithParam<ResourceSettingsCase>; + +TEST_P(ParseResourceSettingsTest, Sample) { + std::vector<ResourceSetting> settings; + std::string err; + const bool succeeded = ParseResourceSettings(GetParam().input, &settings, &err); + EXPECT_THAT(succeeded, Eq(GetParam().success)); + EXPECT_THAT(settings, Eq(GetParam().settings)); + EXPECT_THAT(err, Eq(GetParam().message)); +} + +INSTANTIATE_TEST_CASE_P(ParseResources, ParseResourceSettingsTest, + ::testing::ValuesIn(std::vector<ResourceSettingsCase>{ + {"", true, {}, ""}, + {" \t \t \n ", true, {}, ""}, + {" blorp blam", false, {}, "invalid resource limit: blorp"}, + {"MaxLightsxyz", false, {}, "invalid resource limit: MaxLightsxyz"}, + {"MaxLights", false, {}, "missing value after limit: MaxLights"}, + {"MaxLights x", false, {}, "invalid integer: x"}, + {"MaxLights 99x", false, {}, "invalid integer: 99x"}, + {"MaxLights 12 blam", false, {}, "invalid resource limit: blam"}, + {"MaxLights 12", true, {{shaderc_limit_max_lights, 12}}, ""}, + // Test negative number + {"MinProgramTexelOffset -9", true, {{shaderc_limit_min_program_texel_offset, -9}}, ""}, + // Test leading, intervening, and trailing whitespace + {" \tMaxLights \n 12 \t ", true, {{shaderc_limit_max_lights, 12}}, ""}, + // Test more than one limit setting. + {"MinProgramTexelOffset -10 MaxLights 4", true, {{shaderc_limit_min_program_texel_offset, -10}, {shaderc_limit_max_lights, 4}}, ""}, + // Check ignore cases. + {"nonInductiveForLoops", false, {}, "missing value after limit: nonInductiveForLoops"}, + {"nonInductiveForLoops 1", true, {}, ""}, + {"whileLoops 1", true, {}, ""}, + {"doWhileLoops 1", true, {}, ""}, + {"generalUniformIndexing 1", true, {}, ""}, + {"generalAttributeMatrixVectorIndexing 1", true, {}, ""}, + {"generalVaryingIndexing 1", true, {}, ""}, + {"generalSamplerIndexing 1", true, {}, ""}, + {"generalVariableIndexing 1", true, {}, ""}, + {"generalConstantMatrixVectorIndexing 1", true, {}, ""}, + // Check an ignore case with a regular case + {"whileLoops 1 MaxLights 99", true, {{shaderc_limit_max_lights, 99}}, ""}, + }), ); + +} // anonymous namespace diff --git a/chromium/third_party/shaderc/src/glslc/src/shader_stage.cc b/chromium/third_party/shaderc/src/glslc/src/shader_stage.cc new file mode 100644 index 00000000000..3e4716d37eb --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/shader_stage.cc @@ -0,0 +1,104 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "shader_stage.h" + +#include "file.h" + +using shaderc_util::string_piece; + +namespace { + +// Maps an identifier to a shader stage. +struct StageMapping { + const char* id; + shaderc_shader_kind stage; +}; + +} // anonymous namespace + +namespace glslc { + +shaderc_shader_kind MapStageNameToForcedKind(const string_piece& stage_name) { + const StageMapping string_to_kind[] = { + {"vertex", shaderc_glsl_vertex_shader}, + {"vert", shaderc_glsl_vertex_shader}, + {"fragment", shaderc_glsl_fragment_shader}, + {"frag", shaderc_glsl_fragment_shader}, + {"tesscontrol", shaderc_glsl_tess_control_shader}, + {"tesc", shaderc_glsl_tess_control_shader}, + {"tesseval", shaderc_glsl_tess_evaluation_shader}, + {"tese", shaderc_glsl_tess_evaluation_shader}, + {"geometry", shaderc_glsl_geometry_shader}, + {"geom", shaderc_glsl_geometry_shader}, + {"compute", shaderc_glsl_compute_shader}, + {"comp", shaderc_glsl_compute_shader}, +#ifdef NV_EXTENSIONS + {"rgen", shaderc_glsl_raygen_shader }, + {"rahit", shaderc_glsl_anyhit_shader }, + {"rchit", shaderc_glsl_closesthit_shader }, + {"rmiss", shaderc_glsl_miss_shader }, + {"rint", shaderc_glsl_intersection_shader }, + {"rcall", shaderc_glsl_callable_shader }, + {"task", shaderc_glsl_task_shader }, + {"mesh", shaderc_glsl_mesh_shader }, +#endif + }; + for (const auto& entry : string_to_kind) { + if (stage_name == entry.id) return entry.stage; + } + return shaderc_glsl_infer_from_source; +} + +shaderc_shader_kind GetForcedShaderKindFromCmdLine( + const shaderc_util::string_piece& f_shader_stage_str) { + size_t equal_pos = f_shader_stage_str.find_first_of("="); + if (equal_pos == std::string::npos) return shaderc_glsl_infer_from_source; + return MapStageNameToForcedKind(f_shader_stage_str.substr(equal_pos + 1)); +} + +shaderc_shader_kind DeduceDefaultShaderKindFromFileName( + const string_piece file_name) { + // Add new stage types here. + static const StageMapping kStringToStage[] = { + {"vert", shaderc_glsl_default_vertex_shader}, + {"frag", shaderc_glsl_default_fragment_shader}, + {"tesc", shaderc_glsl_default_tess_control_shader}, + {"tese", shaderc_glsl_default_tess_evaluation_shader}, + {"geom", shaderc_glsl_default_geometry_shader}, + {"comp", shaderc_glsl_default_compute_shader}, + {"spvasm", shaderc_spirv_assembly}, +#ifdef NV_EXTENSIONS + {"rgen", shaderc_glsl_default_raygen_shader }, + {"rahit", shaderc_glsl_default_anyhit_shader }, + {"rchit", shaderc_glsl_default_closesthit_shader }, + {"rmiss", shaderc_glsl_default_miss_shader }, + {"rint", shaderc_glsl_default_intersection_shader }, + {"rcall", shaderc_glsl_default_callable_shader }, + {"task", shaderc_glsl_default_task_shader }, + {"mesh", shaderc_glsl_default_mesh_shader }, +#endif + }; + + const string_piece extension = glslc::GetFileExtension(file_name); + shaderc_shader_kind stage = shaderc_glsl_infer_from_source; + + for (const auto& entry : kStringToStage) { + if (extension == entry.id) stage = entry.stage; + } + + return stage; +} + +} // namespace glslc diff --git a/chromium/third_party/shaderc/src/glslc/src/shader_stage.h b/chromium/third_party/shaderc/src/glslc/src/shader_stage.h new file mode 100644 index 00000000000..8e4ffde360a --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/shader_stage.h @@ -0,0 +1,42 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef GLSLC_SHADER_STAGE_H_ +#define GLSLC_SHADER_STAGE_H_ + +#include <ostream> + +#include "libshaderc_util/string_piece.h" +#include "shaderc/shaderc.h" + +namespace glslc { + +// Maps a shader stage name to a forced shader stage enum value. Returns +// 'shaderc_glsl_infer_from_source' if the stage name is unrecognized. +shaderc_shader_kind MapStageNameToForcedKind( + const shaderc_util::string_piece& f_shader_stage_str); + +// Parse the string piece from command line to get the force shader stage. +// If the 'f_shader_stage_str' cannot be parsed to a valid force shader stage, +// returns 'shaderc_glsl_infer_from_source'. Requires the string to begin with +// '='. +shaderc_shader_kind GetForcedShaderKindFromCmdLine( + const shaderc_util::string_piece& f_shader_stage_str); + +// Parse the file name extension to get the default shader kind. +shaderc_shader_kind DeduceDefaultShaderKindFromFileName( + shaderc_util::string_piece file_name); +} // namespace glslc + +#endif // GLSLC_SHADER_STAGE_H_ diff --git a/chromium/third_party/shaderc/src/glslc/src/stage_test.cc b/chromium/third_party/shaderc/src/glslc/src/stage_test.cc new file mode 100644 index 00000000000..80eef92ac88 --- /dev/null +++ b/chromium/third_party/shaderc/src/glslc/src/stage_test.cc @@ -0,0 +1,94 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Some of the tests here check code paths that are not checked by +// integration tests. +// Generally, these would be conditions not generated by the Glslang +// compiler. It's easier to write these unit tests than to inject +// a dependency on a fake compiler. + +#include <sstream> + +#include <gtest/gtest.h> +#include "shaderc/shaderc.h" + +#include "shader_stage.h" + +using shaderc_util::string_piece; + +namespace { + +TEST(DeduceDefaultShaderKindFromFileName, ValidStage) { + std::stringstream error_stream; + EXPECT_EQ(shaderc_glsl_default_vertex_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.vert")); + + EXPECT_EQ(shaderc_glsl_default_fragment_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.frag")); + + EXPECT_EQ(shaderc_glsl_default_geometry_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.geom")); + + EXPECT_EQ(shaderc_glsl_default_tess_control_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.tesc")); + + EXPECT_EQ(shaderc_glsl_default_tess_evaluation_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.tese")); + + EXPECT_EQ(shaderc_glsl_default_compute_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.comp")); + +#ifdef NV_EXTENSIONS + EXPECT_EQ(shaderc_glsl_default_raygen_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.rgen")); + + EXPECT_EQ(shaderc_glsl_default_anyhit_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.rahit")); + + EXPECT_EQ(shaderc_glsl_default_closesthit_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.rchit")); + + EXPECT_EQ(shaderc_glsl_default_miss_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.rmiss")); + + EXPECT_EQ(shaderc_glsl_default_intersection_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.rint")); + + EXPECT_EQ(shaderc_glsl_default_callable_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.rcall")); + + EXPECT_EQ(shaderc_glsl_default_task_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.task")); + + EXPECT_EQ(shaderc_glsl_default_mesh_shader, + glslc::DeduceDefaultShaderKindFromFileName("a.mesh")); +#endif +} + +TEST(DeduceDefaultShaderKindFromFileName, InvalidStage) { + std::stringstream error_stream; + EXPECT_EQ(shaderc_glsl_infer_from_source, + glslc::DeduceDefaultShaderKindFromFileName("a.glsl")); + + EXPECT_EQ(shaderc_glsl_infer_from_source, + glslc::DeduceDefaultShaderKindFromFileName("-")); + + EXPECT_EQ(shaderc_glsl_infer_from_source, + glslc::DeduceDefaultShaderKindFromFileName("a.foo")); + + EXPECT_EQ(shaderc_glsl_infer_from_source, + glslc::DeduceDefaultShaderKindFromFileName("no-file-extension")); +} + +} // anonymous namespace diff --git a/chromium/third_party/shaderc/src/kokoro/android-release/build.sh b/chromium/third_party/shaderc/src/kokoro/android-release/build.sh new file mode 100644 index 00000000000..b32f7fdedfc --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/android-release/build.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Android Build Script. + + +# Fail on any error. +set -e +# Display commands being run. +set -x + +BUILD_ROOT=$PWD +SRC=$PWD/github/shaderc +TARGET_ARCH=$1 + +# Get NINJA. +wget -q https://github.com/ninja-build/ninja/releases/download/v1.7.2/ninja-linux.zip +unzip -q ninja-linux.zip +export PATH="$PWD:$PATH" +export BUILD_NDK=ON +export ANDROID_NDK=/opt/android-ndk-r15c +git clone --depth=1 https://github.com/taka-no-me/android-cmake.git android-cmake +export TOOLCHAIN_PATH=$PWD/android-cmake/android.toolchain.cmake + + +cd $SRC/third_party +git clone https://github.com/google/googletest.git +git clone https://github.com/google/glslang.git +git clone https://github.com/KhronosGroup/SPIRV-Tools.git spirv-tools +git clone https://github.com/KhronosGroup/SPIRV-Headers.git spirv-headers +git clone https://github.com/google/re2 spirv-tools/external/re2 +git clone https://github.com/google/effcee spirv-tools/external/effcee + +cd $SRC/ +mkdir build +cd $SRC/build + +# Invoke the build. +BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT} +echo $(date): Starting build... +cmake -DRE2_BUILD_TESTING=OFF -GNinja -DCMAKE_BUILD_TYPE=Release -DANDROID_NATIVE_API_LEVEL=android-14 -DANDROID_ABI=$TARGET_ARCH -DSHADERC_SKIP_TESTS=ON -DSPIRV_SKIP_TESTS=ON -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN_PATH -DANDROID_NDK=$ANDROID_NDK .. + + +echo $(date): Build glslang... +ninja glslangValidator + +echo $(date): Build everything... +ninja + +echo $(date): Check Shaderc for copyright notices... +ninja check-copyright + +echo $(date): Build completed. diff --git a/chromium/third_party/shaderc/src/kokoro/android-release/build_arm.sh b/chromium/third_party/shaderc/src/kokoro/android-release/build_arm.sh new file mode 100644 index 00000000000..6d43504a500 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/android-release/build_arm.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Android Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh "armeabi-v7a with NEON" diff --git a/chromium/third_party/shaderc/src/kokoro/android-release/build_x86.sh b/chromium/third_party/shaderc/src/kokoro/android-release/build_x86.sh new file mode 100644 index 00000000000..c642ab1c956 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/android-release/build_x86.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Android Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh x86 + diff --git a/chromium/third_party/shaderc/src/kokoro/android-release/continuous_arm.cfg b/chromium/third_party/shaderc/src/kokoro/android-release/continuous_arm.cfg new file mode 100644 index 00000000000..a4f931a09b1 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/android-release/continuous_arm.cfg @@ -0,0 +1,17 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +# +build_file: "shaderc/kokoro/android-release/build_arm.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/android-release/continuous_x86.cfg b/chromium/third_party/shaderc/src/kokoro/android-release/continuous_x86.cfg new file mode 100644 index 00000000000..a8643d5d090 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/android-release/continuous_x86.cfg @@ -0,0 +1,17 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +# +build_file: "shaderc/kokoro/android-release/build_x86.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/android-release/presubmit_arm.cfg b/chromium/third_party/shaderc/src/kokoro/android-release/presubmit_arm.cfg new file mode 100644 index 00000000000..b88294da7b4 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/android-release/presubmit_arm.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Presubmit build configuration. +build_file: "shaderc/kokoro/android-release/build_arm.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/android-release/presubmit_x86.cfg b/chromium/third_party/shaderc/src/kokoro/android-release/presubmit_x86.cfg new file mode 100644 index 00000000000..590753e0b45 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/android-release/presubmit_x86.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Presubmit build configuration. +build_file: "shaderc/kokoro/android-release/build_x86.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/img/linux.png b/chromium/third_party/shaderc/src/kokoro/img/linux.png Binary files differnew file mode 100644 index 00000000000..ff066d979e1 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/img/linux.png diff --git a/chromium/third_party/shaderc/src/kokoro/img/macos.png b/chromium/third_party/shaderc/src/kokoro/img/macos.png Binary files differnew file mode 100644 index 00000000000..d1349c0928e --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/img/macos.png diff --git a/chromium/third_party/shaderc/src/kokoro/img/windows.png b/chromium/third_party/shaderc/src/kokoro/img/windows.png Binary files differnew file mode 100644 index 00000000000..a3784699905 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/img/windows.png diff --git a/chromium/third_party/shaderc/src/kokoro/linux/build.sh b/chromium/third_party/shaderc/src/kokoro/linux/build.sh new file mode 100644 index 00000000000..67656563ca0 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/build.sh @@ -0,0 +1,112 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Linux Build Script. + + +# Fail on any error. +set -e +# Display commands being run. +set -x + +BUILD_ROOT=$PWD +SRC=$PWD/github/shaderc +CONFIG=$1 +COMPILER=$2 + +SKIP_TESTS="False" +BUILD_TYPE="Debug" + +CMAKE_C_CXX_COMPILER="" +if [ $COMPILER = "clang" ] +then + sudo ln -s /usr/bin/clang-3.8 /usr/bin/clang + sudo ln -s /usr/bin/clang++-3.8 /usr/bin/clang++ + CMAKE_C_CXX_COMPILER="-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++" +fi + +# Possible configurations are: +# ASAN, COVERAGE, RELEASE, DEBUG, DEBUG_EXCEPTION, RELEASE_MINGW + +if [ $CONFIG = "RELEASE" ] || [ $CONFIG = "RELEASE_MINGW" ] +then + BUILD_TYPE="RelWithDebInfo" +fi + +ADDITIONAL_CMAKE_FLAGS="" +if [ $CONFIG = "ASAN" ] +then + ADDITIONAL_CMAKE_FLAGS="-DCMAKE_CXX_FLAGS=-fsanitize=address -DCMAKE_C_FLAGS=-fsanitize=address" + export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-3.4 +elif [ $CONFIG = "COVERAGE" ] +then + ADDITIONAL_CMAKE_FLAGS="-DENABLE_CODE_COVERAGE=ON" + SKIP_TESTS="True" +elif [ $CONFIG = "DEBUG_EXCEPTION" ] +then + ADDITIONAL_CMAKE_FLAGS="-DDISABLE_EXCEPTIONS=ON -DDISABLE_RTTI=ON" +elif [ $CONFIG = "RELEASE_MINGW" ] +then + ADDITIONAL_CMAKE_FLAGS="-Dgtest_disable_pthreads=ON -DCMAKE_TOOLCHAIN_FILE=$SRC/cmake/linux-mingw-toolchain.cmake" + SKIP_TESTS="True" +fi + +# Get NINJA. +wget -q https://github.com/ninja-build/ninja/releases/download/v1.7.2/ninja-linux.zip +unzip -q ninja-linux.zip +export PATH="$PWD:$PATH" + +cd $SRC/third_party +git clone https://github.com/google/googletest.git +git clone https://github.com/google/glslang.git +git clone https://github.com/KhronosGroup/SPIRV-Tools.git spirv-tools +git clone https://github.com/KhronosGroup/SPIRV-Headers.git spirv-headers +git clone https://github.com/google/re2 spirv-tools/external/re2 +git clone https://github.com/google/effcee spirv-tools/external/effcee + +cd $SRC/ +mkdir build +cd $SRC/build + +# Invoke the build. +BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT} +echo $(date): Starting build... +cmake -GNinja -DRE2_BUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=$BUILD_TYPE $ADDITIONAL_CMAKE_FLAGS $CMAKE_C_CXX_COMPILER .. + +echo $(date): Build glslang... +ninja glslangValidator + +echo $(date): Build everything... +ninja +echo $(date): Build completed. + +echo $(date): Check Shaderc for copyright notices... +ninja check-copyright + +if [ $CONFIG = "COVERAGE" ] +then + echo $(date): Check coverage... + ninja report-coverage + echo $(date): Check coverage completed. +fi + +echo $(date): Starting ctest... +if [ $SKIP_TESTS = "False" ] +then + ctest --output-on-failure -j4 +fi +echo $(date): ctest completed. + diff --git a/chromium/third_party/shaderc/src/kokoro/linux/build_clang_asan.sh b/chromium/third_party/shaderc/src/kokoro/linux/build_clang_asan.sh new file mode 100644 index 00000000000..dae31730635 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/build_clang_asan.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Linux Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh ASAN clang diff --git a/chromium/third_party/shaderc/src/kokoro/linux/build_clang_debug.sh b/chromium/third_party/shaderc/src/kokoro/linux/build_clang_debug.sh new file mode 100644 index 00000000000..6e045ae65ff --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/build_clang_debug.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Linux Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh DEBUG clang diff --git a/chromium/third_party/shaderc/src/kokoro/linux/build_clang_release.sh b/chromium/third_party/shaderc/src/kokoro/linux/build_clang_release.sh new file mode 100644 index 00000000000..de73841d494 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/build_clang_release.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Linux Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh RELEASE clang diff --git a/chromium/third_party/shaderc/src/kokoro/linux/build_gcc_coverage.sh b/chromium/third_party/shaderc/src/kokoro/linux/build_gcc_coverage.sh new file mode 100644 index 00000000000..4ee18484677 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/build_gcc_coverage.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Linux Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh COVERAGE gcc diff --git a/chromium/third_party/shaderc/src/kokoro/linux/build_gcc_debug.sh b/chromium/third_party/shaderc/src/kokoro/linux/build_gcc_debug.sh new file mode 100644 index 00000000000..23f4819b32d --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/build_gcc_debug.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Linux Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh DEBUG gcc diff --git a/chromium/third_party/shaderc/src/kokoro/linux/build_gcc_debug_exception.sh b/chromium/third_party/shaderc/src/kokoro/linux/build_gcc_debug_exception.sh new file mode 100644 index 00000000000..d2c8e9a8238 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/build_gcc_debug_exception.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Linux Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh DEBUG_EXCEPTION gcc diff --git a/chromium/third_party/shaderc/src/kokoro/linux/build_gcc_release.sh b/chromium/third_party/shaderc/src/kokoro/linux/build_gcc_release.sh new file mode 100644 index 00000000000..fedc393677b --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/build_gcc_release.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Linux Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh RELEASE gcc diff --git a/chromium/third_party/shaderc/src/kokoro/linux/build_mingw_release.sh b/chromium/third_party/shaderc/src/kokoro/linux/build_mingw_release.sh new file mode 100644 index 00000000000..0b54dc68cd2 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/build_mingw_release.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Linux Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh RELEASE_MINGW diff --git a/chromium/third_party/shaderc/src/kokoro/linux/continuous_clang_asan.cfg b/chromium/third_party/shaderc/src/kokoro/linux/continuous_clang_asan.cfg new file mode 100644 index 00000000000..129115135ab --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/continuous_clang_asan.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/linux/build_clang_asan.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/linux/continuous_clang_debug.cfg b/chromium/third_party/shaderc/src/kokoro/linux/continuous_clang_debug.cfg new file mode 100644 index 00000000000..8d48ddc193d --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/continuous_clang_debug.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/linux/build_clang_debug.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/linux/continuous_clang_release.cfg b/chromium/third_party/shaderc/src/kokoro/linux/continuous_clang_release.cfg new file mode 100644 index 00000000000..6ba10a328ec --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/continuous_clang_release.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/linux/build_clang_release.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/linux/continuous_gcc_coverage.cfg b/chromium/third_party/shaderc/src/kokoro/linux/continuous_gcc_coverage.cfg new file mode 100644 index 00000000000..ab2878c1a7d --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/continuous_gcc_coverage.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/linux/build_gcc_coverage.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/linux/continuous_gcc_debug.cfg b/chromium/third_party/shaderc/src/kokoro/linux/continuous_gcc_debug.cfg new file mode 100644 index 00000000000..d74ac3b0b3f --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/continuous_gcc_debug.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/linux/build_gcc_debug.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/linux/continuous_gcc_debug_exception.cfg b/chromium/third_party/shaderc/src/kokoro/linux/continuous_gcc_debug_exception.cfg new file mode 100644 index 00000000000..cecd1556c6f --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/continuous_gcc_debug_exception.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/linux/build_gcc_debug_exception.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/linux/continuous_gcc_release.cfg b/chromium/third_party/shaderc/src/kokoro/linux/continuous_gcc_release.cfg new file mode 100644 index 00000000000..55fab2a6eb6 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/continuous_gcc_release.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/linux/build_gcc_release.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/linux/continuous_mingw_release.cfg b/chromium/third_party/shaderc/src/kokoro/linux/continuous_mingw_release.cfg new file mode 100644 index 00000000000..a0d4e76fe77 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/continuous_mingw_release.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/linux/build_mingw_release.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/linux/presubmit_clang_debug.cfg b/chromium/third_party/shaderc/src/kokoro/linux/presubmit_clang_debug.cfg new file mode 100644 index 00000000000..87abaf72d6e --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/presubmit_clang_debug.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Presubmit build configuration. +build_file: "shaderc/kokoro/linux/build_clang_debug.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/linux/presubmit_clang_release.cfg b/chromium/third_party/shaderc/src/kokoro/linux/presubmit_clang_release.cfg new file mode 100644 index 00000000000..81ba77d289c --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/presubmit_clang_release.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Presubmit build configuration. +build_file: "shaderc/kokoro/linux/build_clang_release.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/linux/presubmit_gcc_coverage.cfg b/chromium/third_party/shaderc/src/kokoro/linux/presubmit_gcc_coverage.cfg new file mode 100644 index 00000000000..54733b0321c --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/presubmit_gcc_coverage.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Presubmit build configuration. +build_file: "shaderc/kokoro/linux/build_gcc_coverage.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/linux/presubmit_gcc_debug.cfg b/chromium/third_party/shaderc/src/kokoro/linux/presubmit_gcc_debug.cfg new file mode 100644 index 00000000000..f0eec27caf3 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/presubmit_gcc_debug.cfg @@ -0,0 +1,17 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Presubmit build configuration. +build_file: "shaderc/kokoro/linux/build_gcc_debug.sh" + diff --git a/chromium/third_party/shaderc/src/kokoro/linux/presubmit_gcc_release.cfg b/chromium/third_party/shaderc/src/kokoro/linux/presubmit_gcc_release.cfg new file mode 100644 index 00000000000..fda4333f8a3 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/linux/presubmit_gcc_release.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Presubmit build configuration. +build_file: "shaderc/kokoro/linux/build_gcc_release.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/macos/build.sh b/chromium/third_party/shaderc/src/kokoro/macos/build.sh new file mode 100644 index 00000000000..7ae097c820e --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/macos/build.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# MacOS Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +BUILD_ROOT=$PWD +SRC=$PWD/github/shaderc +BUILD_TYPE=$1 + +# Get NINJA. +wget -q https://github.com/ninja-build/ninja/releases/download/v1.7.2/ninja-mac.zip +unzip -q ninja-mac.zip +chmod +x ninja +export PATH="$PWD:$PATH" + +cd $SRC/third_party +git clone https://github.com/google/googletest.git +git clone https://github.com/google/glslang.git +git clone https://github.com/KhronosGroup/SPIRV-Tools.git spirv-tools +git clone https://github.com/KhronosGroup/SPIRV-Headers.git spirv-headers +git clone https://github.com/google/re2 spirv-tools/external/re2 +git clone https://github.com/google/effcee spirv-tools/external/effcee + +cd $SRC/ +mkdir build +cd $SRC/build + +# Invoke the build. +BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT} +echo $(date): Starting build... +cmake -GNinja -DRE2_BUILD_TESTING=OFF -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=$BUILD_TYPE .. + +echo $(date): Build glslang... +ninja glslangValidator + +echo $(date): Build everything... +ninja + +echo $(date): Check Shaderc for copyright notices... +ninja check-copyright + +echo $(date): Build completed. + +echo $(date): Starting ctest... +ctest --output-on-failure -j4 +echo $(date): ctest completed. + diff --git a/chromium/third_party/shaderc/src/kokoro/macos/build_clang_debug.sh b/chromium/third_party/shaderc/src/kokoro/macos/build_clang_debug.sh new file mode 100644 index 00000000000..ed889ff8997 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/macos/build_clang_debug.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# MacOS Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh Debug + diff --git a/chromium/third_party/shaderc/src/kokoro/macos/build_clang_release.sh b/chromium/third_party/shaderc/src/kokoro/macos/build_clang_release.sh new file mode 100644 index 00000000000..9599bac392a --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/macos/build_clang_release.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# MacOS Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh RelWithDebInfo + diff --git a/chromium/third_party/shaderc/src/kokoro/macos/continuous_clang_debug.cfg b/chromium/third_party/shaderc/src/kokoro/macos/continuous_clang_debug.cfg new file mode 100644 index 00000000000..7fb261ca1fb --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/macos/continuous_clang_debug.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/macos/build_clang_debug.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/macos/continuous_clang_release.cfg b/chromium/third_party/shaderc/src/kokoro/macos/continuous_clang_release.cfg new file mode 100644 index 00000000000..85ad37760db --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/macos/continuous_clang_release.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/macos/build_clang_release.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/macos/presubmit_clang_debug.cfg b/chromium/third_party/shaderc/src/kokoro/macos/presubmit_clang_debug.cfg new file mode 100644 index 00000000000..d2748ae7a78 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/macos/presubmit_clang_debug.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Presubmit build configuration. +build_file: "shaderc/kokoro/macos/build_clang_debug.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/macos/presubmit_clang_release.cfg b/chromium/third_party/shaderc/src/kokoro/macos/presubmit_clang_release.cfg new file mode 100644 index 00000000000..3041155e2ba --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/macos/presubmit_clang_release.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Presubmit build configuration. +build_file: "shaderc/kokoro/macos/build_clang_release.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/ndk-build/build.sh b/chromium/third_party/shaderc/src/kokoro/ndk-build/build.sh new file mode 100644 index 00000000000..5e1e1263382 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/ndk-build/build.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Linux Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +BUILD_ROOT=$PWD +SRC=$PWD/github/shaderc + +# Set the glslang repo URL. +GLSLANG_REMOTE=$1 +GLSLANG_REPO_URL="https://github.com/google/glslang.git" +if [ $GLSLANG_REMOTE = "KHRONOS" ] +then + GLSLANG_REPO_URL="https://github.com/KhronosGroup/glslang.git" +fi + +# Get NINJA. +wget -q https://github.com/ninja-build/ninja/releases/download/v1.7.2/ninja-linux.zip +unzip -q ninja-linux.zip +export PATH="$PWD:$PATH" + +# NDK Path +export ANDROID_NDK=/opt/android-ndk-r15c + +# Get shaderc dependencies. +cd $SRC/third_party +git clone $GLSLANG_REPO_URL +git clone https://github.com/google/googletest.git +git clone https://github.com/KhronosGroup/SPIRV-Tools.git spirv-tools +git clone https://github.com/KhronosGroup/SPIRV-Headers.git spirv-tools/external/spirv-headers +git clone https://github.com/google/re2 spirv-tools/external/re2 +git clone https://github.com/google/effcee spirv-tools/external/effcee + +cd $SRC/ +mkdir build +cd $SRC/build + +# Invoke the build. +BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT} +echo $(date): Starting ndk-build ... +$ANDROID_NDK/ndk-build \ + -C $SRC/android_test \ + NDK_APP_OUT=`pwd` \ + V=1 \ + SPVTOOLS_LOCAL_PATH=$SRC/third_party/spirv-tools \ + SPVHEADERS_LOCAL_PATH=$SRC/third_party/spirv-tools/external/spirv-headers \ + -j 8 + +echo $(date): ndk-build completed. + diff --git a/chromium/third_party/shaderc/src/kokoro/ndk-build/build_google.sh b/chromium/third_party/shaderc/src/kokoro/ndk-build/build_google.sh new file mode 100644 index 00000000000..e2be8eb7b6f --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/ndk-build/build_google.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Linux Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh GOOGLE diff --git a/chromium/third_party/shaderc/src/kokoro/ndk-build/build_khronos.sh b/chromium/third_party/shaderc/src/kokoro/ndk-build/build_khronos.sh new file mode 100644 index 00000000000..ce1adf8baac --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/ndk-build/build_khronos.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Linux Build Script. + +# Fail on any error. +set -e +# Display commands being run. +set -x + +SCRIPT_DIR=`dirname "$BASH_SOURCE"` +source $SCRIPT_DIR/build.sh KHRONOS diff --git a/chromium/third_party/shaderc/src/kokoro/ndk-build/continuous_google.cfg b/chromium/third_party/shaderc/src/kokoro/ndk-build/continuous_google.cfg new file mode 100644 index 00000000000..ea86d053d7c --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/ndk-build/continuous_google.cfg @@ -0,0 +1,17 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +# +build_file: "shaderc/kokoro/ndk-build/build_google.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/ndk-build/continuous_khronos.cfg b/chromium/third_party/shaderc/src/kokoro/ndk-build/continuous_khronos.cfg new file mode 100644 index 00000000000..482138376e3 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/ndk-build/continuous_khronos.cfg @@ -0,0 +1,17 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +# +build_file: "shaderc/kokoro/ndk-build/build_khronos.sh" diff --git a/chromium/third_party/shaderc/src/kokoro/windows/build.bat b/chromium/third_party/shaderc/src/kokoro/windows/build.bat new file mode 100644 index 00000000000..2278d86e328 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/windows/build.bat @@ -0,0 +1,106 @@ +:: Copyright (C) 2017 Google Inc. +:: +:: Licensed under the Apache License, Version 2.0 (the "License"); +:: you may not use this file except in compliance with the License. +:: You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, software +:: distributed under the License is distributed on an "AS IS" BASIS, +:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +:: See the License for the specific language governing permissions and +:: limitations under the License. +:: +:: Windows Build Script. + +@echo on + +set BUILD_ROOT=%cd% +set SRC=%cd%\github\shaderc +set BUILD_TYPE=%1 +set VS_VERSION=%2 + +:: Force usage of python 2.7 rather than 3.6 +set PATH=C:\python27;%PATH% + +cd %SRC%\third_party +git clone https://github.com/google/googletest.git +git clone https://github.com/google/glslang.git +git clone https://github.com/KhronosGroup/SPIRV-Tools.git spirv-tools +git clone https://github.com/KhronosGroup/SPIRV-Headers.git spirv-headers +git clone https://github.com/google/re2 spirv-tools/external/re2 +git clone https://github.com/google/effcee spirv-tools/external/effcee + +cmake --version + +:: CMake 3.7 does not support $<IF:...> syntax, which is now used in later +:: googletest code +cd googletest +git checkout e93da23920e5b6887d6a6a291c3a59f83f5b579e + +cd %SRC% +mkdir build +cd %SRC%\build + +:: ######################################### +:: set up msvc build env +:: ######################################### +if %VS_VERSION% == 2017 ( + call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64 + echo "Using VS 2017..." +) else if %VS_VERSION% == 2015 ( + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 + echo "Using VS 2015..." +) else if %VS_VERSION% == 2013 ( + call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64 + echo "Using VS 2013..." +) + +:: ######################################### +:: Start building. +:: ######################################### +echo "Starting build... %DATE% %TIME%" +if "%KOKORO_GITHUB_COMMIT%." == "." ( + set BUILD_SHA=%KOKORO_GITHUB_PULL_REQUEST_COMMIT% +) else ( + set BUILD_SHA=%KOKORO_GITHUB_COMMIT% +) + +:: Skip building SPIRV-Tools tests for VS2013 +if %VS_VERSION% == 2013 ( + cmake -DRE2_BUILD_TESTING=OFF -DSPIRV_SKIP_TESTS=ON -GNinja -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DCMAKE_C_COMPILER=cl.exe -DCMAKE_CXX_COMPILER=cl.exe .. +) else ( + cmake -DRE2_BUILD_TESTING=OFF -GNinja -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DCMAKE_C_COMPILER=cl.exe -DCMAKE_CXX_COMPILER=cl.exe .. +) + +if %ERRORLEVEL% GEQ 1 exit /b %ERRORLEVEL% + +echo "Build glslang... %DATE% %TIME%" +ninja glslangValidator +if %ERRORLEVEL% GEQ 1 exit /b %ERRORLEVEL% + +echo "Build everything... %DATE% %TIME%" +ninja +if %ERRORLEVEL% GEQ 1 exit /b %ERRORLEVEL% + +echo "Check Shaderc for copyright notices... %DATE% %TIME%" +ninja check-copyright +if %ERRORLEVEL% GEQ 1 exit /b %ERRORLEVEL% +echo "Build Completed %DATE% %TIME%" + +:: ######################################### +:: Run the tests. +:: ######################################### +echo "Running Tests... %DATE% %TIME%" +ctest -C %BUILD_TYPE% --output-on-failure -j4 +if %ERRORLEVEL% GEQ 1 exit /b %ERRORLEVEL% +echo "Tests Completed %DATE% %TIME%" + +:: Clean up some directories. +rm -rf %SRC%\build +rm -rf %SRC%\third_party + + +exit /b %ERRORLEVEL% + diff --git a/chromium/third_party/shaderc/src/kokoro/windows/build_debug_2017.bat b/chromium/third_party/shaderc/src/kokoro/windows/build_debug_2017.bat new file mode 100644 index 00000000000..c1ecf87b66f --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/windows/build_debug_2017.bat @@ -0,0 +1,23 @@ +:: Copyright (C) 2017 Google Inc. +:: +:: Licensed under the Apache License, Version 2.0 (the "License"); +:: you may not use this file except in compliance with the License. +:: You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, software +:: distributed under the License is distributed on an "AS IS" BASIS, +:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +:: See the License for the specific language governing permissions and +:: limitations under the License. +:: +:: Windows Build Script. + +@echo on + +:: Find out the directory of the common build script. +set SCRIPT_DIR=%~dp0 + +:: Call with correct parameter +call %SCRIPT_DIR%\build.bat Debug 2017 diff --git a/chromium/third_party/shaderc/src/kokoro/windows/build_release_2013.bat b/chromium/third_party/shaderc/src/kokoro/windows/build_release_2013.bat new file mode 100644 index 00000000000..84e7ede4932 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/windows/build_release_2013.bat @@ -0,0 +1,24 @@ +:: Copyright (C) 2017 Google Inc. +:: +:: Licensed under the Apache License, Version 2.0 (the "License"); +:: you may not use this file except in compliance with the License. +:: You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, software +:: distributed under the License is distributed on an "AS IS" BASIS, +:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +:: See the License for the specific language governing permissions and +:: limitations under the License. +:: +:: Windows Build Script. + +@echo on + +:: Find out the directory of the common build script. +set SCRIPT_DIR=%~dp0 + +:: Call with correct parameter +call %SCRIPT_DIR%\build.bat RelWithDebInfo 2013 + diff --git a/chromium/third_party/shaderc/src/kokoro/windows/build_release_2015.bat b/chromium/third_party/shaderc/src/kokoro/windows/build_release_2015.bat new file mode 100644 index 00000000000..ea156fe2417 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/windows/build_release_2015.bat @@ -0,0 +1,24 @@ +:: Copyright (C) 2017 Google Inc. +:: +:: Licensed under the Apache License, Version 2.0 (the "License"); +:: you may not use this file except in compliance with the License. +:: You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, software +:: distributed under the License is distributed on an "AS IS" BASIS, +:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +:: See the License for the specific language governing permissions and +:: limitations under the License. +:: +:: Windows Build Script. + +@echo on + +:: Find out the directory of the common build script. +set SCRIPT_DIR=%~dp0 + +:: Call with correct parameter +call %SCRIPT_DIR%\build.bat RelWithDebInfo 2015 + diff --git a/chromium/third_party/shaderc/src/kokoro/windows/build_release_2017.bat b/chromium/third_party/shaderc/src/kokoro/windows/build_release_2017.bat new file mode 100644 index 00000000000..4102eaa45d4 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/windows/build_release_2017.bat @@ -0,0 +1,24 @@ +:: Copyright (C) 2017 Google Inc. +:: +:: Licensed under the Apache License, Version 2.0 (the "License"); +:: you may not use this file except in compliance with the License. +:: You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, software +:: distributed under the License is distributed on an "AS IS" BASIS, +:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +:: See the License for the specific language governing permissions and +:: limitations under the License. +:: +:: Windows Build Script. + +@echo on + +:: Find out the directory of the common build script. +set SCRIPT_DIR=%~dp0 + +:: Call with correct parameter +call %SCRIPT_DIR%\build.bat RelWithDebInfo 2017 + diff --git a/chromium/third_party/shaderc/src/kokoro/windows/continuous_debug_2017.cfg b/chromium/third_party/shaderc/src/kokoro/windows/continuous_debug_2017.cfg new file mode 100644 index 00000000000..2e0b62e8d94 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/windows/continuous_debug_2017.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/windows/build_debug_2017.bat" diff --git a/chromium/third_party/shaderc/src/kokoro/windows/continuous_release_2013.cfg b/chromium/third_party/shaderc/src/kokoro/windows/continuous_release_2013.cfg new file mode 100644 index 00000000000..7c330794f31 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/windows/continuous_release_2013.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/windows/build_release_2013.bat" diff --git a/chromium/third_party/shaderc/src/kokoro/windows/continuous_release_2015.cfg b/chromium/third_party/shaderc/src/kokoro/windows/continuous_release_2015.cfg new file mode 100644 index 00000000000..6ee9e93541b --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/windows/continuous_release_2015.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/windows/build_release_2015.bat" diff --git a/chromium/third_party/shaderc/src/kokoro/windows/continuous_release_2017.cfg b/chromium/third_party/shaderc/src/kokoro/windows/continuous_release_2017.cfg new file mode 100644 index 00000000000..20475bd012b --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/windows/continuous_release_2017.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Continuous build configuration. +build_file: "shaderc/kokoro/windows/build_release_2017.bat" diff --git a/chromium/third_party/shaderc/src/kokoro/windows/presubmit_debug_2017.cfg b/chromium/third_party/shaderc/src/kokoro/windows/presubmit_debug_2017.cfg new file mode 100644 index 00000000000..57168d3978f --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/windows/presubmit_debug_2017.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Presubmit build configuration. +build_file: "shaderc/kokoro/windows/build_debug_2017.bat" diff --git a/chromium/third_party/shaderc/src/kokoro/windows/presubmit_release_2013.cfg b/chromium/third_party/shaderc/src/kokoro/windows/presubmit_release_2013.cfg new file mode 100644 index 00000000000..fbb64d4a978 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/windows/presubmit_release_2013.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Presubmit build configuration. +build_file: "shaderc/kokoro/windows/build_release_2013.bat" diff --git a/chromium/third_party/shaderc/src/kokoro/windows/presubmit_release_2015.cfg b/chromium/third_party/shaderc/src/kokoro/windows/presubmit_release_2015.cfg new file mode 100644 index 00000000000..bd24415ee3c --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/windows/presubmit_release_2015.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Presubmit build configuration. +build_file: "shaderc/kokoro/windows/build_release_2015.bat" diff --git a/chromium/third_party/shaderc/src/kokoro/windows/presubmit_release_2017.cfg b/chromium/third_party/shaderc/src/kokoro/windows/presubmit_release_2017.cfg new file mode 100644 index 00000000000..16499fc2154 --- /dev/null +++ b/chromium/third_party/shaderc/src/kokoro/windows/presubmit_release_2017.cfg @@ -0,0 +1,16 @@ +# Copyright (C) 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Presubmit build configuration. +build_file: "shaderc/kokoro/windows/build_release_2017.bat" diff --git a/chromium/third_party/shaderc/src/libshaderc/.clang-format b/chromium/third_party/shaderc/src/libshaderc/.clang-format new file mode 100644 index 00000000000..e209e8cb803 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc/.clang-format @@ -0,0 +1,5 @@ +--- +# Use Google code formatting rules. +Language: Cpp +BasedOnStyle: Google +... diff --git a/chromium/third_party/shaderc/src/libshaderc/Android.mk b/chromium/third_party/shaderc/src/libshaderc/Android.mk new file mode 100644 index 00000000000..cdccab2f695 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc/Android.mk @@ -0,0 +1,13 @@ +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 +LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include +LOCAL_STATIC_LIBRARIES:=shaderc_util SPIRV-Tools-opt +LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -DNV_EXTENSIONS +LOCAL_EXPORT_CPPFLAGS:=-std=c++11 +LOCAL_EXPORT_LDFLAGS:=-latomic +include $(BUILD_STATIC_LIBRARY) diff --git a/chromium/third_party/shaderc/src/libshaderc/CMakeLists.txt b/chromium/third_party/shaderc/src/libshaderc/CMakeLists.txt new file mode 100644 index 00000000000..0eb36980104 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc/CMakeLists.txt @@ -0,0 +1,103 @@ +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}) + +add_library(shaderc_shared SHARED ${SHADERC_SOURCES}) +shaderc_default_compile_options(shaderc_shared) +target_include_directories(shaderc_shared PUBLIC include PRIVATE ${glslang_SOURCE_DIR}) +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/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 + 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 + 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 ${CMAKE_CURRENT_BINARY_DIR}/${install_location} DESTINATION ${CMAKE_INSTALL_LIBDIR}) + else() + install(FILES ${generated_location} DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() +endif(SHADERC_ENABLE_INSTALL) + +shaderc_add_tests( + TEST_PREFIX shaderc_combined + LINK_LIBS shaderc_combined ${CMAKE_THREAD_LIBS_INIT} + INCLUDE_DIRS include ${glslang_SOURCE_DIR} ${spirv-tools_SOURCE_DIR}/include + 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_link_libraries(shaderc_c_smoke_test PRIVATE shaderc) + add_test(NAME shaderc_c_smoke_test COMMAND shaderc_c_smoke_test) +endif() diff --git a/chromium/third_party/shaderc/src/libshaderc/README.md b/chromium/third_party/shaderc/src/libshaderc/README.md new file mode 100644 index 00000000000..bf9d317f394 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc/README.md @@ -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. diff --git a/chromium/third_party/shaderc/src/libshaderc/include/shaderc/shaderc.h b/chromium/third_party/shaderc/src/libshaderc/include/shaderc/shaderc.h new file mode 100644 index 00000000000..6addebf31fd --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc/include/shaderc/shaderc.h @@ -0,0 +1,611 @@ +// 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> + +// SHADERC_EXPORT tags symbol that will be exposed by the shared library. +#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 + +// 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, +#ifdef NV_EXTENSIONS + 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, +#endif +} shaderc_shader_kind; + +typedef enum { + shaderc_target_env_vulkan, // create SPIR-V under Vulkan semantics + shaderc_target_env_opengl, // create SPIR-V under OpenGL semantics + // NOTE: SPIR-V code generation is not supported for shaders under OpenGL + // compatibility profile. + shaderc_target_env_opengl_compat, // create SPIR-V under OpenGL semantics, + // including compatibility profile + // functions + shaderc_target_env_default = shaderc_target_env_vulkan +} shaderc_target_env; + +typedef enum { + // For Vulkan, use Vulkan's mapping of version numbers to integers. + // See vulkan.h + shaderc_env_version_vulkan_1_0 = (((uint32_t)1 << 22)), + shaderc_env_version_vulkan_1_1 = (((uint32_t)1 << 22) | (1 << 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; + +typedef enum { + shaderc_profile_none, // Used if and only if GLSL version did not specify + // profiles. + shaderc_profile_core, + shaderc_profile_compatibility, + shaderc_profile_es, +} shaderc_profile; + +// Indicate the status of a compilation. +typedef enum { + shaderc_compilation_status_success = 0, + shaderc_compilation_status_invalid_stage, // error stage deduction + shaderc_compilation_status_compilation_error, + shaderc_compilation_status_internal_error, // unexpected failure + shaderc_compilation_status_null_result_object, + shaderc_compilation_status_invalid_assembly, +} shaderc_compilation_status; + +// Optimization level. +typedef enum { + shaderc_optimization_level_zero, // no optimization + shaderc_optimization_level_size, // optimize towards reducing code size + shaderc_optimization_level_performance, // optimize towards performance +} shaderc_optimization_level; + +// Resource limits. +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 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 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); + +// 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_ diff --git a/chromium/third_party/shaderc/src/libshaderc/include/shaderc/shaderc.hpp b/chromium/third_party/shaderc/src/libshaderc/include/shaderc/shaderc.hpp new file mode 100644 index 00000000000..d0fbae71c8e --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc/include/shaderc/shaderc.hpp @@ -0,0 +1,573 @@ +// 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* includer = static_cast<IncluderInterface*>(user_data); + return includer->GetInclude(requested_source, + (shaderc_include_type)type, + requesting_source, include_depth); + }, + [](void* user_data, shaderc_include_result* include_result) { + auto* includer = static_cast<IncluderInterface*>(user_data); + return includer->ReleaseInclude(include_result); + }, + 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 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 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); + } + + 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_ diff --git a/chromium/third_party/shaderc/src/libshaderc/src/common_shaders_for_test.h b/chromium/third_party/shaderc/src/libshaderc/src/common_shaders_for_test.h new file mode 100644 index 00000000000..46bfd2065da --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc/src/common_shaders_for_test.h @@ -0,0 +1,347 @@ +// 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" + "}"; + +// 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; 7\n" + "; Bound:", + + " OpCapability Shader\n", + " %1 = 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; 7 + ; 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 + 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(); })"; + +#ifdef NV_EXTENSIONS +// 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(); })"; +#endif + +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; }; + + 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; } + + Texture2D Tex; + SamplerState Sampler1; + 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); + })"; + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // COMMON_SHADERS_FOR_TESTS_H_ diff --git a/chromium/third_party/shaderc/src/libshaderc/src/shaderc.cc b/chromium/third_party/shaderc/src/libshaderc/src/shaderc.cc new file mode 100644 index 00000000000..5f5db168c56 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc/src/shaderc.cc @@ -0,0 +1,766 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "shaderc_private.h" + +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <sstream> +#include <vector> + +#include "SPIRV/spirv.hpp" + +#include "libshaderc_util/compiler.h" +#include "libshaderc_util/counting_includer.h" +#include "libshaderc_util/resources.h" +#include "libshaderc_util/spirv_tools_wrapper.h" +#include "libshaderc_util/version_profile.h" + +#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; + +#ifdef NV_EXTENSIONS + 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; +#endif + + 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: +#ifdef NV_EXTENSIONS + 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: +#endif + 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: +#ifdef NV_EXTENSIONS + 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: +#endif + 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; +#ifdef NV_EXTENSIONS + 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: +#endif + 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_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::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_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_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); +} + +shaderc_compiler_t shaderc_compiler_initialize() { + static shaderc_util::GlslangInitializer* initializer = + new shaderc_util::GlslangInitializer; + shaderc_compiler_t compiler = new (std::nothrow) shaderc_compiler; + compiler->initializer = initializer; + 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, compiler->initializer); + } 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, compiler->initializer); + } + + 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: + return false; + } + + // Shouldn't reach here, all profile enum should be handled above. + // Be strict to return false. + return false; +} diff --git a/chromium/third_party/shaderc/src/libshaderc/src/shaderc_c_smoke_test.c b/chromium/third_party/shaderc/src/libshaderc/src/shaderc_c_smoke_test.c new file mode 100644 index 00000000000..80c40486d3e --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc/src/shaderc_c_smoke_test.c @@ -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; +} + diff --git a/chromium/third_party/shaderc/src/libshaderc/src/shaderc_cpp_test.cc b/chromium/third_party/shaderc/src/libshaderc/src/shaderc_cpp_test.cc new file mode 100644 index 00000000000..86557b5a24e --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc/src/shaderc_cpp_test.cc @@ -0,0 +1,1423 @@ +// 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 <gmock/gmock.h> +#include <gtest/gtest.h> +#include <memory> +#include <thread> +#include <unordered_map> + +#include "SPIRV/spirv.hpp" +#include "spirv-tools/libspirv.hpp" + +#include "common_shaders_for_test.h" +#include "shaderc/shaderc.hpp" + +namespace { + +using shaderc::AssemblyCompilationResult; +using shaderc::CompileOptions; +using shaderc::PreprocessedSourceCompilationResult; +using shaderc::SpvCompilationResult; +using testing::Each; +using testing::Eq; +using testing::HasSubstr; +using testing::Not; + +// Helper function to check if the compilation result indicates a successful +// compilation. +template <typename T> +bool CompilationResultIsSuccess(const shaderc::CompilationResult<T>& result) { + return result.GetCompilationStatus() == shaderc_compilation_status_success; +} + +// Examines whether a compilation result has valid SPIR-V code, by checking the +// magic number in the fixed postion of the byte array in the result object. +// Returns true if the magic number is found at the correct postion, otherwise +// returns false. +bool IsValidSpv(const SpvCompilationResult& result) { + if (!CompilationResultIsSuccess(result)) return false; + size_t length_in_words = result.cend() - result.cbegin(); + if (length_in_words < 5) return false; + const uint32_t* bytes = result.cbegin(); + return bytes[0] == spv::MagicNumber; +} + +// Compiles a shader and returns true if the result is valid SPIR-V. The +// input_file_name is set to "shader". +bool CompilesToValidSpv(const shaderc::Compiler& compiler, + const std::string& shader, shaderc_shader_kind kind) { + return IsValidSpv(compiler.CompileGlslToSpv(shader, kind, "shader")); +} + +// Compiles a shader with options and returns true if the result is valid +// SPIR-V. The input_file_name is set to "shader". +bool CompilesToValidSpv(const shaderc::Compiler& compiler, + const std::string& shader, shaderc_shader_kind kind, + const CompileOptions& options) { + return IsValidSpv(compiler.CompileGlslToSpv(shader, kind, "shader", options)); +} + +// Returns the compiler's output from a compilation result as a string. +template <typename T> +std::string CompilerOutputAsString( + const shaderc::CompilationResult<T>& result) { + return std::string(reinterpret_cast<const char*>(result.cbegin()), + reinterpret_cast<const char*>(result.cend())); +} + +class CppInterface : public testing::Test { + protected: + // Compiles a shader and returns true on success, false on failure. + // The input file name is set to "shader" by default. + bool CompilationSuccess(const std::string& shader, + shaderc_shader_kind kind) const { + return compiler_ + .CompileGlslToSpv(shader.c_str(), shader.length(), kind, + "shader") + .GetCompilationStatus() == shaderc_compilation_status_success; + } + + // Compiles a shader with options and returns true on success, false on + // failure. + // The input file name is set to "shader" by default. + bool CompilationSuccess(const std::string& shader, shaderc_shader_kind kind, + const CompileOptions& options) const { + return compiler_ + .CompileGlslToSpv(shader.c_str(), shader.length(), kind, + "shader", options) + .GetCompilationStatus() == shaderc_compilation_status_success; + } + + // Compiles a shader, asserts compilation success, and returns the warning + // messages. + // The input file name is set to "shader" by default. + std::string CompilationWarnings( + const std::string& shader, shaderc_shader_kind kind, + // This could default to options_, but that can + // be easily confused with a no-options-provided + // case: + const CompileOptions& options) { + const auto compilation_result = + compiler_.CompileGlslToSpv(shader, kind, "shader", options); + EXPECT_TRUE(CompilationResultIsSuccess(compilation_result)) << kind << '\n' + << shader; + return compilation_result.GetErrorMessage(); + } + + // Compiles a shader, asserts compilation fail, and returns the error + // messages. + std::string CompilationErrors(const std::string& shader, + shaderc_shader_kind kind, + // This could default to options_, but that can + // be easily confused with a no-options-provided + // case: + const CompileOptions& options) { + const auto compilation_result = + compiler_.CompileGlslToSpv(shader, kind, "shader", options); + EXPECT_FALSE(CompilationResultIsSuccess(compilation_result)) << kind << '\n' + << shader; + return compilation_result.GetErrorMessage(); + } + + // Assembles the given SPIR-V assembly and returns true on success. + bool AssemblingSuccess(const std::string& shader, + const CompileOptions& options) const { + return compiler_.AssembleToSpv(shader, options).GetCompilationStatus() == + shaderc_compilation_status_success; + } + + // Assembles the given SPIR-V assembly and returns true if the result contains + // a valid SPIR-V module. + bool AssemblingValid(const std::string& shader, + const CompileOptions& options) const { + return IsValidSpv(compiler_.AssembleToSpv(shader, options)); + } + + // Compiles a shader, expects compilation success, and returns the output + // bytes. + // The input file name is set to "shader" by default. + std::string CompilationOutput(const std::string& shader, + shaderc_shader_kind kind, + const CompileOptions& options) const { + const auto compilation_result = + compiler_.CompileGlslToSpv(shader, kind, "shader", options); + EXPECT_TRUE(CompilationResultIsSuccess(compilation_result)) << kind << '\n'; + // Need to make sure you get complete binary data, including embedded nulls. + return CompilerOutputAsString(compilation_result); + } + + // Compiles a shader to SPIR-V assembly, expects compilation success, and + // returns the output bytes. + // The input file name is set to "shader" by default. + std::string AssemblyOutput(const std::string& shader, + shaderc_shader_kind kind, + const CompileOptions& options) const { + const auto compilation_result = + compiler_.CompileGlslToSpvAssembly(shader, kind, "shader", options); + EXPECT_TRUE(CompilationResultIsSuccess(compilation_result)) << kind << '\n'; + // Need to make sure you get complete binary data, including embedded nulls. + return CompilerOutputAsString(compilation_result); + } + + // For compiling shaders in subclass tests: + shaderc::Compiler compiler_; + CompileOptions options_; +}; + +TEST_F(CppInterface, CompilerValidUponConstruction) { + EXPECT_TRUE(compiler_.IsValid()); +} + +TEST_F(CppInterface, MultipleCalls) { + shaderc::Compiler compiler1, compiler2, compiler3; + EXPECT_TRUE(compiler1.IsValid()); + EXPECT_TRUE(compiler2.IsValid()); + EXPECT_TRUE(compiler3.IsValid()); +} + +#ifndef SHADERC_DISABLE_THREADED_TESTS +TEST_F(CppInterface, MultipleThreadsInitializing) { + std::unique_ptr<shaderc::Compiler> compiler1; + std::unique_ptr<shaderc::Compiler> compiler2; + std::unique_ptr<shaderc::Compiler> compiler3; + std::thread t1([&compiler1]() { + compiler1 = std::unique_ptr<shaderc::Compiler>(new shaderc::Compiler()); + }); + std::thread t2([&compiler2]() { + compiler2 = std::unique_ptr<shaderc::Compiler>(new shaderc::Compiler()); + }); + std::thread t3([&compiler3]() { + compiler3 = std::unique_ptr<shaderc::Compiler>(new shaderc::Compiler()); + }); + t1.join(); + t2.join(); + t3.join(); + EXPECT_TRUE(compiler1->IsValid()); + EXPECT_TRUE(compiler2->IsValid()); + EXPECT_TRUE(compiler3->IsValid()); +} +#endif + +TEST_F(CppInterface, CompilerMoves) { + shaderc::Compiler compiler2(std::move(compiler_)); + ASSERT_FALSE(compiler_.IsValid()); + ASSERT_TRUE(compiler2.IsValid()); +} + +TEST_F(CppInterface, EmptyString) { + EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_vertex_shader)); + EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_fragment_shader)); +} + +TEST_F(CppInterface, AssembleEmptyString) { + EXPECT_TRUE(AssemblingSuccess("", options_)); +} + +TEST_F(CppInterface, ResultObjectMoves) { + SpvCompilationResult result = compiler_.CompileGlslToSpv( + kMinimalShader, shaderc_glsl_vertex_shader, "shader"); + EXPECT_TRUE(CompilationResultIsSuccess(result)); + const SpvCompilationResult result2(std::move(result)); + EXPECT_FALSE(CompilationResultIsSuccess(result)); + EXPECT_TRUE(CompilationResultIsSuccess(result2)); +} + +TEST_F(CppInterface, GarbageString) { + EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_vertex_shader)); + EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_fragment_shader)); +} + +TEST_F(CppInterface, AssembleGarbageString) { + const auto result = compiler_.AssembleToSpv("jfalkds", options_); + EXPECT_FALSE(CompilationResultIsSuccess(result)); + EXPECT_EQ(0u, result.GetNumWarnings()); + EXPECT_EQ(1u, result.GetNumErrors()); +} + +// TODO(antiagainst): right now there is no assembling difference for all the +// target environments exposed by shaderc. So the following is just testing the +// target environment is accepted. +TEST_F(CppInterface, AssembleTargetEnv) { + options_.SetTargetEnvironment(shaderc_target_env_opengl, 0); + EXPECT_TRUE(AssemblingValid("OpCapability Shader", options_)); +} + +TEST_F(CppInterface, MinimalShader) { + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, + shaderc_glsl_vertex_shader)); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, + shaderc_glsl_fragment_shader)); +} + +TEST_F(CppInterface, AssembleMinimalShader) { + EXPECT_TRUE(AssemblingValid(kMinimalShaderAssembly, options_)); +} + +TEST_F(CppInterface, BasicOptions) { + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, + shaderc_glsl_vertex_shader, options_)); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, + shaderc_glsl_fragment_shader, options_)); +} + +TEST_F(CppInterface, CopiedOptions) { + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, + shaderc_glsl_vertex_shader, options_)); + CompileOptions copied_options(options_); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, + shaderc_glsl_fragment_shader, copied_options)); +} + +TEST_F(CppInterface, MovedOptions) { + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, + shaderc_glsl_vertex_shader, options_)); + CompileOptions copied_options(std::move(options_)); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, + shaderc_glsl_fragment_shader, copied_options)); +} + +TEST_F(CppInterface, StdAndCString) { + const SpvCompilationResult result1 = + compiler_.CompileGlslToSpv(kMinimalShader, strlen(kMinimalShader), + shaderc_glsl_fragment_shader, "shader"); + const SpvCompilationResult result2 = compiler_.CompileGlslToSpv( + std::string(kMinimalShader), shaderc_glsl_fragment_shader, "shader"); + EXPECT_TRUE(CompilationResultIsSuccess(result1)); + EXPECT_TRUE(CompilationResultIsSuccess(result2)); + EXPECT_EQ(std::vector<uint32_t>(result1.cbegin(), result1.cend()), + std::vector<uint32_t>(result2.cbegin(), result2.cend())); +} + +TEST_F(CppInterface, ErrorsReported) { + const SpvCompilationResult result = compiler_.CompileGlslToSpv( + "int f(){return wrongname;}", shaderc_glsl_vertex_shader, "shader"); + ASSERT_FALSE(CompilationResultIsSuccess(result)); + EXPECT_THAT(result.GetErrorMessage(), HasSubstr("wrongname")); +} + +#ifndef SHADERC_DISABLE_THREADED_TESTS +TEST_F(CppInterface, MultipleThreadsCalling) { + bool results[10]; + std::vector<std::thread> threads; + for (auto& r : results) { + threads.emplace_back([this, &r]() { + r = CompilationSuccess(kMinimalShader, shaderc_glsl_vertex_shader); + }); + } + for (auto& t : threads) { + t.join(); + } + EXPECT_THAT(results, Each(true)); +} +#endif + +TEST_F(CppInterface, AccessorsOnNullResultObject) { + const SpvCompilationResult result(nullptr); + EXPECT_FALSE(CompilationResultIsSuccess(result)); + EXPECT_EQ(std::string(), result.GetErrorMessage()); + EXPECT_EQ(result.cend(), result.cbegin()); + EXPECT_EQ(nullptr, result.cbegin()); + EXPECT_EQ(nullptr, result.cend()); + EXPECT_EQ(nullptr, result.begin()); + EXPECT_EQ(nullptr, result.end()); +} + +TEST_F(CppInterface, MacroCompileOptions) { + options_.AddMacroDefinition("E", "main"); + const std::string kMinimalExpandedShader = "#version 150\nvoid E(){}"; + const std::string kMinimalDoubleExpandedShader = "#version 150\nF E(){}"; + EXPECT_TRUE(CompilationSuccess(kMinimalExpandedShader, + shaderc_glsl_vertex_shader, options_)); + + CompileOptions cloned_options(options_); + // The simplest should still compile with the cloned options. + EXPECT_TRUE(CompilationSuccess(kMinimalExpandedShader, + shaderc_glsl_vertex_shader, cloned_options)); + + EXPECT_FALSE(CompilationSuccess(kMinimalDoubleExpandedShader, + shaderc_glsl_vertex_shader, cloned_options)); + + cloned_options.AddMacroDefinition("F", "void"); + // This should still not work with the original options. + EXPECT_FALSE(CompilationSuccess(kMinimalDoubleExpandedShader, + shaderc_glsl_vertex_shader, options_)); + // This should work with the cloned options that have the additional + // parameter. + EXPECT_TRUE(CompilationSuccess(kMinimalDoubleExpandedShader, + shaderc_glsl_vertex_shader, cloned_options)); +} + +TEST_F(CppInterface, D_DisassemblyOption) { + const AssemblyCompilationResult result = compiler_.CompileGlslToSpvAssembly( + kMinimalShader, shaderc_glsl_vertex_shader, "shader", options_); + EXPECT_TRUE(CompilationResultIsSuccess(result)); + // This should work with both the glslang native disassembly format and the + // SPIR-V Tools assembly format. + EXPECT_THAT(CompilerOutputAsString(result), HasSubstr("Capability Shader")); + EXPECT_THAT(CompilerOutputAsString(result), HasSubstr("MemoryModel")); + + CompileOptions cloned_options(options_); + auto result_from_cloned_options = compiler_.CompileGlslToSpvAssembly( + kMinimalShader, shaderc_glsl_vertex_shader, "shader", cloned_options); + EXPECT_TRUE(CompilationResultIsSuccess(result_from_cloned_options)); + // The mode should be carried into any clone of the original option object. + EXPECT_THAT(CompilerOutputAsString(result_from_cloned_options), + HasSubstr("Capability Shader")); + EXPECT_THAT(CompilerOutputAsString(result_from_cloned_options), + HasSubstr("MemoryModel")); +} + +TEST_F(CppInterface, DisassembleMinimalShader) { + const AssemblyCompilationResult result = compiler_.CompileGlslToSpvAssembly( + kMinimalShader, shaderc_glsl_vertex_shader, "shader", options_); + EXPECT_TRUE(CompilationResultIsSuccess(result)); + for (const auto& substring : kMinimalShaderDisassemblySubstrings) { + EXPECT_THAT(CompilerOutputAsString(result), HasSubstr(substring)); + } +} + +TEST_F(CppInterface, ForcedVersionProfileCorrectStd) { + // Forces the version and profile to 450core, which fixes the missing + // #version. + options_.SetForcedVersionProfile(450, shaderc_profile_core); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion, + shaderc_glsl_vertex_shader, options_)); +} + +TEST_F(CppInterface, ForcedVersionProfileCorrectStdClonedOptions) { + // Forces the version and profile to 450core, which fixes the missing + // #version. + options_.SetForcedVersionProfile(450, shaderc_profile_core); + CompileOptions cloned_options(options_); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion, + shaderc_glsl_vertex_shader, cloned_options)); +} + +TEST_F(CppInterface, ForcedVersionProfileInvalidModule) { + // Forces the version and profile to 310es, while the source module is invalid + // for this version of GLSL. Compilation should fail. + options_.SetForcedVersionProfile(310, shaderc_profile_es); + EXPECT_THAT(CompilationErrors(kCoreVertShaderWithoutVersion, + shaderc_glsl_vertex_shader, options_), + HasSubstr("error: 'gl_ClipDistance' : undeclared identifier\n")); +} + +TEST_F(CppInterface, ForcedVersionProfileConflictingStd) { + // Forces the version and profile to 450core, which is in conflict with the + // #version in shader. + const std::string kVertexShader = + std::string("#version 310 es\n") + kCoreVertShaderWithoutVersion; + options_.SetForcedVersionProfile(450, shaderc_profile_core); + EXPECT_THAT( + CompilationWarnings(kVertexShader, shaderc_glsl_vertex_shader, options_), + HasSubstr("warning: (version, profile) forced to be (450, core), " + "while in source code it is (310, es)\n")); +} + +TEST_F(CppInterface, ForcedVersionProfileUnknownVersionStd) { + // Forces the version and profile to 4242core, which is an unknown version. + options_.SetForcedVersionProfile(4242 /*unknown version*/, + shaderc_profile_core); + auto const errs = + CompilationErrors(kMinimalShader, shaderc_glsl_vertex_shader, options_); + EXPECT_THAT(errs, + HasSubstr("warning: (version, profile) forced to be (4242, core)," + " while in source code it is (140, none)\n")); + EXPECT_THAT(errs, HasSubstr("error: version not supported\n")); +} + +TEST_F(CppInterface, ForcedVersionProfileVersionsBefore150) { + // Versions before 150 do not allow a profile token, shaderc_profile_none + // should be passed down as the profile parameter. + options_.SetForcedVersionProfile(140, shaderc_profile_none); + EXPECT_TRUE( + CompilationSuccess(kMinimalShader, shaderc_glsl_vertex_shader, options_)); +} + +TEST_F(CppInterface, ForcedVersionProfileRedundantProfileStd) { + // Forces the version and profile to 100core. But versions before 150 do not + // allow a profile token, compilation should fail. + options_.SetForcedVersionProfile(100, shaderc_profile_core); + EXPECT_THAT( + CompilationErrors(kMinimalShader, shaderc_glsl_vertex_shader, options_), + HasSubstr("error: #version: versions before 150 do not allow a profile " + "token\n")); +} + +TEST_F(CppInterface, GenerateDebugInfoBinary) { + options_.SetGenerateDebugInfo(); + // The output binary should contain the name of the vector: debug_info_sample + // as char array. + EXPECT_THAT(CompilationOutput(kMinimalDebugInfoShader, + shaderc_glsl_vertex_shader, options_), + HasSubstr("debug_info_sample")); +} + +TEST_F(CppInterface, GenerateDebugInfoBinaryClonedOptions) { + options_.SetGenerateDebugInfo(); + CompileOptions cloned_options(options_); + // The output binary should contain the name of the vector: debug_info_sample + // as char array. + EXPECT_THAT(CompilationOutput(kMinimalDebugInfoShader, + shaderc_glsl_vertex_shader, cloned_options), + HasSubstr("debug_info_sample")); +} + +TEST_F(CppInterface, GenerateDebugInfoDisassembly) { + options_.SetGenerateDebugInfo(); + // Debug info should also be emitted in disassembly mode. + // The output disassembly should contain the name of the vector: + // debug_info_sample. + EXPECT_THAT(AssemblyOutput(kMinimalDebugInfoShader, + shaderc_glsl_vertex_shader, options_), + HasSubstr("debug_info_sample")); +} + +TEST_F(CppInterface, GenerateDebugInfoDisassemblyClonedOptions) { + options_.SetGenerateDebugInfo(); + // Generate debug info mode should be carried to the cloned options. + CompileOptions cloned_options(options_); + EXPECT_THAT(CompilationOutput(kMinimalDebugInfoShader, + shaderc_glsl_vertex_shader, cloned_options), + HasSubstr("debug_info_sample")); +} + +TEST_F(CppInterface, CompileAndOptimizeWithLevelZero) { + options_.SetOptimizationLevel(shaderc_optimization_level_zero); + const std::string disassembly_text = + AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_); + for (const auto& substring : kMinimalShaderDisassemblySubstrings) { + EXPECT_THAT(disassembly_text, HasSubstr(substring)); + } + // Check that we still have debug instructions. + EXPECT_THAT(disassembly_text, HasSubstr("OpName")); + EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); +} + +TEST_F(CppInterface, CompileAndOptimizeWithLevelPerformance) { + options_.SetOptimizationLevel(shaderc_optimization_level_performance); + const std::string disassembly_text = AssemblyOutput( + kGlslMultipleFnShader, shaderc_glsl_fragment_shader, options_); + // Check that we do not have function calls anymore. + EXPECT_THAT(disassembly_text, Not(HasSubstr("OpFunctionCall"))); +} + +TEST_F(CppInterface, CompileAndOptimizeWithLevelSize) { + options_.SetOptimizationLevel(shaderc_optimization_level_size); + const std::string disassembly_text = + AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_); + for (const auto& substring : kMinimalShaderDisassemblySubstrings) { + EXPECT_THAT(disassembly_text, HasSubstr(substring)); + } + // Check that we do not have debug instructions. + EXPECT_THAT(disassembly_text, Not(HasSubstr("OpName"))); + EXPECT_THAT(disassembly_text, Not(HasSubstr("OpSource"))); +} + +TEST_F(CppInterface, CompileAndOptimizeForVulkan10Failure) { + options_.SetSourceLanguage(shaderc_source_language_hlsl); + options_.SetTargetEnvironment(shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_0); + options_.SetOptimizationLevel(shaderc_optimization_level_performance); + + EXPECT_THAT(CompilationErrors(kHlslWaveActiveSumeComputeShader, + shaderc_compute_shader, options_), + // TODO(antiagainst): the error message can be improved to be more + // explicit regarding Vulkan 1.1 + HasSubstr("compilation succeeded but failed to optimize: " + "Invalid capability operand")); +} + +TEST_F(CppInterface, CompileAndOptimizeForVulkan11Success) { + options_.SetSourceLanguage(shaderc_source_language_hlsl); + options_.SetTargetEnvironment(shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_1); + options_.SetOptimizationLevel(shaderc_optimization_level_performance); + + const std::string disassembly_text = AssemblyOutput( + kHlslWaveActiveSumeComputeShader, shaderc_compute_shader, options_); + EXPECT_THAT(disassembly_text, HasSubstr("OpGroupNonUniformIAdd")); +} + +TEST_F(CppInterface, FollowingOptLevelOverridesPreviousOne) { + options_.SetOptimizationLevel(shaderc_optimization_level_size); + // Optimization level settings overridden by + options_.SetOptimizationLevel(shaderc_optimization_level_zero); + const std::string disassembly_text = + AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_); + for (const auto& substring : kMinimalShaderDisassemblySubstrings) { + EXPECT_THAT(disassembly_text, HasSubstr(substring)); + } + // Check that we still have debug instructions. + EXPECT_THAT(disassembly_text, HasSubstr("OpName")); + EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); +} + +TEST_F(CppInterface, GenerateDebugInfoOverridesOptimizationLevel) { + options_.SetOptimizationLevel(shaderc_optimization_level_size); + // Optimization level settings overridden by + options_.SetGenerateDebugInfo(); + const std::string disassembly_text = + AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_); + for (const auto& substring : kMinimalShaderDisassemblySubstrings) { + EXPECT_THAT(disassembly_text, HasSubstr(substring)); + } + // Check that we still have debug instructions. + EXPECT_THAT(disassembly_text, HasSubstr("OpName")); + EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); +} + +TEST_F(CppInterface, GenerateDebugInfoProhibitsOptimizationLevel) { + // Setting generate debug info first also works. + options_.SetGenerateDebugInfo(); + options_.SetOptimizationLevel(shaderc_optimization_level_size); + const std::string disassembly_text = + AssemblyOutput(kMinimalShader, shaderc_glsl_vertex_shader, options_); + for (const auto& substring : kMinimalShaderDisassemblySubstrings) { + EXPECT_THAT(disassembly_text, HasSubstr(substring)); + } + // Check that we still have debug instructions. + EXPECT_THAT(disassembly_text, HasSubstr("OpName")); + EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); +} + +TEST_F(CppInterface, GetNumErrors) { + std::string shader(kTwoErrorsShader); + const SpvCompilationResult compilation_result = + compiler_.CompileGlslToSpv(kTwoErrorsShader, strlen(kTwoErrorsShader), + shaderc_glsl_vertex_shader, "shader"); + EXPECT_FALSE(CompilationResultIsSuccess(compilation_result)); + EXPECT_EQ(2u, compilation_result.GetNumErrors()); + EXPECT_EQ(0u, compilation_result.GetNumWarnings()); +} + +TEST_F(CppInterface, GetNumWarnings) { + const SpvCompilationResult compilation_result = + compiler_.CompileGlslToSpv(kTwoWarningsShader, strlen(kTwoWarningsShader), + shaderc_glsl_vertex_shader, "shader"); + EXPECT_TRUE(CompilationResultIsSuccess(compilation_result)); + EXPECT_EQ(2u, compilation_result.GetNumWarnings()); + EXPECT_EQ(0u, compilation_result.GetNumErrors()); +} + +TEST_F(CppInterface, ZeroErrorsZeroWarnings) { + const SpvCompilationResult compilation_result = + compiler_.CompileGlslToSpv(kMinimalShader, strlen(kMinimalShader), + shaderc_glsl_vertex_shader, "shader"); + EXPECT_TRUE(CompilationResultIsSuccess(compilation_result)); + EXPECT_EQ(0u, compilation_result.GetNumErrors()); + EXPECT_EQ(0u, compilation_result.GetNumWarnings()); +} + +TEST_F(CppInterface, ErrorTypeUnknownShaderStage) { + // The shader kind/stage can not be determined, the error type field should + // indicate the error type is shaderc_shader_kind_error. + const SpvCompilationResult compilation_result = + compiler_.CompileGlslToSpv(kMinimalShader, strlen(kMinimalShader), + shaderc_glsl_infer_from_source, "shader"); + EXPECT_EQ(shaderc_compilation_status_invalid_stage, + compilation_result.GetCompilationStatus()); +} + +TEST_F(CppInterface, ErrorTypeCompilationError) { + // The shader kind is valid, the result object's error type field should + // indicate this compilaion fails due to compilation errors. + const SpvCompilationResult compilation_result = compiler_.CompileGlslToSpv( + kTwoErrorsShader, shaderc_glsl_vertex_shader, "shader"); + EXPECT_EQ(shaderc_compilation_status_compilation_error, + compilation_result.GetCompilationStatus()); +} + +TEST_F(CppInterface, ErrorTagIsInputFileName) { + std::string shader(kTwoErrorsShader); + const SpvCompilationResult compilation_result = + compiler_.CompileGlslToSpv(kTwoErrorsShader, strlen(kTwoErrorsShader), + shaderc_glsl_vertex_shader, "SampleInputFile"); + // Expects compilation failure errors. The error tag should be + // 'SampleInputFile' + EXPECT_FALSE(CompilationResultIsSuccess(compilation_result)); + EXPECT_THAT(compilation_result.GetErrorMessage(), + HasSubstr("SampleInputFile:3: error:")); +} + +TEST_F(CppInterface, PreprocessingOnlyOption) { + const PreprocessedSourceCompilationResult result = compiler_.PreprocessGlsl( + kMinimalShaderWithMacro, shaderc_glsl_vertex_shader, "shader", options_); + EXPECT_TRUE(CompilationResultIsSuccess(result)); + EXPECT_THAT(CompilerOutputAsString(result), HasSubstr("void main(){ }")); + + const std::string kMinimalShaderCloneOption = + "#version 140\n" + "#define E_CLONE_OPTION main\n" + "void E_CLONE_OPTION(){}\n"; + CompileOptions cloned_options(options_); + const PreprocessedSourceCompilationResult result_from_cloned_options = + compiler_.PreprocessGlsl(kMinimalShaderCloneOption, + shaderc_glsl_vertex_shader, "shader", + cloned_options); + EXPECT_TRUE(CompilationResultIsSuccess(result_from_cloned_options)); + EXPECT_THAT(CompilerOutputAsString(result_from_cloned_options), + HasSubstr("void main(){ }")); +} + +// A shader kind test case needs: 1) A shader text with or without #pragma +// annotation, 2) shader_kind. +struct ShaderKindTestCase { + const char* shader_; + shaderc_shader_kind shader_kind_; +}; + +// Test the shader kind deduction process. If the shader kind is one +// of the non-default ones, the compiler will just try to compile the +// source code in that specified shader kind. If the shader kind is +// shaderc_glsl_deduce_from_pragma, the compiler will determine the shader +// kind from #pragma annotation in the source code and emit error if none +// such annotation is found. When the shader kind is one of the default +// ones, the compiler will fall back to use the specified shader kind if +// and only if #pragma annoation is not found. + +// Valid shader kind settings should generate valid SPIR-V code. +using ValidShaderKind = testing::TestWithParam<ShaderKindTestCase>; + +TEST_P(ValidShaderKind, ValidSpvCode) { + const ShaderKindTestCase& test_case = GetParam(); + shaderc::Compiler compiler; + EXPECT_TRUE( + CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_)); +} + +INSTANTIATE_TEST_CASE_P( + CompileStringTest, ValidShaderKind, + testing::ValuesIn(std::vector<ShaderKindTestCase>{ + // Valid default shader kinds. + {kEmpty310ESShader, shaderc_glsl_default_vertex_shader}, + {kEmpty310ESShader, shaderc_glsl_default_fragment_shader}, + {kEmpty310ESShader, shaderc_glsl_default_compute_shader}, + {kGeometryOnlyShader, shaderc_glsl_default_geometry_shader}, + {kTessControlOnlyShader, shaderc_glsl_default_tess_control_shader}, + {kTessEvaluationOnlyShader, + shaderc_glsl_default_tess_evaluation_shader}, + + // #pragma annotation overrides default shader kinds. + {kVertexOnlyShaderWithPragma, shaderc_glsl_default_compute_shader}, + {kFragmentOnlyShaderWithPragma, shaderc_glsl_default_vertex_shader}, + {kTessControlOnlyShaderWithPragma, + shaderc_glsl_default_fragment_shader}, + {kTessEvaluationOnlyShaderWithPragma, + shaderc_glsl_default_tess_control_shader}, + {kGeometryOnlyShaderWithPragma, + shaderc_glsl_default_tess_evaluation_shader}, + {kComputeOnlyShaderWithPragma, shaderc_glsl_default_geometry_shader}, + + // Specified non-default shader kind overrides #pragma annotation. + {kVertexOnlyShaderWithInvalidPragma, shaderc_glsl_vertex_shader}, + })); + +// Invalid shader kind settings should generate errors. +using InvalidShaderKind = testing::TestWithParam<ShaderKindTestCase>; + +TEST_P(InvalidShaderKind, CompilationShouldFail) { + const ShaderKindTestCase& test_case = GetParam(); + shaderc::Compiler compiler; + EXPECT_FALSE( + CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_)); +} + +INSTANTIATE_TEST_CASE_P( + CompileStringTest, InvalidShaderKind, + testing::ValuesIn(std::vector<ShaderKindTestCase>{ + // Invalid default shader kind. + {kVertexOnlyShader, shaderc_glsl_default_fragment_shader}, + // Sets to deduce shader kind from #pragma, but #pragma is defined in + // the source code. + {kVertexOnlyShader, shaderc_glsl_infer_from_source}, + // Invalid #pragma cause errors, even though default shader kind is set + // to valid shader kind. + {kVertexOnlyShaderWithInvalidPragma, + shaderc_glsl_default_vertex_shader}, + })); + +// To test file inclusion, use an unordered_map as a fake file system to store +// fake files to be included. The unordered_map represents a filesystem by +// mapping filename (or path) string to the contents of that file as a string. +using FakeFS = std::unordered_map<std::string, std::string>; + +// An includer test case needs: 1) A fake file system which is actually an +// unordered_map, so that we can resolve the content given a string. A valid +// fake file system must have one entry with key:'root' to specify the start +// shader file for compilation. 2) An string that we expect to see in the +// compilation output. +class IncluderTestCase { + public: + IncluderTestCase(FakeFS fake_fs, std::string expected_substring) + : fake_fs_(fake_fs), expected_substring_(expected_substring) { + assert(fake_fs_.find("root") != fake_fs_.end() && + "Valid fake file system needs a 'root' file\n"); + } + + const FakeFS& fake_fs() const { return fake_fs_; } + const std::string& expected_substring() const { return expected_substring_; } + + private: + FakeFS fake_fs_; + std::string expected_substring_; +}; + +// A mock class that simulates an includer. This class implements +// IncluderInterface to provide GetInclude() and ReleaseInclude() methods. +class TestIncluder : public shaderc::CompileOptions::IncluderInterface { + public: + explicit TestIncluder(const FakeFS& fake_fs) + : fake_fs_(fake_fs), responses_({}) {} + + // Get path and content from the fake file system. + shaderc_include_result* GetInclude(const char* requested_source, + shaderc_include_type type, + const char* requesting_source, + size_t include_depth) override { + responses_.emplace_back(shaderc_include_result{ + requested_source, strlen(requested_source), + fake_fs_.at(std::string(requested_source)).c_str(), + fake_fs_.at(std::string(requested_source)).size()}); + return &responses_.back(); + } + + // Response data is owned as private property, no need to release explicitly. + void ReleaseInclude(shaderc_include_result*) override {} + + private: + const FakeFS& fake_fs_; + std::vector<shaderc_include_result> responses_; +}; + +using IncluderTests = testing::TestWithParam<IncluderTestCase>; + +// Parameterized tests for includer. +TEST_P(IncluderTests, SetIncluder) { + const IncluderTestCase& test_case = GetParam(); + const FakeFS& fs = test_case.fake_fs(); + const std::string& shader = fs.at("root"); + shaderc::Compiler compiler; + CompileOptions options; + options.SetIncluder(std::unique_ptr<TestIncluder>(new TestIncluder(fs))); + const auto compilation_result = compiler.PreprocessGlsl( + shader.c_str(), shaderc_glsl_vertex_shader, "shader", options); + // Checks the existence of the expected string. + EXPECT_THAT(CompilerOutputAsString(compilation_result), + HasSubstr(test_case.expected_substring())); +} + +TEST_P(IncluderTests, SetIncluderClonedOptions) { + const IncluderTestCase& test_case = GetParam(); + const FakeFS& fs = test_case.fake_fs(); + const std::string& shader = fs.at("root"); + shaderc::Compiler compiler; + CompileOptions options; + options.SetIncluder(std::unique_ptr<TestIncluder>(new TestIncluder(fs))); + + // Cloned options should have all the settings. + CompileOptions cloned_options(options); + const auto compilation_result = compiler.PreprocessGlsl( + shader.c_str(), shaderc_glsl_vertex_shader, "shader", cloned_options); + // Checks the existence of the expected string. + EXPECT_THAT(CompilerOutputAsString(compilation_result), + HasSubstr(test_case.expected_substring())); +} + +INSTANTIATE_TEST_CASE_P(CppInterface, IncluderTests, + testing::ValuesIn(std::vector<IncluderTestCase>{ + IncluderTestCase( + // Fake file system. + { + {"root", + "#version 150\n" + "void foo() {}\n" + "#include \"path/to/file_1\"\n"}, + {"path/to/file_1", "content of file_1\n"}, + }, + // Expected output. + "#line 0 \"path/to/file_1\"\n" + " content of file_1\n" + "#line 3"), + IncluderTestCase( + // Fake file system. + {{"root", + "#version 150\n" + "void foo() {}\n" + "#include \"path/to/file_1\"\n"}, + {"path/to/file_1", + "#include \"path/to/file_2\"\n" + "content of file_1\n"}, + {"path/to/file_2", "content of file_2\n"}}, + // Expected output. + "#line 0 \"path/to/file_1\"\n" + "#line 0 \"path/to/file_2\"\n" + " content of file_2\n" + "#line 1 \"path/to/file_1\"\n" + " content of file_1\n" + "#line 3"), + + })); + +TEST_F(CppInterface, WarningsOnLine) { + // By default the compiler will emit a warning on line 2 complaining + // that 'float' is a deprecated attribute in version 130. + EXPECT_THAT( + CompilationWarnings(kDeprecatedAttributeShader, + shaderc_glsl_vertex_shader, CompileOptions()), + HasSubstr(":2: warning: attribute deprecated in version 130; may be " + "removed in future release\n")); +} + +TEST_F(CppInterface, SuppressWarningsOnLine) { + // Sets the compiler to suppress warnings, so that the deprecated attribute + // warning won't be emitted. + options_.SetSuppressWarnings(); + EXPECT_EQ("", CompilationWarnings(kDeprecatedAttributeShader, + shaderc_glsl_vertex_shader, options_)); +} + +TEST_F(CppInterface, SuppressWarningsOnLineClonedOptions) { + // Sets the compiler to suppress warnings, so that the deprecated attribute + // warning won't be emitted, and the mode should be carried into any clone of + // the original option object. + options_.SetSuppressWarnings(); + CompileOptions cloned_options(options_); + EXPECT_EQ("", + CompilationWarnings(kDeprecatedAttributeShader, + shaderc_glsl_vertex_shader, cloned_options)); +} + +TEST_F(CppInterface, WarningsOnLineAsErrors) { + // Sets the compiler to make warnings into errors. So that the deprecated + // attribute warning will be emitted as an error and compilation should fail. + options_.SetWarningsAsErrors(); + EXPECT_THAT( + CompilationErrors(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, + options_), + HasSubstr(":2: error: attribute deprecated in version 130; may be " + "removed in future release\n")); +} + +TEST_F(CppInterface, WarningsOnLineAsErrorsClonedOptions) { + // Sets the compiler to make warnings into errors. So that the deprecated + // attribute warning will be emitted as an error and compilation should fail. + options_.SetWarningsAsErrors(); + CompileOptions cloned_options(options_); + // The error message should show an error instead of a warning. + EXPECT_THAT( + CompilationErrors(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, + cloned_options), + HasSubstr(":2: error: attribute deprecated in version 130; may be " + "removed in future release\n")); +} + +TEST_F(CppInterface, GlobalWarnings) { + // By default the compiler will emit a warning as version 550 is an unknown + // version. + options_.SetForcedVersionProfile(400, shaderc_profile_core); + EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, options_), + HasSubstr("(version, profile) forced to be (400, core)," + " while in source code it is (550, none)\n")); +} + +TEST_F(CppInterface, SuppressGlobalWarnings) { + // Sets the compiler to suppress warnings, so that the unknown version warning + // won't be emitted. + options_.SetSuppressWarnings(); + options_.SetForcedVersionProfile(400, shaderc_profile_core); + EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, options_), + Eq("")); +} + +TEST_F(CppInterface, SuppressGlobalWarningsClonedOptions) { + // Sets the compiler to suppress warnings, so that the unknown version warning + // won't be emitted, and the mode should be carried into any clone of the + // original option object. + options_.SetSuppressWarnings(); + options_.SetForcedVersionProfile(400, shaderc_profile_core); + CompileOptions cloned_options(options_); + EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, cloned_options), + Eq("")); +} + +TEST_F(CppInterface, GlobalWarningsAsErrors) { + // Sets the compiler to make warnings into errors. So that the unknown + // version warning will be emitted as an error and compilation should fail. + options_.SetWarningsAsErrors(); + options_.SetForcedVersionProfile(400, shaderc_profile_core); + EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, options_), + HasSubstr("(version, profile) forced to be (400, core)," + " while in source code it is (550, none)\n")); +} + +TEST_F(CppInterface, GlobalWarningsAsErrorsClonedOptions) { + // Sets the compiler to make warnings into errors. This mode should be carried + // into any clone of the original option object. + options_.SetWarningsAsErrors(); + options_.SetForcedVersionProfile(400, shaderc_profile_core); + CompileOptions cloned_options(options_); + EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, cloned_options), + HasSubstr("(version, profile) forced to be (400, core)," + " while in source code it is (550, none)\n")); +} + +TEST_F(CppInterface, SuppressWarningsModeFirstOverridesWarningsAsErrorsMode) { + // Sets suppress-warnings mode first, then sets warnings-as-errors mode. + // suppress-warnings mode should override warnings-as-errors mode, no + // error message should be output for this case. + options_.SetSuppressWarnings(); + options_.SetWarningsAsErrors(); + // Warnings on line should be inhibited. + EXPECT_EQ("", CompilationWarnings(kDeprecatedAttributeShader, + shaderc_glsl_vertex_shader, options_)); + + // Global warnings should be inhibited. + // However, the unknown version will cause an error. + EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, options_), + Eq("shader: error: version not supported\n")); +} + +TEST_F(CppInterface, SuppressWarningsModeSecondOverridesWarningsAsErrorsMode) { + // Sets warnings-as-errors mode first, then sets suppress-warnings mode. + // suppress-warnings mode should override warnings-as-errors mode, no + // error message should be output for this case. + options_.SetWarningsAsErrors(); + options_.SetSuppressWarnings(); + // Warnings on line should be inhibited. + EXPECT_EQ("", CompilationWarnings(kDeprecatedAttributeShader, + shaderc_glsl_vertex_shader, options_)); + + // Global warnings should be inhibited. + // However, the unknown version will cause an error. + EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, options_), + Eq("shader: error: version not supported\n")); +} + +TEST_F(CppInterface, TargetEnvCompileOptionsOpenGLCompatibilityShadersFail) { + // Glslang does not support SPIR-V code generation for OpenGL compatibility + // profile. + options_.SetTargetEnvironment(shaderc_target_env_opengl_compat, 0); + const std::string kGlslShader = + R"(#version 150 compatibility + uniform highp sampler2D tex; + void main() { + gl_FragColor = texture2D(tex, vec2(0.0,0.0)); + } + )"; + + EXPECT_THAT( + CompilationErrors(kGlslShader, shaderc_glsl_fragment_shader, options_), + HasSubstr( + "compilation for SPIR-V does not support the compatibility profile")); +} + +std::string BarrierComputeShader() { + return R"(#version 450 + void main() { barrier(); })"; +}; + +std::string SubgroupBarrierComputeShader() { + return R"(#version 450 + #extension GL_KHR_shader_subgroup_basic : enable + void main() { subgroupBarrier(); })"; +}; + +TEST_F(CppInterface, TargetEnvCompileOptionsVulkanEnvVulkan1_0ShaderSucceeds) { + options_.SetTargetEnvironment(shaderc_target_env_vulkan, 0); + EXPECT_TRUE(CompilationSuccess(BarrierComputeShader(), + shaderc_glsl_compute_shader, options_)); +} + +TEST_F(CppInterface, TargetEnvCompileOptionsVulkanEnvVulkan1_0ShaderFails) { + options_.SetTargetEnvironment(shaderc_target_env_vulkan, 0); + EXPECT_FALSE(CompilationSuccess(SubgroupBarrierComputeShader(), + shaderc_glsl_compute_shader, options_)); +} + +TEST_F(CppInterface, + TargetEnvCompileOptionsVulkan1_0EnvVulkan1_0ShaderSucceeds) { + options_.SetTargetEnvironment(shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_0); + EXPECT_TRUE(CompilationSuccess(BarrierComputeShader(), + shaderc_glsl_compute_shader, options_)); +} + +TEST_F(CppInterface, TargetEnvCompileOptionsVulkan1_0EnvVulkan1_1ShaderFails) { + options_.SetTargetEnvironment(shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_0); + EXPECT_FALSE(CompilationSuccess(SubgroupBarrierComputeShader(), + shaderc_glsl_compute_shader, options_)); +} + +TEST_F(CppInterface, + TargetEnvCompileOptionsVulkan1_1EnvVulkan1_0ShaderSucceeds) { + options_.SetTargetEnvironment(shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_1); + EXPECT_TRUE(CompilationSuccess(BarrierComputeShader(), + shaderc_glsl_compute_shader, options_)); +} + +TEST_F(CppInterface, + TargetEnvCompileOptionsVulkan1_1EnvVulkan1_1ShaderSucceeds) { + options_.SetTargetEnvironment(shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_1); + EXPECT_TRUE(CompilationSuccess(SubgroupBarrierComputeShader(), + shaderc_glsl_compute_shader, options_)); +} + +TEST_F(CppInterface, BeginAndEndOnSpvCompilationResult) { + const SpvCompilationResult compilation_result = compiler_.CompileGlslToSpv( + kMinimalShader, shaderc_glsl_vertex_shader, "shader"); + EXPECT_TRUE(IsValidSpv(compilation_result)); + // Use range-based for to exercise begin() and end(). + std::vector<uint32_t> binary_words; + for (const auto& element : compilation_result) { + binary_words.push_back(element); + } + EXPECT_THAT(binary_words, + Eq(std::vector<uint32_t>(compilation_result.cbegin(), + compilation_result.cend()))); +} + +TEST_F(CppInterface, BeginAndEndOnAssemblyCompilationResult) { + const AssemblyCompilationResult compilation_result = + compiler_.CompileGlslToSpvAssembly( + kMinimalShader, shaderc_glsl_vertex_shader, "shader", options_); + const std::string forced_to_be_a_string = + CompilerOutputAsString(compilation_result); + EXPECT_THAT(forced_to_be_a_string, HasSubstr("MemoryModel")); + const std::string string_via_begin_end(compilation_result.begin(), + compilation_result.end()); + EXPECT_THAT(string_via_begin_end, Eq(forced_to_be_a_string)); +} + +TEST_F(CppInterface, BeginAndEndOnPreprocessedResult) { + const PreprocessedSourceCompilationResult compilation_result = + compiler_.PreprocessGlsl(kMinimalShader, shaderc_glsl_vertex_shader, + "shader", options_); + const std::string forced_to_be_a_string = + CompilerOutputAsString(compilation_result); + EXPECT_THAT(forced_to_be_a_string, HasSubstr("void main()")); + const std::string string_via_begin_end(compilation_result.begin(), + compilation_result.end()); + EXPECT_THAT(string_via_begin_end, Eq(forced_to_be_a_string)); +} + +TEST_F(CppInterface, SourceLangGlslMinimalGlslVertexShaderSucceeds) { + options_.SetSourceLanguage(shaderc_source_language_glsl); + EXPECT_TRUE(CompilationSuccess(kVertexOnlyShader, shaderc_glsl_vertex_shader, + options_)); +} + +TEST_F(CppInterface, SourceLangGlslMinimalHlslVertexShaderFails) { + options_.SetSourceLanguage(shaderc_source_language_glsl); + EXPECT_FALSE(CompilationSuccess(kMinimalHlslShader, + shaderc_glsl_vertex_shader, options_)); +} + +TEST_F(CppInterface, SourceLangHlslMinimalGlslVertexShaderFails) { + options_.SetSourceLanguage(shaderc_source_language_hlsl); + EXPECT_FALSE(CompilationSuccess(kVertexOnlyShader, shaderc_glsl_vertex_shader, + options_)); +} + +TEST_F(CppInterface, SourceLangHlslMinimalHlslVertexShaderSucceeds) { + options_.SetSourceLanguage(shaderc_source_language_hlsl); + EXPECT_TRUE(CompilationSuccess(kMinimalHlslShader, shaderc_glsl_vertex_shader, + options_)); +} + +TEST( + EntryPointTest, + SourceLangHlslMinimalHlslVertexShaderAsConstCharPtrSucceedsWithEntryPointName) { + shaderc::Compiler compiler; + CompileOptions options; + options.SetSourceLanguage(shaderc_source_language_hlsl); + auto result = compiler.CompileGlslToSpv( + kMinimalHlslShader, strlen(kMinimalHlslShader), + shaderc_glsl_vertex_shader, "shader", "EntryPoint", options); + std::vector<uint32_t> binary(result.begin(), result.end()); + std::string assembly; + spvtools::SpirvTools(SPV_ENV_UNIVERSAL_1_0).Disassemble(binary, &assembly); + EXPECT_THAT(assembly, + HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\"")) + << assembly; +} + +TEST( + EntryPointTest, + SourceLangHlslMinimalHlslVertexShaderAsStdStringSucceedsWithEntryPointName) { + shaderc::Compiler compiler; + CompileOptions options; + options.SetSourceLanguage(shaderc_source_language_hlsl); + std::string shader(kMinimalHlslShader); + auto result = compiler.CompileGlslToSpv(shader, shaderc_glsl_vertex_shader, + "shader", "EntryPoint", options); + std::vector<uint32_t> binary(result.begin(), result.end()); + std::string assembly; + spvtools::SpirvTools(SPV_ENV_UNIVERSAL_1_0).Disassemble(binary, &assembly); + EXPECT_THAT(assembly, + HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\"")) + << assembly; +} + +TEST( + EntryPointTest, + SourceLangHlslMinimalHlslVertexShaderAsConstCharPtrSucceedsToAssemblyWithEntryPointName) { + shaderc::Compiler compiler; + CompileOptions options; + options.SetSourceLanguage(shaderc_source_language_hlsl); + auto assembly = compiler.CompileGlslToSpvAssembly( + kMinimalHlslShader, strlen(kMinimalHlslShader), + shaderc_glsl_vertex_shader, "shader", "EntryPoint", options); + EXPECT_THAT(std::string(assembly.begin(), assembly.end()), + HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\"")); +} + +TEST( + EntryPointTest, + SourceLangHlslMinimalHlslVertexShaderAsStdStringSucceedsToAssemblyWithEntryPointName) { + shaderc::Compiler compiler; + CompileOptions options; + options.SetSourceLanguage(shaderc_source_language_hlsl); + std::string shader(kMinimalHlslShader); + auto assembly = compiler.CompileGlslToSpvAssembly( + shader, shaderc_glsl_vertex_shader, "shader", "EntryPoint", options); + EXPECT_THAT(std::string(assembly.begin(), assembly.end()), + HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\"")); +} + +// Returns a fragment shader accessing a texture with the given +// offset. +std::string ShaderWithTexOffset(int offset) { + std::ostringstream oss; + oss << "#version 450\n" + "layout (binding=0) uniform sampler1D tex;\n" + "void main() { vec4 x = textureOffset(tex, 1.0, " + << offset << "); }\n"; + return oss.str(); +} + +// Ensure compilation is sensitive to limit setting. Sample just +// two particular limits. +TEST_F(CppInterface, LimitsTexelOffsetDefault) { + EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-9).c_str(), + shaderc_glsl_fragment_shader, options_)); + EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(), + shaderc_glsl_fragment_shader, options_)); + EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(), + shaderc_glsl_fragment_shader, options_)); + EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(8).c_str(), + shaderc_glsl_fragment_shader, options_)); +} + +TEST_F(CppInterface, LimitsTexelOffsetLowerMinimum) { + options_.SetLimit(shaderc_limit_min_program_texel_offset, -99); + EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-100).c_str(), + shaderc_glsl_fragment_shader, options_)); + EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-99).c_str(), + shaderc_glsl_fragment_shader, options_)); +} + +TEST_F(CppInterface, LimitsTexelOffsetHigherMaximum) { + options_.SetLimit(shaderc_limit_max_program_texel_offset, 10); + EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(10).c_str(), + shaderc_glsl_fragment_shader, options_)); + EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(11).c_str(), + shaderc_glsl_fragment_shader, options_)); +} + +TEST_F(CppInterface, UniformsWithoutBindingsFailCompilation) { + CompileOptions options; + const std::string errors = CompilationErrors( + kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options); + EXPECT_THAT(errors, + HasSubstr("sampler/texture/image requires layout(binding=X)")); +} + +TEST_F(CppInterface, + UniformsWithoutBindingsOptionSetAutoBindingsAssignsBindings) { + CompileOptions options; + options.SetAutoBindUniforms(true); + const std::string disassembly_text = AssemblyOutput( + kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4")); +} + +TEST_F(CppInterface, SetBindingBaseForTextureAdjustsTextureBindingsOnly) { + CompileOptions options; + options.SetAutoBindUniforms(true); + options.SetBindingBase(shaderc_uniform_kind_texture, 44); + const std::string disassembly_text = AssemblyOutput( + kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 44")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3")); +} + +TEST_F(CppInterface, SetBindingBaseForSamplerAdjustsSamplerBindingsOnly) { + CompileOptions options; + options.SetAutoBindUniforms(true); + options.SetBindingBase(shaderc_uniform_kind_sampler, 44); + const std::string disassembly_text = AssemblyOutput( + kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 44")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3")); +} + +TEST_F(CppInterface, SetBindingBaseForImageAdjustsImageBindingsOnly) { + CompileOptions options; + options.SetAutoBindUniforms(true); + options.SetBindingBase(shaderc_uniform_kind_image, 44); + const std::string disassembly_text = AssemblyOutput( + kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 44")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 45")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 2")); +} + +TEST_F(CppInterface, SetBindingBaseForBufferAdjustsBufferBindingsOnly) { + CompileOptions options; + options.SetAutoBindUniforms(true); + options.SetBindingBase(shaderc_uniform_kind_buffer, 44); + const std::string disassembly_text = AssemblyOutput( + kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, options); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 44")); +} + +TEST_F(CppInterface, SetBindingBaseSurvivesCloning) { + CompileOptions options; + options.SetAutoBindUniforms(true); + options.SetBindingBase(shaderc_uniform_kind_texture, 40); + options.SetBindingBase(shaderc_uniform_kind_sampler, 50); + options.SetBindingBase(shaderc_uniform_kind_image, 60); + options.SetBindingBase(shaderc_uniform_kind_buffer, 70); + CompileOptions cloned_options(options); + const std::string disassembly_text = + AssemblyOutput(kShaderWithUniformsWithoutBindings, + shaderc_glsl_vertex_shader, cloned_options); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 40")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 50")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 60")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 61")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 70")); +} + +TEST_F(CppInterface, GlslDefaultPackingUsed) { + CompileOptions options; + const std::string disassembly_text = AssemblyOutput( + kGlslShaderWeirdPacking, shaderc_glsl_vertex_shader, options); + EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16")); +} + +TEST_F(CppInterface, HlslOffsetsOptionDisableRespected) { + CompileOptions options; + options.SetHlslOffsets(false); + const std::string disassembly_text = AssemblyOutput( + kGlslShaderWeirdPacking, shaderc_glsl_vertex_shader, options); + EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16")); +} + +TEST_F(CppInterface, HlslOffsetsOptionEnableRespected) { + CompileOptions options; + options.SetHlslOffsets(true); + const std::string disassembly_text = AssemblyOutput( + kGlslShaderWeirdPacking, shaderc_glsl_vertex_shader, options); + EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 4")); +} + +TEST_F(CppInterface, HlslRegSetBindingForFragmentRespected) { + CompileOptions options; + options.SetSourceLanguage(shaderc_source_language_hlsl); + options.SetHlslRegisterSetAndBindingForStage(shaderc_fragment_shader, "t4", + "9", "16"); + const std::string disassembly_text = AssemblyOutput( + kHlslFragShaderWithRegisters, shaderc_glsl_fragment_shader, options); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 DescriptorSet 9")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 Binding 16")); +} + +TEST_F(CppInterface, HlslRegSetBindingForDifferentStageIgnored) { + CompileOptions options; + options.SetSourceLanguage(shaderc_source_language_hlsl); + options.SetHlslRegisterSetAndBindingForStage(shaderc_vertex_shader, "t4", "9", + "16"); + const std::string disassembly_text = AssemblyOutput( + kHlslFragShaderWithRegisters, shaderc_glsl_fragment_shader, options); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 DescriptorSet 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 Binding 4")); +} + +TEST_F(CppInterface, HlslRegSetBindingForAllStagesRespected) { + CompileOptions options; + options.SetSourceLanguage(shaderc_source_language_hlsl); + options.SetHlslRegisterSetAndBinding("t4", "9", "16"); + const std::string disassembly_text = AssemblyOutput( + kHlslFragShaderWithRegisters, shaderc_glsl_fragment_shader, options); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 DescriptorSet 9")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %t4 Binding 16")); +} + +TEST_F(CppInterface, HlslFunctionality1OffByDefault) { + CompileOptions options; + options.SetSourceLanguage(shaderc_source_language_hlsl); + const std::string disassembly_text = AssemblyOutput( + kHlslShaderWithCounterBuffer, shaderc_glsl_fragment_shader, options); + EXPECT_THAT(disassembly_text, Not(HasSubstr("OpDecorateStringGOOGLE"))); +} + +TEST_F(CppInterface, HlslFunctionality1Respected) { + CompileOptions options; + options.SetSourceLanguage(shaderc_source_language_hlsl); + options.SetHlslFunctionality1(true); + const std::string disassembly_text = AssemblyOutput( + kHlslShaderWithCounterBuffer, shaderc_glsl_fragment_shader, options); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateStringGOOGLE")); +} + +TEST_F(CppInterface, HlslFunctionality1SurvivesCloning) { + CompileOptions options; + options.SetSourceLanguage(shaderc_source_language_hlsl); + options.SetHlslFunctionality1(true); + CompileOptions cloned_options(options); + const std::string disassembly_text = AssemblyOutput( + kHlslShaderWithCounterBuffer, shaderc_glsl_fragment_shader, cloned_options); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateStringGOOGLE")); +} + +} // anonymous namespace diff --git a/chromium/third_party/shaderc/src/libshaderc/src/shaderc_private.h b/chromium/third_party/shaderc/src/libshaderc/src/shaderc_private.h new file mode 100644 index 00000000000..30dc86366cb --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc/src/shaderc_private.h @@ -0,0 +1,141 @@ +// 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 { + 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; +#if NV_EXTENSIONS + 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; +#endif + default: + // We don't care about the other kinds. + break; + } + // This should not occur. + assert(false && "Should have specified a specific stage"); + return shaderc_util::Compiler::Stage::TessEval; +} + +#endif // LIBSHADERC_SRC_SHADERC_PRIVATE_H_ diff --git a/chromium/third_party/shaderc/src/libshaderc/src/shaderc_private_test.cc b/chromium/third_party/shaderc/src/libshaderc/src/shaderc_private_test.cc new file mode 100644 index 00000000000..3b645512f8b --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc/src/shaderc_private_test.cc @@ -0,0 +1,52 @@ +// 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)); +#ifdef NV_EXTENSIONS + 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)); +#endif +} +} // anonymous namespace diff --git a/chromium/third_party/shaderc/src/libshaderc/src/shaderc_test.cc b/chromium/third_party/shaderc/src/libshaderc/src/shaderc_test.cc new file mode 100644 index 00000000000..3e3d6b9dbc3 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc/src/shaderc_test.cc @@ -0,0 +1,1820 @@ +// 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 <gmock/gmock.h> +#include <gtest/gtest.h> +#include <memory> +#include <thread> +#include <unordered_map> + +#include "SPIRV/spirv.hpp" + +#include "common_shaders_for_test.h" +#include "shaderc/shaderc.h" + +namespace { + +using testing::Each; +using testing::HasSubstr; +using testing::Not; + +TEST(Init, MultipleCalls) { + shaderc_compiler_t compiler1, compiler2, compiler3; + EXPECT_NE(nullptr, compiler1 = shaderc_compiler_initialize()); + EXPECT_NE(nullptr, compiler2 = shaderc_compiler_initialize()); + EXPECT_NE(nullptr, compiler3 = shaderc_compiler_initialize()); + shaderc_compiler_release(compiler1); + shaderc_compiler_release(compiler2); + shaderc_compiler_release(compiler3); +} + +#ifndef SHADERC_DISABLE_THREADED_TESTS +TEST(Init, MultipleThreadsCalling) { + shaderc_compiler_t compiler1, compiler2, compiler3; + std::thread t1([&compiler1]() { compiler1 = shaderc_compiler_initialize(); }); + std::thread t2([&compiler2]() { compiler2 = shaderc_compiler_initialize(); }); + std::thread t3([&compiler3]() { compiler3 = shaderc_compiler_initialize(); }); + t1.join(); + t2.join(); + t3.join(); + EXPECT_NE(nullptr, compiler1); + EXPECT_NE(nullptr, compiler2); + EXPECT_NE(nullptr, compiler3); + shaderc_compiler_release(compiler1); + shaderc_compiler_release(compiler2); + shaderc_compiler_release(compiler3); +} +#endif + +TEST(Init, SPVVersion) { + unsigned int version = 0; + unsigned int revision = 0; + shaderc_get_spv_version(&version, &revision); + EXPECT_EQ(spv::Version, version); + EXPECT_EQ(spv::Revision, revision); +} + +// Determines the kind of output required from the compiler. +enum class OutputType { + SpirvBinary, + SpirvAssemblyText, + PreprocessedText, +}; + +// Generate a compilation result object with the given compile, +// shader source, shader kind, input file name, entry point name, options, +// and for the specified output type. The entry point name is only significant +// for HLSL compilation. +shaderc_compilation_result_t MakeCompilationResult( + const shaderc_compiler_t compiler, const std::string& shader, + shaderc_shader_kind kind, const char* input_file_name, + const char* entry_point_name, const shaderc_compile_options_t options, + OutputType output_type) { + switch (output_type) { + case OutputType::SpirvBinary: + return shaderc_compile_into_spv(compiler, shader.c_str(), shader.size(), + kind, input_file_name, entry_point_name, + options); + break; + case OutputType::SpirvAssemblyText: + return shaderc_compile_into_spv_assembly( + compiler, shader.c_str(), shader.size(), kind, input_file_name, + entry_point_name, options); + break; + case OutputType::PreprocessedText: + return shaderc_compile_into_preprocessed_text( + compiler, shader.c_str(), shader.size(), kind, input_file_name, + entry_point_name, options); + break; + } + // We shouldn't reach here. But some compilers might not know that. + // Be a little defensive and produce something. + return shaderc_compile_into_spv(compiler, shader.c_str(), shader.size(), kind, + input_file_name, entry_point_name, options); +} + +// RAII class for shaderc_compilation_result. Used for shader compilation. +class Compilation { + public: + // Compiles shader and keeps the result. + Compilation(const shaderc_compiler_t compiler, const std::string& shader, + shaderc_shader_kind kind, const char* input_file_name, + const char* entry_point_name, + const shaderc_compile_options_t options = nullptr, + OutputType output_type = OutputType::SpirvBinary) + : compiled_result_( + MakeCompilationResult(compiler, shader, kind, input_file_name, + entry_point_name, options, output_type)) {} + + ~Compilation() { shaderc_result_release(compiled_result_); } + + shaderc_compilation_result_t result() const { return compiled_result_; } + + private: + shaderc_compilation_result_t compiled_result_; +}; + +// RAII class for shaderc_compilation_result. Used for shader assembling. +class Assembling { + public: + // Assembles shader and keeps the result. + Assembling(const shaderc_compiler_t compiler, const std::string& assembly, + const shaderc_compile_options_t options = nullptr) + : compiled_result_(shaderc_assemble_into_spv(compiler, assembly.data(), + assembly.size(), options)) {} + + ~Assembling() { shaderc_result_release(compiled_result_); } + + shaderc_compilation_result_t result() const { return compiled_result_; } + + private: + shaderc_compilation_result_t compiled_result_; +}; + +struct CleanupOptions { + void operator()(shaderc_compile_options_t options) const { + shaderc_compile_options_release(options); + } +}; + +typedef std::unique_ptr<shaderc_compile_options, CleanupOptions> + compile_options_ptr; + +// RAII class for shaderc_compiler_t +class Compiler { + public: + Compiler() { compiler = shaderc_compiler_initialize(); } + ~Compiler() { shaderc_compiler_release(compiler); } + shaderc_compiler_t get_compiler_handle() { return compiler; } + + private: + shaderc_compiler_t compiler; +}; + +// RAII class for shader_compiler_options_t +class Options { + public: + Options() : options_(shaderc_compile_options_initialize()) {} + ~Options() { shaderc_compile_options_release(options_); } + shaderc_compile_options_t get() { return options_; } + + private: + shaderc_compile_options_t options_; +}; + +// Helper function to check if the compilation result indicates a successful +// compilation. +bool CompilationResultIsSuccess(const shaderc_compilation_result_t result) { + return shaderc_result_get_compilation_status(result) == + shaderc_compilation_status_success; +} + +// Returns true if the given result contains a SPIR-V module that contains +// at least the number of bytes of the header and the correct magic number. +bool ResultContainsValidSpv(shaderc_compilation_result_t result) { + if (!CompilationResultIsSuccess(result)) return false; + size_t length = shaderc_result_get_length(result); + if (length < 20) return false; + const uint32_t* bytes = static_cast<const uint32_t*>( + static_cast<const void*>(shaderc_result_get_bytes(result))); + return bytes[0] == spv::MagicNumber; +} + +// Compiles a shader and returns true if the result is valid SPIR-V. +bool CompilesToValidSpv(Compiler& compiler, const std::string& shader, + shaderc_shader_kind kind, + const shaderc_compile_options_t options = nullptr) { + const Compilation comp(compiler.get_compiler_handle(), shader, kind, "shader", + "main", options, OutputType::SpirvBinary); + return ResultContainsValidSpv(comp.result()); +} + +// A testing class to test the compilation of a string with or without options. +// This class wraps the initailization of compiler and compiler options and +// groups the result checking methods. Subclass tests can access the compiler +// object and compiler option object to set their properties. Input file names +// are set to "shader". +class CompileStringTest : public testing::Test { + protected: + // Compiles a shader and returns true on success, false on failure. + bool CompilationSuccess(const std::string& shader, shaderc_shader_kind kind, + shaderc_compile_options_t options = nullptr, + OutputType output_type = OutputType::SpirvBinary) { + return CompilationResultIsSuccess( + Compilation(compiler_.get_compiler_handle(), shader, kind, "shader", + "main", options, output_type) + .result()); + } + + // Compiles a shader, expects compilation success, and returns the warning + // messages. + const std::string CompilationWarnings( + const std::string& shader, shaderc_shader_kind kind, + const shaderc_compile_options_t options = nullptr, + OutputType output_type = OutputType::SpirvBinary) { + const Compilation comp(compiler_.get_compiler_handle(), shader, kind, + "shader", "main", options, output_type); + EXPECT_TRUE(CompilationResultIsSuccess(comp.result())) << kind << '\n' + << shader; + return shaderc_result_get_error_message(comp.result()); + }; + + // Compiles a shader, expects compilation failure, and returns the messages. + const std::string CompilationErrors( + const std::string& shader, shaderc_shader_kind kind, + const shaderc_compile_options_t options = nullptr, + OutputType output_type = OutputType::SpirvBinary, + const char* source_name = "shader") { + const Compilation comp(compiler_.get_compiler_handle(), shader, kind, + source_name, "main", options, output_type); + EXPECT_FALSE(CompilationResultIsSuccess(comp.result())) << kind << '\n' + << shader; + EXPECT_EQ(0u, shaderc_result_get_length(comp.result())); + return shaderc_result_get_error_message(comp.result()); + }; + + // Compiles a shader and returns the messages. + const std::string CompilationMessages( + const std::string& shader, shaderc_shader_kind kind, + const shaderc_compile_options_t options = nullptr, + OutputType output_type = OutputType::SpirvBinary) { + const Compilation comp(compiler_.get_compiler_handle(), shader, kind, + "shader", "main", options, output_type); + return shaderc_result_get_error_message(comp.result()); + }; + + // Compiles a shader, expects compilation success, and returns the output + // bytes. + const std::string CompilationOutput( + const std::string& shader, shaderc_shader_kind kind, + const shaderc_compile_options_t options = nullptr, + OutputType output_type = OutputType::SpirvBinary) { + const Compilation comp(compiler_.get_compiler_handle(), shader, kind, + "shader", "main", options, output_type); + EXPECT_TRUE(CompilationResultIsSuccess(comp.result())) + << "shader kind: " << kind << "\nerror message: " + << shaderc_result_get_error_message(comp.result()) + << "\nshader source code: \n" + << shader; + // Use string(const char* s, size_t n) constructor instead of + // string(const char* s) to make sure the string has complete binary data. + // string(const char* s) assumes a null-terminated C-string, which will cut + // the binary data when it sees a '\0' byte. + return std::string(shaderc_result_get_bytes(comp.result()), + shaderc_result_get_length(comp.result())); + }; + + Compiler compiler_; + compile_options_ptr options_; + + public: + CompileStringTest() : options_(shaderc_compile_options_initialize()) {} +}; + +// A testing class to test the assembling of a string. +// This class wraps the initailization of compiler and groups the result +// checking methods. Subclass tests can access the compiler object to set their +// properties. +class AssembleStringTest : public testing::Test { + public: + AssembleStringTest() : options_(shaderc_compile_options_initialize()) {} + ~AssembleStringTest() { shaderc_compile_options_release(options_); } + + protected: + // Assembles the given assembly and returns true on success. + bool AssemblingSuccess(const std::string& assembly) { + return CompilationResultIsSuccess( + Assembling(compiler_.get_compiler_handle(), assembly, options_) + .result()); + } + + bool AssemblingValid(const std::string& assembly) { + const auto assembling = + Assembling(compiler_.get_compiler_handle(), assembly); + return ResultContainsValidSpv(assembling.result()); + } + + Compiler compiler_; + shaderc_compile_options_t options_; +}; + +// Name holders so that we have test cases being grouped with only one real +// compilation class. +using CompileStringWithOptionsTest = CompileStringTest; +using CompileKindsTest = CompileStringTest; + +TEST_F(CompileStringTest, EmptyString) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_vertex_shader)); + EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_fragment_shader)); +} + +TEST_F(AssembleStringTest, EmptyString) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_TRUE(AssemblingSuccess("")); +} + +TEST_F(CompileStringTest, GarbageString) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_vertex_shader)); + EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_fragment_shader)); +} + +TEST_F(AssembleStringTest, GarbageString) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + auto assembling = Assembling(compiler_.get_compiler_handle(), "jfalkds"); + EXPECT_FALSE(CompilationResultIsSuccess(assembling.result())); + EXPECT_EQ(1u, shaderc_result_get_num_errors(assembling.result())); + EXPECT_EQ(0u, shaderc_result_get_num_warnings(assembling.result())); +} + +// TODO(antiagainst): right now there is no assembling difference for all the +// target environments exposed by shaderc. So the following is just testing the +// target environment is accepted. +TEST_F(AssembleStringTest, AcceptTargetEnv) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + shaderc_compile_options_set_target_env(options_, shaderc_target_env_opengl, + /* version = */ 0); + EXPECT_TRUE(AssemblingSuccess("OpCapability Shader")); +} + +TEST_F(CompileStringTest, ReallyLongShader) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + std::string minimal_shader = ""; + minimal_shader += "#version 140\n"; + minimal_shader += "void foo(){}"; + minimal_shader.append(1024 * 1024 * 8, ' '); // 8MB of spaces. + minimal_shader += "void main(){}"; + EXPECT_TRUE(CompilesToValidSpv(compiler_, minimal_shader, + shaderc_glsl_vertex_shader)); + EXPECT_TRUE(CompilesToValidSpv(compiler_, minimal_shader, + shaderc_glsl_fragment_shader)); +} + +TEST_F(CompileStringTest, MinimalShader) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, + shaderc_glsl_vertex_shader)); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, + shaderc_glsl_fragment_shader)); +} + +TEST_F(AssembleStringTest, MinimalShader) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_TRUE(AssemblingValid(kMinimalShaderAssembly)); +} + +TEST_F(CompileStringTest, WorksWithCompileOptions) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, + shaderc_glsl_vertex_shader, options_.get())); +} + +TEST_F(CompileStringTest, GetNumErrors) { + Compilation comp(compiler_.get_compiler_handle(), kTwoErrorsShader, + shaderc_glsl_vertex_shader, "shader", "main"); + // Expects compilation failure and two errors. + EXPECT_FALSE(CompilationResultIsSuccess(comp.result())); + EXPECT_EQ(2u, shaderc_result_get_num_errors(comp.result())); + // Expects the number of warnings to be zero. + EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp.result())); +} + +TEST_F(CompileStringTest, GetNumWarnings) { + Compilation comp(compiler_.get_compiler_handle(), kTwoWarningsShader, + shaderc_glsl_vertex_shader, "shader", "main"); + // Expects compilation success with two warnings. + EXPECT_TRUE(CompilationResultIsSuccess(comp.result())); + EXPECT_EQ(2u, shaderc_result_get_num_warnings(comp.result())); + // Expects the number of errors to be zero. + EXPECT_EQ(0u, shaderc_result_get_num_errors(comp.result())); +} + +TEST_F(CompileStringTest, ZeroErrorsZeroWarnings) { + Compilation comp(compiler_.get_compiler_handle(), kMinimalShader, + shaderc_glsl_vertex_shader, "shader", "main"); + // Expects compilation success with zero warnings. + EXPECT_TRUE(CompilationResultIsSuccess(comp.result())); + EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp.result())); + // Expects the number of errors to be zero. + EXPECT_EQ(0u, shaderc_result_get_num_errors(comp.result())); +} + +TEST_F(CompileStringTest, ErrorTypeUnknownShaderStage) { + // The shader kind/stage can not be determined, the error type field should + // indicate the error type is shaderc_shader_kind_error. + Compilation comp(compiler_.get_compiler_handle(), kMinimalShader, + shaderc_glsl_infer_from_source, "shader", "main"); + EXPECT_EQ(shaderc_compilation_status_invalid_stage, + shaderc_result_get_compilation_status(comp.result())); +} +TEST_F(CompileStringTest, ErrorTypeCompilationError) { + // The shader kind is valid, the result object's error type field should + // indicate this compilaion fails due to compilation errors. + Compilation comp(compiler_.get_compiler_handle(), kTwoErrorsShader, + shaderc_glsl_vertex_shader, "shader", "main"); + EXPECT_EQ(shaderc_compilation_status_compilation_error, + shaderc_result_get_compilation_status(comp.result())); +} + +TEST_F(CompileStringWithOptionsTest, CloneCompilerOptions) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + compile_options_ptr options_(shaderc_compile_options_initialize()); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, + shaderc_glsl_vertex_shader, options_.get())); + compile_options_ptr cloned_options( + shaderc_compile_options_clone(options_.get())); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader, + shaderc_glsl_vertex_shader, + cloned_options.get())); +} + +TEST_F(CompileStringWithOptionsTest, MacroCompileOptions) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, "main", + 4u); + const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}"; + const std::string kMinimalDoubleExpandedShader = "#version 140\nF E(){}"; + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader, + shaderc_glsl_vertex_shader, options_.get())); + compile_options_ptr cloned_options( + shaderc_compile_options_clone(options_.get())); + // The simplest should still compile with the cloned options. + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader, + shaderc_glsl_vertex_shader, + cloned_options.get())); + EXPECT_FALSE(CompilesToValidSpv(compiler_, kMinimalDoubleExpandedShader, + shaderc_glsl_vertex_shader, + cloned_options.get())); + + shaderc_compile_options_add_macro_definition(cloned_options.get(), "F", 1u, + "void", 4u); + // This should still not work with the original options. + EXPECT_FALSE(CompilesToValidSpv(compiler_, kMinimalDoubleExpandedShader, + shaderc_glsl_vertex_shader, options_.get())); + // This should work with the cloned options that have the additional + // parameter. + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalDoubleExpandedShader, + shaderc_glsl_vertex_shader, + cloned_options.get())); +} + +TEST_F(CompileStringWithOptionsTest, MacroCompileOptionsNotNullTerminated) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + shaderc_compile_options_add_macro_definition(options_.get(), "EFGH", 1u, + "mainnnnnn", 4u); + const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}"; + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader, + shaderc_glsl_vertex_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, ValuelessMacroCompileOptionsZeroLength) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, + "somthing", 0u); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kValuelessPredefinitionShader, + shaderc_glsl_vertex_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, ValuelessMacroCompileOptionsNullPointer) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, nullptr, + 100u); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kValuelessPredefinitionShader, + shaderc_glsl_vertex_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, DisassemblyOption) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + // This should work with both the glslang native assembly format and the + // SPIR-V tools assembly format. + const std::string disassembly_text = + CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("Capability Shader")); + EXPECT_THAT(disassembly_text, HasSubstr("MemoryModel")); +} + +TEST_F(CompileStringWithOptionsTest, DisassembleMinimalShader) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + const std::string disassembly_text = + CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + for (const auto& substring : kMinimalShaderDisassemblySubstrings) { + EXPECT_THAT(disassembly_text, HasSubstr(substring)); + } +} + +TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileCorrectStd) { + // Forces the version and profile to 450core, which fixes the missing + // #version. + shaderc_compile_options_set_forced_version_profile(options_.get(), 450, + shaderc_profile_core); + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion, + shaderc_glsl_vertex_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, + ForcedVersionProfileCorrectStdClonedOptions) { + // Forces the version and profile to 450core, which fixes the missing + // #version. + shaderc_compile_options_set_forced_version_profile(options_.get(), 450, + shaderc_profile_core); + // This mode should be carried to any clone of the original options object. + compile_options_ptr cloned_options( + shaderc_compile_options_clone(options_.get())); + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion, + shaderc_glsl_vertex_shader, + cloned_options.get())); +} + +TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileInvalidModule) { + // Forces the version and profile to 310es, while the source module is invalid + // for this version of GLSL. Compilation should fail. + shaderc_compile_options_set_forced_version_profile(options_.get(), 310, + shaderc_profile_es); + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_THAT(CompilationErrors(kCoreVertShaderWithoutVersion, + shaderc_glsl_vertex_shader, options_.get()), + HasSubstr("error: 'gl_ClipDistance' : undeclared identifier\n")); +} + +TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileConflictingStd) { + // Forces the version and profile to 450core, which is in conflict with the + // #version in shader. + shaderc_compile_options_set_forced_version_profile(options_.get(), 450, + shaderc_profile_core); + const std::string kVertexShader = + std::string("#version 310 es\n") + kCoreVertShaderWithoutVersion; + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_THAT(CompilationWarnings(kVertexShader, shaderc_glsl_vertex_shader, + options_.get()), + HasSubstr("warning: (version, profile) forced to be (450, core), " + "while in source code it is (310, es)\n")); +} + +TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileUnknownVersionStd) { + // Forces the version and profile to 4242core, which is an unknown version. + shaderc_compile_options_set_forced_version_profile( + options_.get(), 4242 /*unknown version*/, shaderc_profile_core); + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + // Warning message should complain about the unknown version. + // + // Also, Glslang errors out on unkown versions, due to commit: + // https://github.com/KhronosGroup/glslang/commit/9353f1afab8d1c2b1811c6acd807675128eaabc5 + const auto errs = CompilationErrors( + kMinimalShader, shaderc_glsl_vertex_shader, options_.get()); + EXPECT_THAT( + errs, HasSubstr("warning: (version, profile) forced to be (4242, core), " + "while in source code it is (140, none)\n")); + EXPECT_THAT(errs, HasSubstr("error: version not supported\n")); +} + +TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileVersionsBefore150) { + // Versions before 150 do not allow a profile token, shaderc_profile_none + // should be passed down as the profile parameter. + shaderc_compile_options_set_forced_version_profile(options_.get(), 140, + shaderc_profile_none); + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_TRUE(CompilationSuccess(kMinimalShaderWithoutVersion, + shaderc_glsl_vertex_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileRedundantProfileStd) { + // Forces the version and profile to 100core. But versions before 150 do not + // allow a profile token, compilation should fail. + shaderc_compile_options_set_forced_version_profile(options_.get(), 100, + shaderc_profile_core); + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_THAT(CompilationErrors(kMinimalShader, shaderc_glsl_vertex_shader, + options_.get()), + HasSubstr("error: #version: versions before 150 do not allow a " + "profile token\n")); +} + +TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoBinary) { + shaderc_compile_options_set_generate_debug_info(options_.get()); + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + // The binary output should contain the name of the vector: debug_info_sample. + EXPECT_THAT(CompilationOutput(kMinimalDebugInfoShader, + shaderc_glsl_vertex_shader, options_.get()), + HasSubstr("debug_info_sample")); +} + +TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoBinaryClonedOptions) { + shaderc_compile_options_set_generate_debug_info(options_.get()); + compile_options_ptr cloned_options( + shaderc_compile_options_clone(options_.get())); + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + // The binary output should contain the name of the vector: debug_info_sample. + EXPECT_THAT( + CompilationOutput(kMinimalDebugInfoShader, shaderc_glsl_vertex_shader, + cloned_options.get()), + HasSubstr("debug_info_sample")); +} + +TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoDisassembly) { + shaderc_compile_options_set_generate_debug_info(options_.get()); + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + // Generate assembly text we can compare its output as a string. + // The disassembly output should contain the name of the vector: + // debug_info_sample. + EXPECT_THAT( + CompilationOutput(kMinimalDebugInfoShader, shaderc_glsl_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText), + HasSubstr("debug_info_sample")); +} + +TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeWithLevelZero) { + shaderc_compile_options_set_optimization_level( + options_.get(), shaderc_optimization_level_zero); + const std::string disassembly_text = + CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + for (const auto& substring : kMinimalShaderDisassemblySubstrings) { + EXPECT_THAT(disassembly_text, HasSubstr(substring)); + } + // Check that we still have debug instructions. + EXPECT_THAT(disassembly_text, HasSubstr("OpName")); + EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); +} + +TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeWithLevelPerformance) { + shaderc_compile_options_set_optimization_level( + options_.get(), shaderc_optimization_level_performance); + const std::string disassembly_text = + CompilationOutput(kGlslMultipleFnShader, shaderc_glsl_fragment_shader, + options_.get(), OutputType::SpirvAssemblyText); + // Check that we do not have function calls anymore. + EXPECT_THAT(disassembly_text, Not(HasSubstr("OpFunctionCall"))); +} + +TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeWithLevelSize) { + shaderc_compile_options_set_optimization_level( + options_.get(), shaderc_optimization_level_size); + const std::string disassembly_text = + CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + for (const auto& substring : kMinimalShaderDisassemblySubstrings) { + EXPECT_THAT(disassembly_text, HasSubstr(substring)); + } + // Check that we do not have debug instructions. + EXPECT_THAT(disassembly_text, Not(HasSubstr("OpName"))); + EXPECT_THAT(disassembly_text, Not(HasSubstr("OpSource"))); +} + +TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeForVulkan10Failure) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_hlsl); + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_0); + shaderc_compile_options_set_optimization_level( + options_.get(), shaderc_optimization_level_performance); + + EXPECT_FALSE(CompilesToValidSpv(compiler_, kHlslWaveActiveSumeComputeShader, + shaderc_compute_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeForVulkan11Success) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_hlsl); + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_1); + shaderc_compile_options_set_optimization_level( + options_.get(), shaderc_optimization_level_performance); + + const std::string disassembly_text = CompilationOutput( + kHlslWaveActiveSumeComputeShader, shaderc_compute_shader, options_.get(), + OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpGroupNonUniformIAdd")); +} + +TEST_F(CompileStringWithOptionsTest, FollowingOptLevelOverridesPreviousOne) { + shaderc_compile_options_set_optimization_level( + options_.get(), shaderc_optimization_level_size); + // Optimization level settings overridden by + shaderc_compile_options_set_optimization_level( + options_.get(), shaderc_optimization_level_zero); + const std::string disassembly_text = + CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + for (const auto& substring : kMinimalShaderDisassemblySubstrings) { + EXPECT_THAT(disassembly_text, HasSubstr(substring)); + } + // Check that we still have debug instructions. + EXPECT_THAT(disassembly_text, HasSubstr("OpName")); + EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); +} + +TEST_F(CompileStringWithOptionsTest, + GenerateDebugInfoOverridesOptimizationLevel) { + shaderc_compile_options_set_optimization_level( + options_.get(), shaderc_optimization_level_size); + // Optimization level settings overridden by + shaderc_compile_options_set_generate_debug_info(options_.get()); + const std::string disassembly_text = + CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + for (const auto& substring : kMinimalShaderDisassemblySubstrings) { + EXPECT_THAT(disassembly_text, HasSubstr(substring)); + } + // Check that we still have debug instructions. + EXPECT_THAT(disassembly_text, HasSubstr("OpName")); + EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); +} + +TEST_F(CompileStringWithOptionsTest, + GenerateDebugInfoProhibitsOptimizationLevel) { + // Setting generate debug info first also works. + shaderc_compile_options_set_generate_debug_info(options_.get()); + shaderc_compile_options_set_optimization_level( + options_.get(), shaderc_optimization_level_size); + const std::string disassembly_text = + CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + for (const auto& substring : kMinimalShaderDisassemblySubstrings) { + EXPECT_THAT(disassembly_text, HasSubstr(substring)); + } + // Check that we still have debug instructions. + EXPECT_THAT(disassembly_text, HasSubstr("OpName")); + EXPECT_THAT(disassembly_text, HasSubstr("OpSource")); +} + +TEST_F(CompileStringWithOptionsTest, PreprocessingOnlyOption) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + const std::string kMinimalShaderWithMacro = + "#version 150\n" + "#define E main\n" + "void E(){}\n"; + const std::string preprocessed_text = + CompilationOutput(kMinimalShaderWithMacro, shaderc_glsl_vertex_shader, + options_.get(), OutputType::PreprocessedText); + EXPECT_THAT(preprocessed_text, HasSubstr("void main(){ }")); + + const std::string kMinimalShaderWithMacroCloneOption = + "#version 150\n" + "#define E_CLONE_OPTION main\n" + "void E_CLONE_OPTION(){}\n"; + compile_options_ptr cloned_options( + shaderc_compile_options_clone(options_.get())); + const std::string preprocessed_text_cloned_options = CompilationOutput( + kMinimalShaderWithMacroCloneOption, shaderc_glsl_vertex_shader, + options_.get(), OutputType::PreprocessedText); + EXPECT_THAT(preprocessed_text_cloned_options, HasSubstr("void main(){ }")); +} + +// A shader kind test cases needs: 1) A shader text with or without #pragma +// annotation, 2) shader_kind. +struct ShaderKindTestCase { + const char* shader_; + shaderc_shader_kind shader_kind_; +}; + +// Test the shader kind deduction process. If the shader kind is one of the +// forced ones, the compiler will just try to compile the source code in that +// specified shader kind. If the shader kind is shaderc_glsl_deduce_from_pragma, +// the compiler will determine the shader kind from #pragma annotation in the +// source code and emit error if none such annotation is found. When the shader +// kind is one of the default ones, the compiler will fall back to use the +// specified shader kind if and only if #pragma annoation is not found. + +// Valid shader kind settings should generate valid SPIR-V code. +using ValidShaderKind = testing::TestWithParam<ShaderKindTestCase>; + +TEST_P(ValidShaderKind, ValidSpvCode) { + const ShaderKindTestCase& test_case = GetParam(); + Compiler compiler; + EXPECT_TRUE( + CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_)); +} + +INSTANTIATE_TEST_CASE_P( + CompileStringTest, ValidShaderKind, + testing::ValuesIn(std::vector<ShaderKindTestCase>{ + // Valid default shader kinds. + {kEmpty310ESShader, shaderc_glsl_default_vertex_shader}, + {kEmpty310ESShader, shaderc_glsl_default_fragment_shader}, + {kEmpty310ESShader, shaderc_glsl_default_compute_shader}, + {kGeometryOnlyShader, shaderc_glsl_default_geometry_shader}, + {kTessControlOnlyShader, shaderc_glsl_default_tess_control_shader}, + {kTessEvaluationOnlyShader, + shaderc_glsl_default_tess_evaluation_shader}, + + // #pragma annotation overrides default shader kinds. + {kVertexOnlyShaderWithPragma, shaderc_glsl_default_compute_shader}, + {kFragmentOnlyShaderWithPragma, shaderc_glsl_default_vertex_shader}, + {kTessControlOnlyShaderWithPragma, + shaderc_glsl_default_fragment_shader}, + {kTessEvaluationOnlyShaderWithPragma, + shaderc_glsl_default_tess_control_shader}, + {kGeometryOnlyShaderWithPragma, + shaderc_glsl_default_tess_evaluation_shader}, + {kComputeOnlyShaderWithPragma, shaderc_glsl_default_geometry_shader}, + + // Specified non-default shader kind overrides #pragma annotation. + {kVertexOnlyShaderWithInvalidPragma, shaderc_glsl_vertex_shader}, + })); + +using InvalidShaderKind = testing::TestWithParam<ShaderKindTestCase>; + +// Invalid shader kind settings should generate errors. +TEST_P(InvalidShaderKind, CompilationShouldFail) { + const ShaderKindTestCase& test_case = GetParam(); + Compiler compiler; + EXPECT_FALSE( + CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_)); +} + +INSTANTIATE_TEST_CASE_P( + CompileStringTest, InvalidShaderKind, + testing::ValuesIn(std::vector<ShaderKindTestCase>{ + // Invalid default shader kind. + {kVertexOnlyShader, shaderc_glsl_default_fragment_shader}, + // Sets to deduce shader kind from #pragma, but #pragma is defined in + // the source code. + {kVertexOnlyShader, shaderc_glsl_infer_from_source}, + // Invalid #pragma cause errors, even though default shader kind is set + // to valid shader kind. + {kVertexOnlyShaderWithInvalidPragma, + shaderc_glsl_default_vertex_shader}, + })); + +// To test file inclusion, use an unordered_map as a fake file system to store +// fake files to be included. The unordered_map represents a filesystem by +// mapping filename (or path) string to the contents of that file as a string. +using FakeFS = std::unordered_map<std::string, std::string>; + +// An includer test case needs: 1) A fake file system which is actually an +// unordered_map, so that we can resolve the content given a string. A valid +// fake file system must have one entry with key:'root' to specify the start +// shader file for compilation. 2) An string that we expect to see in the +// compilation output. +class IncluderTestCase { + public: + IncluderTestCase(FakeFS fake_fs, std::string expected_substring) + : fake_fs_(fake_fs), expected_substring_(expected_substring) { + assert(fake_fs_.find("root") != fake_fs_.end() && + "Valid fake file system needs a 'root' file\n"); + } + + const FakeFS& fake_fs() const { return fake_fs_; } + const std::string& expected_substring() const { return expected_substring_; } + + private: + FakeFS fake_fs_; + std::string expected_substring_; +}; + +// A mock class that simulate an includer. C API needs two function pointers +// each for get including data and release the data. This class defined two +// static functions, which wrap their matching member functions, to be passed to +// libshaderc C API. +class TestIncluder { + public: + explicit TestIncluder(const FakeFS& fake_fs) + : fake_fs_(fake_fs), responses_({}) {} + + // Get path and content from the fake file system. + shaderc_include_result* GetInclude(const char* filename) { + responses_.emplace_back(shaderc_include_result{ + filename, strlen(filename), fake_fs_.at(std::string(filename)).c_str(), + fake_fs_.at(std::string(filename)).size()}); + return &responses_.back(); + } + + // Response data is owned as private property, no need to release explicitly. + void ReleaseInclude(shaderc_include_result*) {} + + // Wrapper for the corresponding member function. + static shaderc_include_result* GetIncluderResponseWrapper( + void* user_data, const char* filename, int, const char* includer, + size_t include_depth) { + return static_cast<TestIncluder*>(user_data)->GetInclude(filename); + } + + // Wrapper for the corresponding member function. + static void ReleaseIncluderResponseWrapper(void* user_data, + shaderc_include_result* data) { + return static_cast<TestIncluder*>(user_data)->ReleaseInclude(data); + } + + private: + // Includer response data is stored as private property. + const FakeFS& fake_fs_; + std::vector<shaderc_include_result> responses_; +}; + +using IncluderTests = testing::TestWithParam<IncluderTestCase>; + +// Parameterized tests for includer. +TEST_P(IncluderTests, SetIncluderCallbacks) { + const IncluderTestCase& test_case = GetParam(); + const FakeFS& fs = test_case.fake_fs(); + const std::string& shader = fs.at("root"); + TestIncluder includer(fs); + Compiler compiler; + compile_options_ptr options(shaderc_compile_options_initialize()); + shaderc_compile_options_set_include_callbacks( + options.get(), TestIncluder::GetIncluderResponseWrapper, + TestIncluder::ReleaseIncluderResponseWrapper, &includer); + + const Compilation comp(compiler.get_compiler_handle(), shader, + shaderc_glsl_vertex_shader, "shader", "main", + options.get(), OutputType::PreprocessedText); + // Checks the existence of the expected string. + EXPECT_THAT(shaderc_result_get_bytes(comp.result()), + HasSubstr(test_case.expected_substring())); +} + +TEST_P(IncluderTests, SetIncluderCallbacksClonedOptions) { + const IncluderTestCase& test_case = GetParam(); + const FakeFS& fs = test_case.fake_fs(); + const std::string& shader = fs.at("root"); + TestIncluder includer(fs); + Compiler compiler; + compile_options_ptr options(shaderc_compile_options_initialize()); + shaderc_compile_options_set_include_callbacks( + options.get(), TestIncluder::GetIncluderResponseWrapper, + TestIncluder::ReleaseIncluderResponseWrapper, &includer); + + // Cloned options should have all the settings. + compile_options_ptr cloned_options( + shaderc_compile_options_clone(options.get())); + + const Compilation comp(compiler.get_compiler_handle(), shader, + shaderc_glsl_vertex_shader, "shader", "main", + cloned_options.get(), OutputType::PreprocessedText); + // Checks the existence of the expected string. + EXPECT_THAT(shaderc_result_get_bytes(comp.result()), + HasSubstr(test_case.expected_substring())); +} + +INSTANTIATE_TEST_CASE_P(CompileStringTest, IncluderTests, + testing::ValuesIn(std::vector<IncluderTestCase>{ + IncluderTestCase( + // Fake file system. + { + {"root", + "#version 150\n" + "void foo() {}\n" + "#include \"path/to/file_1\"\n"}, + {"path/to/file_1", "content of file_1\n"}, + }, + // Expected output. + "#line 0 \"path/to/file_1\"\n" + " content of file_1\n" + "#line 3"), + IncluderTestCase( + // Fake file system. + {{"root", + "#version 150\n" + "void foo() {}\n" + "#include \"path/to/file_1\"\n"}, + {"path/to/file_1", + "#include \"path/to/file_2\"\n" + "content of file_1\n"}, + {"path/to/file_2", "content of file_2\n"}}, + // Expected output. + "#line 0 \"path/to/file_1\"\n" + "#line 0 \"path/to/file_2\"\n" + " content of file_2\n" + "#line 1 \"path/to/file_1\"\n" + " content of file_1\n" + "#line 3"), + + })); + +TEST_F(CompileStringWithOptionsTest, WarningsOnLine) { + // Some versions of Glslang will return an error, some will return just + // warnings. + EXPECT_THAT( + CompilationMessages(kDeprecatedAttributeShader, + shaderc_glsl_vertex_shader, options_.get()), + HasSubstr(":2: warning: attribute deprecated in version 130; may be " + "removed in future release\n")); +} + +TEST_F(CompileStringWithOptionsTest, WarningsOnLineAsErrors) { + shaderc_compile_options_set_warnings_as_errors(options_.get()); + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_THAT( + CompilationErrors(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, + options_.get()), + HasSubstr(":2: error: attribute deprecated in version 130; may be " + "removed in future release\n")); +} + +TEST_F(CompileStringWithOptionsTest, SuppressWarningsOnLine) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + shaderc_compile_options_set_suppress_warnings(options_.get()); + EXPECT_THAT( + CompilationMessages(kDeprecatedAttributeShader, + shaderc_glsl_vertex_shader, options_.get()), + Not(HasSubstr(":2: warning: attribute deprecated in version 130; may be " + "removed in future release\n"))); +} + +TEST_F(CompileStringWithOptionsTest, GlobalWarnings) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + shaderc_compile_options_set_forced_version_profile(options_.get(), 400, + shaderc_profile_core); + EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, options_.get()), + HasSubstr("(version, profile) forced to be (400, core)," + " while in source code it is (550, none)\n")); +} + +TEST_F(CompileStringWithOptionsTest, GlobalWarningsAsErrors) { + shaderc_compile_options_set_warnings_as_errors(options_.get()); + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + shaderc_compile_options_set_forced_version_profile(options_.get(), 400, + shaderc_profile_core); + EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, options_.get()), + HasSubstr("(version, profile) forced to be (400, core)," + " while in source code it is (550, none)\n")); +} + +TEST_F(CompileStringWithOptionsTest, SuppressGlobalWarnings) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + shaderc_compile_options_set_suppress_warnings(options_.get()); + shaderc_compile_options_set_forced_version_profile(options_.get(), 400, + shaderc_profile_core); + EXPECT_EQ("", + CompilationWarnings(kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, + SuppressWarningsModeFirstOverridesWarningsAsErrorsMode) { + // Sets suppress-warnings mode first, then sets warnings-as-errors mode. + // suppress-warnings mode should override warnings-as-errors mode. + shaderc_compile_options_set_suppress_warnings(options_.get()); + shaderc_compile_options_set_warnings_as_errors(options_.get()); + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + + // Warnings on particular lines should be inhibited. + Compilation comp_line(compiler_.get_compiler_handle(), + kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, + "shader", "main", options_.get()); + EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_line.result())); + + // Global warnings should be inhibited. + Compilation comp_global( + compiler_.get_compiler_handle(), kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, "shader", "main", options_.get()); + EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_global.result())); +} + +TEST_F(CompileStringWithOptionsTest, + SuppressWarningsModeSecondOverridesWarningsAsErrorsMode) { + // Sets suppress-warnings mode first, then sets warnings-as-errors mode. + // suppress-warnings mode should override warnings-as-errors mode. + shaderc_compile_options_set_warnings_as_errors(options_.get()); + shaderc_compile_options_set_suppress_warnings(options_.get()); + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + + // Warnings on particular lines should be inhibited. + Compilation comp_line(compiler_.get_compiler_handle(), + kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, + "shader", "main", options_.get()); + EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_line.result())); + + // Global warnings should be inhibited. + Compilation comp_global( + compiler_.get_compiler_handle(), kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, "shader", "main", options_.get()); + EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_global.result())); +} + +TEST_F(CompileStringWithOptionsTest, IfDefCompileOption) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, nullptr, + 0u); + const std::string kMinimalExpandedShader = + "#version 140\n" + "#ifdef E\n" + "void main(){}\n" + "#else\n" + "#error\n" + "#endif"; + EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader, + shaderc_glsl_vertex_shader, options_.get())); +} + +TEST_F( + CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingOpenGLCompatibilityShaderToBinaryAndAlwaysFails) { + // Glslang does not support generating SPIR-V for compatibility profile + // shaders. + + EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader, + shaderc_glsl_fragment_shader, + options_.get())); + + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_opengl_compat, 0); + EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader, + shaderc_glsl_fragment_shader, + options_.get())); + + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_opengl, 0); + EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader, + shaderc_glsl_fragment_shader, + options_.get())); + + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, 0); + EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader, + shaderc_glsl_fragment_shader, + options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingOpenGLCoreShaderToBinary) { + // Confirm that kOpenGLVertexShader compiles when targeting OpenGL + // compatibility or core profiles. + + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_opengl_compat, 0); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kOpenGLVertexShader, + shaderc_glsl_vertex_shader, options_.get())); + + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_opengl, 0); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kOpenGLVertexShader, + shaderc_glsl_vertex_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingVulkan1_0ShaderToVulkan1_0Succeeds) { + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_0); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeBarrier, + shaderc_glsl_compute_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingVulkan1_0ShaderToVulkan1_1Succeeds) { + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_1); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeBarrier, + shaderc_glsl_compute_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingVulkan1_1ShaderToVulkan1_0Fails) { + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_0); + EXPECT_FALSE(CompilesToValidSpv(compiler_, kGlslShaderComputeSubgroupBarrier, + shaderc_glsl_compute_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingVulkan1_1ShaderToVulkan1_1Succeeds) { + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_1); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeSubgroupBarrier, + shaderc_glsl_compute_shader, options_.get())); +} + +#ifdef NV_EXTENSIONS +// task shader +TEST_F(CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingVulkan1_0TaskShaderToVulkan1_0Succeeds) { + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_0); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderTaskBarrier, + shaderc_glsl_task_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingVulkan1_0TaskShaderToVulkan1_1Succeeds) { + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_1); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderTaskBarrier, + shaderc_glsl_task_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingVulkan1_1TaskShaderToVulkan1_0Fails) { + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_0); + EXPECT_FALSE(CompilesToValidSpv(compiler_, kGlslShaderTaskSubgroupBarrier, + shaderc_glsl_task_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingVulkan1_1TaskShaderToVulkan1_1Succeeds) { + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_1); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderTaskSubgroupBarrier, + shaderc_glsl_task_shader, options_.get())); +} + +// mesh shader +TEST_F(CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingVulkan1_0MeshShaderToVulkan1_0Succeeds) { + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_0); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderMeshBarrier, + shaderc_glsl_mesh_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingVulkan1_0MeshShaderToVulkan1_1Succeeds) { + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_1); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderMeshBarrier, + shaderc_glsl_mesh_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingVulkan1_1MeshShaderToVulkan1_0Fails) { + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_0); + EXPECT_FALSE(CompilesToValidSpv(compiler_, kGlslShaderMeshSubgroupBarrier, + shaderc_glsl_mesh_shader, options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, + TargetEnvRespectedWhenCompilingVulkan1_1MeshShaderToVulkan1_1Succeeds) { + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_1); + EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderMeshSubgroupBarrier, + shaderc_glsl_mesh_shader, options_.get())); +} +#endif + +TEST_F(CompileStringWithOptionsTest, + DISABLED_TargetEnvIgnoredWhenPreprocessing) { + // This test is disabled since some versions of glslang may refuse to compile + // very old shaders to SPIR-V with OpenGL target. Re-enable and rewrite this + // test once we have a differential set of environments to test. + const auto output_type = OutputType::PreprocessedText; + + EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader, + shaderc_glsl_fragment_shader, options_.get(), + output_type)); + + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_opengl_compat, 0); + EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader, + shaderc_glsl_fragment_shader, options_.get(), + output_type)); + + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_opengl, 0); + EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader, + shaderc_glsl_fragment_shader, options_.get(), + output_type)); + + shaderc_compile_options_set_target_env(options_.get(), + shaderc_target_env_vulkan, 0); + EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader, + shaderc_glsl_fragment_shader, options_.get(), + output_type)); +} + +TEST_F(CompileStringTest, ShaderKindRespected) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + const std::string kVertexShader = + "#version 140\nvoid main(){ gl_Position = vec4(0);}"; + EXPECT_TRUE(CompilationSuccess(kVertexShader, shaderc_glsl_vertex_shader)); + EXPECT_FALSE(CompilationSuccess(kVertexShader, shaderc_glsl_fragment_shader)); +} + +TEST_F(CompileStringTest, ErrorsReported) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + EXPECT_THAT(CompilationErrors("int f(){return wrongname;}", + shaderc_glsl_vertex_shader), + HasSubstr("wrongname")); +} + +#ifndef SHADERC_DISABLE_THREADED_TESTS +TEST_F(CompileStringTest, MultipleThreadsCalling) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + bool results[10]; + std::vector<std::thread> threads; + for (auto& r : results) { + threads.emplace_back([&r, this]() { + r = CompilationSuccess("#version 140\nvoid main(){}", + shaderc_glsl_vertex_shader); + }); + } + for (auto& t : threads) { + t.join(); + } + EXPECT_THAT(results, Each(true)); +} +#endif + +TEST_F(CompileKindsTest, Vertex) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + const std::string kVertexShader = + "#version 140\nvoid main(){ gl_Position = vec4(0);}"; + EXPECT_TRUE(CompilationSuccess(kVertexShader, shaderc_glsl_vertex_shader)); +} + +TEST_F(CompileKindsTest, Fragment) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + const std::string kFragShader = + "#version 140\nvoid main(){ gl_FragColor = vec4(0);}"; + EXPECT_TRUE(CompilationSuccess(kFragShader, shaderc_glsl_fragment_shader)); +} + +TEST_F(CompileKindsTest, Compute) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + const std::string kCompShader = + R"(#version 310 es + void main() {} + )"; + EXPECT_TRUE(CompilationSuccess(kCompShader, shaderc_glsl_compute_shader)); +} + +TEST_F(CompileKindsTest, Geometry) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + const std::string kGeoShader = + + R"(#version 310 es + #extension GL_OES_geometry_shader : enable + layout(points) in; + layout(points, max_vertices=1) out; + void main() { + gl_Position = vec4(1.0); + EmitVertex(); + EndPrimitive(); + } + )"; + EXPECT_TRUE(CompilationSuccess(kGeoShader, shaderc_glsl_geometry_shader)); +} + +TEST_F(CompileKindsTest, TessControl) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + const std::string kTessControlShader = + R"(#version 310 es + #extension GL_OES_tessellation_shader : enable + layout(vertices=1) out; + void main() {} + )"; + EXPECT_TRUE( + CompilationSuccess(kTessControlShader, shaderc_glsl_tess_control_shader)); +} + +TEST_F(CompileKindsTest, TessEvaluation) { + ASSERT_NE(nullptr, compiler_.get_compiler_handle()); + const std::string kTessEvaluationShader = + R"(#version 310 es + #extension GL_OES_tessellation_shader : enable + layout(triangles, equal_spacing, ccw) in; + void main() { + gl_Position = vec4(gl_TessCoord, 1.0); + } + )"; + EXPECT_TRUE(CompilationSuccess(kTessEvaluationShader, + shaderc_glsl_tess_evaluation_shader)); +} + +// A test case for ParseVersionProfileTest needs: 1) the input string, 2) +// expected parsing results, including 'succeed' flag, version value, and +// profile enum. +struct ParseVersionProfileTestCase { + ParseVersionProfileTestCase( + const std::string& input_string, bool expected_succeed, + int expected_version = 0, + shaderc_profile expected_profile = shaderc_profile_none) + : input_string_(input_string), + expected_succeed_(expected_succeed), + expected_version_(expected_version), + expected_profile_(expected_profile) {} + std::string input_string_; + bool expected_succeed_; + int expected_version_; + shaderc_profile expected_profile_; +}; + +// Test for a helper function to parse version and profile from string. +using ParseVersionProfileTest = + testing::TestWithParam<ParseVersionProfileTestCase>; + +TEST_P(ParseVersionProfileTest, FromNullTerminatedString) { + const ParseVersionProfileTestCase& test_case = GetParam(); + int version; + shaderc_profile profile; + bool succeed = shaderc_parse_version_profile(test_case.input_string_.c_str(), + &version, &profile); + EXPECT_EQ(test_case.expected_succeed_, succeed); + // check the return version and profile only when the parsing succeeds. + if (succeed) { + EXPECT_EQ(test_case.expected_version_, version); + EXPECT_EQ(test_case.expected_profile_, profile); + } +} + +INSTANTIATE_TEST_CASE_P( + HelperMethods, ParseVersionProfileTest, + testing::ValuesIn(std::vector<ParseVersionProfileTestCase>{ + // Valid version profiles + ParseVersionProfileTestCase("450core", true, 450, shaderc_profile_core), + ParseVersionProfileTestCase("450compatibility", true, 450, + shaderc_profile_compatibility), + ParseVersionProfileTestCase("310es", true, 310, shaderc_profile_es), + ParseVersionProfileTestCase("100", true, 100, shaderc_profile_none), + + // Invalid version profiles, the expected_version and expected_profile + // doesn't matter as they won't be checked if the tests pass correctly. + ParseVersionProfileTestCase("totally_wrong", false), + ParseVersionProfileTestCase("111core", false), + ParseVersionProfileTestCase("450wrongprofile", false), + ParseVersionProfileTestCase("", false), + })); + +TEST_F(CompileStringTest, NullSourceNameFailsCompilingToBinary) { + EXPECT_THAT(CompilationErrors(kEmpty310ESShader, shaderc_glsl_vertex_shader, + nullptr, OutputType::SpirvBinary, nullptr), + HasSubstr("Input file name string was null.")); +} + +TEST_F(CompileStringTest, NullSourceNameFailsCompilingToAssemblyText) { + EXPECT_THAT( + CompilationErrors(kEmpty310ESShader, shaderc_glsl_vertex_shader, nullptr, + OutputType::SpirvAssemblyText, nullptr), + HasSubstr("Input file name string was null.")); +} + +TEST_F(CompileStringTest, NullSourceNameFailsCompilingToPreprocessedText) { + EXPECT_THAT(CompilationErrors(kEmpty310ESShader, shaderc_glsl_vertex_shader, + nullptr, OutputType::PreprocessedText, nullptr), + HasSubstr("Input file name string was null.")); +} + +const char kGlslVertexShader[] = + "#version 140\nvoid main(){ gl_Position = vec4(0);}"; + +const char kHlslVertexShader[] = + "float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION\n" + "{ return float4(1.0, 2.0, 3.0, 4.0); }"; + +TEST_F(CompileStringTest, LangGlslOnGlslVertexSucceeds) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_glsl); + EXPECT_TRUE(CompilationSuccess(kGlslVertexShader, shaderc_glsl_vertex_shader, + options_.get())); +} + +TEST_F(CompileStringTest, LangGlslOnHlslVertexFails) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_glsl); + EXPECT_FALSE(CompilationSuccess(kHlslVertexShader, shaderc_glsl_vertex_shader, + options_.get())); +} + +TEST_F(CompileStringTest, LangHlslOnGlslVertexFails) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_hlsl); + EXPECT_FALSE(CompilationSuccess(kGlslVertexShader, shaderc_glsl_vertex_shader, + options_.get())); +} + +TEST_F(CompileStringTest, LangHlslOnHlslVertexSucceeds) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_hlsl); + EXPECT_TRUE(CompilationSuccess(kHlslVertexShader, shaderc_glsl_vertex_shader, + options_.get())); +} + +TEST(EntryPointTest, + LangGlslOnHlslVertexSucceedsButAssumesEntryPointNameIsMain) { + Compiler compiler; + Options options; + auto compilation = + Compilation(compiler.get_compiler_handle(), kGlslVertexShader, + shaderc_glsl_vertex_shader, "shader", "blah blah blah", + options.get(), OutputType::SpirvAssemblyText); + + EXPECT_THAT(shaderc_result_get_bytes(compilation.result()), + HasSubstr("OpEntryPoint Vertex %main \"main\"")) + << std::string(shaderc_result_get_bytes(compilation.result())); +} + +TEST(EntryPointTest, LangHlslOnHlslVertexSucceedsWithGivenEntryPointName) { + Compiler compiler; + Options options; + shaderc_compile_options_set_source_language(options.get(), + shaderc_source_language_hlsl); + auto compilation = + Compilation(compiler.get_compiler_handle(), kHlslVertexShader, + shaderc_glsl_vertex_shader, "shader", "EntryPoint", + options.get(), OutputType::SpirvAssemblyText); + + EXPECT_THAT(shaderc_result_get_bytes(compilation.result()), + HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\"")) + << std::string(shaderc_result_get_bytes(compilation.result())); +} + +// Returns a fragment shader accessing a texture with the given +// offset. +std::string ShaderWithTexOffset(int offset) { + std::ostringstream oss; + oss << "#version 450\n" + "layout (binding=0) uniform sampler1D tex;\n" + "void main() { vec4 x = textureOffset(tex, 1.0, " + << offset << "); }\n"; + return oss.str(); +} + +// Ensure compilation is sensitive to limit setting. Sample just +// two particular limits. +TEST_F(CompileStringTest, LimitsTexelOffsetDefault) { + EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-9).c_str(), + shaderc_glsl_fragment_shader, + options_.get())); + EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(), + shaderc_glsl_fragment_shader, options_.get())); + EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(), + shaderc_glsl_fragment_shader, options_.get())); + EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(8).c_str(), + shaderc_glsl_fragment_shader, + options_.get())); +} + +TEST_F(CompileStringTest, LimitsTexelOffsetLowerMinimum) { + shaderc_compile_options_set_limit( + options_.get(), shaderc_limit_min_program_texel_offset, -99); + EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-100).c_str(), + shaderc_glsl_fragment_shader, + options_.get())); + EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-99).c_str(), + shaderc_glsl_fragment_shader, options_.get())); +} + +TEST_F(CompileStringTest, LimitsTexelOffsetHigherMaximum) { + shaderc_compile_options_set_limit(options_.get(), + shaderc_limit_max_program_texel_offset, 10); + EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(10).c_str(), + shaderc_glsl_fragment_shader, options_.get())); + EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(11).c_str(), + shaderc_glsl_fragment_shader, + options_.get())); +} + +TEST_F(CompileStringWithOptionsTest, UniformsWithoutBindingsFailCompilation) { + const std::string errors = + CompilationErrors(kShaderWithUniformsWithoutBindings, + shaderc_glsl_vertex_shader, options_.get()); + EXPECT_THAT(errors, + HasSubstr("sampler/texture/image requires layout(binding=X)")); +} + +TEST_F(CompileStringWithOptionsTest, + UniformsWithoutBindingsOptionSetAutoBindingsAssignsBindings) { + shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); + const std::string disassembly_text = CompilationOutput( + kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4")); +} + +TEST_F(CompileStringWithOptionsTest, AutoBindUniformsOptionsSurvivesCloning) { + shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); + compile_options_ptr cloned_options( + shaderc_compile_options_clone(options_.get())); + const std::string disassembly_text = CompilationOutput( + kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, + cloned_options.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4")); +} + +TEST_F(CompileStringWithOptionsTest, + SetBindingBaseForTextureAdjustsTextureBindingsOnly) { + shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); + shaderc_compile_options_set_binding_base(options_.get(), + shaderc_uniform_kind_texture, 44); + const std::string disassembly_text = CompilationOutput( + kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 44")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3")); +} + +TEST_F(CompileStringWithOptionsTest, + SetBindingBaseForSamplerAdjustsSamplerBindingsOnly) { + shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); + shaderc_compile_options_set_binding_base(options_.get(), + shaderc_uniform_kind_sampler, 44); + const std::string disassembly_text = CompilationOutput( + kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 44")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3")); +} + +TEST_F(CompileStringWithOptionsTest, + SetBindingBaseForImageAdjustsImageBindingsOnly) { + shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); + shaderc_compile_options_set_binding_base(options_.get(), + shaderc_uniform_kind_image, 44); + const std::string disassembly_text = CompilationOutput( + kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 44")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 45")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 2")); +} + +TEST_F(CompileStringWithOptionsTest, + SetBindingBaseForBufferAdjustsBufferBindingsOnly) { + shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); + shaderc_compile_options_set_binding_base(options_.get(), + shaderc_uniform_kind_buffer, 44); + const std::string disassembly_text = CompilationOutput( + kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 44")); +} + +TEST_F(CompileStringWithOptionsTest, SetBindingBaseSurvivesCloning) { + shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); + shaderc_compile_options_set_binding_base(options_.get(), + shaderc_uniform_kind_texture, 40); + shaderc_compile_options_set_binding_base(options_.get(), + shaderc_uniform_kind_sampler, 50); + shaderc_compile_options_set_binding_base(options_.get(), + shaderc_uniform_kind_image, 60); + shaderc_compile_options_set_binding_base(options_.get(), + shaderc_uniform_kind_buffer, 70); + compile_options_ptr cloned_options( + shaderc_compile_options_clone(options_.get())); + const std::string disassembly_text = CompilationOutput( + kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader, + cloned_options.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 40")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 50")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 60")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 61")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 70")); +} + +TEST(Compiler, IncludeWithoutOptionsReturnsValidError) { + auto compiler = shaderc_compiler_initialize(); + const char source[] = "#version 450\n#include \"no where\""; + auto result = shaderc_compile_into_spv(compiler, source, strlen(source), + shaderc_glsl_vertex_shader, "file", + "main", nullptr); + EXPECT_EQ(shaderc_compilation_status_compilation_error, + shaderc_result_get_compilation_status(result)); + EXPECT_THAT(shaderc_result_get_error_message(result), + HasSubstr("error: '#include' : #error unexpected include " + "directive for header name: no where")); + + shaderc_result_release(result); + shaderc_compiler_release(compiler); +} + +TEST_F( + CompileStringWithOptionsTest, + SetBindingBaseForTextureForVertexAdjustsTextureBindingsOnlyCompilingAsVertex) { + shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); + shaderc_compile_options_set_binding_base_for_stage( + options_.get(), shaderc_vertex_shader, shaderc_uniform_kind_texture, 100); + const std::string disassembly_text = CompilationOutput( + kShaderWithUniformsWithoutBindings, shaderc_vertex_shader, options_.get(), + OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 100")) + << disassembly_text; + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3")); +} + +TEST_F(CompileStringWithOptionsTest, + SetBindingBaseForTextureForVertexIgnoredWhenCompilingAsFragment) { + shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true); + // This is ignored since we're compiling as a different stage. + shaderc_compile_options_set_binding_base_for_stage( + options_.get(), shaderc_vertex_shader, shaderc_uniform_kind_texture, 100); + const std::string disassembly_text = CompilationOutput( + kShaderWithUniformsWithoutBindings, shaderc_fragment_shader, + options_.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3")); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4")); +} + +TEST_F(CompileStringWithOptionsTest, GlslDefaultPackingUsed) { + const std::string disassembly_text = + CompilationOutput(kGlslShaderWeirdPacking, shaderc_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16")); +} + +TEST_F(CompileStringWithOptionsTest, HlslOffsetsOptionDisableRespected) { + shaderc_compile_options_set_hlsl_offsets(options_.get(), false); + const std::string disassembly_text = + CompilationOutput(kGlslShaderWeirdPacking, shaderc_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16")); +} + +TEST_F(CompileStringWithOptionsTest, HlslOffsetsOptionEnableRespected) { + shaderc_compile_options_set_hlsl_offsets(options_.get(), true); + const std::string disassembly_text = + CompilationOutput(kGlslShaderWeirdPacking, shaderc_vertex_shader, + options_.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 4")); +} + +TEST_F(CompileStringWithOptionsTest, HlslFunctionality1OffByDefault) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_hlsl); + const std::string disassembly_text = + CompilationOutput(kHlslShaderWithCounterBuffer, shaderc_fragment_shader, + options_.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, Not(HasSubstr("OpDecorateStringGOOGLE"))) + << disassembly_text; +} + +TEST_F(CompileStringWithOptionsTest, HlslFunctionality1Respected) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_hlsl); + shaderc_compile_options_set_hlsl_functionality1(options_.get(), true); + const std::string disassembly_text = + CompilationOutput(kHlslShaderWithCounterBuffer, shaderc_fragment_shader, + options_.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateStringGOOGLE")); +} + +TEST_F(CompileStringWithOptionsTest, HlslFunctionality1SurvivesCloning) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_hlsl); + shaderc_compile_options_set_hlsl_functionality1(options_.get(), true); + compile_options_ptr cloned_options( + shaderc_compile_options_clone(options_.get())); + const std::string disassembly_text = + CompilationOutput(kHlslShaderWithCounterBuffer, shaderc_fragment_shader, + cloned_options.get(), OutputType::SpirvAssemblyText); + EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateStringGOOGLE")); +} + +TEST_F(CompileStringWithOptionsTest, HlslFlexibleMemoryLayoutAllowed) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_hlsl); + shaderc_compile_options_set_optimization_level( + options_.get(), shaderc_optimization_level_performance); + + EXPECT_TRUE(CompilesToValidSpv(compiler_, kHlslMemLayoutResourceSelect, + shaderc_fragment_shader, options_.get())); +} + +} // anonymous namespace diff --git a/chromium/third_party/shaderc/src/libshaderc_util/.clang-format b/chromium/third_party/shaderc/src/libshaderc_util/.clang-format new file mode 100644 index 00000000000..e209e8cb803 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/.clang-format @@ -0,0 +1,5 @@ +--- +# Use Google code formatting rules. +Language: Cpp +BasedOnStyle: Google +... diff --git a/chromium/third_party/shaderc/src/libshaderc_util/Android.mk b/chromium/third_party/shaderc/src/libshaderc_util/Android.mk new file mode 100644 index 00000000000..3ef93b3d17f --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/Android.mk @@ -0,0 +1,17 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE:=shaderc_util +LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -DNV_EXTENSIONS +LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/include +LOCAL_SRC_FILES:=src/compiler.cc \ + src/file_finder.cc \ + src/io.cc \ + src/message.cc \ + src/resources.cc \ + src/shader_stage.cc \ + src/spirv_tools_wrapper.cc \ + src/version_profile.cc +LOCAL_STATIC_LIBRARIES:=glslang SPIRV-Tools-opt +LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include +include $(BUILD_STATIC_LIBRARY) diff --git a/chromium/third_party/shaderc/src/libshaderc_util/CMakeLists.txt b/chromium/third_party/shaderc/src/libshaderc_util/CMakeLists.txt new file mode 100644 index 00000000000..873540ab7d8 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/CMakeLists.txt @@ -0,0 +1,77 @@ +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.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/compiler.cc + src/file_finder.cc + src/io.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}) + +if(SHADERC_ENABLE_INSTALL) + install(TARGETS shaderc_util + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif(SHADERC_ENABLE_INSTALL) + +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 + 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_test testdata) +endif() diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/compiler.h b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/compiler.h new file mode 100644 index 00000000000..f36a97fd895 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/compiler.h @@ -0,0 +1,555 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSHADERC_UTIL_INC_COMPILER_H +#define LIBSHADERC_UTIL_INC_COMPILER_H + +#include <array> +#include <cassert> +#include <functional> +#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. +// This object is expected to be a singleton, so that internal +// glslang state can be correctly handled. +// TODO(awoloszyn): Once glslang no longer has static global mutable state +// remove this class. +class GlslangInitializer { + public: + GlslangInitializer() { glslang::InitializeProcess(); } + + ~GlslangInitializer() { glslang::FinalizeProcess(); } + + // Calls release on GlslangInitializer used to intialize this object + // when it is destroyed. + class InitializationToken { + public: + ~InitializationToken() { + if (initializer_) { + initializer_->Release(); + } + } + + InitializationToken(InitializationToken&& other) + : initializer_(other.initializer_) { + other.initializer_ = nullptr; + } + + InitializationToken(const InitializationToken&) = delete; + + private: + InitializationToken(GlslangInitializer* initializer) + : initializer_(initializer) {} + + friend class GlslangInitializer; + GlslangInitializer* initializer_; + }; + + // Obtains exclusive access to the glslang state. The state remains + // exclusive until the Initialization Token has been destroyed. + InitializationToken Acquire() { + state_lock_.lock(); + return InitializationToken(this); + } + + private: + void Release() { state_lock_.unlock(); } + + friend class InitializationToken; + + mutex state_lock_; +}; + +// 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, // Deprecated. + }; + + // Target environment versions. These numbers match those used by Glslang. + enum class TargetEnvVersion : uint32_t { + Default = 0, // Default for the corresponding target environment + // For Vulkan, use numbering scheme from vulkan.h + Vulkan_1_0 = ((1 << 22)), // Vulkan 1.0 + Vulkan_1_1 = ((1 << 22) | (1 << 12)), // Vulkan 1.1 + // For OpenGL, use the numbering from #version in shaders. + OpenGL_4_5 = 450, + }; + + 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, +#ifdef NV_EXTENSIONS + RayGenNV, + IntersectNV, + AnyHitNV, + ClosestHitNV, + MissNV, + CallableNV, + TaskNV, + MeshNV, +#endif + 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, +#ifdef NV_EXTENSIONS + Stage::RayGenNV, + Stage::IntersectNV, + Stage::AnyHitNV, + Stage::ClosestHitNV, + Stage::MissNV, + Stage::CallableNV, + Stage::TaskNV, + Stage::MeshNV, +#endif + }}; + 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), + source_language_(SourceLanguage::GLSL), + limits_(kDefaultTBuiltInResource), + auto_bind_uniforms_(false), + auto_binding_base_(), + auto_map_locations_(false), + hlsl_iomap_(false), + hlsl_offsets_(false), + hlsl_legalization_enabled_(true), + hlsl_functionality1_enabled_(false), + 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); + + // 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 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 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, + GlslangInitializer* initializer) 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 source language. Defaults to GLSL. + SourceLanguage source_language_; + + // The resource limits to be used. + TBuiltInResource limits_; + + // True if the compiler should automatically bind uniforms that don't + // have explicit bindings. + bool auto_bind_uniforms_; + + // The base binding number per uniform type, per stage, used when automatically + // binding uniforms that don't hzve explicit bindings in the shader source. + // The default is zero. + uint32_t auto_binding_base_[kNumStages][kNumUniformKinds]; + + // True if the compiler should automatically map uniforms that don't + // have explicit locations. + bool auto_map_locations_; + + // True if the compiler should use HLSL IO mapping rules when compiling HLSL. + bool hlsl_iomap_; + + // True if the compiler should determine block member offsets using HLSL + // packing rules instead of standard GLSL rules. + bool hlsl_offsets_; + + // True if the compiler should perform legalization optimization passes if + // source language is HLSL. + bool hlsl_legalization_enabled_; + + // True if the compiler should support extension SPV_GOOGLE_hlsl_functionality1. + bool hlsl_functionality1_enabled_; + + // 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; + default: + break; + } + assert(false && "Invalid case"); + return Compiler::Stage::Compute; +} + +} // namespace shaderc_util +#endif // LIBSHADERC_UTIL_INC_COMPILER_H diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/counting_includer.h b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/counting_includer.h new file mode 100644 index 00000000000..3e6b0a69cd1 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/counting_includer.h @@ -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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/file_finder.h b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/file_finder.h new file mode 100644 index 00000000000..2c1c9d12279 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/file_finder.h @@ -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, blind to 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_ diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/format.h b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/format.h new file mode 100644 index 00000000000..182f050279b --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/format.h @@ -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_ diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/io.h b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/io.h new file mode 100644 index 00000000000..b9116c11e3f --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/io.h @@ -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_ diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/message.h b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/message.h new file mode 100644 index 00000000000..f07a62c646f --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/message.h @@ -0,0 +1,83 @@ +// 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". +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_ diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/mutex.h b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/mutex.h new file mode 100644 index 00000000000..4147cac2a22 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/mutex.h @@ -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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/resources.h b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/resources.h new file mode 100644 index 00000000000..a8f635b2661 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/resources.h @@ -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_ diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/resources.inc b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/resources.inc new file mode 100644 index 00000000000..8e86f015ffd --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/resources.inc @@ -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) diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/shader_stage.h b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/shader_stage.h new file mode 100644 index 00000000000..a939cb22a17 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/shader_stage.h @@ -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_ diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h new file mode 100644 index 00000000000..09d84627312 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h @@ -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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/string_piece.h b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/string_piece.h new file mode 100644 index 00000000000..5b8efe57d7a --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/string_piece.h @@ -0,0 +1,355 @@ +// 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_; + } + + // 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_ diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/universal_unistd.h b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/universal_unistd.h new file mode 100644 index 00000000000..bd14c5a7033 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/universal_unistd.h @@ -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_
\ No newline at end of file diff --git a/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/version_profile.h b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/version_profile.h new file mode 100644 index 00000000000..f536b300e2f --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/include/libshaderc_util/version_profile.h @@ -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_ diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/compiler.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/compiler.cc new file mode 100644 index 00000000000..3271ed48f48 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/compiler.cc @@ -0,0 +1,702 @@ +// 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 <tuple> + +#include "libshaderc_util/format.h" +#include "libshaderc_util/io.h" +#include "libshaderc_util/message.h" +#include "libshaderc_util/resources.h" +#include "libshaderc_util/shader_stage.h" +#include "libshaderc_util/spirv_tools_wrapper.h" +#include "libshaderc_util/string_piece.h" +#include "libshaderc_util/version_profile.h" + +#include "SPIRV/GlslangToSpv.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) { + using shaderc_util::Compiler; + EShMessages result = EShMsgCascadingErrors; + if (lang == Compiler::SourceLanguage::HLSL) { + result = static_cast<EShMessages>(result | EShMsgReadHlsl); + } + switch (env) { + case Compiler::TargetEnv::OpenGLCompat: + 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); + } + return result; +} + +// A GlslangClientInfo captures target client version and desired SPIR-V +// version. +struct GlslangClientInfo { + bool valid_client = false; + glslang::EShClient client = glslang::EShClientNone; + bool valid_client_version = false; + 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( + shaderc_util::Compiler::TargetEnv env, + shaderc_util::Compiler::TargetEnvVersion version) { + GlslangClientInfo result; + + using shaderc_util::Compiler; + switch (env) { + case Compiler::TargetEnv::Vulkan: + result.valid_client = true; + result.client = glslang::EShClientVulkan; + if (version == Compiler::TargetEnvVersion::Default || + version == Compiler::TargetEnvVersion::Vulkan_1_0) { + result.client_version = glslang::EShTargetVulkan_1_0; + result.valid_client_version = true; + } else if (version == Compiler::TargetEnvVersion::Vulkan_1_1) { + result.client_version = glslang::EShTargetVulkan_1_1; + result.valid_client_version = true; + result.target_language_version = glslang::EShTargetSpv_1_3; + } + break; + case Compiler::TargetEnv::OpenGLCompat: // TODO(dneto): remove this + case Compiler::TargetEnv::OpenGL: + result.valid_client = true; + result.client = glslang::EShClientOpenGL; + if (version == Compiler::TargetEnvVersion::Default || + version == Compiler::TargetEnvVersion::OpenGL_4_5) { + result.client_version = glslang::EShTargetOpenGL_450; + result.valid_client_version = true; + } + break; + } + return result; +} + +} // anonymous namespace + +namespace shaderc_util { + +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, + GlslangInitializer* initializer) 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(target_env_, target_env_version_); + if (!target_client_info.valid_client) { + *error_stream << "error:" << error_tag + << ": Invalid target client environment " << int(target_env_); + *total_warnings = 0; + *total_errors = 1; + return result_tuple; + } + if (!target_client_info.valid_client_version) { + *error_stream << "error:" << error_tag << ": Invalid target client version " + << static_cast<uint32_t>(target_env_version_) + << " for environment " << int(target_env_); + *total_warnings = 0; + *total_errors = 1; + return result_tuple; + } + + auto token = initializer->Acquire(); + 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_); + 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(); + } + + // TODO(dneto): Generate source-level debug info if requested. + bool success = shader.parse( + &limits_, default_version_, default_profile_, force_version_profile_, + kNotForwardCompatible, + GetMessageRules(target_env_, source_language_, hlsl_offsets_), 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 = false; + 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::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::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(target_env_, target_env_version_); + if (!target_client_info.valid_client) { + std::ostringstream os; + os << "error:" << error_tag << ": Invalid target client " + << int(target_env_); + return std::make_tuple(false, "", os.str()); + } + if (!target_client_info.valid_client_version) { + std::ostringstream os; + os << "error:" << error_tag << ": Invalid target client " + << int(target_env_version_) << " for environmnent " << int(target_env_); + return std::make_tuple(false, "", os.str()); + } + shader.setEnvClient(target_client_info.client, + target_client_info.client_version); + if (hlsl_functionality1_enabled_) { + shader.setEnvTargetHlslFunctionality1(); + } + + // 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_)); + + 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; +} + +} // namespace shaderc_util diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/compiler_test.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/compiler_test.cc new file mode 100644 index 00000000000..0b8a0f62527 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/compiler_test.cc @@ -0,0 +1,738 @@ +// 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 ::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 + 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); +}; + +Texture2D gTex; +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"( +RWStructuredBuffer<float4> Ainc; +float4 main() : SV_Target0 { + return float4(Ainc.IncrementCounter(), 0, 0, 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_1, + 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) { + std::stringstream errors; + size_t total_warnings = 0; + size_t total_errors = 0; + shaderc_util::GlslangInitializer initializer; + bool result = false; + DummyCountingIncluder dummy_includer; + std::tie(result, std::ignore, std::ignore) = compiler_.Compile( + source, stage, "shader", "main", dummy_stage_callback_, dummy_includer, + Compiler::OutputType::SpirvBinary, &errors, &total_warnings, + &total_errors, &initializer); + 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) { + 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( + source, stage, "shader", "main", dummy_stage_callback_, dummy_includer, + Compiler::OutputType::SpirvBinary, &errors, &total_warnings, + &total_errors, &initializer); + errors_ = errors.str(); + EXPECT_TRUE(result); + 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, RespectTargetEnvOnOpenGLShader) { + const EShLanguage stage = EShLangVertex; + + compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat); + EXPECT_TRUE(SimpleCompilationSucceeds(kOpenGLVertexShader, stage)); + + compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL); + EXPECT_TRUE(SimpleCompilationSucceeds(kOpenGLVertexShader, stage)); +} + +TEST_F(CompilerTest, RespectTargetEnvOnOpenGLShaderWhenDeducingStage) { + const EShLanguage stage = EShLangCount; + + compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat); + EXPECT_TRUE( + SimpleCompilationSucceeds(kOpenGLVertexShaderDeducibleStage, stage)); + + 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, 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, BadTargetEnvVersionFails) { + 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 environment 0")); +} + +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_CASE_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, &initializer); + 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_CASE_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, &initializer); + 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); + 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("OpDecorateStringGOOGLE %_entryPointOutput " + "HlslSemanticGOOGLE \"SV_TARGET0\"")) + << disassembly; +} + +} // anonymous namespace diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/counting_includer_test.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/counting_includer_test.cc new file mode 100644 index 00000000000..fbac4417b0f --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/counting_includer_test.cc @@ -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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/death_test.h b/chromium/third_party/shaderc/src/libshaderc_util/src/death_test.h new file mode 100644 index 00000000000..d672f130dc5 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/death_test.h @@ -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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/file_finder.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/file_finder.cc new file mode 100644 index 00000000000..d25c6114082 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/file_finder.cc @@ -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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/file_finder_test.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/file_finder_test.cc new file mode 100644 index 00000000000..607af43cab1 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/file_finder_test.cc @@ -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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/format_test.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/format_test.cc new file mode 100644 index 00000000000..c0d6e39917a --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/format_test.cc @@ -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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/io.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/io.cc new file mode 100644 index 00000000000..42ae89d25e3 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/io.cc @@ -0,0 +1,145 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "libshaderc_util/io.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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/io_test.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/io_test.cc new file mode 100644 index 00000000000..0f605dc4dd9 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/io_test.cc @@ -0,0 +1,140 @@ +// Copyright 2015 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "libshaderc_util/io.h" + +#include <fstream> + +#include <gmock/gmock.h> + +namespace { + +using shaderc_util::IsAbsolutePath; +using shaderc_util::ReadFile; +using shaderc_util::WriteFile; +using shaderc_util::GetOutputStream; +using shaderc_util::GetBaseFileName; +using testing::Eq; +using testing::HasSubstr; + +std::string ToString(const std::vector<char>& v) { + return std::string(v.data(), v.size()); +} + +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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/message.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/message.cc new file mode 100644 index 00000000000..11fd10adc0c --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/message.cc @@ -0,0 +1,260 @@ +// 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>:". If the deduction +// is successful, returns true and updates source_name and line_number to the +// deduced source name and line numer respectively. The prefix standing for the +// location specification in message is skipped. Otherwise, returns false and +// keeps all parameters untouched. +bool DeduceLocationSpec(string_piece* message, string_piece* source_name, + string_piece* line_number) { + // TODO(antiagainst): we use ':' as a delimiter here. It may be a valid + // character in the filename. Also be aware of other special characters, + // for example, ' '. + string_piece rest(*message); + size_t colon_after_source = rest.find_first_of(':'); + if (colon_after_source == string_piece::npos) return false; + + string_piece source = rest.substr(0, colon_after_source); + rest = rest.substr(colon_after_source + 1); + size_t colon_after_line = rest.find_first_of(':'); + if (source.size() == 1 && ::isalpha(source.front()) && rest.size() > 0 && + rest.front() == '\\') { + // Handle Windows path. + colon_after_source += colon_after_line + 1; + source = message->substr(0, colon_after_source); + rest = rest.substr(colon_after_line + 1); + colon_after_line = rest.find_first_of(':'); + } + + if (colon_after_line == string_piece::npos) return false; + const string_piece line = rest.substr(0, colon_after_line); + + if (!std::all_of(line.begin(), line.end(), ::isdigit)) return false; + + *source_name = source; + *line_number = line; + *message = rest.substr(colon_after_line + 1).strip_whitespace(); + return true; +} + +// 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. + + 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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/message_test.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/message_test.cc new file mode 100644 index 00000000000..5d6502310fe --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/message_test.cc @@ -0,0 +1,213 @@ +// 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; + + 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) { + 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()); + + 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()); + + 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, 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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/mutex_test.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/mutex_test.cc new file mode 100644 index 00000000000..189208968ff --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/mutex_test.cc @@ -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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/resources.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/resources.cc new file mode 100644 index 00000000000..458a63f57df --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/resources.cc @@ -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, + + // 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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/shader_stage.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/shader_stage.cc new file mode 100644 index 00000000000..9b693c37229 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/shader_stage.cc @@ -0,0 +1,44 @@ +// 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}}; + + for (const auto& entry : string_to_stage) { + if (stage_name == entry.id) return entry.language; + } + return EShLangCount; +} + +} // namespace shaderc_util diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/spirv_tools_wrapper.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/spirv_tools_wrapper.cc new file mode 100644 index 00000000000..cc6ec4c2736 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/spirv_tools_wrapper.cc @@ -0,0 +1,161 @@ +// 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; + default: + break; + } + break; + case Compiler::TargetEnv::OpenGL: + return SPV_ENV_OPENGL_4_5; + case Compiler::TargetEnv::OpenGLCompat: // Deprecated + return SPV_ENV_OPENGL_4_5; + } + assert(false && "unexpected target environment or version"); + return SPV_ENV_VULKAN_1_0; +} + +} // anonymous namespace + +bool SpirvToolsDisassemble(Compiler::TargetEnv env, + Compiler::TargetEnvVersion version, + const std::vector<uint32_t>& binary, + std::string* text_or_error) { + spvtools::SpirvTools tools(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); + + 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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/string_piece_test.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/string_piece_test.cc new file mode 100644 index 00000000000..2b75e58e142 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/string_piece_test.cc @@ -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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/version_profile.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/version_profile.cc new file mode 100644 index 00000000000..cefbb3b8460 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/version_profile.cc @@ -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 diff --git a/chromium/third_party/shaderc/src/libshaderc_util/src/version_profile_test.cc b/chromium/third_party/shaderc/src/libshaderc_util/src/version_profile_test.cc new file mode 100644 index 00000000000..1cbedfd9b30 --- /dev/null +++ b/chromium/third_party/shaderc/src/libshaderc_util/src/version_profile_test.cc @@ -0,0 +1,133 @@ +// Copyright 2017 The Shaderc Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "libshaderc_util/version_profile.h" + +#include "gmock/gmock.h" + +namespace { + +using shaderc_util::IsKnownVersion; +using shaderc_util::ParseVersionProfile; +using ::testing::Eq; +using ::testing::ValuesIn; + + +TEST(IsKnownVersionTest, Samples) { + EXPECT_TRUE(IsKnownVersion(100)); + EXPECT_TRUE(IsKnownVersion(110)); + EXPECT_TRUE(IsKnownVersion(120)); + EXPECT_TRUE(IsKnownVersion(130)); + EXPECT_TRUE(IsKnownVersion(140)); + EXPECT_TRUE(IsKnownVersion(150)); + EXPECT_TRUE(IsKnownVersion(300)); + EXPECT_TRUE(IsKnownVersion(330)); + EXPECT_TRUE(IsKnownVersion(310)); + EXPECT_TRUE(IsKnownVersion(400)); + EXPECT_TRUE(IsKnownVersion(410)); + EXPECT_TRUE(IsKnownVersion(420)); + EXPECT_TRUE(IsKnownVersion(430)); + EXPECT_TRUE(IsKnownVersion(440)); + EXPECT_TRUE(IsKnownVersion(450)); + EXPECT_TRUE(IsKnownVersion(460)); + EXPECT_FALSE(IsKnownVersion(101)); + EXPECT_FALSE(IsKnownVersion(470)); +} + + +struct ParseVersionProfileCase { + std::string input; + bool success; + // The following are only used when success is true. + int expected_version; + EProfile expected_profile; +}; + +using ParseVersionProfileTest = ::testing::TestWithParam<ParseVersionProfileCase>; + +TEST_P(ParseVersionProfileTest, Sample) { + int version = 0; + EProfile profile = EBadProfile; + const bool result = ParseVersionProfile(GetParam().input, &version, &profile); + EXPECT_THAT(result, GetParam().success); + if (result) { + EXPECT_THAT(version, GetParam().expected_version); + EXPECT_THAT(profile, GetParam().expected_profile); + } +} + + +// For OpenGL ES GLSL (ESSL) versions, see +// https://www.khronos.org/registry/OpenGL/index_e.php + +INSTANTIATE_TEST_CASE_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_CASE_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_CASE_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_CASE_P( + OpenGLCompatibilityCases, ParseVersionProfileTest, + ValuesIn(std::vector<ParseVersionProfileCase>{ + {"320compatibility", true, 320, ECompatibilityProfile}, + {"330compatibility", true, 330, ECompatibilityProfile}, + {"400compatibility", true, 400, ECompatibilityProfile}, + {"410compatibility", true, 410, ECompatibilityProfile}, + {"420compatibility", true, 420, ECompatibilityProfile}, + {"430compatibility", true, 430, ECompatibilityProfile}, + {"440compatibility", true, 440, ECompatibilityProfile}, + {"450compatibility", true, 450, ECompatibilityProfile}, + {"460compatibility", true, 460, ECompatibilityProfile}, + }), ); + +} // anonymous namespace diff --git a/chromium/third_party/shaderc/src/third_party/Android.mk b/chromium/third_party/shaderc/src/third_party/Android.mk new file mode 100644 index 00000000000..a6f506c2d69 --- /dev/null +++ b/chromium/third_party/shaderc/src/third_party/Android.mk @@ -0,0 +1,117 @@ +THIRD_PARTY_PATH := $(call my-dir) + +GLSLANG_LOCAL_PATH := $(THIRD_PARTY_PATH)/glslang +LOCAL_PATH := $(GLSLANG_LOCAL_PATH) + +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:=SPIRV +LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -Werror $(GLSLANG_DEFINES) +LOCAL_EXPORT_C_INCLUDES:=$(GLSLANG_LOCAL_PATH) +LOCAL_SRC_FILES:= \ + SPIRV/GlslangToSpv.cpp \ + SPIRV/InReadableOrder.cpp \ + SPIRV/Logger.cpp \ + SPIRV/SPVRemapper.cpp \ + SPIRV/SpvBuilder.cpp \ + SPIRV/SpvPostProcess.cpp \ + SPIRV/SpvTools.cpp \ + SPIRV/disassemble.cpp \ + SPIRV/doc.cpp + +LOCAL_C_INCLUDES:=$(GLSLANG_LOCAL_PATH) $(GLSLANG_LOCAL_PATH)/glslang/SPIRV +LOCAL_EXPORT_C_INCLUDES:=$(GLSLANG_LOCAL_PATH)/glslang/SPIRV +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE:=OSDependent +LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES) +LOCAL_EXPORT_C_INCLUDES:=$(GLSLANG_LOCAL_PATH) +LOCAL_SRC_FILES:=glslang/OSDependent/Unix/ossource.cpp +LOCAL_C_INCLUDES:=$(GLSLANG_LOCAL_PATH) $(GLSLANG_LOCAL_PATH)/glslang/OSDependent/Unix/ +LOCAL_EXPORT_C_INCLUDES:=$(GLSLANG_LOCAL_PATH)/glslang/OSDependent/Unix/ +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE:=OGLCompiler +LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES) +LOCAL_EXPORT_C_INCLUDES:=$(GLSLANG_LOCAL_PATH) +LOCAL_SRC_FILES:=OGLCompilersDLL/InitializeDll.cpp +LOCAL_C_INCLUDES:=$(GLSLANG_LOCAL_PATH)/OGLCompiler +LOCAL_STATIC_LIBRARIES:=OSDependent +include $(BUILD_STATIC_LIBRARY) + + +# Build Glslang's HLSL parser library. +include $(CLEAR_VARS) +LOCAL_MODULE:=HLSL +LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES) +LOCAL_SRC_FILES:= \ + hlsl/hlslAttributes.cpp \ + hlsl/hlslGrammar.cpp \ + hlsl/hlslOpMap.cpp \ + hlsl/hlslParseables.cpp \ + hlsl/hlslParseHelper.cpp \ + hlsl/hlslScanContext.cpp \ + hlsl/hlslTokenStream.cpp +LOCAL_C_INCLUDES:=$(GLSLANG_LOCAL_PATH) \ + $(GLSLANG_LOCAL_PATH)/hlsl +include $(BUILD_STATIC_LIBRARY) + + +include $(CLEAR_VARS) + +GLSLANG_OUT_PATH=$(if $(call host-path-is-absolute,$(TARGET_OUT)),$(TARGET_OUT),$(abspath $(TARGET_OUT))) + +LOCAL_MODULE:=glslang +LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES) +LOCAL_EXPORT_C_INCLUDES:=$(GLSLANG_LOCAL_PATH) + +LOCAL_SRC_FILES:= \ + glslang/GenericCodeGen/CodeGen.cpp \ + glslang/GenericCodeGen/Link.cpp \ + glslang/MachineIndependent/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/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:=$(GLSLANG_LOCAL_PATH) \ + $(GLSLANG_LOCAL_PATH)/glslang/MachineIndependent \ + $(GLSLANG_OUT_PATH) +LOCAL_STATIC_LIBRARIES:=OSDependent OGLCompiler SPIRV HLSL +include $(BUILD_STATIC_LIBRARY) + +# 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 + +# Now include the SPIRV-Tools dependency +include $(SPVTOOLS_LOCAL_PATH)/Android.mk diff --git a/chromium/third_party/shaderc/src/third_party/CMakeLists.txt b/chromium/third_party/shaderc/src/third_party/CMakeLists.txt new file mode 100644 index 00000000000..b2f677bed22 --- /dev/null +++ b/chromium/third_party/shaderc/src/third_party/CMakeLists.txt @@ -0,0 +1,106 @@ +# 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( 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}) + +if (IS_DIRECTORY ${SHADERC_SPIRV_HEADERS_DIR}) + add_subdirectory(${SHADERC_SPIRV_HEADERS_DIR} spirv-headers) +endif() + +# 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") + endif() + add_subdirectory(${SHADERC_SPIRV_TOOLS_DIR} spirv-tools) +endif() +if (NOT TARGET SPIRV-Tools) + message(FATAL_ERROR "SPIRV-Tools was not found - required for compilation") +endif() + +if (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() + +if(${SHADERC_ENABLE_TESTS}) + # Configure out-of-source-directory tests for glslang. + # The glslang project uses a bash script called "runtests" to run tests. + # The runtests script assumes the glslangValidator executable exists in + # a location inside the source tree, but we build it elsewhere. + # We need to copy the test files, fix the path references, and then run tests. + # Use test directory named "Test" to match Glslangs Test directory, so + # that we get the right relative path names in the "include" test output. + set(GLSLANG_TEST_SRC_DIR ${SHADERC_GLSLANG_DIR}/Test) + set(GLSLANG_TEST_BIN_DIR + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/Test) + + # If we are building in a multi-configuration setting we have + # to put the glslang tests into their respective subdirectories. + if (CMAKE_CONFIGURATION_TYPES) + set(GLSLANG_CONFIGURATION_DIR ${CMAKE_CFG_INTDIR}) + endif() + + add_custom_target(copy-tests-if-necessary ALL + COMMAND ${PYTHON_EXE} + ${shaderc_SOURCE_DIR}/utils/copy-tests-if-necessary.py + ${GLSLANG_TEST_SRC_DIR} ${GLSLANG_TEST_BIN_DIR} ${GLSLANG_CONFIGURATION_DIR} + COMMENT "Copying and patching glslang tests if needed") + + # 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) + # If we are running a multi-configuration project, + # the tests will be in ${Configuration}/Test + add_test(NAME glslang-testsuite + COMMAND bash ${IGNORE_CR_FLAG} runtests + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>/Test + ) + else() + add_test(NAME glslang-testsuite + COMMAND bash ${IGNORE_CR_FLAG} runtests + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Test/ + ) + endif() +endif() diff --git a/chromium/third_party/shaderc/src/third_party/LICENSE.glslang b/chromium/third_party/shaderc/src/third_party/LICENSE.glslang new file mode 100644 index 00000000000..7075f338b91 --- /dev/null +++ b/chromium/third_party/shaderc/src/third_party/LICENSE.glslang @@ -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/>. + diff --git a/chromium/third_party/shaderc/src/third_party/LICENSE.spirv-tools b/chromium/third_party/shaderc/src/third_party/LICENSE.spirv-tools new file mode 100644 index 00000000000..12204d24147 --- /dev/null +++ b/chromium/third_party/shaderc/src/third_party/LICENSE.spirv-tools @@ -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. diff --git a/chromium/third_party/shaderc/src/utils/add_copyright.py b/chromium/third_party/shaderc/src/utils/add_copyright.py new file mode 100755 index 00000000000..ab5104bbefd --- /dev/null +++ b/chromium/third_party/shaderc/src/utils/add_copyright.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python +# Copyright 2015 The Shaderc Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Adds copyright notices to all the files that need them under the +current directory. + +usage: add_copyright.py [--check] + +With --check, prints out all the files missing the copyright notice and exits +with status 1 if any such files are found, 0 if none. +""" + +from __future__ import print_function + +import fileinput +import fnmatch +import os +import re +import sys + +COPYRIGHTRE = re.compile( + r'Copyright \d+ The Shaderc Authors. All rights reserved.') +COPYRIGHT = 'Copyright 2016 The Shaderc Authors. All rights reserved.' +LICENSED = """ +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.""" + + +def find(top, filename_glob, skip_glob_list): + """Returns files in the tree rooted at top matching filename_glob but not + in directories matching skip_glob_list.""" + + file_list = [] + for path, dirs, files in os.walk(top): + for glob in skip_glob_list: + for match in fnmatch.filter(dirs, glob): + dirs.remove(match) + for filename in fnmatch.filter(files, filename_glob): + file_list.append(os.path.join(path, filename)) + return file_list + + +def filtered_descendants(glob): + """Returns glob-matching filenames under the current directory, but skips + some irrelevant paths.""" + return find('.', glob, ['third_party', 'external', 'build*', 'out*', + 'CompilerIdCXX']) + + +def skip(line): + """Returns true if line is all whitespace or shebang.""" + stripped = line.lstrip() + return stripped == '' or stripped.startswith('#!') + + +def comment(text, prefix): + """Returns commented-out text. + + Each line of text will be prefixed by prefix and a space character. Any + trailing whitespace will be trimmed. + """ + accum = [] + for line in text.split('\n'): + accum.append((prefix + ' ' + line).rstrip()) + return '\n'.join(accum) + + +def insert_copyright(glob, comment_prefix): + """Finds all glob-matching files under the current directory and inserts the + copyright message into them unless they already have it or are empty. + + The copyright message goes into the first non-whitespace, non-shebang line + in a file. It is prefixed on each line by comment_prefix and a space. + """ + copyright = comment(COPYRIGHT, comment_prefix) + '\n' + licensed = comment(LICENSED, comment_prefix) + '\n\n' + for file in filtered_descendants(glob): + has_copyright = False + for line in fileinput.input(file, inplace=1): + has_copyright = has_copyright or COPYRIGHTRE.search(line) + if not has_copyright and not skip(line): + sys.stdout.write(copyright) + sys.stdout.write(licensed) + has_copyright = True + sys.stdout.write(line) + if not has_copyright: + open(file, 'a').write(copyright + licensed) + + +def alert_if_no_copyright(glob, comment_prefix): + """Prints names of all files missing a copyright message. + + Finds all glob-matching files under the current directory and checks if they + contain the copyright message. Prints the names of all the files that + don't. + + Returns the total number of file names printed. + """ + printed_count = 0 + for file in filtered_descendants(glob): + has_copyright = False + with open(file) as contents: + for line in contents: + if COPYRIGHTRE.search(line): + has_copyright = True + break + if not has_copyright: + print(file, ' has no copyright message.') + printed_count += 1 + return printed_count + + +def main(): + glob_comment_pairs = [('*.h', '//'), ('*.hpp', '//'), ('*.cc', '//'), + ('*.py', '#'), ('*.cpp', '//')] + if '--check' in sys.argv: + count = 0 + for pair in glob_comment_pairs: + count += alert_if_no_copyright(*pair) + sys.exit(count > 0) + else: + for pair in glob_comment_pairs: + insert_copyright(*pair) + + +if __name__ == '__main__': + main() diff --git a/chromium/third_party/shaderc/src/utils/build.py b/chromium/third_party/shaderc/src/utils/build.py new file mode 100755 index 00000000000..733e958a272 --- /dev/null +++ b/chromium/third_party/shaderc/src/utils/build.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python + +# Copyright 2016 The Shaderc Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Builds the Shaderc project, on Linux, Mac, or Windows. +""" + +from __future__ import print_function +import argparse +import os +import platform +import subprocess +import sys + + +OS = platform.system() + + +def run(cmd, cwd, env, justprint): + """Prints a command to run, and optionally runs it. + + Raises a RuntimeError if the command does not launch or otherwise fails. + + Args: + justprint: If true, then only print the command. Otherwise run the + command after printing it. + cmd: List of words in the command. + cwd: Working directory for the command. + env: Environment to pass to subprocess. + """ + print(cmd) + if justprint: + return + + p = subprocess.Popen(cmd, cwd=cwd, env=env) + (_, _) = p.communicate() + if p.returncode != 0: + raise RuntimeError('Failed to run %s in %s' % (cmd, cwd)) + + +def build(args): + """ Builds Shaderc under specified conditions. + + Args: + args: An object with attributes: + srcdir: where Shaderc source can be found + builddir: build working directory + installdir: install directory + """ + + if not os.path.isdir(args.srcdir): + raise RuntimeError('Soure directory %s does not exist' % (args.srcdir)) + + # Make paths absolute, and ensure directories exist. + for d in [args.builddir, args.installdir]: + if not os.path.isdir(d): + os.makedirs(d) + args.srcdir = os.path.abspath(args.srcdir) + args.builddir = os.path.abspath(args.builddir) + args.installdir = os.path.abspath(args.installdir) + + print('Building Shaderc:') + print(' Source : ', args.srcdir) + print(' Build dir : ', args.builddir) + print(' Install dir: ', args.installdir) + cmake_command = ['cmake', args.srcdir, '-GNinja', + '-DCMAKE_BUILD_TYPE=%s' % args.buildtype, + '-DCMAKE_INSTALL_PREFIX=%s' % args.installdir] + + env = None + if OS == 'Windows': + p = subprocess.Popen( + '"%VS140COMNTOOLS%..\\..\\VC\\vcvarsall.bat" & set', + stdout=subprocess.PIPE, cwd=args.builddir, shell=True) + env = dict([tuple(line.split('=', 1)) + for line in p.communicate()[0].splitlines()]) + run(cmake_command, args.builddir, env, args.dry_run) + run(['ninja', 'install'], args.builddir, env, args.dry_run) + run(['ctest', '--output-on-failure'], args.builddir, env, args.dry_run) + + +def cygpath(f): + p = subprocess.Popen(['cygpath', '-w', f], stdout=subprocess.PIPE) + return p.communicate()[0].rstrip() + +def main(): + """Builds Shaderc after parsing argument specifying locations of + files, level of parallelism, and whether it's a dry run that should + skip actual compilation and installation.""" + + parser = argparse.ArgumentParser(description='Build Shaderc simply') + parser.add_argument('-n', '--dry_run', dest='dry_run', default=False, + action='store_true', + help='Dry run: Make dirs and only print commands ' + 'to be run') + parser.add_argument('--srcdir', dest='srcdir', default='src/shaderc', + help='Shaderc source directory. Default "src/shaderc".') + parser.add_argument('--builddir', dest='builddir', default='out', + help='Build directory. Default is "out".') + parser.add_argument('--installdir', dest='installdir', required=True, + help='Installation directory. Required.') + parser.add_argument('--type', dest='buildtype', default='RelWithDebInfo', + help='Build type. Default is RelWithDebInfo') + + arch = None + if (OS == 'Windows' or OS.startswith('CYGWIN')): + arch = 'windows-x86' + if OS == 'Linux': + arch = 'linux-x86' + if OS == 'Darwin': + arch = 'darwin-x86' + if arch is None: + raise RuntimeError('Unknown OS: %s' % OS) + + path_default = os.pathsep.join([ + os.path.join(os.getcwd(), 'prebuilts', 'cmake', arch, 'bin'), + os.path.join(os.getcwd(), 'prebuilts', 'ninja', arch), + os.path.join(os.getcwd(), 'prebuilts', 'python', arch, 'x64')]) + + parser.add_argument('--path', dest='path', + default=path_default, + help='Extra directories to prepend to the system path, ' + 'separated by your system\'s path delimiter (typically ' + '":" or ";"). After prepending, path must contain ' + 'cmake, ninja, and python. On Cygwin, the native ' + 'Windows Python must come first. Default is %s.' + % path_default) + + args = parser.parse_args() + + if args.path: + os.environ['PATH'] = os.pathsep.join([args.path, os.getenv('PATH')]) + + if OS.startswith('CYGWIN'): + # Escape to Windows. + winargv = [] + args_dict = vars(args) + for k in args_dict: + if k=='path' or k.endswith('dir'): + winargv.extend(['--%s' % k, cygpath(args_dict[k])]) + elif k=='buildtype': + winargv.extend(['--type', args.buildtype]) + elif k=='dry_run': + if args.dry_run: + winargv.append('-n') + else: + winargv.extend(['--%s' % k, args_dict[k]]) + os.execlp('python', 'python', sys.argv[0], *winargv) + + build(args) + + +if __name__ == '__main__': + main() diff --git a/chromium/third_party/shaderc/src/utils/copy-tests-if-necessary.py b/chromium/third_party/shaderc/src/utils/copy-tests-if-necessary.py new file mode 100755 index 00000000000..f0b67ebe834 --- /dev/null +++ b/chromium/third_party/shaderc/src/utils/copy-tests-if-necessary.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +# Copyright 2015 The Shaderc Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Copies tests from the source directory to the binary directory if something +in the source directory has changed. It also updates the path in runtests +to point to the correct binary directory. + +Arguments: glslang_test_source_dir glslang_test_bin_dir [intermediate-dir] + +intermediate-dir is optional, it specifies that there the additional directory +between the root, and the tests/binary. +""" + +import errno +import os +import shutil +import sys + + +def get_modified_times(path): + """Returns a string containing a newline-separated set of + filename:last_modified_time pairs for all files rooted at path. + """ + output = [] + for root, _, filenames in os.walk(path): + for filename in filenames: + fullpath = os.path.join(root, filename) + output.append( + filename + ":" + + str(os.path.getmtime(fullpath)) + "\n") + return "".join(sorted(output)) + + +def read_file(path): + """Reads a file and returns the data as a string.""" + output = "" + try: + # If we could not open then we simply return "" as the output + with open(path, "r") as content: + output = content.read() + except: + pass + return output + + +def write_file(path, output): + """Writes an output string to the file located at path.""" + with open(path, "w") as content: + content.write(output) + + +def substitute_file(path, substitution): + """Substitutes all instances of substitution[0] with substitution[1] for the + file located at path.""" + with open(path, "r") as content: + f_input = content.read() + if f_input: + f_input = f_input.replace(substitution[0], substitution[1]) + with open(path, "w") as content: + content.write(f_input) + + +def substitute_files(path, substitution): + """Runs substitute_file() on all files rooted at path.""" + for root, _, filenames in os.walk(path): + for filename in filenames: + substitute_file(os.path.join(root, filename), substitution) + + +def setup_directory(source, dest): + """Removes the destination directory if it exists and copies the source + directory over the destination if it exists. + """ + try: + shutil.rmtree(dest) + except OSError as e: + # shutil will throw if it could not find the directory. + if e.errno == errno.ENOENT: + pass + else: + raise + shutil.copytree(source, dest) + + +def main(): + glsl_src_dir = os.path.normpath(sys.argv[1]) + glsl_bin_dir = os.path.normpath(sys.argv[2]) + intermediate_directory = None + if (len(sys.argv) > 3): + intermediate_directory = sys.argv[3] + glsl_list_file = os.path.join(glsl_bin_dir, "glsl_test_list") + + src_glsl_stamp = get_modified_times(glsl_src_dir) + old_glsl_stamp = read_file(glsl_list_file) + + target_location = "../glslang/StandAlone/" + if intermediate_directory: + target_location = "../" + target_location + intermediate_directory + "/" + target_location = "EXE=" + target_location + + if src_glsl_stamp != old_glsl_stamp: + setup_directory(glsl_src_dir, glsl_bin_dir) + runtests_script = os.path.join(glsl_bin_dir, "runtests") + substitute_file(runtests_script, + ("EXE=../build/install/bin/", target_location)) + write_file(glsl_list_file, src_glsl_stamp) + + +if __name__ == "__main__": + main() diff --git a/chromium/third_party/shaderc/src/utils/remove-file-by-suffix.py b/chromium/third_party/shaderc/src/utils/remove-file-by-suffix.py new file mode 100755 index 00000000000..39af161c60a --- /dev/null +++ b/chromium/third_party/shaderc/src/utils/remove-file-by-suffix.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +# Copyright 2015 The Shaderc Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Removes all files with a certain suffix in a given path recursively. + +# Arguments: path suffix + +import os +import sys + + +def main(): + path = sys.argv[1] + suffix = sys.argv[2] + for root, _, filenames in os.walk(path): + for filename in filenames: + if filename.endswith(suffix): + os.remove(os.path.join(root, filename)) + + +if __name__ == '__main__': + main() diff --git a/chromium/third_party/shaderc/src/utils/update_build_version.py b/chromium/third_party/shaderc/src/utils/update_build_version.py new file mode 100755 index 00000000000..2ea66338db2 --- /dev/null +++ b/chromium/third_party/shaderc/src/utils/update_build_version.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python + +# Copyright 2016 The Shaderc Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Updates build-version.inc in the current directory, unless the update is +# identical to the existing content. +# +# Args: <shaderc-dir> <spirv-tools-dir> <glslang-dir> +# +# For each directory, there will be a line in build-version.inc containing that +# directory's "git describe" output enclosed in double quotes and appropriately +# escaped. + +from __future__ import print_function + +import datetime +import os.path +import re +import subprocess +import sys +import time + +OUTFILE = 'build-version.inc' + + +def command_output(cmd, directory): + """Runs a command in a directory and returns its standard output stream. + + Captures the standard error stream. + + Raises a RuntimeError if the command fails to launch or otherwise fails. + """ + p = subprocess.Popen(cmd, + cwd=directory, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + (stdout, _) = p.communicate() + if p.returncode != 0: + raise RuntimeError('Failed to run {} in {}'.format(cmd, directory)) + return stdout + + +def deduce_software_version(directory): + """Returns a software version number parsed from the CHANGES file + in the given directory. + + The CHANGES file describes most recent versions first. + """ + + # Match the first well-formed version-and-date line. + # Allow trailing whitespace in the checked-out source code has + # unexpected carriage returns on a linefeed-only system such as + # Linux. + pattern = re.compile(r'^(v\d+\.\d+(-dev)?) \d\d\d\d-\d\d-\d\d\s*$') + changes_file = os.path.join(directory, 'CHANGES') + with open(changes_file) as f: + for line in f.readlines(): + match = pattern.match(line) + if match: + return match.group(1) + raise Exception('No version number found in {}'.format(changes_file)) + + +def describe(directory): + """Returns a string describing the current Git HEAD version as descriptively + as possible. + + Runs 'git describe', or alternately 'git rev-parse HEAD', in directory. If + successful, returns the output; otherwise returns 'unknown hash, <date>'.""" + try: + # decode() is needed here for Python3 compatibility. In Python2, + # str and bytes are the same type, but not in Python3. + # Popen.communicate() returns a bytes instance, which needs to be + # decoded into text data first in Python3. And this decode() won't + # hurt Python2. + return command_output(['git', 'describe'], directory).rstrip().decode() + except: + try: + return command_output( + ['git', 'rev-parse', 'HEAD'], directory).rstrip().decode() + except: + # This is the fallback case where git gives us no information, + # e.g. because the source tree might not be in a git tree. + # In this case, usually use a timestamp. However, to ensure + # reproducible builds, allow the builder to override the wall + # clock time with enviornment variable SOURCE_DATE_EPOCH + # containing a (presumably) fixed timestamp. + timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', time.time())) + formatted = datetime.date.fromtimestamp(timestamp).isoformat() + return 'unknown hash, {}'.format(formatted) + + +def get_version_string(project, directory): + """Returns a detailed version string for a given project with its directory, + which consists of software version string and git description string.""" + detailed_version_string_lst = [project] + if project != 'glslang': + detailed_version_string_lst.append(deduce_software_version(directory)) + detailed_version_string_lst.append(describe(directory).replace('"', '\\"')) + return ' '.join(detailed_version_string_lst) + + +def main(): + if len(sys.argv) != 4: + print('usage: {} <shaderc-dir> <spirv-tools-dir> <glslang-dir>'.format( + sys.argv[0])) + sys.exit(1) + + projects = ['shaderc', 'spirv-tools', 'glslang'] + new_content = ''.join([ + '"{}\\n"\n'.format(get_version_string(p, d)) + for (p, d) in zip(projects, sys.argv[1:]) + ]) + + if os.path.isfile(OUTFILE): + with open(OUTFILE, 'r') as f: + if new_content == f.read(): + return + with open(OUTFILE, 'w') as f: + f.write(new_content) + + +if __name__ == '__main__': + main() |