Merge tag 'v2023.7' into 268

Bug:b/319117470

Change-Id: I134660993b0c68aa8a12ee2a399f8bb05036aac6
diff --git a/.github/workflows/autoroll.yml b/.github/workflows/autoroll.yml
new file mode 100644
index 0000000..e55cecb
--- /dev/null
+++ b/.github/workflows/autoroll.yml
@@ -0,0 +1,66 @@
+# Copyright 2023 The Shaderc Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,s either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+name: Update dependencies
+permissions:
+  contents: read
+
+on:
+  schedule:
+    - cron: '0 2 * * *'
+  workflow_dispatch:
+
+jobs:
+  update-dependencies:
+    permissions:
+      contents: write
+      pull-requests: write
+    name: Update dependencies
+    runs-on: ubuntu-latest
+
+    steps:
+      - uses: actions/checkout@v3
+
+      # Checkout the depot tools they are needed by roll_deps.sh
+      - name: Checkout depot tools
+        run: git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
+
+      - name: Update PATH
+        run: echo "$(pwd)/depot_tools" >> $GITHUB_PATH
+
+      - name: Download dependencies
+        run: python3 utils/git-sync-deps
+
+      - name: Setup git user information
+        run: |
+          git config user.name "GitHub Actions[bot]"
+          git config user.email "<>"
+          git checkout -b roll_deps
+
+      - name: Update dependencies
+        run: |
+          utils/roll-deps
+          if [[ `git diff HEAD..origin/main --name-only | wc -l` == 0 ]]; then
+            echo "changed=false" >> $GITHUB_OUTPUT
+          else
+            echo "changed=true" >> $GITHUB_OUTPUT
+          fi
+        id: update_dependencies
+      - name: Push changes and create PR
+        if: steps.update_dependencies.outputs.changed == 'true'
+        run: |
+          git push --force --set-upstream origin roll_deps
+          gh pr create --label 'kokoro:run' --base main -f || true
+        env:
+          GITHUB_TOKEN: ${{ github.token }}
diff --git a/.gitignore b/.gitignore
index 2565dcd..06673ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@
 compile_commands.json
 .ycm_extra_conf.py
 cscope.*
+third_party/abseil_cpp
 third_party/effcee
 third_party/glslang
 third_party/googletest
diff --git a/Android.mk b/Android.mk
index 147d959..ed4a782 100644
--- a/Android.mk
+++ b/Android.mk
@@ -32,45 +32,38 @@
 SHADERC_HEADERS_IN_OUT_DIR=$(foreach H,$(SHADERC_HEADERS),$(NDK_APP_LIBS_OUT)/../include/shaderc/$(H))
 
 define gen_libshaderc_header
+$(call generate-file-dir,$(NDK_APP_LIBS_OUT)/../include/shaderc/$(1))
 $(NDK_APP_LIBS_OUT)/../include/shaderc/$(1) : \
 		$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/$(1)
-	$(call host-mkdir,$(NDK_APP_LIBS_OUT)/../include/shaderc)
 	$(call host-cp,$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/$(1) \
 		,$(NDK_APP_LIBS_OUT)/../include/shaderc/$(1))
 
 endef
+# Generate headers
+$(eval $(foreach H,$(SHADERC_HEADERS),$(call gen_libshaderc_header,$(H))))
+libshaderc_headers: $(SHADERC_HEADERS_IN_OUT_DIR)
+.PHONY: libshaderc_headers
 
-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
+# Rules for combining library files to form a single libshader_combined.a.
+# It always goes into $(TARGET_OUT)
+$(call generate-file-dir,$(TARGET_OUT)/combine.ar)
+$(TARGET_OUT)/combine.ar: $(TARGET_OUT) $(addprefix $(TARGET_OUT)/, $(ALL_LIBS))
+	$(file >$(TARGET_OUT)/combine.ar,create libshaderc_combined.a)
+	$(foreach lib,$(ALL_LIBS),$(file >>$(TARGET_OUT)/combine.ar,addlib $(lib)))
+	$(file >>$(TARGET_OUT)/combine.ar,save)
+	$(file >>$(TARGET_OUT)/combine.ar,end)
 
-$(1)/libshaderc_combined.a: $(addprefix $(1)/, $(ALL_LIBS)) $(1)/combine.ar
+$(TARGET_OUT)/libshaderc_combined.a: $(addprefix $(TARGET_OUT)/, $(ALL_LIBS)) $(TARGET_OUT)/combine.ar
 	@echo "[$(TARGET_ARCH_ABI)] Combine: libshaderc_combined.a <= $(ALL_LIBS)"
-	@cd $(1) && $(TARGET_AR) -M < combine.ar && cd $(ROOT_SHADERC_PATH)
-	@$(TARGET_STRIP) --strip-debug $(1)/libshaderc_combined.a
+	@cd $(TARGET_OUT) && $(TARGET_AR) -M < combine.ar && cd $(ROOT_SHADERC_PATH)
+	@$(TARGET_STRIP) --strip-debug $(TARGET_OUT)/libshaderc_combined.a
 
+$(call generate-file-dir,$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a)
 $(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a: \
-		$(1)/libshaderc_combined.a
-	$(call host-mkdir,$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI))
-	$(call host-cp,$(1)/libshaderc_combined.a \
+		$(TARGET_OUT)/libshaderc_combined.a
+	$(call host-cp,$(TARGET_OUT)/libshaderc_combined.a \
 		,$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a)
 
-ifndef HEADER_TARGET
-HEADER_TARGET=1
-$(eval $(foreach H,$(SHADERC_HEADERS),$(call gen_libshaderc_header,$(H))))
-endif
-
-libshaderc_combined: \
+libshaderc_combined: libshaderc_headers \
 	$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a
-
-endef
-
-libshaderc_combined: $(SHADERC_HEADERS_IN_OUT_DIR)
-
-$(eval $(call gen_libshaderc,$(TARGET_OUT)))
diff --git a/CHANGES b/CHANGES
index 0110c41..7de30b5 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,7 +1,50 @@
 Revision history for Shaderc
 
-v2022.4-dev 2022-10-12
- - Start v2202.4 development
+v2023.7 2023-10-12
+ - Update dependencies
+ - Finish converting build instructions and flags to always use C++17
+ - Add GitHub CI to test more flows
+
+v2023.6 2023-08-09
+ - Update dependencies, including SPIRV-Tools v2023.4.rc2
+
+v2023.5 2023-07-19
+ - Update dependencies
+ - Update to Android NDK r25c
+ - Update Android API level for test project (#1333)
+ - For testing, add a dependency on Abseil's C++ library
+ - Fix MSVC runtime library linking in CMake (#1339)
+
+v2023.4 2023-05-24
+ - Refresh Glslang, SPIRV-Tools, SPIRV-Headers
+ - Android.mk:
+    - Require NDK 21d or later
+    - Update scripts for generating the shared library, which
+      should fix Windows
+ - glslc and APIs:
+    - Add options to control mesh shading limits
+
+v2023.3 2023-03-17
+ - Shaderc now requires C++17
+ - Drop support for VS 2015
+ - Add glslc option -fpreserve-bindings
+ - Refresh Glslang, SPIRV-Tools
+
+v2023.2 2023-01-18
+ - Update DEPS to pull in SPIRV-Tools bugfix #5049
+
+v2023.1 2023-01-13
+ - General/Build
+   - Removed support for GCC-based code coverage builds
+   - Update minimum CMake to 3.17.2
+ - Fix C++20 compatibility: explicitly construct string_piece when
+   comparing to `char*`
+
+v2022.4 2022-11-30
+ - Update to Glslang 11
+ - Update SPIRV-Tools, SPIRV-Headers dependencies
+ - Add Cmake BUNDLE DESTINATION option for target install
+ - The code coverage build is no longer being tested
 
 v2022.3 2022-10-12
  - #1264: Implement defaults for SPV_EXT_mesh_shader builtins
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3bf9d16..075641e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,12 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-cmake_minimum_required(VERSION 2.8.12)
-
-if (POLICY CMP00091)
-  # Enable MSVC Runtime Library Property
-  cmake_policy(SET CMP0091 NEW)
-endif()
+cmake_minimum_required(VERSION 3.17.2)
 
 project(shaderc)
 enable_testing()
@@ -68,7 +63,7 @@
 
 option(SHADERC_ENABLE_WERROR_COMPILE "Enable passing -Werror to compiler, if available" ON)
 
-set (CMAKE_CXX_STANDARD 11)
+set (CMAKE_CXX_STANDARD 17)
 
 include(GNUInstallDirs)
 include(cmake/setup_build.cmake)
@@ -114,17 +109,12 @@
 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)
+		  OFF)
+  if (SHADERC_ENABLE_SHARED_CRT)
+    set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
+  else()
+    set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
+  endif()
 endif(MSVC)
 
 
diff --git a/DEPS b/DEPS
index 61e1b72..a7dc1d3 100644
--- a/DEPS
+++ b/DEPS
@@ -1,18 +1,23 @@
 use_relative_paths = True
 
 vars = {
+  'abseil_git':  'https://github.com/abseil',
   'google_git':  'https://github.com/google',
   'khronos_git': 'https://github.com/KhronosGroup',
 
-  'effcee_revision' : '35912e1b7778ec2ddcff7e7188177761539e59',
-  'glslang_revision': '89db4e1caa273a057ea46deba709c6e50001b314',
-  'googletest_revision': 'd9bb8412d60b993365abb53f00b6dad9b2c01b62',
-  're2_revision': 'd2836d1b1c34c4e330a85a1006201db474bf2c8a',
-  'spirv_headers_revision': '85a1ed200d50660786c1a88d9166e871123cce39',
-  'spirv_tools_revision': 'eb0a36633d2acf4de82588504f951ad0f2cecacb',
+  'abseil_revision': '5be22f98733c674d532598454ae729253bc53e82',
+  'effcee_revision' : '19b4aa87af25cb4ee779a071409732f34bfc305c',
+  'glslang_revision': '48f9ed8b08be974f4e463ef38136c8f23513b2cf',
+  'googletest_revision': 'e47544ad31cb3ceecd04cc13e8fe556f8df9fe0b',
+  're2_revision': 'c9cba76063cf4235c1a15dd14a24a4ef8d623761',
+  'spirv_headers_revision': '4183b260f4cccae52a89efdfcdd43c4897989f42',
+  'spirv_tools_revision': '360d469b9eac54d6c6e20f609f9ec35e3a5380ad',
 }
 
 deps = {
+  'third_party/abseil_cpp':
+      Var('abseil_git') + '/abseil-cpp.git@' + Var('abseil_revision'),
+
   'third_party/effcee': Var('google_git') + '/effcee.git@' +
       Var('effcee_revision'),
 
diff --git a/README.md b/README.md
index 0e3075b..3f54ded 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@
 [Android NDK](https://developer.android.com/ndk/index.html) since version r12b.
 (The NDK build uses sources from https://android.googlesource.com/platform/external/shaderc/.
 Those repos are downstream from GitHub.)
-We currently require r18b.
+We currently require r25c.
 
 For licensing terms, please see the [`LICENSE`](LICENSE) file.  If interested in
 contributing to this project, please see [`CONTRIBUTING.md`](CONTRIBUTING.md).
@@ -69,8 +69,13 @@
 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.
+For testing, Shaderc depends on:
+| Library | URL | Description |
+| -- | -- | -- |
+| Googletest | https://github.com/google/googletest | Testing framework |
+| Effcee | https://github.com/google/effcee | Stateful pattern matcher inspired by LLVM's FileCheck |
+| RE2 | https://github.com/google/re2 | Regular expression matcher |
+| Abseil | https://github.com/abseil/abseil-cpp | Common basic utilities in C++ |
 
 In the following sections, `$SOURCE_DIR` is the directory you intend to clone
 Shaderc into.
@@ -135,14 +140,11 @@
 ```
 
 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
+   -DCMAKE_TOOLCHAIN_FILE=$SOURCE_DIR/cmake/linux-mingw-toolchain.cmake
 ninja
 ```
 
@@ -162,26 +164,19 @@
 For building, testing, and profiling Shaderc, the following tools should be
 installed regardless of your OS:
 
+- A C++17 compiler. Recent versions of Clang, GCC, and MSVC work.
 - [CMake](http://www.cmake.org/) 3.14 or later: for generating compilation targets.
     - Shaderc is tested with cmake 3.17.2
 - [Python 3](http://www.python.org/): for utility scripts and running the test suite.
 
-On Linux, the following tools should be installed:
-
-- [`gcov`](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html): for testing code
-    coverage, provided by the `gcc` package on Ubuntu.
-- [`lcov`](http://ltp.sourceforge.net/coverage/lcov.php): a graphical frontend
-    for `gcov`, provided by the `lcov` package on Ubuntu.
-- [`genhtml`](http://linux.die.net/man/1/genhtml): for creating reports in html
-    format from `lcov` output, provided by the `lcov` package on Ubuntu.
-
 On Linux, if cross compiling to Windows:
 - [`mingw`](http://www.mingw.org): A GCC-based cross compiler targeting Windows
     so that generated executables use the Microsoft C runtime libraries.
+    The MinGW compiler must support C++17.
 
 On Windows, the following tools should be installed and available on your path:
 
-- Visual Studio 2015 or later. Previous versions of Visual Studio may work but
+- Visual Studio 2017 or later. Previous versions of Visual Studio may work but
   are untested and unsupported.
 - Git - including the associated tools, Bash, `diff`.
 
@@ -225,20 +220,6 @@
 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
diff --git a/android_test/jni/Application.mk b/android_test/jni/Application.mk
index ef50946..05a9aa3 100644
--- a/android_test/jni/Application.mk
+++ b/android_test/jni/Application.mk
@@ -15,4 +15,6 @@
 APP_ABI := all
 APP_BUILD_SCRIPT := Android.mk
 APP_STL := c++_static
-APP_PLATFORM := android-16
+# Vulkan was added at API level 24.
+# Android NDK 26 will drop support for APIs before 21.
+APP_PLATFORM := android-24
diff --git a/cmake/setup_build.cmake b/cmake/setup_build.cmake
index 5dab384..994de9f 100644
--- a/cmake/setup_build.cmake
+++ b/cmake/setup_build.cmake
@@ -52,80 +52,6 @@
 find_package(PythonInterp 3 REQUIRED)
 endif()
 
-
-option(ENABLE_CODE_COVERAGE "Enable collecting code coverage." OFF)
-if (ENABLE_CODE_COVERAGE)
-  message(STATUS "Shaderc: code coverage report is on.")
-  if (NOT UNIX)
-    message(FATAL_ERROR "Code coverage on non-UNIX system not supported yet.")
-  endif()
-  if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
-    message(FATAL_ERROR "Code coverage with non-Debug build can be misleading.")
-  endif()
-  find_program(LCOV_EXE NAMES lcov)
-  if (NOT LCOV_EXE)
-    message(FATAL_ERROR "lcov was not found")
-  endif()
-  find_program(GENHTML_EXE NAMES genhtml)
-  if (NOT GENHTML_EXE)
-    message(FATAL_ERROR "genhtml was not found")
-  endif()
-
-  set(LCOV_BASE_DIR ${CMAKE_BINARY_DIR})
-  set(LCOV_INFO_FILE ${LCOV_BASE_DIR}/lcov.info)
-  set(COVERAGE_STAT_HTML_DIR ${LCOV_BASE_DIR}/coverage-report)
-
-  add_custom_target(clean-coverage
-    # Remove all gcov .gcda files in the directory recursively.
-    COMMAND ${LCOV_EXE} --directory . --zerocounters -q
-    # Remove all lcov .info files.
-    COMMAND ${CMAKE_COMMAND} -E remove ${LCOV_INFO_FILE}
-    # Remove all html report files.
-    COMMAND ${CMAKE_COMMAND} -E remove_directory ${COVERAGE_STAT_HTML_DIR}
-    # TODO(antiagainst): the following two commands are here to remedy the
-    # problem of "reached unexpected end of file" experienced by lcov.
-    # The symptom is that some .gcno files are wrong after code change and
-    # recompiling. We don't know the exact reason yet. Figure it out.
-    # Remove all .gcno files in the directory recursively.
-    COMMAND ${PYTHON_EXECUTABLE}
-    ${shaderc_SOURCE_DIR}/utils/remove-file-by-suffix.py . ".gcno"
-    # .gcno files are not tracked by CMake. So no recompiling is triggered
-    # even if they are missing. Unfortunately, we just removed all of them
-    # in the above.
-    COMMAND ${CMAKE_COMMAND} --build . --target clean
-    WORKING_DIRECTORY ${LCOV_BASE_DIR}
-    COMMENT "Clean coverage files"
-  )
-
-  add_custom_target(report-coverage
-    COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}
-    # Run all tests.
-    COMMAND ctest --output-on-failure
-    # Collect coverage data from gcov .gcda files.
-    COMMAND ${LCOV_EXE} --directory . --capture -o ${LCOV_INFO_FILE}
-    # Remove coverage info for system header files.
-    COMMAND ${LCOV_EXE}
-      --remove ${LCOV_INFO_FILE} '/usr/include/*' -o ${LCOV_INFO_FILE}
-    # Remove coverage info for external and third_party code.
-    COMMAND ${LCOV_EXE}
-      --remove ${LCOV_INFO_FILE} '${shaderc_SOURCE_DIR}/ext/*'
-      -o ${LCOV_INFO_FILE}
-
-    COMMAND ${LCOV_EXE}
-      --remove ${LCOV_INFO_FILE} '${shaderc_SOURCE_DIR}/third_party/*'
-      -o ${LCOV_INFO_FILE}
-    # Remove coverage info for tests.
-    COMMAND ${LCOV_EXE}
-      --remove ${LCOV_INFO_FILE} '*_test.cc' -o ${LCOV_INFO_FILE}
-    # Generate html report file.
-    COMMAND ${GENHTML_EXE}
-      ${LCOV_INFO_FILE} -t "Coverage Report" -o ${COVERAGE_STAT_HTML_DIR}
-    DEPENDS clean-coverage
-    WORKING_DIRECTORY ${LCOV_BASE_DIR}
-    COMMENT "Collect and analyze coverage data"
-  )
-endif()
-
 option(DISABLE_RTTI "Disable RTTI in builds")
 if(DISABLE_RTTI)
   if(UNIX)
diff --git a/cmake/utils.cmake b/cmake/utils.cmake
index d64757d..e9475b9 100644
--- a/cmake/utils.cmake
+++ b/cmake/utils.cmake
@@ -59,7 +59,6 @@
 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.
diff --git a/downloads.md b/downloads.md
index 1738668..b610422 100644
--- a/downloads.md
+++ b/downloads.md
@@ -7,11 +7,11 @@
 ## Release
 | Windows | Linux | MacOS |
 | --- | --- | --- |
-| [MSVC 2017](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2017_release.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_linux_clang_release.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_macos_clang_release.html) |
-| [MSVC 2015](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2015_release.html) | [gcc](https://storage.googleapis.com/shaderc/badges/build_link_linux_gcc_release.html) | |
+| [MSVC 2019](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2019_release.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_linux_clang_release.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_macos_clang_release.html) |
+| [MSVC 2017](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2017_release.html) | [gcc](https://storage.googleapis.com/shaderc/badges/build_link_linux_gcc_release.html) | |
 
 ## Debug
 | Windows | Linux | MacOS |
 | --- | --- | --- |
-| [MSVC 2017](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2017_debug.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_linux_clang_debug.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_macos_clang_debug.html) |
-| | [gcc](https://storage.googleapis.com/shaderc/badges/build_link_linux_gcc_debug.html) | |
+| [MSVC 2019](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2019_debug.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_linux_clang_debug.html) | [clang](https://storage.googleapis.com/shaderc/badges/build_link_macos_clang_debug.html) |
+| [MSVC 2017](https://storage.googleapis.com/shaderc/badges/build_link_windows_vs2017_debug.html) | [gcc](https://storage.googleapis.com/shaderc/badges/build_link_linux_gcc_debug.html) | |
diff --git a/glslc/CMakeLists.txt b/glslc/CMakeLists.txt
index 31664d1..c8fa6d5 100644
--- a/glslc/CMakeLists.txt
+++ b/glslc/CMakeLists.txt
@@ -67,7 +67,8 @@
 
 if(SHADERC_ENABLE_INSTALL)
   install(TARGETS glslc_exe
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR})
 endif(SHADERC_ENABLE_INSTALL)
 
 add_subdirectory(test)
diff --git a/glslc/README.asciidoc b/glslc/README.asciidoc
index 9b754b8..c9ffbdc 100644
--- a/glslc/README.asciidoc
+++ b/glslc/README.asciidoc
@@ -437,6 +437,13 @@
 }
 ----
 
+[[option-fpreserve-bindings
+==== `-fpreserve-bindings`
+
+Directs the optimizer to preserve bindings declarations, even when those
+bindings are known to be unused.
+
+
 === Warning and Error Options
 
 ==== `-w`
diff --git a/glslc/src/main.cc b/glslc/src/main.cc
index d989455..5cc3f43 100644
--- a/glslc/src/main.cc
+++ b/glslc/src/main.cc
@@ -87,6 +87,9 @@
                     a NaN operand, the other operand is returned. Similarly,
                     the clamp builtin will favour the non-NaN operands, as if
                     clamp were implemented as a composition of max and min.
+  -fpreserve-bindings
+                    Preserve all binding declarations, even if those bindings
+                    are not used.
   -fresource-set-binding [stage] <reg0> <set0> <binding0>
                         [<reg1> <set1> <binding1>...]
                     Explicitly sets the descriptor set and binding for
@@ -330,6 +333,8 @@
       compiler.options().SetInvertY(true);
     } else if (arg == "-fnan-clamp") {
       compiler.options().SetNanClamp(true);
+    } else if (arg.starts_with("-fpreserve-bindings")) {
+      compiler.options().SetPreserveBindings(true);
     } else if (((u_kind = shaderc_uniform_kind_image),
                 (arg == "-fimage-binding-base")) ||
                ((u_kind = shaderc_uniform_kind_texture),
diff --git a/glslc/test/assembly.py b/glslc/test/assembly.py
index 30fdba4..c7b8511 100644
--- a/glslc/test/assembly.py
+++ b/glslc/test/assembly.py
@@ -21,7 +21,7 @@
     return """
     ; SPIR-V
     ; Version: 1.0
-    ; Generator: Google Shaderc over Glslang; 10
+    ; Generator: Google Shaderc over Glslang; 11
     ; Bound: 6
     ; Schema: 0"""
 
diff --git a/glslc/test/expect.py b/glslc/test/expect.py
index 9ac54b2..c58557d 100644
--- a/glslc/test/expect.py
+++ b/glslc/test/expect.py
@@ -27,7 +27,7 @@
 from glslc_test_framework import GlslCTest
 from builtins import bytes
 
-GLSLANG_GENERATOR_VERSION=10
+GLSLANG_GENERATOR_VERSION=11
 SHADERC_GENERATOR_NUMBER=13
 SHADERC_GENERATOR_WORD=(SHADERC_GENERATOR_NUMBER << 16) + GLSLANG_GENERATOR_VERSION
 ASSEMBLER_GENERATOR_WORD=(7<<16)
diff --git a/glslc/test/line.py b/glslc/test/line.py
index 0b4cd2c..790a5e8 100644
--- a/glslc/test/line.py
+++ b/glslc/test/line.py
@@ -36,7 +36,7 @@
 #line 1 "a.vert"
 
 #line 1 "b.glsl"
-void main(){ }
+void main() { }
 #line 3 "a.vert"
 
 """
@@ -61,7 +61,7 @@
 #line 0 "a.vert"
 
 #line 0 "b.glsl"
-void main(){ }
+void main() { }
 #line 2 "a.vert"
 
 """
@@ -138,7 +138,7 @@
 #line 1 "a.vert"
 
 #line 1 "b.glsl"
-void main(){ }
+void main() { }
 #line 3 "a.vert"
 
 """
@@ -161,7 +161,7 @@
 #line 0 "a.vert"
 
 #line 0 "b.glsl"
-void main(){ }
+void main() { }
 #line 2 "a.vert"
 
 """
@@ -183,7 +183,7 @@
 """#extension GL_GOOGLE_include_directive : enable
 #line 1 "a.vert"
 #line 1 "b.glsl"
-void main(){ }
+void main() { }
 #line 2 "a.vert"
 
 """
@@ -205,7 +205,7 @@
 """#extension GL_GOOGLE_include_directive : enable
 #line 0 "a.vert"
 #line 0 "b.glsl"
-void main(){ }
+void main() { }
 #line 1 "a.vert"
 
 """
@@ -230,7 +230,7 @@
 #line 1 "a.vert"
 
 #line 1 "b.glsl"
-void main(){ }
+void main() { }
 #line 3 "a.vert"
 
 """
@@ -288,14 +288,14 @@
 #line 1 "a.vert"
 
 #line 10000 "injected.glsl"
-int plus1(int a){ return a + 1;}
+int plus1(int a) { return a + 1; }
 #line 1 "inc.glsl"
- int inc(int a){ return a + 1;}
+ int inc(int a) { return a + 1; }
 #line 10002 "injected.glsl"
- int plus2(int a){ return a + 2;}
+ int plus2(int a) { return a + 2; }
 #line 55555
 #line 1 "main.glsl"
- void main(){
+ void main() {
   gl_Position = vec4(1.);
 }
 #line 55556 "injected.glsl"
diff --git a/glslc/test/option_dash_D.py b/glslc/test/option_dash_D.py
index ca71d6e..fcd16f1 100644
--- a/glslc/test/option_dash_D.py
+++ b/glslc/test/option_dash_D.py
@@ -224,7 +224,7 @@
 
     expected_stdout =  [
         """
-        void main(){ return 3;}
+        void main() { return 3; }
 """]
 
 @inside_glslc_testsuite('OptionCapD')
@@ -239,18 +239,18 @@
         #else
           void f() { int x; }
         #endif
-        void main(){ return 3;}
+        void main(){ return 3; }
 """, '.vert')
     glslc_args = ['-DX', '-E', '-std=450core', shader]
 
     expected_stdout =  [
         """
 
-          void f(){ }
+          void f() { }
 
 
 
-        void main(){ return 3;}
+        void main() { return 3; }
 """]
 
 @inside_glslc_testsuite('OptionCapD')
@@ -265,7 +265,7 @@
         #else
           void f() { int x; }
         #endif
-        void main(){ return 3;}
+        void main(){ return 3; }
 """, '.vert')
     glslc_args = ['-DX', '-E', '-std=450core', shader]
 
@@ -274,9 +274,9 @@
 
 
 
-          void f(){ int x;}
+          void f() { int x; }
 
-        void main(){ return 3;}
+        void main() { return 3; }
 """]
 
 
@@ -292,18 +292,18 @@
         #else
           void f() { int x; }
         #endif
-        void main(){ return 3;}
+        void main() { return 3; }
 """, '.vert')
     glslc_args = ['-DX=', '-E', '-std=450core', shader]
 
     expected_stdout =  [
         """
 
-          void f(){ }
+          void f() { }
 
 
 
-        void main(){ return 3;}
+        void main() { return 3; }
 """]
 
 @inside_glslc_testsuite('OptionCapD')
@@ -318,7 +318,7 @@
         #else
           void f() { int x; }
         #endif
-        void main(){ return 3;}
+        void main(){ return 3; }
 """, '.vert')
     glslc_args = ['-DX=', '-E', '-std=450core', shader]
 
@@ -327,9 +327,9 @@
 
 
 
-          void f(){ int x;}
+          void f() { int x; }
 
-        void main(){ return 3;}
+        void main() { return 3; }
 """]
 
 @inside_glslc_testsuite('OptionCapD')
@@ -339,13 +339,13 @@
 
     shader = FileShader(
         """
-        void main(){ return FOO(3);}
+        void main(){ return FOO(3); }
 """, '.vert')
     glslc_args = ['-DFOO(x)=(2*x+1)*x*x', '-E', '-std=450core', shader]
 
     expected_stdout =  [
         """
-        void main(){ return(2 * 3 + 1)* 3 * 3;}
+        void main() { return(2 * 3 + 1) * 3 * 3; }
 """]
 
 @inside_glslc_testsuite('OptionCapD')
@@ -355,11 +355,11 @@
 
     shader = FileShader(
         """
-        void main(){ return X;}
+        void main() { return X; }
 """, '.vert')
     glslc_args = ['-DY=4', '-DX=Y', '-E', '-std=450core', shader]
 
     expected_stdout =  [
         """
-        void main(){ return 4;}
+        void main() { return 4; }
 """]
diff --git a/glslc/test/option_dash_E.py b/glslc/test/option_dash_E.py
index b1b6443..69b2e0a 100644
--- a/glslc/test/option_dash_E.py
+++ b/glslc/test/option_dash_E.py
@@ -22,7 +22,7 @@
     """Tests -E without any defines."""
 
     shader = FileShader('#version 140\nvoid main(){}', '.vert')
-    expected_stdout = '#version 140\nvoid main(){ }\n'
+    expected_stdout = '#version 140\nvoid main() { }\n'
     glslc_args = ['-E', shader]
 
 
@@ -31,7 +31,7 @@
     """Tests -E if we provide a .glsl file without an explicit stage."""
 
     shader = FileShader('#version 140\nvoid main(){}', '.glsl')
-    expected_stdout = '#version 140\nvoid main(){ }\n'
+    expected_stdout = '#version 140\nvoid main() { }\n'
     glslc_args = ['-E', shader]
 
 
@@ -40,7 +40,7 @@
     """Tests -E with command-line define."""
 
     shader = FileShader('#version 140\nvoid main(){ int a = X; }', '.vert')
-    expected_stdout = '#version 140\nvoid main(){ int a = 4;}\n'
+    expected_stdout = '#version 140\nvoid main() { int a = 4; }\n'
     glslc_args = ['-DX=4', '-E', shader]
 
 
@@ -57,7 +57,7 @@
 
     expected_stdout = '''#version 140
 
-void main(){
+void main() {
   int a = 4;
 }
 '''
@@ -77,7 +77,7 @@
 
     expected_stdout = '''#version 140
 
-void main(){
+void main() {
   int a = 4 + 1;
 }
 '''
@@ -96,7 +96,7 @@
 
     expected_stdout = '''#version 140
 #pragma optimize(off)
-void main(){
+void main() {
 }
 '''
     glslc_args = ['-E', shader]
@@ -114,7 +114,7 @@
 
     expected_stdout = '''#version 140
 #extension foo : require
-void main(){
+void main() {
 }
 '''
     glslc_args = ['-E', shader]
@@ -140,7 +140,7 @@
 
 #line 2 3
 
-void main(){
+void main() {
 }
 '''
     glslc_args = ['-E', shader]
@@ -176,7 +176,7 @@
 ''')
 
     expected_stdout = '''#version 140
-void main(){
+void main() {
 }
 '''
     glslc_args = ['-E', '-fshader-stage=vertex', shader]
@@ -193,7 +193,7 @@
 ''')
 
     expected_stdout = '''#version 140
-void main(){
+void main() {
 }
 '''
     glslc_args = ['-E', shader]
@@ -212,10 +212,10 @@
 }
 ''', '.vert')
     expected_stdout = '''#version 140
-void main(){
+void main() {
 }
 #version 140
-void function(){
+void function() {
 }
 '''
     glslc_args = ['-E', '-fshader-stage=vertex', shader, shader2]
@@ -235,10 +235,10 @@
 }
 ''', '.glsl')
     expected_stdout = '''#version 140
-void main(){
+void main() {
 }
 #version 140
-void function(){
+void function() {
 }
 '''
     glslc_args = ['-E', shader, shader2]
@@ -253,7 +253,7 @@
 }
 ''', '.vert')
     expected_file_contents = '''#version 140
-void function(){
+void function() {
 }
 '''
     target_filename = 'foo'
@@ -265,7 +265,7 @@
     """Tests -E in the presence of -S."""
 
     shader = FileShader('#version 140\nvoid main(){}', '.vert')
-    expected_stdout = '#version 140\nvoid main(){ }\n'
+    expected_stdout = '#version 140\nvoid main() { }\n'
     glslc_args = ['-E', '-S', shader]
 
 
@@ -274,7 +274,7 @@
     """Tests that using -E multiple times works."""
 
     shader = FileShader('#version 140\nvoid main(){}', '.vert')
-    expected_stdout = '#version 140\nvoid main(){ }\n'
+    expected_stdout = '#version 140\nvoid main() { }\n'
     glslc_args = ['-E', '-E', shader, '-E']
 
 
@@ -283,7 +283,7 @@
     """Tests that using -E after the filename also works."""
 
     shader = FileShader('#version 140\nvoid main(){}', '.vert')
-    expected_stdout = '#version 140\nvoid main(){ }\n'
+    expected_stdout = '#version 140\nvoid main() { }\n'
     glslc_args = [shader, '-E']
 
 
@@ -300,10 +300,10 @@
 }
 ''', '.vert')
     expected_stdout = '''#version 140
-void main(){
+void main() {
 }
 #version 140
-void function(){
+void function() {
 }
 '''
     glslc_args = ['-E', '-c', shader, shader2]
diff --git a/glslc/test/option_dash_M.py b/glslc/test/option_dash_M.py
index 9fadb01..e32ff07 100644
--- a/glslc/test/option_dash_M.py
+++ b/glslc/test/option_dash_M.py
@@ -552,8 +552,8 @@
     dependency_info_files_expected_contents.append([{'target': 'b.vert.spv',
                                                      'dependency': {'b.vert'}}
                                                     ])
-    expected_stdout = ("#version 140\nvoid main(){ }\n"
-                       "#version 140\nvoid main(){ }\n")
+    expected_stdout = ("#version 140\nvoid main() { }\n"
+                       "#version 140\nvoid main() { }\n")
 
 
 @inside_glslc_testsuite('OptionsCapM')
diff --git a/glslc/test/option_dash_cap_O.py b/glslc/test/option_dash_cap_O.py
index 337610a..fa474f9 100644
--- a/glslc/test/option_dash_cap_O.py
+++ b/glslc/test/option_dash_cap_O.py
@@ -23,7 +23,7 @@
 ASSEMBLY_WITH_DEBUG_SOURCE = [
     '; SPIR-V\n',
     '; Version: 1.0\n',
-    '; Generator: Google Shaderc over Glslang; 10\n',
+    '; Generator: Google Shaderc over Glslang; 11\n',
     '; Bound: 7\n',
     '; Schema: 0\n',
     '               OpCapability Shader\n',
@@ -52,7 +52,7 @@
 ASSEMBLY_WITH_DEBUG = [
     '; SPIR-V\n',
     '; Version: 1.0\n',
-    '; Generator: Google Shaderc over Glslang; 10\n',
+    '; Generator: Google Shaderc over Glslang; 11\n',
     '; Bound: 6\n',
     '; Schema: 0\n',
     '               OpCapability Shader\n',
@@ -73,7 +73,7 @@
 ASSEMBLY_WITHOUT_DEBUG = [
     '; SPIR-V\n',
     '; Version: 1.0\n',
-    '; Generator: Google Shaderc over Glslang; 10\n',
+    '; Generator: Google Shaderc over Glslang; 11\n',
     '; Bound: 6\n',
     '; Schema: 0\n',
     '               OpCapability Shader\n',
diff --git a/glslc/test/option_dash_o.py b/glslc/test/option_dash_o.py
index cd7f1d1..5b9ef45 100644
--- a/glslc/test/option_dash_o.py
+++ b/glslc/test/option_dash_o.py
@@ -92,7 +92,7 @@
         num_newlines = len(newlines)
         if num_newlines % 4 == 0:
             return False, "Bad test. Need nontrivial number of newlines"
-        if num_newlines != 3:
+        if num_newlines != 2:
             return False, ("Update this test. Expected 3 newlines in the "
                            "binary, but found {}").format(num_newlines)
         return self.verify_binary_length_and_header(bytes(status.stdout))
diff --git a/glslc/test/option_flimit.py b/glslc/test/option_flimit.py
index 30a0e02..6f50616 100644
--- a/glslc/test/option_flimit.py
+++ b/glslc/test/option_flimit.py
@@ -31,7 +31,6 @@
 
     return FileShader(shader_source_with_tex_offset(offset), ".vert")
 
-
 @inside_glslc_testsuite('OptionFLimit')
 class TestFLimitNoEqual(expect.ErrorMessage):
     """Tests -flimit without equal."""
@@ -134,3 +133,246 @@
     environment = Directory('.', [limits_file, shader])
     glslc_args = ['-c', shader.name, '-flimit-file', limits_file.name]
     expected_error = 'glslc: error: -flimit-file error: invalid resource limit: thisIsBad\n'
+
+## Mesh shading
+
+def mesh_shader_with_params(kwargs):
+    """Returns a mesh shader as a FileShader, with given parameters"""
+    import sys
+
+    source = """#version 450
+#extension {} : enable
+      layout(local_size_x={}) in;
+      layout(local_size_y={}) in;
+      layout(local_size_z={}) in;
+      layout(triangles) out;
+      layout(max_vertices={}) out;
+      layout(max_primitives={}) out;
+      layout(triangles) out;
+      void main() {{ }}
+      """.format(kwargs['extension'],kwargs['x'],kwargs['y'],kwargs['z'],kwargs['max_vert'],kwargs['max_prim'])
+    return FileShader(source,".mesh")
+
+def task_shader_with_params(kwargs):
+    """Returns a task shader as a FileShader, with given parameters"""
+    import sys
+
+    source = """#version 450
+#extension {} : enable
+      layout(local_size_x={}) in;
+      layout(local_size_y={}) in;
+      layout(local_size_z={}) in;
+      void main() {{ }}
+      """.format(kwargs['extension'],kwargs['x'],kwargs['y'],kwargs['z'])
+    return FileShader(source,".task")
+
+
+def meshDefaults(nv_or_ext,show=False):
+  result = dict({
+    # See Glslang's glslang/ResourceLimits/ResourceLimits.cpp
+    'nv': { 'extension': 'GL_NV_mesh_shader', 'x': 32, 'y': 1, 'z': 1, 'max_vert': 256, 'max_prim': 512 },
+    'ext': { 'extension': 'GL_EXT_mesh_shader', 'x': 128, 'y': 128, 'z': 128, 'max_vert': 256, 'max_prim': 256 }
+  })[nv_or_ext]
+  if show:
+      import sys
+      print(result,file=sys.stderr)
+  return result
+
+## GL_NV_mesh_shader
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_NV_X_ok(expect.ValidObjectFile):
+    shader = mesh_shader_with_params(meshDefaults('nv'))
+    glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeX_NV 32']
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_NV_X_bad(expect.ErrorMessageSubstr):
+    shader = mesh_shader_with_params(meshDefaults('nv'))
+    expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeNV"
+    glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeX_NV 31']
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_NV_Y_ok(expect.ValidObjectFile):
+    shader = mesh_shader_with_params(meshDefaults('nv'))
+    glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeY_NV 1']
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_NV_Y_bad(expect.ErrorMessageSubstr):
+    d = meshDefaults('nv')
+    d['y'] = 3
+    shader = mesh_shader_with_params(d)
+    expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeNV"
+    glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeY_NV 2']
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_NV_Z_ok(expect.ValidObjectFile):
+    shader = mesh_shader_with_params(meshDefaults('nv'))
+    glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeZ_NV 1']
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_NV_Z_bad(expect.ErrorMessageSubstr):
+    d = meshDefaults('nv')
+    d['z'] = 3
+    shader = mesh_shader_with_params(d)
+    expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeNV"
+    glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeZ_NV 2']
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_NV_MaxVert_ok(expect.ValidObjectFile):
+    shader = mesh_shader_with_params(meshDefaults('nv'))
+    glslc_args = ['-c', shader, '-flimit= MaxMeshOutputVerticesNV 256']
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_NV_MaxVert_bad(expect.ErrorMessageSubstr):
+    shader = mesh_shader_with_params(meshDefaults('nv'))
+    expected_error_substr = "'max_vertices' : too large, must be less than gl_MaxMeshOutputVerticesNV"
+    glslc_args = ['-c', shader, '-flimit= MaxMeshOutputVerticesNV 255']
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_NV_MaxPrim_ok(expect.ValidObjectFile):
+    shader = mesh_shader_with_params(meshDefaults('nv'))
+    glslc_args = ['-c', shader, '-flimit= MaxMeshOutputPrimitivesNV 512']
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_NV_MaxPrim_bad(expect.ErrorMessageSubstr):
+    shader = mesh_shader_with_params(meshDefaults('nv'))
+    expected_error_substr = "'max_primitives' : too large, must be less than gl_MaxMeshOutputPrimitivesNV"
+    glslc_args = ['-c', shader, '-flimit= MaxMeshOutputPrimitivesNV 511']
+
+@inside_glslc_testsuite('OptionFLimit_Task')
+class TestFLimitTaskShader_NV_X_ok(expect.ValidObjectFile):
+    shader = task_shader_with_params(meshDefaults('nv'))
+    glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeX_NV 32']
+
+@inside_glslc_testsuite('OptionFLimit_Task')
+class TestFLimitTaskShader_NV_X_bad(expect.ErrorMessageSubstr):
+    shader = task_shader_with_params(meshDefaults('nv'))
+    expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeNV"
+    glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeX_NV 31']
+
+@inside_glslc_testsuite('OptionFLimit_Task')
+class TestFLimitTaskShader_NV_Y_ok(expect.ValidObjectFile):
+    shader = task_shader_with_params(meshDefaults('nv'))
+    glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeY_NV 1']
+
+@inside_glslc_testsuite('OptionFLimit_Task')
+class TestFLimitTaskShader_NV_Y_bad(expect.ErrorMessageSubstr):
+    d = meshDefaults('nv')
+    d['y'] = 3
+    shader = task_shader_with_params(d)
+    expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeNV"
+    glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeY_NV 2']
+
+@inside_glslc_testsuite('OptionFLimit_Task')
+class TestFLimitTaskShader_NV_Z_ok(expect.ValidObjectFile):
+    shader = task_shader_with_params(meshDefaults('nv'))
+    glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeZ_NV 1']
+
+@inside_glslc_testsuite('OptionFLimit_Task')
+class TestFLimitTaskShader_NV_Z_bad(expect.ErrorMessageSubstr):
+    d = meshDefaults('nv')
+    d['z'] = 3
+    shader = task_shader_with_params(d)
+    expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeNV"
+    glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeZ_NV 2']
+
+# TODO: Test MaxMeshViewCountNV
+
+
+## GL_EXT_mesh_shader
+## It requires SPIR-V 1.4
+
+s14 = '--target-spv=spv1.4'
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_EXT_X_ok(expect.ValidObjectFile1_4):
+    shader = mesh_shader_with_params(meshDefaults('ext'))
+    glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeX_EXT 128', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_EXT_X_bad(expect.ErrorMessageSubstr):
+    shader = mesh_shader_with_params(meshDefaults('ext'))
+    expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeEXT"
+    glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeX_EXT 127', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_EXT_Y_ok(expect.ValidObjectFile1_4):
+    shader = mesh_shader_with_params(meshDefaults('ext'))
+    glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeY_EXT 128', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_EXT_Y_bad(expect.ErrorMessageSubstr):
+    shader = mesh_shader_with_params(meshDefaults('ext'))
+    expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeEXT"
+    glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeY_EXT 127', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_EXT_Z_ok(expect.ValidObjectFile1_4):
+    shader = mesh_shader_with_params(meshDefaults('ext'))
+    glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeZ_EXT 128', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_EXT_Z_bad(expect.ErrorMessageSubstr):
+    shader = mesh_shader_with_params(meshDefaults('ext'))
+    expected_error_substr = "'local_size' : too large, see gl_MaxMeshWorkGroupSizeEXT"
+    glslc_args = ['-c', shader, '-flimit= MaxMeshWorkGroupSizeZ_EXT 127', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_EXT_MaxVert_ok(expect.ValidObjectFile1_4):
+    shader = mesh_shader_with_params(meshDefaults('ext'))
+    glslc_args = ['-c', shader, '-flimit= MaxMeshOutputVerticesEXT 256', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_EXT_MaxVert_bad(expect.ErrorMessageSubstr):
+    shader = mesh_shader_with_params(meshDefaults('ext'))
+    expected_error_substr = "'max_vertices' : too large, must be less than gl_MaxMeshOutputVerticesEXT"
+    glslc_args = ['-c', shader, '-flimit= MaxMeshOutputVerticesEXT 255', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_EXT_MaxPrim_ok(expect.ValidObjectFile1_4):
+    shader = mesh_shader_with_params(meshDefaults('ext'))
+    glslc_args = ['-c', shader, '-flimit= MaxMeshOutputPrimitivesEXT 256', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Mesh')
+class TestFLimitMeshShader_EXT_MaxPrim_bad(expect.ErrorMessageSubstr):
+    shader = mesh_shader_with_params(meshDefaults('ext'))
+    expected_error_substr = "'max_primitives' : too large, must be less than gl_MaxMeshOutputPrimitivesEXT"
+    glslc_args = ['-c', shader, '-flimit= MaxMeshOutputPrimitivesEXT 255', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Task')
+class TestFLimitTaskShader_EXT_X_ok(expect.ValidObjectFile1_4):
+    shader = task_shader_with_params(meshDefaults('ext'))
+    glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeX_EXT 128', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Task')
+class TestFLimitTaskShader_EXT_X_bad(expect.ErrorMessageSubstr):
+    shader = task_shader_with_params(meshDefaults('ext'))
+    expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeEXT"
+    glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeX_EXT 127', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Task')
+class TestFLimitTaskShader_EXT_Y_ok(expect.ValidObjectFile1_4):
+    shader = task_shader_with_params(meshDefaults('ext'))
+    glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeY_EXT 128', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Task')
+class TestFLimitTaskShader_EXT_Y_bad(expect.ErrorMessageSubstr):
+    import sys
+    d = meshDefaults('ext',True)
+    print("TaskShader_EXT_Y_bad {}".format(str(d)),file=sys.stderr)
+    shader = task_shader_with_params(meshDefaults('ext',True))
+    expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeEXT"
+    glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeY_EXT 127', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Task')
+class TestFLimitTaskShader_EXT_Z_ok(expect.ValidObjectFile1_4):
+    shader = task_shader_with_params(meshDefaults('ext'))
+    glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeZ_EXT 128', s14]
+
+@inside_glslc_testsuite('OptionFLimit_Task')
+class TestFLimitTaskShader_EXT_Z_bad(expect.ErrorMessageSubstr):
+    shader = task_shader_with_params(meshDefaults('ext'))
+    expected_error_substr = "'local_size' : too large, see gl_MaxTaskWorkGroupSizeEXT"
+    glslc_args = ['-c', shader, '-flimit= MaxTaskWorkGroupSizeZ_EXT 127', s14]
+
+# TODO: Test MaxMeshViewCountEXT
diff --git a/glslc/test/option_fpreserve_bindings.py b/glslc/test/option_fpreserve_bindings.py
new file mode 100644
index 0000000..5235ffa
--- /dev/null
+++ b/glslc/test/option_fpreserve_bindings.py
@@ -0,0 +1,70 @@
+# Copyright 2023 The Shaderc Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import expect
+from glslc_test_framework import inside_glslc_testsuite
+from placeholder import FileShader
+
+# A GLSL shader with unused bindings.
+GLSL_SHADER_WITH_UNUSED_BINDINGS = """#version 450
+  layout(binding=0) buffer InputA { vec4 x[]; } inputA;
+  layout(binding=1) buffer InputB { vec4 x[]; } inputB;
+  layout(binding=2) buffer Output { vec4 x[]; } outputO;
+
+  void main() {}
+  """
+
+
+@inside_glslc_testsuite('OptionFPreserveBindings')
+class TestFPreserveBindingsInputA(expect.ValidAssemblyFileWithSubstr):
+    """Tests that the compiler preserves bindings when optimizations are
+    enabled."""
+
+    shader = FileShader(GLSL_SHADER_WITH_UNUSED_BINDINGS, '.comp')
+    glslc_args = ['-S', '-O', shader, '-fpreserve-bindings']
+    # Check the first buffer.
+    expected_assembly_substr = "Binding 0"
+
+
+@inside_glslc_testsuite('OptionFPreserveBindings')
+class TestFPreserveBindingsInputB(expect.ValidAssemblyFileWithSubstr):
+    """Tests that the compiler preserves bindings when optimizations are
+    enabled."""
+
+    shader = FileShader(GLSL_SHADER_WITH_UNUSED_BINDINGS, '.comp')
+    glslc_args = ['-S', '-O', shader, '-fpreserve-bindings']
+    # Check the first buffer.
+    expected_assembly_substr = "Binding 1"
+
+
+@inside_glslc_testsuite('OptionFPreserveBindings')
+class TestFPreserveBindingsOutputO(expect.ValidAssemblyFileWithSubstr):
+    """Tests that the compiler preserves bindings when optimizations are
+    enabled."""
+
+    shader = FileShader(GLSL_SHADER_WITH_UNUSED_BINDINGS, '.comp')
+    glslc_args = ['-S', '-O', shader, '-fpreserve-bindings']
+    # Check the first buffer.
+    expected_assembly_substr = "Binding 2"
+
+
+@inside_glslc_testsuite('OptionFPreserveBindings')
+class TestFNoPreserveBindings(expect.ValidAssemblyFileWithoutSubstr):
+    """Tests that the compiler removes bindings when -fpreserve-bindings is not
+    set."""
+
+    shader = FileShader(GLSL_SHADER_WITH_UNUSED_BINDINGS, '.comp')
+    glslc_args = ['-S', '-O', shader]
+    # Check that all binding decorations are gone.
+    unexpected_assembly_substr = "OpDecorate"
diff --git a/glslc/test/parameter_tests.py b/glslc/test/parameter_tests.py
index c8cfa0c..6e3e1cd 100644
--- a/glslc/test/parameter_tests.py
+++ b/glslc/test/parameter_tests.py
@@ -91,6 +91,9 @@
                     a NaN operand, the other operand is returned. Similarly,
                     the clamp builtin will favour the non-NaN operands, as if
                     clamp were implemented as a composition of max and min.
+  -fpreserve-bindings
+                    Preserve all binding declarations, even if those bindings
+                    are not used.
   -fresource-set-binding [stage] <reg0> <set0> <binding0>
                         [<reg1> <set1> <binding1>...]
                     Explicitly sets the descriptor set and binding for
@@ -365,4 +368,23 @@
 MaxCullDistances 8
 MaxCombinedClipAndCullDistances 8
 MaxSamples 4
+MaxMeshOutputVerticesNV 256
+MaxMeshOutputPrimitivesNV 512
+MaxMeshWorkGroupSizeX_NV 32
+MaxMeshWorkGroupSizeY_NV 1
+MaxMeshWorkGroupSizeZ_NV 1
+MaxTaskWorkGroupSizeX_NV 32
+MaxTaskWorkGroupSizeY_NV 1
+MaxTaskWorkGroupSizeZ_NV 1
+MaxMeshViewCountNV 4
+MaxMeshOutputVerticesEXT 256
+MaxMeshOutputPrimitivesEXT 256
+MaxMeshWorkGroupSizeX_EXT 128
+MaxMeshWorkGroupSizeY_EXT 128
+MaxMeshWorkGroupSizeZ_EXT 128
+MaxTaskWorkGroupSizeX_EXT 128
+MaxTaskWorkGroupSizeY_EXT 128
+MaxTaskWorkGroupSizeZ_EXT 128
+MaxMeshViewCountEXT 4
+MaxDualSourceDrawBuffersEXT 1
 """
diff --git a/kokoro/android-release/build-docker.sh b/kokoro/android-release/build-docker.sh
index b05e6e7..8bd5215 100755
--- a/kokoro/android-release/build-docker.sh
+++ b/kokoro/android-release/build-docker.sh
@@ -27,7 +27,7 @@
 
 using cmake-3.17.2
 using ninja-1.10.0
-using ndk-r21d # Sets ANDROID_NDK_HOME, pointing at the NDK's root dir
+using ndk-r25c # Sets ANDROID_NDK_HOME, pointing at the NDK's root dir
 
 cd $ROOT_DIR
 ./utils/git-sync-deps
@@ -49,7 +49,7 @@
   -DANDROID_NDK=$ANDROID_NDK_HOME ..
 
 echo $(date): Build glslang...
-ninja glslangValidator
+ninja glslang-standalone
 
 echo $(date): Build everything...
 ninja
diff --git a/kokoro/linux/build-docker.sh b/kokoro/linux/build-docker.sh
index 9687d0a..7d71b61 100755
--- a/kokoro/linux/build-docker.sh
+++ b/kokoro/linux/build-docker.sh
@@ -53,7 +53,7 @@
   ADDITIONAL_CMAKE_FLAGS="-DDISABLE_EXCEPTIONS=ON -DDISABLE_RTTI=ON"
 elif [ $CONFIG = "RELEASE_MINGW" ]
 then
-  ADDITIONAL_CMAKE_FLAGS="-Dgtest_disable_pthreads=ON -DCMAKE_TOOLCHAIN_FILE=$ROOT_DIR/cmake/linux-mingw-toolchain.cmake"
+  ADDITIONAL_CMAKE_FLAGS="-DCMAKE_TOOLCHAIN_FILE=$ROOT_DIR/cmake/linux-mingw-toolchain.cmake"
   SKIP_TESTS="True"
 fi
 
@@ -66,10 +66,10 @@
 # Invoke the build.
 BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
 echo $(date): Starting build...
-cmake -GNinja -DCMAKE_INSTALL_PREFIX=$KOKORO_ARTIFACTS_DIR/install -DSHADERC_ENABLE_SPVC=ON -DRE2_BUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=$BUILD_TYPE $ADDITIONAL_CMAKE_FLAGS ..
+cmake -GNinja -DCMAKE_INSTALL_PREFIX=$KOKORO_ARTIFACTS_DIR/install -DRE2_BUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=$BUILD_TYPE $ADDITIONAL_CMAKE_FLAGS ..
 
 echo $(date): Build glslang...
-ninja glslangValidator
+ninja glslang-standalone
 
 echo $(date): Build everything...
 ninja
diff --git a/kokoro/linux/continuous_gcc_coverage.cfg b/kokoro/linux/continuous_gcc_coverage.cfg
deleted file mode 100644
index ab2878c..0000000
--- a/kokoro/linux/continuous_gcc_coverage.cfg
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (C) 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Continuous build configuration.
-build_file: "shaderc/kokoro/linux/build_gcc_coverage.sh"
diff --git a/kokoro/linux/presubmit_gcc_coverage.cfg b/kokoro/linux/presubmit_mingw_release.cfg
similarity index 91%
rename from kokoro/linux/presubmit_gcc_coverage.cfg
rename to kokoro/linux/presubmit_mingw_release.cfg
index 54733b0..bfc53ad 100644
--- a/kokoro/linux/presubmit_gcc_coverage.cfg
+++ b/kokoro/linux/presubmit_mingw_release.cfg
@@ -13,4 +13,4 @@
 # limitations under the License.
 
 # Presubmit build configuration.
-build_file: "shaderc/kokoro/linux/build_gcc_coverage.sh"
+build_file: "shaderc/kokoro/linux/build_mingw_release.sh"
diff --git a/kokoro/macos/build.sh b/kokoro/macos/build.sh
index ff2d38c..c39c9b4 100644
--- a/kokoro/macos/build.sh
+++ b/kokoro/macos/build.sh
@@ -40,10 +40,10 @@
 # Invoke the build.
 BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
 echo $(date): Starting build...
-cmake -GNinja -DCMAKE_INSTALL_PREFIX=$KOKORO_ARTIFACTS_DIR/install -DSHADERC_ENABLE_SPVC=ON -DRE2_BUILD_TESTING=OFF -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
+cmake -GNinja -DCMAKE_INSTALL_PREFIX=$KOKORO_ARTIFACTS_DIR/install -DRE2_BUILD_TESTING=OFF -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
 
 echo $(date): Build glslang...
-ninja glslangValidator
+ninja glslang-standalone
 
 echo $(date): Build everything...
 ninja
diff --git a/kokoro/ndk-build/build-docker.sh b/kokoro/ndk-build/build-docker.sh
new file mode 100755
index 0000000..12d178b
--- /dev/null
+++ b/kokoro/ndk-build/build-docker.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+# Copyright (c) 2018 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Linux Build Script.
+
+# Fail on any error.
+set -e
+# Display commands being run.
+set -x
+
+# This is required to run any git command in the docker since owner will
+# have changed between the clone environment, and the docker container.
+# Marking the root of the repo as safe for ownership changes.
+git config --global --add safe.directory $ROOT_DIR
+
+. /bin/using.sh # Declare the bash `using` function for configuring toolchains.
+
+cd $ROOT_DIR
+
+function clean_dir() {
+  dir=$1
+  if [[ -d "$dir" ]]; then
+    rm -fr "$dir"
+  fi
+  mkdir "$dir"
+}
+
+# Get source for dependencies, as specified in the DEPS file
+/usr/bin/python3 utils/git-sync-deps --treeless
+
+using ndk-r25c
+
+clean_dir "$ROOT_DIR/build"
+cd "$ROOT_DIR/build"
+
+function do_ndk_build () {
+  echo $(date): Starting ndk-build $@...
+  $ANDROID_NDK_HOME/ndk-build \
+    -C $ROOT_DIR/android_test \
+    NDK_PROJECT_PATH=. \
+    NDK_LIBS_OUT=./libs \
+    NDK_APP_OUT=./app \
+    V=1 \
+    SPVTOOLS_LOCAL_PATH=$ROOT_DIR/third_party/spirv-tools \
+    SPVHEADERS_LOCAL_PATH=$ROOT_DIR/third_party/spirv-headers \
+    -j8 $@
+}
+
+# Builds all the ABIs (see APP_ABI in jni/Application.mk)
+do_ndk_build
+
+# Check that libshaderc_combined builds
+# Explicitly set each ABI, otherwise it will only pick x86.
+# It seems to be the behaviour when specifying an explicit target.
+for abi in x86 x86_64 armeabi-v7a arm64-v8a; do
+  do_ndk_build APP_ABI=$abi libshaderc_combined
+done
+
+echo $(date): ndk-build completed.
diff --git a/kokoro/ndk-build/build.sh b/kokoro/ndk-build/build.sh
index 0b9e124..bf85b2d 100644
--- a/kokoro/ndk-build/build.sh
+++ b/kokoro/ndk-build/build.sh
@@ -1,6 +1,5 @@
 #!/bin/bash
-
-# Copyright (C) 2017 Google Inc.
+# Copyright (c) 2021 Google LLC.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -18,47 +17,40 @@
 
 # Fail on any error.
 set -e
-# Display commands being run.
-set -x
 
-BUILD_ROOT=$PWD
-SRC=$PWD/github/shaderc
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd )"
+ROOT_DIR="$( cd "${SCRIPT_DIR}/../.." >/dev/null 2>&1 && pwd )"
 
-# Get NINJA.
-wget -q https://github.com/ninja-build/ninja/releases/download/v1.7.2/ninja-linux.zip
-unzip -q ninja-linux.zip
-export PATH="$PWD:$PATH"
-
-# Get Android NDK.
-wget -q https://dl.google.com/android/repository/android-ndk-r18b-linux-x86_64.zip
-unzip -q android-ndk-r18b-linux-x86_64.zip
-export ANDROID_NDK=$PWD/android-ndk-r18b
-
-# Get shaderc dependencies.
-cd $SRC
-./utils/git-sync-deps
-
-cd $SRC
-mkdir build
-cd $SRC/build
-
-# Invoke the build.
 BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
 
-function do_ndk_build () {
-  echo $(date): Starting ndk-build $@...
-  $ANDROID_NDK/ndk-build \
-    -C $SRC/android_test \
-    NDK_APP_OUT=`pwd` \
-    V=1 \
-    SPVTOOLS_LOCAL_PATH=$SRC/third_party/spirv-tools \
-    SPVHEADERS_LOCAL_PATH=$SRC/third_party/spirv-headers \
-    -j 8 $@
+# chown the given directory to the current user, if it exists.
+# Docker creates files with the root user - this can upset the Kokoro artifact copier.
+function chown_dir() {
+  dir=$1
+  if [[ -d "$dir" ]]; then
+    sudo chown -R "$(id -u):$(id -g)" "$dir"
+  fi
 }
 
-do_ndk_build
+set +e
+# Allow build failures
 
-# Check that libshaderc_combined builds
-do_ndk_build libshaderc_combined
+# "--privileged" is required to run ptrace in the asan builds.
+docker run --rm -i \
+  --privileged \
+  --volume "${ROOT_DIR}:${ROOT_DIR}" \
+  --volume "${KOKORO_ARTIFACTS_DIR}:${KOKORO_ARTIFACTS_DIR}" \
+  --workdir "${ROOT_DIR}" \
+  --env SCRIPT_DIR=${SCRIPT_DIR} \
+  --env ROOT_DIR=${ROOT_DIR} \
+  --env KOKORO_ARTIFACTS_DIR="${KOKORO_ARTIFACTS_DIR}" \
+  --env BUILD_SHA="${BUILD_SHA}" \
+  --entrypoint "${SCRIPT_DIR}/build-docker.sh" \
+  "gcr.io/shaderc-build/radial-build:latest"
+RESULT=$?
 
-echo $(date): ndk-build completed.
+# This is important. If the permissions are not fixed, kokoro will fail
+# to pull build artifacts, and put the build in tool-failure state, which
+# blocks the logs.
+chown_dir "${ROOT_DIR}/build"
+exit $RESULT
diff --git a/kokoro/windows/build.bat b/kokoro/windows/build.bat
index 077caef..a87cfea 100644
--- a/kokoro/windows/build.bat
+++ b/kokoro/windows/build.bat
@@ -35,12 +35,12 @@
 :: #########################################
 :: set up msvc build env
 :: #########################################
-if %VS_VERSION% == 2017 (
+if %VS_VERSION% == 2019 (
+  call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64
+  echo "Using VS 2019..."
+) else 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..."
 )
 
 :: #########################################
@@ -53,13 +53,13 @@
   set BUILD_SHA=%KOKORO_GITHUB_COMMIT%
 )
 
-set CMAKE_FLAGS=-DCMAKE_INSTALL_PREFIX=%KOKORO_ARTIFACTS_DIR%\install -DSHADERC_ENABLE_SPVC=ON -DRE2_BUILD_TESTING=OFF -GNinja -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DCMAKE_C_COMPILER=cl.exe -DCMAKE_CXX_COMPILER=cl.exe
+set CMAKE_FLAGS=-DCMAKE_INSTALL_PREFIX=%KOKORO_ARTIFACTS_DIR%\install -DRE2_BUILD_TESTING=OFF -GNinja -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DCMAKE_C_COMPILER=cl.exe -DCMAKE_CXX_COMPILER=cl.exe
 
 cmake %CMAKE_FLAGS% ..
 if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL%
 
 echo "Build glslang... %DATE% %TIME%"
-ninja glslangValidator
+ninja glslang-standalone
 if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL%
 
 echo "Build everything... %DATE% %TIME%"
diff --git a/kokoro/windows/build_release_2015.bat b/kokoro/windows/build_debug_2019.bat
similarity index 89%
copy from kokoro/windows/build_release_2015.bat
copy to kokoro/windows/build_debug_2019.bat
index ea156fe..ea173d9 100644
--- a/kokoro/windows/build_release_2015.bat
+++ b/kokoro/windows/build_debug_2019.bat
@@ -1,4 +1,4 @@
-:: Copyright (C) 2017 Google Inc.
+:: Copyright (C) 2023 Google Inc.
 ::
 :: Licensed under the Apache License, Version 2.0 (the "License");
 :: you may not use this file except in compliance with the License.
@@ -20,5 +20,4 @@
 set SCRIPT_DIR=%~dp0
 
 :: Call with correct parameter
-call %SCRIPT_DIR%\build.bat RelWithDebInfo 2015
-
+call %SCRIPT_DIR%\build.bat Debug 2019
diff --git a/kokoro/windows/build_release_2015.bat b/kokoro/windows/build_release_2019.bat
similarity index 89%
rename from kokoro/windows/build_release_2015.bat
rename to kokoro/windows/build_release_2019.bat
index ea156fe..f0611e3 100644
--- a/kokoro/windows/build_release_2015.bat
+++ b/kokoro/windows/build_release_2019.bat
@@ -1,4 +1,4 @@
-:: Copyright (C) 2017 Google Inc.
+:: Copyright (C) 2023 Google Inc.
 ::
 :: Licensed under the Apache License, Version 2.0 (the "License");
 :: you may not use this file except in compliance with the License.
@@ -20,5 +20,4 @@
 set SCRIPT_DIR=%~dp0
 
 :: Call with correct parameter
-call %SCRIPT_DIR%\build.bat RelWithDebInfo 2015
-
+call %SCRIPT_DIR%\build.bat RelWithDebInfo 2019
diff --git a/kokoro/windows/continuous_release_2015.cfg b/kokoro/windows/continuous_debug_2019.cfg
similarity index 87%
rename from kokoro/windows/continuous_release_2015.cfg
rename to kokoro/windows/continuous_debug_2019.cfg
index 9017c86..3600e1b 100644
--- a/kokoro/windows/continuous_release_2015.cfg
+++ b/kokoro/windows/continuous_debug_2019.cfg
@@ -1,4 +1,4 @@
-# Copyright (C) 2017 Google Inc.
+# Copyright (C) 2023 Google Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 # Continuous build configuration.
-build_file: "shaderc/kokoro/windows/build_release_2015.bat"
+build_file: "shaderc/kokoro/windows/build_debug_2019.bat"
 
 action {
   define_artifacts {
diff --git a/kokoro/windows/continuous_release_2015.cfg b/kokoro/windows/continuous_release_2019.cfg
similarity index 87%
copy from kokoro/windows/continuous_release_2015.cfg
copy to kokoro/windows/continuous_release_2019.cfg
index 9017c86..8cbbc7e 100644
--- a/kokoro/windows/continuous_release_2015.cfg
+++ b/kokoro/windows/continuous_release_2019.cfg
@@ -1,4 +1,4 @@
-# Copyright (C) 2017 Google Inc.
+# Copyright (C) 2023 Google Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 # Continuous build configuration.
-build_file: "shaderc/kokoro/windows/build_release_2015.bat"
+build_file: "shaderc/kokoro/windows/build_release_2019.bat"
 
 action {
   define_artifacts {
diff --git a/kokoro/linux/presubmit_gcc_coverage.cfg b/kokoro/windows/presubmit_debug_2019.cfg
similarity index 85%
copy from kokoro/linux/presubmit_gcc_coverage.cfg
copy to kokoro/windows/presubmit_debug_2019.cfg
index 54733b0..7aa76d8 100644
--- a/kokoro/linux/presubmit_gcc_coverage.cfg
+++ b/kokoro/windows/presubmit_debug_2019.cfg
@@ -1,4 +1,4 @@
-# Copyright (C) 2017 Google Inc.
+# Copyright (C) 2023 Google Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,4 +13,4 @@
 # limitations under the License.
 
 # Presubmit build configuration.
-build_file: "shaderc/kokoro/linux/build_gcc_coverage.sh"
+build_file: "shaderc/kokoro/windows/build_debug_2019.bat"
diff --git a/kokoro/windows/presubmit_release_2015.cfg b/kokoro/windows/presubmit_release_2015.cfg
deleted file mode 100644
index bd24415..0000000
--- a/kokoro/windows/presubmit_release_2015.cfg
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (C) 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Presubmit build configuration.
-build_file: "shaderc/kokoro/windows/build_release_2015.bat"
diff --git a/kokoro/linux/presubmit_gcc_coverage.cfg b/kokoro/windows/presubmit_release_2019.cfg
similarity index 85%
copy from kokoro/linux/presubmit_gcc_coverage.cfg
copy to kokoro/windows/presubmit_release_2019.cfg
index 54733b0..734cff0 100644
--- a/kokoro/linux/presubmit_gcc_coverage.cfg
+++ b/kokoro/windows/presubmit_release_2019.cfg
@@ -1,4 +1,4 @@
-# Copyright (C) 2017 Google Inc.
+# Copyright (C) 2023 Google Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,4 +13,4 @@
 # limitations under the License.
 
 # Presubmit build configuration.
-build_file: "shaderc/kokoro/linux/build_gcc_coverage.sh"
+build_file: "shaderc/kokoro/windows/build_release_2019.bat"
diff --git a/libshaderc/Android.mk b/libshaderc/Android.mk
index 294af69..a482730 100644
--- a/libshaderc/Android.mk
+++ b/libshaderc/Android.mk
@@ -23,7 +23,7 @@
 # or delegates that responsibility to SPIRV-Tools' Android.mk.
 LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include $(SPVHEADERS_LOCAL_PATH)/include
 LOCAL_STATIC_LIBRARIES:=shaderc_util SPIRV-Tools-opt
-LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -DENABLE_HLSL=1
-LOCAL_EXPORT_CPPFLAGS:=-std=c++11
+LOCAL_CXXFLAGS:=-std=c++17 -fno-exceptions -fno-rtti -DENABLE_HLSL=1
+LOCAL_EXPORT_CPPFLAGS:=-std=c++17
 LOCAL_EXPORT_LDFLAGS:=-latomic
 include $(BUILD_STATIC_LIBRARY)
diff --git a/libshaderc/CMakeLists.txt b/libshaderc/CMakeLists.txt
index 3ada419..2cced9e 100644
--- a/libshaderc/CMakeLists.txt
+++ b/libshaderc/CMakeLists.txt
@@ -57,6 +57,7 @@
   install(TARGETS shaderc shaderc_shared
     LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}
     ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
 endif(SHADERC_ENABLE_INSTALL)
 
diff --git a/libshaderc/include/shaderc/shaderc.h b/libshaderc/include/shaderc/shaderc.h
index 84e068b..235f607 100644
--- a/libshaderc/include/shaderc/shaderc.h
+++ b/libshaderc/include/shaderc/shaderc.h
@@ -189,6 +189,25 @@
   shaderc_limit_max_cull_distances,
   shaderc_limit_max_combined_clip_and_cull_distances,
   shaderc_limit_max_samples,
+  shaderc_limit_max_mesh_output_vertices_nv,
+  shaderc_limit_max_mesh_output_primitives_nv,
+  shaderc_limit_max_mesh_work_group_size_x_nv,
+  shaderc_limit_max_mesh_work_group_size_y_nv,
+  shaderc_limit_max_mesh_work_group_size_z_nv,
+  shaderc_limit_max_task_work_group_size_x_nv,
+  shaderc_limit_max_task_work_group_size_y_nv,
+  shaderc_limit_max_task_work_group_size_z_nv,
+  shaderc_limit_max_mesh_view_count_nv,
+  shaderc_limit_max_mesh_output_vertices_ext,
+  shaderc_limit_max_mesh_output_primitives_ext,
+  shaderc_limit_max_mesh_work_group_size_x_ext,
+  shaderc_limit_max_mesh_work_group_size_y_ext,
+  shaderc_limit_max_mesh_work_group_size_z_ext,
+  shaderc_limit_max_task_work_group_size_x_ext,
+  shaderc_limit_max_task_work_group_size_y_ext,
+  shaderc_limit_max_task_work_group_size_z_ext,
+  shaderc_limit_max_mesh_view_count_ext,
+  shaderc_limit_max_dual_source_draw_buffers_ext,
 } shaderc_limit;
 
 // Uniform resource kinds.
@@ -439,6 +458,11 @@
     shaderc_compile_options_t options, shaderc_shader_kind shader_kind,
     shaderc_uniform_kind kind, uint32_t base);
 
+// Sets whether the compiler should preserve all bindings, even when those
+// bindings are not used.
+SHADERC_EXPORT void shaderc_compile_options_set_preserve_bindings(
+    shaderc_compile_options_t options, bool preserve_bindings);
+
 // Sets whether the compiler should automatically assign locations to
 // uniform variables that don't have explicit locations in the shader source.
 SHADERC_EXPORT void shaderc_compile_options_set_auto_map_locations(
diff --git a/libshaderc/include/shaderc/shaderc.hpp b/libshaderc/include/shaderc/shaderc.hpp
index 599a2eb..bc057c1 100644
--- a/libshaderc/include/shaderc/shaderc.hpp
+++ b/libshaderc/include/shaderc/shaderc.hpp
@@ -311,6 +311,12 @@
                                                        kind, base);
   }
 
+  // Sets whether the compiler should preserve all bindings, even when those
+  // bindings are not used.
+  void SetPreserveBindings(bool preserve_bindings) {
+    shaderc_compile_options_set_preserve_bindings(options_, preserve_bindings);
+  }
+
   // Sets whether the compiler automatically assigns locations to
   // uniform variables that don't have explicit locations.
   void SetAutoMapLocations(bool auto_map) {
diff --git a/libshaderc/src/common_shaders_for_test.h b/libshaderc/src/common_shaders_for_test.h
index e177797..b8c581f 100644
--- a/libshaderc/src/common_shaders_for_test.h
+++ b/libshaderc/src/common_shaders_for_test.h
@@ -233,7 +233,7 @@
 const char* kMinimalShaderDisassemblySubstrings[] = {
     "; SPIR-V\n"
     "; Version: 1.0\n"
-    "; Generator: Google Shaderc over Glslang; 10\n"
+    "; Generator: Google Shaderc over Glslang; 11\n"
     "; Bound:",
 
     "               OpCapability Shader\n",
@@ -245,7 +245,7 @@
 const char* kMinimalShaderDebugInfoDisassemblySubstrings[] = {
     "; SPIR-V\n"
     "; Version: 1.0\n"
-    "; Generator: Google Shaderc over Glslang; 10\n"
+    "; Generator: Google Shaderc over Glslang; 11\n"
     "; Bound:",
 
     "               OpCapability Shader\n",
@@ -257,7 +257,7 @@
 const char kMinimalShaderAssembly[] = R"(
     ; SPIR-V
     ; Version: 1.0
-    ; Generator: Google Shaderc over Glslang; 10
+    ; Generator: Google Shaderc over Glslang; 11
     ; Bound: 6
     ; Schema: 0
 
diff --git a/libshaderc/src/shaderc.cc b/libshaderc/src/shaderc.cc
index a2822b5..3223820 100644
--- a/libshaderc/src/shaderc.cc
+++ b/libshaderc/src/shaderc.cc
@@ -12,6 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "shaderc/shaderc.h"
+
 #include <algorithm>
 #include <cassert>
 #include <cstdint>
@@ -529,6 +531,11 @@
                                                GetUniformKind(kind), base);
 }
 
+void shaderc_compile_options_set_preserve_bindings(
+    shaderc_compile_options_t options, bool preserve_bindings) {
+  options->compiler.SetPreserveBindings(preserve_bindings);
+}
+
 void shaderc_compile_options_set_auto_map_locations(
     shaderc_compile_options_t options, bool auto_map) {
   options->compiler.SetAutoMapLocations(auto_map);
diff --git a/libshaderc/src/shaderc_cpp_test.cc b/libshaderc/src/shaderc_cpp_test.cc
index 3166704..0f1f37f 100644
--- a/libshaderc/src/shaderc_cpp_test.cc
+++ b/libshaderc/src/shaderc_cpp_test.cc
@@ -545,7 +545,8 @@
               // 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"));
+                        "Capability GroupNonUniform is not allowed by Vulkan "
+                        "1.0 specification (or requires extension)"));
 }
 
 TEST_F(CppInterface, CompileAndOptimizeForVulkan11Success) {
@@ -664,7 +665,7 @@
   const PreprocessedSourceCompilationResult result = compiler_.PreprocessGlsl(
       kMinimalShaderWithMacro, shaderc_glsl_vertex_shader, "shader", options_);
   EXPECT_TRUE(CompilationResultIsSuccess(result));
-  EXPECT_THAT(CompilerOutputAsString(result), HasSubstr("void main(){ }"));
+  EXPECT_THAT(CompilerOutputAsString(result), HasSubstr("void main() { }"));
 
   const std::string kMinimalShaderCloneOption =
       "#version 140\n"
@@ -677,7 +678,7 @@
                                cloned_options);
   EXPECT_TRUE(CompilationResultIsSuccess(result_from_cloned_options));
   EXPECT_THAT(CompilerOutputAsString(result_from_cloned_options),
-              HasSubstr("void main(){ }"));
+              HasSubstr("void main() { }"));
 }
 
 // A shader kind test case needs: 1) A shader text with or without #pragma
diff --git a/libshaderc/src/shaderc_test.cc b/libshaderc/src/shaderc_test.cc
index aba95d1..5610b0b 100644
--- a/libshaderc/src/shaderc_test.cc
+++ b/libshaderc/src/shaderc_test.cc
@@ -774,7 +774,7 @@
   const std::string preprocessed_text =
       CompilationOutput(kMinimalShaderWithMacro, shaderc_glsl_vertex_shader,
                         options_.get(), OutputType::PreprocessedText);
-  EXPECT_THAT(preprocessed_text, HasSubstr("void main(){ }"));
+  EXPECT_THAT(preprocessed_text, HasSubstr("void main() { }"));
 
   const std::string kMinimalShaderWithMacroCloneOption =
       "#version 150\n"
@@ -785,7 +785,7 @@
   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(){ }"));
+  EXPECT_THAT(preprocessed_text_cloned_options, HasSubstr("void main() { }"));
 }
 
 // A shader kind test cases needs: 1) A shader text with or without #pragma
diff --git a/libshaderc_util/Android.mk b/libshaderc_util/Android.mk
index ade568c..9642e25 100644
--- a/libshaderc_util/Android.mk
+++ b/libshaderc_util/Android.mk
@@ -16,7 +16,7 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE:=shaderc_util
-LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -DENABLE_HLSL=1
+LOCAL_CXXFLAGS:=-std=c++17 -fno-exceptions -fno-rtti -DENABLE_HLSL=1
 LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/include
 LOCAL_SRC_FILES:=src/args.cc \
                 src/compiler.cc \
diff --git a/libshaderc_util/include/libshaderc_util/compiler.h b/libshaderc_util/include/libshaderc_util/compiler.h
index 420f285..ffd7c24 100644
--- a/libshaderc_util/include/libshaderc_util/compiler.h
+++ b/libshaderc_util/include/libshaderc_util/compiler.h
@@ -206,6 +206,7 @@
         auto_combined_image_sampler_(false),
         auto_binding_base_(),
         auto_map_locations_(false),
+        preserve_bindings_(false),
         hlsl_iomap_(false),
         hlsl_offsets_(false),
         hlsl_legalization_enabled_(true),
@@ -307,6 +308,12 @@
     auto_binding_base_[static_cast<int>(stage)][static_cast<int>(kind)] = base;
   }
 
+  // Sets whether the compiler should preserve all bindings, even when those
+  // bindings are not used.
+  void SetPreserveBindings(bool preserve_bindings) {
+    preserve_bindings_ = preserve_bindings;
+  }
+
   // Sets whether the compiler automatically assigns locations to
   // uniform variables that don't have explicit locations.
   void SetAutoMapLocations(bool auto_map) { auto_map_locations_ = auto_map; }
@@ -518,6 +525,9 @@
   // have explicit locations.
   bool auto_map_locations_;
 
+  // True if the compiler should preserve all bindings, even when unused.
+  bool preserve_bindings_;
+
   // True if the compiler should use HLSL IO mapping rules when compiling HLSL.
   bool hlsl_iomap_;
 
diff --git a/libshaderc_util/include/libshaderc_util/resources.inc b/libshaderc_util/include/libshaderc_util/resources.inc
index 8e86f01..147f31f 100644
--- a/libshaderc_util/include/libshaderc_util/resources.inc
+++ b/libshaderc_util/include/libshaderc_util/resources.inc
@@ -105,3 +105,39 @@
 RESOURCE(MaxCullDistances,maxCullDistances,max_cull_distances)
 RESOURCE(MaxCombinedClipAndCullDistances,maxCombinedClipAndCullDistances,max_combined_clip_and_cull_distances)
 RESOURCE(MaxSamples,maxSamples,max_samples)
+RESOURCE(MaxMeshOutputVerticesNV, maxMeshOutputVerticesNV,
+         max_mesh_output_vertices_nv)
+RESOURCE(MaxMeshOutputPrimitivesNV, maxMeshOutputPrimitivesNV,
+         max_mesh_output_primitives_nv)
+RESOURCE(MaxMeshWorkGroupSizeX_NV, maxMeshWorkGroupSizeX_NV,
+         max_mesh_work_group_size_x_nv)
+RESOURCE(MaxMeshWorkGroupSizeY_NV, maxMeshWorkGroupSizeY_NV,
+         max_mesh_work_group_size_y_nv)
+RESOURCE(MaxMeshWorkGroupSizeZ_NV, maxMeshWorkGroupSizeZ_NV,
+         max_mesh_work_group_size_z_nv)
+RESOURCE(MaxTaskWorkGroupSizeX_NV, maxTaskWorkGroupSizeX_NV,
+         max_task_work_group_size_x_nv)
+RESOURCE(MaxTaskWorkGroupSizeY_NV, maxTaskWorkGroupSizeY_NV,
+         max_task_work_group_size_y_nv)
+RESOURCE(MaxTaskWorkGroupSizeZ_NV, maxTaskWorkGroupSizeZ_NV,
+         max_task_work_group_size_z_nv)
+RESOURCE(MaxMeshViewCountNV, maxMeshViewCountNV, max_mesh_view_count_nv)
+RESOURCE(MaxMeshOutputVerticesEXT, maxMeshOutputVerticesEXT,
+         max_mesh_output_vertices_ext)
+RESOURCE(MaxMeshOutputPrimitivesEXT, maxMeshOutputPrimitivesEXT,
+         max_mesh_output_primitives_ext)
+RESOURCE(MaxMeshWorkGroupSizeX_EXT, maxMeshWorkGroupSizeX_EXT,
+         max_mesh_work_group_size_x_ext)
+RESOURCE(MaxMeshWorkGroupSizeY_EXT, maxMeshWorkGroupSizeY_EXT,
+         max_mesh_work_group_size_y_ext)
+RESOURCE(MaxMeshWorkGroupSizeZ_EXT, maxMeshWorkGroupSizeZ_EXT,
+         max_mesh_work_group_size_z_ext)
+RESOURCE(MaxTaskWorkGroupSizeX_EXT, maxTaskWorkGroupSizeX_EXT,
+         max_task_work_group_size_x_ext)
+RESOURCE(MaxTaskWorkGroupSizeY_EXT, maxTaskWorkGroupSizeY_EXT,
+         max_task_work_group_size_y_ext)
+RESOURCE(MaxTaskWorkGroupSizeZ_EXT, maxTaskWorkGroupSizeZ_EXT,
+         max_task_work_group_size_z_ext)
+RESOURCE(MaxMeshViewCountEXT, maxMeshViewCountEXT, max_mesh_view_count_ext)
+RESOURCE(MaxDualSourceDrawBuffersEXT, maxDualSourceDrawBuffersEXT,
+         max_dual_source_draw_buffers_ext)
diff --git a/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h b/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h
index 09d8462..dcf5503 100644
--- a/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h
+++ b/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h
@@ -60,6 +60,7 @@
 bool SpirvToolsOptimize(Compiler::TargetEnv env,
                         Compiler::TargetEnvVersion version,
                         const std::vector<PassId>& enabled_passes,
+                        spvtools::OptimizerOptions& optimizer_options,
                         std::vector<uint32_t>* binary, std::string* errors);
 
 }  // namespace shaderc_util
diff --git a/libshaderc_util/include/libshaderc_util/string_piece.h b/libshaderc_util/include/libshaderc_util/string_piece.h
index 275c6a1..8d334df 100644
--- a/libshaderc_util/include/libshaderc_util/string_piece.h
+++ b/libshaderc_util/include/libshaderc_util/string_piece.h
@@ -332,7 +332,7 @@
 }
 
 inline bool operator==(const char* first, const string_piece second) {
-  return string_piece(first) == second;
+  return second == string_piece(first);
 }
 
 inline bool operator!=(const char* first, const string_piece second) {
diff --git a/libshaderc_util/src/compiler.cc b/libshaderc_util/src/compiler.cc
index e1345d2..525cbc5 100644
--- a/libshaderc_util/src/compiler.cc
+++ b/libshaderc_util/src/compiler.cc
@@ -29,6 +29,7 @@
 #include "libshaderc_util/spirv_tools_wrapper.h"
 #include "libshaderc_util/string_piece.h"
 #include "libshaderc_util/version_profile.h"
+#include "spirv-tools/libspirv.hpp"
 
 namespace {
 using shaderc_util::string_piece;
@@ -348,9 +349,12 @@
                     enabled_opt_passes_.end());
 
   if (!opt_passes.empty()) {
+    spvtools::OptimizerOptions opt_options;
+    opt_options.set_preserve_bindings(preserve_bindings_);
+
     std::string opt_errors;
-    if (!SpirvToolsOptimize(target_env_, target_env_version_,
-                            opt_passes, &spirv, &opt_errors)) {
+    if (!SpirvToolsOptimize(target_env_, target_env_version_, opt_passes,
+                            opt_options, &spirv, &opt_errors)) {
       *error_stream << "shaderc: internal error: compilation succeeded but "
                        "failed to optimize: "
                     << opt_errors << "\n";
diff --git a/libshaderc_util/src/spirv_tools_wrapper.cc b/libshaderc_util/src/spirv_tools_wrapper.cc
index 63bff6a..b4f57f8 100644
--- a/libshaderc_util/src/spirv_tools_wrapper.cc
+++ b/libshaderc_util/src/spirv_tools_wrapper.cc
@@ -17,6 +17,7 @@
 #include <algorithm>
 #include <sstream>
 
+#include "spirv-tools/libspirv.hpp"
 #include "spirv-tools/optimizer.hpp"
 
 namespace shaderc_util {
@@ -108,6 +109,7 @@
 bool SpirvToolsOptimize(Compiler::TargetEnv env,
                         Compiler::TargetEnvVersion version,
                         const std::vector<PassId>& enabled_passes,
+                        spvtools::OptimizerOptions& optimizer_options,
                         std::vector<uint32_t>* binary, std::string* errors) {
   errors->clear();
   if (enabled_passes.empty()) return true;
@@ -125,9 +127,9 @@
   // This uses relaxed rules for pre-legalized HLSL.
   val_opts.SetBeforeHlslLegalization(true);
 
-  spvtools::OptimizerOptions opt_opts;
-  opt_opts.set_validator_options(val_opts);
-  opt_opts.set_run_validator(true);
+  // Set additional optimizer options.
+  optimizer_options.set_validator_options(val_opts);
+  optimizer_options.set_run_validator(true);
 
   spvtools::Optimizer optimizer(GetSpirvToolsTargetEnv(env, version));
 
@@ -159,7 +161,8 @@
     }
   }
 
-  if (!optimizer.Run(binary->data(), binary->size(), binary, opt_opts)) {
+  if (!optimizer.Run(binary->data(), binary->size(), binary,
+                     optimizer_options)) {
     *errors = oss.str();
     return false;
   }
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index 7bd9617..a01f31e 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -17,6 +17,8 @@
   "Location of re2 source")
 set(SHADERC_TINT_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/tint" CACHE STRING
   "Location of tint source")
+set(SHADERC_ABSL_DIR "${SHADERC_THIRD_PARTY_ROOT_DIR}/abseil_cpp" CACHE STRING
+  "Location of re2 source")
 
 set( SKIP_GLSLANG_INSTALL ${SHADERC_SKIP_INSTALL} )
 set( SKIP_SPIRV_TOOLS_INSTALL ${SHADERC_SKIP_INSTALL} )
@@ -49,7 +51,13 @@
       # Also skip building tests in SPIRV-Tools.
       set(SPIRV_SKIP_TESTS ON CACHE BOOL "Skip building SPIRV-Tools tests")
     elseif(NOT "${SPIRV_SKIP_TESTS}")
-      # SPIRV-Tools requires effcee and re2 to build tests.
+      # SPIRV-Tools requires effcee, re2, and abseil to build tests.
+      # re2 depends on abseil, so abseil must be added first.
+      set(ABSL_INTERNAL_AT_LEAST_CXX17 ON)
+      set(ABSL_PROPAGATE_CXX_STD ON)
+      set(ABSL_ENABLE_INSTALL ON)
+      add_subdirectory(${SHADERC_ABSL_DIR} absl EXCLUDE_FROM_ALL)
+
       # re2 tests take a long time and do not add much value, since re2 is a
       # dependency of a dependency, so not running them.
       set(RE2_BUILD_TESTING OFF CACHE STRING "Run RE2 Tests")
@@ -57,6 +65,16 @@
       add_subdirectory(${SHADERC_EFFCEE_DIR} effcee)
     endif()
     add_subdirectory(${SHADERC_SPIRV_TOOLS_DIR} spirv-tools)
+    if (NOT "${SPIRV_SKIP_TESTS}")
+      if (MSVC)
+        if (${MSVC_VERSION} LESS 1920)
+	  # VS 2017 requires /bigobj on test_opt
+	  # https://github.com/google/shaderc/issues/1345
+	  # https://github.com/KhronosGroup/SPIRV-Tools/issues/5335
+	  target_compile_options(test_opt PRIVATE /bigobj)
+        endif()
+      endif()
+    endif()
   endif()
   if (NOT TARGET SPIRV-Tools)
     message(FATAL_ERROR "SPIRV-Tools was not found - required for compilation")
diff --git a/utils/roll-deps b/utils/roll-deps
index 4962fd6..8f145c9 100755
--- a/utils/roll-deps
+++ b/utils/roll-deps
@@ -18,18 +18,23 @@
 #
 # Depends on roll-dep from depot_path being in PATH.
 
-effcee_dir="third_party/effcee/"
-effcee_trunk="origin/main"
-glslang_dir="third_party/glslang/"
-glslang_trunk="origin/master"
-googletest_dir="third_party/googletest/"
-googletest_trunk="origin/master"
-re2_dir="third_party/re2/"
-re2_trunk="origin/master"
-spirv_headers_dir="third_party/spirv-headers/"
-spirv_headers_trunk="origin/master"
-spirv_tools_dir="third_party/spirv-tools/"
-spirv_tools_trunk="origin/master"
+set -eo pipefail
+
+function ExitIfIsInterestingError() {
+  local return_code=$1
+  if [[ ${return_code} -ne 0 && ${return_code} -ne 2 ]]; then
+    exit ${return_code}
+  fi
+  return 0
+}
+
+dependencies=("third_party/effcee/"
+              "third_party/glslang/"
+              "third_party/googletest/"
+              "third_party/re2/"
+              "third_party/spirv-headers/"
+              "third_party/spirv-tools/")
+branch="origin/main"
 
 # This script assumes it's parent directory is the repo root.
 repo_path=$(dirname "$0")/..
@@ -41,13 +46,12 @@
     exit 1
 fi
 
-old_head=$(git rev-parse HEAD)
+echo "*** Ignore messages about running 'git cl upload' ***"
 
-roll-dep --ignore-dirty-tree --roll-to="${effcee_trunk}" "${effcee_dir}"
-roll-dep --ignore-dirty-tree --roll-to="${glslang_trunk}" "${glslang_dir}"
-roll-dep --ignore-dirty-tree --roll-to="${googletest_trunk}" "${googletest_dir}"
-roll-dep --ignore-dirty-tree --roll-to="${re2_trunk}" "${re2_dir}"
-roll-dep --ignore-dirty-tree --roll-to="${spirv_headers_trunk}" "${spirv_headers_dir}"
-roll-dep --ignore-dirty-tree --roll-to="${spirv_tools_trunk}" "${spirv_tools_dir}"
+set +e
 
-git rebase --interactive "${old_head}"
+for dep in ${dependencies[@]}; do
+  echo "Rolling $dep"
+  roll-dep --ignore-dirty-tree --roll-to="${branch}" "${dep}"
+  ExitIfIsInterestingError $?
+done
diff --git a/utils/update_build_version.py b/utils/update_build_version.py
index 5785390..11ee53e 100755
--- a/utils/update_build_version.py
+++ b/utils/update_build_version.py
@@ -75,7 +75,7 @@
     # 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*$')
+    pattern = re.compile(r'^(v\d+\.\d+(-dev|[\.-]rc\d+)?) \d\d\d\d-\d\d-\d\d\s*$')
     changes_file = os.path.join(directory, 'CHANGES')
     with open(changes_file, errors='replace') as f:
         for line in f.readlines():