Remove the dependency on shaderc and glslang.

With all tests converted to WGSL we only use shaderc to assemble SPIRV
assembly to binary. shaderc requires glslang but we don't use it at all.
By using SPIRV-Tools directly to assemble SPIR-V, we can remove both the
shaderc and glslang dependencies.

Bug: dawn:572
Bug: chromium:1150045
Change-Id: I1588428dfb9478e7b724478bec662d002ee920e0
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/45765
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/.gitignore b/.gitignore
index 1baaf4b..526938f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,7 +16,6 @@
 third_party/jsoncpp/
 third_party/llvm-build
 third_party/markupsafe/
-third_party/shaderc/
 third_party/swiftshader/
 third_party/tint/
 third_party/vulkan-deps/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f8c6538..1617094 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -78,9 +78,7 @@
 
 set(DAWN_GLFW_DIR "${DAWN_THIRD_PARTY_DIR}/glfw" CACHE STRING "Directory in which to find GLFW")
 set(DAWN_GLM_DIR "${DAWN_THIRD_PARTY_DIR}/glm" CACHE STRING "Directory in which to find GLM")
-set(DAWN_GLSLANG_DIR "${DAWN_THIRD_PARTY_DIR}/vulkan-deps/glslang/src" CACHE STRING "Directory in which to find GLSLang")
 set(DAWN_JINJA2_DIR "${DAWN_THIRD_PARTY_DIR}/jinja2" CACHE STRING "Directory in which to find Jinja2")
-set(DAWN_SHADERC_DIR "${DAWN_THIRD_PARTY_DIR}/shaderc" CACHE STRING "Directory in which to find shaderc")
 set(DAWN_SPIRV_CROSS_DIR "${DAWN_THIRD_PARTY_DIR}/vulkan-deps/spirv-cross/src" CACHE STRING "Directory in which to find SPIRV-Cross")
 set(DAWN_SPIRV_HEADERS_DIR "${DAWN_THIRD_PARTY_DIR}/vulkan-deps/spirv-headers/src" CACHE STRING "Directory in which to find SPIRV-Headers")
 set(DAWN_SPIRV_TOOLS_DIR "${DAWN_THIRD_PARTY_DIR}/vulkan-deps/spirv-tools/src" CACHE STRING "Directory in which to find SPIRV-Tools")
diff --git a/DEPS b/DEPS
index 60bb2cd..b442674 100644
--- a/DEPS
+++ b/DEPS
@@ -56,12 +56,6 @@
     'condition': 'dawn_standalone',
   },
 
-  # SPIRV compiler dependencies: shaderc
-  'third_party/shaderc': {
-    'url': '{chromium_git}/external/github.com/google/shaderc@8d081127ee28ff5df8123c994c00bc66a57e9e9c',
-    'condition': 'dawn_standalone',
-  },
-
   # WGSL support
   'third_party/tint': {
     'url': '{dawn_git}/tint@84ef13c84fb38d37793d7aef2025be38dd9265f5',
diff --git a/build_overrides/dawn.gni b/build_overrides/dawn.gni
index 6fac7d4..d0190b10 100644
--- a/build_overrides/dawn.gni
+++ b/build_overrides/dawn.gni
@@ -32,7 +32,6 @@
 dawn_glfw_dir = "//third_party/glfw"
 dawn_glm_dir = "//third_party/glm"
 dawn_googletest_dir = "//third_party/googletest"
-dawn_shaderc_dir = "//third_party/shaderc"
 dawn_spirv_tools_dir = "//third_party/vulkan-deps/spirv-tools/src"
 dawn_spirv_cross_dir = "//third_party/vulkan-deps/spirv-cross/src"
 dawn_swiftshader_dir = "//third_party/swiftshader"
diff --git a/build_overrides/shaderc.gni b/build_overrides/shaderc.gni
deleted file mode 100644
index fb0f62b..0000000
--- a/build_overrides/shaderc.gni
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2018 The Dawn Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-shaderc_glslang_dir = "//third_party/vulkan-deps/glslang/src"
-shaderc_spirv_tools_dir = "//third_party/vulkan-deps/spirv-tools/src"
-shaderc_spirv_headers_dir = "//third_party/vulkan-deps/spirv-headers/src"
diff --git a/scripts/dawn_overrides_with_defaults.gni b/scripts/dawn_overrides_with_defaults.gni
index 9120a79..3693194 100644
--- a/scripts/dawn_overrides_with_defaults.gni
+++ b/scripts/dawn_overrides_with_defaults.gni
@@ -49,10 +49,6 @@
   dawn_googletest_dir = "//third_party/googletest"
 }
 
-if (!defined(dawn_shaderc_dir)) {
-  dawn_shaderc_dir = "//third_party/shaderc"
-}
-
 if (!defined(dawn_spirv_cross_dir)) {
   dawn_spirv_cross_dir = "//third_party/vulkan-deps/spirv-cross/src"
 }
diff --git a/scripts/roll-shader-deps.sh b/scripts/roll-shader-deps.sh
index db16800..8fbcac5 100755
--- a/scripts/roll-shader-deps.sh
+++ b/scripts/roll-shader-deps.sh
@@ -18,10 +18,6 @@
 #
 # Depends on roll-dep from depot_path being in PATH.
 
-glslang_dir="third_party/glslang/"
-glslang_trunk="origin/master"
-shaderc_dir="third_party/shaderc/"
-shaderc_trunk="origin/main"
 spirv_cross_dir="third_party/spirv-cross/"
 spirv_cross_trunk="origin/master"
 spirv_headers_dir="third_party/spirv-headers/"
@@ -43,8 +39,6 @@
 
 old_head=$(git rev-parse HEAD)
 
-roll-dep --ignore-dirty-tree --roll-to="${glslang_trunk}" "${glslang_dir}"
-roll-dep --ignore-dirty-tree --roll-to="${shaderc_trunk}" "${shaderc_dir}"
 roll-dep --ignore-dirty-tree --roll-to="${spirv_cross_trunk}" "${spirv_cross_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}"
diff --git a/src/utils/BUILD.gn b/src/utils/BUILD.gn
index ce561b3..64431bf 100644
--- a/src/utils/BUILD.gn
+++ b/src/utils/BUILD.gn
@@ -90,7 +90,7 @@
     "${dawn_root}/src/dawn:dawn_proc",
     "${dawn_root}/src/dawn_native:dawn_native_headers",
     "${dawn_root}/src/dawn_wire",
-    "${dawn_shaderc_dir}:libshaderc",
+    "${dawn_spirv_tools_dir}:spvtools_opt",
   ]
   libs = []
   frameworks = []
diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt
index f553d97..59b2a19 100644
--- a/src/utils/CMakeLists.txt
+++ b/src/utils/CMakeLists.txt
@@ -44,7 +44,7 @@
             dawn_native
             dawn_proc
             dawn_wire
-            shaderc
+            SPIRV-Tools-opt
             glfw
 )
 
diff --git a/src/utils/WGPUHelpers.cpp b/src/utils/WGPUHelpers.cpp
index bc538d3..d8f7f3f 100644
--- a/src/utils/WGPUHelpers.cpp
+++ b/src/utils/WGPUHelpers.cpp
@@ -17,66 +17,50 @@
 #include "common/Constants.h"
 #include "common/Log.h"
 
-#include <shaderc/shaderc.hpp>
+#include "spirv-tools/optimizer.hpp"
 
 #include <cstring>
 #include <iomanip>
+#include <limits>
 #include <mutex>
 #include <sstream>
 
 namespace utils {
 
-    namespace {
-
-        class CompilerSingleton {
-          public:
-            static shaderc::Compiler* Get() {
-                std::call_once(mInitFlag, &CompilerSingleton::Initialize);
-                return mCompiler;
-            }
-
-          private:
-            CompilerSingleton() = default;
-            ~CompilerSingleton() = default;
-            CompilerSingleton(const CompilerSingleton&) = delete;
-            CompilerSingleton& operator=(const CompilerSingleton&) = delete;
-
-            static shaderc::Compiler* mCompiler;
-            static std::once_flag mInitFlag;
-
-            static void Initialize() {
-                mCompiler = new shaderc::Compiler();
-            }
-        };
-
-        shaderc::Compiler* CompilerSingleton::mCompiler = nullptr;
-        std::once_flag CompilerSingleton::mInitFlag;
-
-    }  // anonymous namespace
-
     wgpu::ShaderModule CreateShaderModuleFromASM(const wgpu::Device& device, const char* source) {
-        shaderc::Compiler* compiler = CompilerSingleton::Get();
-        shaderc::SpvCompilationResult result = compiler->AssembleToSpv(source, strlen(source));
-        if (result.GetCompilationStatus() != shaderc_compilation_status_success) {
-            dawn::ErrorLog() << result.GetErrorMessage();
-            return {};
+        // Use SPIRV-Tools's C API to assemble the SPIR-V assembly text to binary. Because the types
+        // aren't RAII, we don't return directly on success and instead always go through the code
+        // path that destroys the SPIRV-Tools objects.
+        wgpu::ShaderModule result = nullptr;
+
+        spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_3);
+        ASSERT(context != nullptr);
+
+        spv_binary spirv = nullptr;
+        spv_diagnostic diagnostic = nullptr;
+        if (spvTextToBinary(context, source, strlen(source), &spirv, &diagnostic) == SPV_SUCCESS) {
+            ASSERT(spirv != nullptr);
+            ASSERT(spirv->wordCount <= std::numeric_limits<uint32_t>::max());
+
+            wgpu::ShaderModuleSPIRVDescriptor spirvDesc;
+            spirvDesc.codeSize = static_cast<uint32_t>(spirv->wordCount);
+            spirvDesc.code = spirv->code;
+
+            wgpu::ShaderModuleDescriptor descriptor;
+            descriptor.nextInChain = &spirvDesc;
+            result = device.CreateShaderModule(&descriptor);
+        } else {
+            ASSERT(diagnostic != nullptr);
+            dawn::WarningLog() << "CreateShaderModuleFromASM SPIRV assembly error:"
+                               << diagnostic->position.line + 1 << ":"
+                               << diagnostic->position.column + 1 << ": " << diagnostic->error;
         }
 
-        // result.cend and result.cbegin return pointers to uint32_t.
-        const uint32_t* resultBegin = result.cbegin();
-        const uint32_t* resultEnd = result.cend();
-        // So this size is in units of sizeof(uint32_t).
-        ptrdiff_t resultSize = resultEnd - resultBegin;
-        // SetSource takes data as uint32_t*.
+        spvDiagnosticDestroy(diagnostic);
+        spvBinaryDestroy(spirv);
+        spvContextDestroy(context);
 
-        wgpu::ShaderModuleSPIRVDescriptor spirvDesc;
-        spirvDesc.codeSize = static_cast<uint32_t>(resultSize);
-        spirvDesc.code = result.cbegin();
-
-        wgpu::ShaderModuleDescriptor descriptor;
-        descriptor.nextInChain = &spirvDesc;
-
-        return device.CreateShaderModule(&descriptor);
+        return result;
     }
 
     wgpu::ShaderModule CreateShaderModule(const wgpu::Device& device, const char* source) {
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index 80e4b43..94e5d83 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -38,30 +38,6 @@
     add_subdirectory(${DAWN_SPIRV_TOOLS_DIR})
 endif()
 
-if (NOT TARGET glslang)
-    set(SKIP_GLSLANG_INSTALL ON CACHE BOOL "" FORCE)
-    set(ENABLE_SPVREMAPPER OFF CACHE BOOL "" FORCE)
-    set(ENABLE_GLSLANG_BINARIES OFF CACHE BOOL "" FORCE)
-    set(ENABLE_CTEST OFF CACHE BOOL "" FORCE)
-
-    message(STATUS "Dawn: using GLSLang at ${DAWN_GLSLANG_DIR}")
-    add_subdirectory(${DAWN_GLSLANG_DIR})
-endif()
-
-if (NOT TARGET shaderc)
-    set(SHADERC_SKIP_TESTS ON CACHE BOOL "" FORCE)
-    set(SHADERC_SKIP_INSTALL ON CACHE BOOL "" FORCE)
-
-    # Change the default value of SHADERC_ENABLE_SHARED_CRT to ON as that's what matches the
-    # CMake defaults better.
-    if(MSVC)
-        set(SHADERC_ENABLE_SHARED_CRT ON CACHE BOOL "Use the shared CRT instead of the static CRT")
-    endif()
-
-    message(STATUS "Dawn: using shaderc at ${DAWN_SHADERC_DIR}")
-    add_subdirectory(${DAWN_SHADERC_DIR})
-endif()
-
 if (DAWN_BUILD_EXAMPLES)
     if (NOT TARGET glfw)
         set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)