Remove usages of SPVC

Remove all usages of SPVC from the code and update the fuzzers. Some
of the include paths and deps came transitively from spvc, so needed
to update build rules.

This patch does NOT remove the flags related to spvc usage, they are
just no-ops as the moment. After this patch lands I will remove the
usage of those flags from the bots, then remove the flags.

BUG=dawn:521

Change-Id: I0d7c3e28f79354c78f00c48b6a383b823094a069
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/27900
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
diff --git a/docs/overview.md b/docs/overview.md
index e63afeb..cf0c162 100644
--- a/docs/overview.md
+++ b/docs/overview.md
@@ -33,7 +33,7 @@
 
 The largest library in Dawn is `dawn_native` which implements the WebGPU API by translating to native graphics APIs such as D3D12, Metal or Vulkan. It is composed of a frontend that does all the state-tracking and validation, and backends that do the actual translation to the native graphics APIs.
 
-`dawn_native` hosts the [SPVC](https://github.com/google/shaderc/tree/master/spvc) shader translator that validates SPIR-V for WebGPU and converts it to an equivalent shader for use in the native graphics API (HLSL for D3D12, MSL for Metal or Vulkan SPIR-V for Vulkan).
+`dawn_native` hosts the [spirv-val](https://github.com/KhronosGroup/SPIRV-Tools) for validation of SPIR-V shaders and uses [SPIRV-Cross](https://github.com/KhronosGroup/SPIRV-Cross) shader translator to convert SPIR-V shaders to an equivalent shader for use in the native graphics API (HLSL for D3D12, MSL for Metal or Vulkan SPIR-V for Vulkan).
 
 ## Dawn Wire (`dawn_wire`)
 
diff --git a/src/dawn_native/BUILD.gn b/src/dawn_native/BUILD.gn
index cecfc1e..b4d0ae5 100644
--- a/src/dawn_native/BUILD.gn
+++ b/src/dawn_native/BUILD.gn
@@ -129,7 +129,7 @@
     ":dawn_native_headers",
     ":dawn_native_utils_gen",
     "${dawn_root}/src/common",
-    "${dawn_shaderc_dir}:spirv_cross",
+    "${dawn_root}/third_party/gn/spirv_cross:spirv_cross",
     "${dawn_spirv_tools_dir}:spvtools_val",
   ]
   defines = []
@@ -141,10 +141,7 @@
   # Dependencies that are needed to compile dawn_native entry points in
   # FooBackend.cpp need to be public deps so they are propagated to the
   # dawn_native target
-  public_deps = [
-    "${dawn_root}/src/dawn_platform",
-    "${dawn_shaderc_dir}:libshaderc_spvc",
-  ]
+  public_deps = [ "${dawn_root}/src/dawn_platform" ]
 
   sources = get_target_outputs(":dawn_native_utils_gen")
   sources += [
diff --git a/src/dawn_native/CMakeLists.txt b/src/dawn_native/CMakeLists.txt
index afac9c5..7f6b85b 100644
--- a/src/dawn_native/CMakeLists.txt
+++ b/src/dawn_native/CMakeLists.txt
@@ -149,7 +149,6 @@
     PRIVATE dawn_common
             dawn_platform
             dawn_internal_config
-            shaderc_spvc
             spirv-cross-core
 )
 
diff --git a/src/dawn_native/ShaderModule.cpp b/src/dawn_native/ShaderModule.cpp
index 96cd483..df98750 100644
--- a/src/dawn_native/ShaderModule.cpp
+++ b/src/dawn_native/ShaderModule.cpp
@@ -74,79 +74,6 @@
             }
         }
 
-        wgpu::TextureViewDimension ToWGPUTextureViewDimension(
-            shaderc_spvc_texture_view_dimension dim) {
-            switch (dim) {
-                case shaderc_spvc_texture_view_dimension_undefined:
-                    return wgpu::TextureViewDimension::Undefined;
-                case shaderc_spvc_texture_view_dimension_e1D:
-                    return wgpu::TextureViewDimension::e1D;
-                case shaderc_spvc_texture_view_dimension_e2D:
-                    return wgpu::TextureViewDimension::e2D;
-                case shaderc_spvc_texture_view_dimension_e2D_array:
-                    return wgpu::TextureViewDimension::e2DArray;
-                case shaderc_spvc_texture_view_dimension_cube:
-                    return wgpu::TextureViewDimension::Cube;
-                case shaderc_spvc_texture_view_dimension_cube_array:
-                    return wgpu::TextureViewDimension::CubeArray;
-                case shaderc_spvc_texture_view_dimension_e3D:
-                    return wgpu::TextureViewDimension::e3D;
-            }
-            UNREACHABLE();
-        }
-
-        Format::Type ToDawnFormatType(shaderc_spvc_texture_format_type type) {
-            switch (type) {
-                case shaderc_spvc_texture_format_type_float:
-                    return Format::Type::Float;
-                case shaderc_spvc_texture_format_type_sint:
-                    return Format::Type::Sint;
-                case shaderc_spvc_texture_format_type_uint:
-                    return Format::Type::Uint;
-                case shaderc_spvc_texture_format_type_other:
-                    return Format::Type::Other;
-            }
-            UNREACHABLE();
-        }
-
-        wgpu::BindingType ToWGPUBindingType(shaderc_spvc_binding_type type) {
-            switch (type) {
-                case shaderc_spvc_binding_type_uniform_buffer:
-                    return wgpu::BindingType::UniformBuffer;
-                case shaderc_spvc_binding_type_storage_buffer:
-                    return wgpu::BindingType::StorageBuffer;
-                case shaderc_spvc_binding_type_readonly_storage_buffer:
-                    return wgpu::BindingType::ReadonlyStorageBuffer;
-                case shaderc_spvc_binding_type_sampler:
-                    return wgpu::BindingType::Sampler;
-                case shaderc_spvc_binding_type_comparison_sampler:
-                    return wgpu::BindingType::ComparisonSampler;
-                case shaderc_spvc_binding_type_sampled_texture:
-                    return wgpu::BindingType::SampledTexture;
-                case shaderc_spvc_binding_type_readonly_storage_texture:
-                    return wgpu::BindingType::ReadonlyStorageTexture;
-                case shaderc_spvc_binding_type_writeonly_storage_texture:
-                    return wgpu::BindingType::WriteonlyStorageTexture;
-                case shaderc_spvc_binding_type_storage_texture:
-                    return wgpu::BindingType::StorageTexture;
-                default:
-                    UNREACHABLE();
-            }
-        }
-
-        SingleShaderStage ToSingleShaderStage(shaderc_spvc_execution_model execution_model) {
-            switch (execution_model) {
-                case shaderc_spvc_execution_model_vertex:
-                    return SingleShaderStage::Vertex;
-                case shaderc_spvc_execution_model_fragment:
-                    return SingleShaderStage::Fragment;
-                case shaderc_spvc_execution_model_glcompute:
-                    return SingleShaderStage::Compute;
-                default:
-                    UNREACHABLE();
-            }
-        }
-
         wgpu::TextureFormat ToWGPUTextureFormat(spv::ImageFormat format) {
             switch (format) {
                 case spv::ImageFormatR8:
@@ -218,77 +145,6 @@
             }
         }
 
-        wgpu::TextureFormat ToWGPUTextureFormat(shaderc_spvc_storage_texture_format format) {
-            switch (format) {
-                case shaderc_spvc_storage_texture_format_r8unorm:
-                    return wgpu::TextureFormat::R8Unorm;
-                case shaderc_spvc_storage_texture_format_r8snorm:
-                    return wgpu::TextureFormat::R8Snorm;
-                case shaderc_spvc_storage_texture_format_r8uint:
-                    return wgpu::TextureFormat::R8Uint;
-                case shaderc_spvc_storage_texture_format_r8sint:
-                    return wgpu::TextureFormat::R8Sint;
-                case shaderc_spvc_storage_texture_format_r16uint:
-                    return wgpu::TextureFormat::R16Uint;
-                case shaderc_spvc_storage_texture_format_r16sint:
-                    return wgpu::TextureFormat::R16Sint;
-                case shaderc_spvc_storage_texture_format_r16float:
-                    return wgpu::TextureFormat::R16Float;
-                case shaderc_spvc_storage_texture_format_rg8unorm:
-                    return wgpu::TextureFormat::RG8Unorm;
-                case shaderc_spvc_storage_texture_format_rg8snorm:
-                    return wgpu::TextureFormat::RG8Snorm;
-                case shaderc_spvc_storage_texture_format_rg8uint:
-                    return wgpu::TextureFormat::RG8Uint;
-                case shaderc_spvc_storage_texture_format_rg8sint:
-                    return wgpu::TextureFormat::RG8Sint;
-                case shaderc_spvc_storage_texture_format_r32float:
-                    return wgpu::TextureFormat::R32Float;
-                case shaderc_spvc_storage_texture_format_r32uint:
-                    return wgpu::TextureFormat::R32Uint;
-                case shaderc_spvc_storage_texture_format_r32sint:
-                    return wgpu::TextureFormat::R32Sint;
-                case shaderc_spvc_storage_texture_format_rg16uint:
-                    return wgpu::TextureFormat::RG16Uint;
-                case shaderc_spvc_storage_texture_format_rg16sint:
-                    return wgpu::TextureFormat::RG16Sint;
-                case shaderc_spvc_storage_texture_format_rg16float:
-                    return wgpu::TextureFormat::RG16Float;
-                case shaderc_spvc_storage_texture_format_rgba8unorm:
-                    return wgpu::TextureFormat::RGBA8Unorm;
-                case shaderc_spvc_storage_texture_format_rgba8snorm:
-                    return wgpu::TextureFormat::RGBA8Snorm;
-                case shaderc_spvc_storage_texture_format_rgba8uint:
-                    return wgpu::TextureFormat::RGBA8Uint;
-                case shaderc_spvc_storage_texture_format_rgba8sint:
-                    return wgpu::TextureFormat::RGBA8Sint;
-                case shaderc_spvc_storage_texture_format_rgb10a2unorm:
-                    return wgpu::TextureFormat::RGB10A2Unorm;
-                case shaderc_spvc_storage_texture_format_rg11b10float:
-                    return wgpu::TextureFormat::RG11B10Ufloat;
-                case shaderc_spvc_storage_texture_format_rg32float:
-                    return wgpu::TextureFormat::RG32Float;
-                case shaderc_spvc_storage_texture_format_rg32uint:
-                    return wgpu::TextureFormat::RG32Uint;
-                case shaderc_spvc_storage_texture_format_rg32sint:
-                    return wgpu::TextureFormat::RG32Sint;
-                case shaderc_spvc_storage_texture_format_rgba16uint:
-                    return wgpu::TextureFormat::RGBA16Uint;
-                case shaderc_spvc_storage_texture_format_rgba16sint:
-                    return wgpu::TextureFormat::RGBA16Sint;
-                case shaderc_spvc_storage_texture_format_rgba16float:
-                    return wgpu::TextureFormat::RGBA16Float;
-                case shaderc_spvc_storage_texture_format_rgba32float:
-                    return wgpu::TextureFormat::RGBA32Float;
-                case shaderc_spvc_storage_texture_format_rgba32uint:
-                    return wgpu::TextureFormat::RGBA32Uint;
-                case shaderc_spvc_storage_texture_format_rgba32sint:
-                    return wgpu::TextureFormat::RGBA32Sint;
-                default:
-                    return wgpu::TextureFormat::Undefined;
-            }
-        }
-
         std::string GetShaderDeclarationString(BindGroupIndex group, BindingNumber binding) {
             std::ostringstream ostream;
             ostream << "the shader module declaration at set " << static_cast<uint32_t>(group)
@@ -790,10 +646,6 @@
             default:
                 UNREACHABLE();
         }
-
-        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvcParser)) {
-            mSpvcContext.SetUseSpvcParser(true);
-        }
     }
 
     ShaderModuleBase::ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag)
@@ -827,186 +679,12 @@
 
     MaybeError ShaderModuleBase::ExtractSpirvInfo(const spirv_cross::Compiler& compiler) {
         ASSERT(!IsError());
-        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-            DAWN_TRY_ASSIGN(mMainEntryPoint, ExtractSpirvInfoWithSpvc());
-        } else {
-            DAWN_TRY_ASSIGN(mMainEntryPoint, ExtractSpirvInfoWithSpirvCross(compiler));
-        }
+        DAWN_TRY_ASSIGN(mMainEntryPoint, ExtractSpirvInfoImpl(compiler));
         return {};
     }
 
-    ResultOrError<std::unique_ptr<EntryPointMetadata>>
-    ShaderModuleBase::ExtractSpirvInfoWithSpvc() {
-        DeviceBase* device = GetDevice();
-        std::unique_ptr<EntryPointMetadata> metadata = std::make_unique<EntryPointMetadata>();
-
-        shaderc_spvc_execution_model execution_model;
-        DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetExecutionModel(&execution_model),
-                                  "Unable to get execution model for shader."));
-        metadata->stage = ToSingleShaderStage(execution_model);
-
-        size_t push_constant_buffers_count;
-        DAWN_TRY(
-            CheckSpvcSuccess(mSpvcContext.GetPushConstantBufferCount(&push_constant_buffers_count),
-                             "Unable to get push constant buffer count for shader."));
-
-        // TODO(rharrison): This should be handled by spirv-val pass in spvc,
-        // but need to confirm.
-        if (push_constant_buffers_count > 0) {
-            return DAWN_VALIDATION_ERROR("Push constants aren't supported.");
-        }
-
-        // Fill in bindingInfo with the SPIRV bindings
-        auto ExtractResourcesBinding =
-            [](const DeviceBase* device, const std::vector<shaderc_spvc_binding_info>& spvcBindings,
-               EntryPointMetadata::BindingInfo* metadataBindings) -> MaybeError {
-            for (const shaderc_spvc_binding_info& binding : spvcBindings) {
-                BindGroupIndex bindGroupIndex(binding.set);
-
-                if (bindGroupIndex >= kMaxBindGroupsTyped) {
-                    return DAWN_VALIDATION_ERROR("Bind group index over limits in the SPIRV");
-                }
-
-                const auto& it = (*metadataBindings)[bindGroupIndex].emplace(
-                    BindingNumber(binding.binding), EntryPointMetadata::ShaderBindingInfo{});
-                if (!it.second) {
-                    return DAWN_VALIDATION_ERROR("Shader has duplicate bindings");
-                }
-
-                EntryPointMetadata::ShaderBindingInfo* info = &it.first->second;
-                info->id = binding.id;
-                info->base_type_id = binding.base_type_id;
-                info->type = ToWGPUBindingType(binding.binding_type);
-
-                switch (info->type) {
-                    case wgpu::BindingType::SampledTexture: {
-                        info->multisampled = binding.multisampled;
-                        info->viewDimension = ToWGPUTextureViewDimension(binding.texture_dimension);
-                        info->textureComponentType =
-                            ToDawnFormatType(binding.texture_component_type);
-                        break;
-                    }
-                    case wgpu::BindingType::StorageTexture:
-                    case wgpu::BindingType::ReadonlyStorageTexture:
-                    case wgpu::BindingType::WriteonlyStorageTexture: {
-                        wgpu::TextureFormat storageTextureFormat =
-                            ToWGPUTextureFormat(binding.storage_texture_format);
-                        if (storageTextureFormat == wgpu::TextureFormat::Undefined) {
-                            return DAWN_VALIDATION_ERROR(
-                                "Invalid image format declaration on storage image");
-                        }
-                        const Format& format = device->GetValidInternalFormat(storageTextureFormat);
-                        if (!format.supportsStorageUsage) {
-                            return DAWN_VALIDATION_ERROR(
-                                "The storage texture format is not supported");
-                        }
-                        info->multisampled = binding.multisampled;
-                        info->storageTextureFormat = storageTextureFormat;
-                        info->viewDimension = ToWGPUTextureViewDimension(binding.texture_dimension);
-                        break;
-                    }
-                    case wgpu::BindingType::UniformBuffer:
-                    case wgpu::BindingType::StorageBuffer:
-                    case wgpu::BindingType::ReadonlyStorageBuffer:
-                        info->minBufferBindingSize = binding.minimum_buffer_size;
-                        break;
-                    default:
-                        break;
-                }
-            }
-            return {};
-        };
-
-        std::vector<shaderc_spvc_binding_info> resource_bindings;
-        DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetBindingInfo(
-                                      shaderc_spvc_shader_resource_uniform_buffers,
-                                      shaderc_spvc_binding_type_uniform_buffer, &resource_bindings),
-                                  "Unable to get binding info for uniform buffers from shader"));
-        DAWN_TRY(ExtractResourcesBinding(device, resource_bindings, &metadata->bindings));
-
-        DAWN_TRY(CheckSpvcSuccess(
-            mSpvcContext.GetBindingInfo(shaderc_spvc_shader_resource_separate_images,
-                                        shaderc_spvc_binding_type_sampled_texture,
-                                        &resource_bindings),
-            "Unable to get binding info for sampled textures from shader"));
-        DAWN_TRY(ExtractResourcesBinding(device, resource_bindings, &metadata->bindings));
-
-        DAWN_TRY(CheckSpvcSuccess(
-            mSpvcContext.GetBindingInfo(shaderc_spvc_shader_resource_separate_samplers,
-                                        shaderc_spvc_binding_type_sampler, &resource_bindings),
-            "Unable to get binding info for samples from shader"));
-        DAWN_TRY(ExtractResourcesBinding(device, resource_bindings, &metadata->bindings));
-
-        DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetBindingInfo(
-                                      shaderc_spvc_shader_resource_storage_buffers,
-                                      shaderc_spvc_binding_type_storage_buffer, &resource_bindings),
-                                  "Unable to get binding info for storage buffers from shader"));
-        DAWN_TRY(ExtractResourcesBinding(device, resource_bindings, &metadata->bindings));
-
-        DAWN_TRY(CheckSpvcSuccess(
-            mSpvcContext.GetBindingInfo(shaderc_spvc_shader_resource_storage_images,
-                                        shaderc_spvc_binding_type_storage_texture,
-                                        &resource_bindings),
-            "Unable to get binding info for storage textures from shader"));
-        DAWN_TRY(ExtractResourcesBinding(device, resource_bindings, &metadata->bindings));
-
-        std::vector<shaderc_spvc_resource_location_info> input_stage_locations;
-        DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetInputStageLocationInfo(&input_stage_locations),
-                                  "Unable to get input stage location information from shader"));
-
-        for (const auto& input : input_stage_locations) {
-            if (metadata->stage == SingleShaderStage::Vertex) {
-                if (input.location >= kMaxVertexAttributes) {
-                    return DAWN_VALIDATION_ERROR("Attribute location over limits in the SPIRV");
-                }
-                metadata->usedVertexAttributes.set(input.location);
-            } else if (metadata->stage == SingleShaderStage::Fragment) {
-                // Without a location qualifier on vertex inputs, spirv_cross::CompilerMSL gives
-                // them all the location 0, causing a compile error.
-                if (!input.has_location) {
-                    return DAWN_VALIDATION_ERROR("Need location qualifier on fragment input");
-                }
-            }
-        }
-
-        std::vector<shaderc_spvc_resource_location_info> output_stage_locations;
-        DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetOutputStageLocationInfo(&output_stage_locations),
-                                  "Unable to get output stage location information from shader"));
-
-        for (const auto& output : output_stage_locations) {
-            if (metadata->stage == SingleShaderStage::Vertex) {
-                // Without a location qualifier on vertex outputs, spirv_cross::CompilerMSL
-                // gives them all the location 0, causing a compile error.
-                if (!output.has_location) {
-                    return DAWN_VALIDATION_ERROR("Need location qualifier on vertex output");
-                }
-            } else if (metadata->stage == SingleShaderStage::Fragment) {
-                if (output.location >= kMaxColorAttachments) {
-                    return DAWN_VALIDATION_ERROR(
-                        "Fragment output location over limits in the SPIRV");
-                }
-            }
-        }
-
-        if (metadata->stage == SingleShaderStage::Fragment) {
-            std::vector<shaderc_spvc_resource_type_info> output_types;
-            DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetOutputStageTypeInfo(&output_types),
-                                      "Unable to get output stage type information from shader"));
-
-            for (const auto& output : output_types) {
-                if (output.type == shaderc_spvc_texture_format_type_other) {
-                    return DAWN_VALIDATION_ERROR("Unexpected Fragment output type");
-                }
-                metadata->fragmentOutputFormatBaseTypes[output.location] =
-                    ToDawnFormatType(output.type);
-            }
-        }
-
-        return {std::move(metadata)};
-    }
-
-    ResultOrError<std::unique_ptr<EntryPointMetadata>>
-    ShaderModuleBase::ExtractSpirvInfoWithSpirvCross(const spirv_cross::Compiler& compiler) {
+    ResultOrError<std::unique_ptr<EntryPointMetadata>> ShaderModuleBase::ExtractSpirvInfoImpl(
+        const spirv_cross::Compiler& compiler) {
         DeviceBase* device = GetDevice();
         std::unique_ptr<EntryPointMetadata> metadata = std::make_unique<EntryPointMetadata>();
 
@@ -1230,18 +908,6 @@
         return a->mSpirv == b->mSpirv;
     }
 
-    MaybeError ShaderModuleBase::CheckSpvcSuccess(shaderc_spvc_status status,
-                                                  const char* error_msg) {
-        if (status != shaderc_spvc_status_success) {
-            return DAWN_VALIDATION_ERROR(error_msg);
-        }
-        return {};
-    }
-
-    shaderc_spvc::Context* ShaderModuleBase::GetContext() {
-        return &mSpvcContext;
-    }
-
     const std::vector<uint32_t>& ShaderModuleBase::GetSpirv() const {
         return mSpirv;
     }
@@ -1256,15 +922,6 @@
     }
 #endif
 
-    shaderc_spvc::CompileOptions ShaderModuleBase::GetCompileOptions() const {
-        shaderc_spvc::CompileOptions options;
-        options.SetValidate(GetDevice()->IsValidationEnabled());
-        options.SetRobustBufferAccessPass(GetDevice()->IsRobustnessEnabled());
-        options.SetSourceEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1);
-        options.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1);
-        return options;
-    }
-
     MaybeError ShaderModuleBase::InitializeBase() {
         if (mType == Type::Wgsl) {
 #ifdef DAWN_ENABLE_WGSL
diff --git a/src/dawn_native/ShaderModule.h b/src/dawn_native/ShaderModule.h
index 15d31ae..edce8f7 100644
--- a/src/dawn_native/ShaderModule.h
+++ b/src/dawn_native/ShaderModule.h
@@ -26,8 +26,6 @@
 
 #include "dawn_native/dawn_platform.h"
 
-#include "spvc/spvc.hpp"
-
 #include <bitset>
 #include <map>
 #include <vector>
@@ -113,7 +111,6 @@
             bool operator()(const ShaderModuleBase* a, const ShaderModuleBase* b) const;
         };
 
-        shaderc_spvc::Context* GetContext();
         const std::vector<uint32_t>& GetSpirv() const;
 
 #ifdef DAWN_ENABLE_WGSL
@@ -124,12 +121,8 @@
 #endif
 
       protected:
-        static MaybeError CheckSpvcSuccess(shaderc_spvc_status status, const char* error_msg);
-        shaderc_spvc::CompileOptions GetCompileOptions() const;
         MaybeError InitializeBase();
 
-        shaderc_spvc::Context mSpvcContext;
-
         // Allows backends to get the stage for the "main" entrypoint while they are transitioned to
         // support multiple entrypoints.
         // TODO(dawn:216): Remove this once the transition is complete.
@@ -138,10 +131,7 @@
       private:
         ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag);
 
-        // Different implementations reflection into the shader depending on
-        // whether using spvc, or directly accessing spirv-cross.
-        ResultOrError<std::unique_ptr<EntryPointMetadata>> ExtractSpirvInfoWithSpvc();
-        ResultOrError<std::unique_ptr<EntryPointMetadata>> ExtractSpirvInfoWithSpirvCross(
+        ResultOrError<std::unique_ptr<EntryPointMetadata>> ExtractSpirvInfoImpl(
             const spirv_cross::Compiler& compiler);
 
         enum class Type { Undefined, Spirv, Wgsl };
diff --git a/src/dawn_native/d3d12/ShaderModuleD3D12.cpp b/src/dawn_native/d3d12/ShaderModuleD3D12.cpp
index 3b16696..ac93525 100644
--- a/src/dawn_native/d3d12/ShaderModuleD3D12.cpp
+++ b/src/dawn_native/d3d12/ShaderModuleD3D12.cpp
@@ -100,37 +100,9 @@
         DAWN_TRY(InitializeBase());
         const std::vector<uint32_t>& spirv = GetSpirv();
 
-        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-            shaderc_spvc::CompileOptions options = GetCompileOptions();
+        spirv_cross::CompilerHLSL compiler(spirv);
+        DAWN_TRY(ExtractSpirvInfo(compiler));
 
-            options.SetForceZeroInitializedVariables(true);
-            if (GetDevice()->IsExtensionEnabled(Extension::ShaderFloat16)) {
-                options.SetHLSLShaderModel(ToBackend(GetDevice())->GetDeviceInfo().shaderModel);
-                options.SetHLSLEnable16BitTypes(true);
-            } else {
-                options.SetHLSLShaderModel(51);
-            }
-            // PointCoord and PointSize are not supported in HLSL
-            // TODO (hao.x.li@intel.com): The point_coord_compat and point_size_compat are
-            // required temporarily for https://bugs.chromium.org/p/dawn/issues/detail?id=146,
-            // but should be removed once WebGPU requires there is no gl_PointSize builtin.
-            // See https://github.com/gpuweb/gpuweb/issues/332
-            options.SetHLSLPointCoordCompat(true);
-            options.SetHLSLPointSizeCompat(true);
-            options.SetHLSLNonWritableUAVTextureAsSRV(true);
-
-            DAWN_TRY(CheckSpvcSuccess(
-                mSpvcContext.InitializeForHlsl(spirv.data(), spirv.size(), options),
-                "Unable to initialize instance of spvc"));
-
-            spirv_cross::Compiler* compiler;
-            DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetCompiler(reinterpret_cast<void**>(&compiler)),
-                                      "Unable to get cross compiler"));
-            DAWN_TRY(ExtractSpirvInfo(*compiler));
-        } else {
-            spirv_cross::CompilerHLSL compiler(spirv);
-            DAWN_TRY(ExtractSpirvInfo(compiler));
-        }
         return {};
     }
 
@@ -138,37 +110,32 @@
         ASSERT(!IsError());
         const std::vector<uint32_t>& spirv = GetSpirv();
 
-        std::unique_ptr<spirv_cross::CompilerHLSL> compilerImpl;
-        spirv_cross::CompilerHLSL* compiler = nullptr;
-        if (!GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-            // If these options are changed, the values in DawnSPIRVCrossHLSLFastFuzzer.cpp need to
-            // be updated.
-            spirv_cross::CompilerGLSL::Options options_glsl;
-            // Force all uninitialized variables to be 0, otherwise they will fail to compile
-            // by FXC.
-            options_glsl.force_zero_initialized_variables = true;
+        // If these options are changed, the values in DawnSPIRVCrossHLSLFastFuzzer.cpp need to
+        // be updated.
+        spirv_cross::CompilerGLSL::Options options_glsl;
+        // Force all uninitialized variables to be 0, otherwise they will fail to compile
+        // by FXC.
+        options_glsl.force_zero_initialized_variables = true;
 
-            spirv_cross::CompilerHLSL::Options options_hlsl;
-            if (GetDevice()->IsExtensionEnabled(Extension::ShaderFloat16)) {
-                options_hlsl.shader_model = ToBackend(GetDevice())->GetDeviceInfo().shaderModel;
-                options_hlsl.enable_16bit_types = true;
-            } else {
-                options_hlsl.shader_model = 51;
-            }
-            // PointCoord and PointSize are not supported in HLSL
-            // TODO (hao.x.li@intel.com): The point_coord_compat and point_size_compat are
-            // required temporarily for https://bugs.chromium.org/p/dawn/issues/detail?id=146,
-            // but should be removed once WebGPU requires there is no gl_PointSize builtin.
-            // See https://github.com/gpuweb/gpuweb/issues/332
-            options_hlsl.point_coord_compat = true;
-            options_hlsl.point_size_compat = true;
-            options_hlsl.nonwritable_uav_texture_as_srv = true;
-
-            compilerImpl = std::make_unique<spirv_cross::CompilerHLSL>(spirv);
-            compiler = compilerImpl.get();
-            compiler->set_common_options(options_glsl);
-            compiler->set_hlsl_options(options_hlsl);
+        spirv_cross::CompilerHLSL::Options options_hlsl;
+        if (GetDevice()->IsExtensionEnabled(Extension::ShaderFloat16)) {
+            options_hlsl.shader_model = ToBackend(GetDevice())->GetDeviceInfo().shaderModel;
+            options_hlsl.enable_16bit_types = true;
+        } else {
+            options_hlsl.shader_model = 51;
         }
+        // PointCoord and PointSize are not supported in HLSL
+        // TODO (hao.x.li@intel.com): The point_coord_compat and point_size_compat are
+        // required temporarily for https://bugs.chromium.org/p/dawn/issues/detail?id=146,
+        // but should be removed once WebGPU requires there is no gl_PointSize builtin.
+        // See https://github.com/gpuweb/gpuweb/issues/332
+        options_hlsl.point_coord_compat = true;
+        options_hlsl.point_size_compat = true;
+        options_hlsl.nonwritable_uav_texture_as_srv = true;
+
+        spirv_cross::CompilerHLSL compiler(spirv);
+        compiler.set_common_options(options_glsl);
+        compiler.set_hlsl_options(options_hlsl);
 
         const EntryPointMetadata::BindingInfo& moduleBindingInfo =
             GetEntryPoint("main", GetMainEntryPointStageForTransition()).bindings;
@@ -190,38 +157,14 @@
                      bgl->GetBindingInfo(bindingIndex).type == wgpu::BindingType::StorageBuffer);
 
                 uint32_t bindingOffset = bindingOffsets[bindingIndex];
-                if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-                    DAWN_TRY(CheckSpvcSuccess(
-                        mSpvcContext.SetDecoration(bindingInfo.id, SHADERC_SPVC_DECORATION_BINDING,
-                                                   bindingOffset),
-                        "Unable to set decorating binding before generating HLSL shader w/ "
-                        "spvc"));
-                    if (forceStorageBufferAsUAV) {
-                        DAWN_TRY(CheckSpvcSuccess(
-                            mSpvcContext.SetHLSLForceStorageBufferAsUAV(
-                                static_cast<uint32_t>(group), static_cast<uint32_t>(bindingNumber)),
-                            "Unable to force read-only storage buffer as UAV w/ spvc"));
-                    }
-                } else {
-                    compiler->set_decoration(bindingInfo.id, spv::DecorationBinding, bindingOffset);
-                    if (forceStorageBufferAsUAV) {
-                        compiler->set_hlsl_force_storage_buffer_as_uav(
-                            static_cast<uint32_t>(group), static_cast<uint32_t>(bindingNumber));
-                    }
+                compiler.set_decoration(bindingInfo.id, spv::DecorationBinding, bindingOffset);
+                if (forceStorageBufferAsUAV) {
+                    compiler.set_hlsl_force_storage_buffer_as_uav(
+                        static_cast<uint32_t>(group), static_cast<uint32_t>(bindingNumber));
                 }
             }
         }
-        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-            shaderc_spvc::CompilationResult result;
-            DAWN_TRY(CheckSpvcSuccess(mSpvcContext.CompileShader(&result),
-                                      "Unable to generate HLSL shader w/ spvc"));
-            std::string result_string;
-            DAWN_TRY(CheckSpvcSuccess(result.GetStringOutput(&result_string),
-                                      "Unable to get HLSL shader text"));
-            return std::move(result_string);
-        } else {
-            return compiler->compile();
-        }
+        return compiler.compile();
     }
 
     ResultOrError<ComPtr<IDxcBlob>> ShaderModule::CompileShaderDXC(SingleShaderStage stage,
diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm
index ca307ed..e6b072d 100644
--- a/src/dawn_native/metal/DeviceMTL.mm
+++ b/src/dawn_native/metal/DeviceMTL.mm
@@ -63,7 +63,7 @@
     MaybeError Device::Initialize() {
         InitTogglesFromDriver();
 
-        if (!IsRobustnessEnabled() || !IsToggleEnabled(Toggle::UseSpvc)) {
+        if (!IsRobustnessEnabled()) {
             ForceSetToggle(Toggle::MetalEnableVertexPulling, false);
         }
 
diff --git a/src/dawn_native/metal/ShaderModuleMTL.h b/src/dawn_native/metal/ShaderModuleMTL.h
index 9193b25..3a211e6 100644
--- a/src/dawn_native/metal/ShaderModuleMTL.h
+++ b/src/dawn_native/metal/ShaderModuleMTL.h
@@ -55,8 +55,6 @@
         ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor);
         ~ShaderModule() override = default;
         MaybeError Initialize();
-
-        shaderc_spvc::CompileOptions GetMSLCompileOptions(uint32_t sampleMask = 0xFFFFFFFF);
     };
 
 }}  // namespace dawn_native::metal
diff --git a/src/dawn_native/metal/ShaderModuleMTL.mm b/src/dawn_native/metal/ShaderModuleMTL.mm
index 1e227ac..030929a 100644
--- a/src/dawn_native/metal/ShaderModuleMTL.mm
+++ b/src/dawn_native/metal/ShaderModuleMTL.mm
@@ -39,20 +39,6 @@
                     UNREACHABLE();
             }
         }
-
-        shaderc_spvc_execution_model ToSpvcExecutionModel(SingleShaderStage stage) {
-            switch (stage) {
-                case SingleShaderStage::Vertex:
-                    return shaderc_spvc_execution_model_vertex;
-                case SingleShaderStage::Fragment:
-                    return shaderc_spvc_execution_model_fragment;
-                case SingleShaderStage::Compute:
-                    return shaderc_spvc_execution_model_glcompute;
-                default:
-                    UNREACHABLE();
-                    return shaderc_spvc_execution_model_invalid;
-            }
-        }
     }  // namespace
 
     // static
@@ -71,21 +57,9 @@
         DAWN_TRY(InitializeBase());
         const std::vector<uint32_t>& spirv = GetSpirv();
 
-        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-            shaderc_spvc::CompileOptions options = GetMSLCompileOptions();
+        spirv_cross::CompilerMSL compiler(spirv);
+        DAWN_TRY(ExtractSpirvInfo(compiler));
 
-            DAWN_TRY(
-                CheckSpvcSuccess(mSpvcContext.InitializeForMsl(spirv.data(), spirv.size(), options),
-                                 "Unable to initialize instance of spvc"));
-
-            spirv_cross::CompilerMSL* compiler;
-            DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetCompiler(reinterpret_cast<void**>(&compiler)),
-                                      "Unable to get cross compiler"));
-            DAWN_TRY(ExtractSpirvInfo(*compiler));
-        } else {
-            spirv_cross::CompilerMSL compiler(spirv);
-            DAWN_TRY(ExtractSpirvInfo(compiler));
-        }
         return {};
     }
 
@@ -112,39 +86,25 @@
         }
 #endif
 
-        std::unique_ptr<spirv_cross::CompilerMSL> compilerImpl;
-        spirv_cross::CompilerMSL* compiler;
-        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-            // Initializing the compiler is needed every call, because this method uses reflection
-            // to mutate the compiler's IR.
-            DAWN_TRY(
-                CheckSpvcSuccess(mSpvcContext.InitializeForMsl(spirv->data(), spirv->size(),
-                                                               GetMSLCompileOptions(sampleMask)),
-                                 "Unable to initialize instance of spvc"));
-            DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetCompiler(reinterpret_cast<void**>(&compiler)),
-                                      "Unable to get cross compiler"));
-        } else {
-            // If these options are changed, the values in DawnSPIRVCrossMSLFastFuzzer.cpp need to
-            // be updated.
-            spirv_cross::CompilerMSL::Options options_msl;
+        // If these options are changed, the values in DawnSPIRVCrossMSLFastFuzzer.cpp need to
+        // be updated.
+        spirv_cross::CompilerMSL::Options options_msl;
 
-            // Disable PointSize builtin for https://bugs.chromium.org/p/dawn/issues/detail?id=146
-            // Because Metal will reject PointSize builtin if the shader is compiled into a render
-            // pipeline that uses a non-point topology.
-            // TODO (hao.x.li@intel.com): Remove this once WebGPU requires there is no
-            // gl_PointSize builtin (https://github.com/gpuweb/gpuweb/issues/332).
-            options_msl.enable_point_size_builtin = false;
+        // Disable PointSize builtin for https://bugs.chromium.org/p/dawn/issues/detail?id=146
+        // Because Metal will reject PointSize builtin if the shader is compiled into a render
+        // pipeline that uses a non-point topology.
+        // TODO (hao.x.li@intel.com): Remove this once WebGPU requires there is no
+        // gl_PointSize builtin (https://github.com/gpuweb/gpuweb/issues/332).
+        options_msl.enable_point_size_builtin = false;
 
-            // Always use vertex buffer 30 (the last one in the vertex buffer table) to contain
-            // the shader storage buffer lengths.
-            options_msl.buffer_size_buffer_index = kBufferLengthBufferSlot;
+        // Always use vertex buffer 30 (the last one in the vertex buffer table) to contain
+        // the shader storage buffer lengths.
+        options_msl.buffer_size_buffer_index = kBufferLengthBufferSlot;
 
-            options_msl.additional_fixed_sample_mask = sampleMask;
+        options_msl.additional_fixed_sample_mask = sampleMask;
 
-            compilerImpl = std::make_unique<spirv_cross::CompilerMSL>(*spirv);
-            compiler = compilerImpl.get();
-            compiler->set_msl_options(options_msl);
-        }
+        spirv_cross::CompilerMSL compiler(*spirv);
+        compiler.set_msl_options(options_msl);
 
         // By default SPIRV-Cross will give MSL resources indices in increasing order.
         // To make the MSL indices match the indices chosen in the PipelineLayout, we build
@@ -164,25 +124,14 @@
 
                 for (auto stage : IterateStages(bindingInfo.visibility)) {
                     uint32_t shaderIndex = layout->GetBindingIndexInfo(stage)[group][bindingIndex];
-                    if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-                        shaderc_spvc_msl_resource_binding mslBinding;
-                        mslBinding.stage = ToSpvcExecutionModel(stage);
-                        mslBinding.desc_set = static_cast<uint32_t>(group);
-                        mslBinding.binding = static_cast<uint32_t>(bindingNumber);
-                        mslBinding.msl_buffer = mslBinding.msl_texture = mslBinding.msl_sampler =
-                            shaderIndex;
-                        DAWN_TRY(CheckSpvcSuccess(mSpvcContext.AddMSLResourceBinding(mslBinding),
-                                                  "Unable to add MSL Resource Binding"));
-                    } else {
-                        spirv_cross::MSLResourceBinding mslBinding;
-                        mslBinding.stage = SpirvExecutionModelForStage(stage);
-                        mslBinding.desc_set = static_cast<uint32_t>(group);
-                        mslBinding.binding = static_cast<uint32_t>(bindingNumber);
-                        mslBinding.msl_buffer = mslBinding.msl_texture = mslBinding.msl_sampler =
-                            shaderIndex;
+                    spirv_cross::MSLResourceBinding mslBinding;
+                    mslBinding.stage = SpirvExecutionModelForStage(stage);
+                    mslBinding.desc_set = static_cast<uint32_t>(group);
+                    mslBinding.binding = static_cast<uint32_t>(bindingNumber);
+                    mslBinding.msl_buffer = mslBinding.msl_texture = mslBinding.msl_sampler =
+                        shaderIndex;
 
-                        compiler->add_msl_resource_binding(mslBinding);
-                    }
+                    compiler.add_msl_resource_binding(mslBinding);
                 }
             }
         }
@@ -193,45 +142,27 @@
             for (uint32_t dawnIndex : IterateBitSet(renderPipeline->GetVertexBufferSlotsUsed())) {
                 uint32_t metalIndex = renderPipeline->GetMtlVertexBufferIndex(dawnIndex);
 
-                shaderc_spvc_msl_resource_binding mslBinding;
-                mslBinding.stage = ToSpvcExecutionModel(SingleShaderStage::Vertex);
+                spirv_cross::MSLResourceBinding mslBinding;
+
+                mslBinding.stage = SpirvExecutionModelForStage(SingleShaderStage::Vertex);
                 mslBinding.desc_set = kPullingBufferBindingSet;
                 mslBinding.binding = dawnIndex;
                 mslBinding.msl_buffer = metalIndex;
-                DAWN_TRY(CheckSpvcSuccess(mSpvcContext.AddMSLResourceBinding(mslBinding),
-                                          "Unable to add MSL Resource Binding"));
+                compiler.add_msl_resource_binding(mslBinding);
             }
         }
 
         {
-            if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-                shaderc_spvc_execution_model executionModel = ToSpvcExecutionModel(functionStage);
-                shaderc_spvc_workgroup_size size;
-                DAWN_TRY(CheckSpvcSuccess(
-                    mSpvcContext.GetWorkgroupSize(functionName, executionModel, &size),
-                    "Unable to get workgroup size for shader"));
-                out->localWorkgroupSize = MTLSizeMake(size.x, size.y, size.z);
-            } else {
-                spv::ExecutionModel executionModel = SpirvExecutionModelForStage(functionStage);
-                auto size = compiler->get_entry_point(functionName, executionModel).workgroup_size;
-                out->localWorkgroupSize = MTLSizeMake(size.x, size.y, size.z);
-            }
+            spv::ExecutionModel executionModel = SpirvExecutionModelForStage(functionStage);
+            auto size = compiler.get_entry_point(functionName, executionModel).workgroup_size;
+            out->localWorkgroupSize = MTLSizeMake(size.x, size.y, size.z);
         }
 
         {
             // SPIRV-Cross also supports re-ordering attributes but it seems to do the correct thing
             // by default.
             NSString* mslSource;
-            std::string msl;
-            if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-                shaderc_spvc::CompilationResult result;
-                DAWN_TRY(CheckSpvcSuccess(mSpvcContext.CompileShader(&result),
-                                          "Unable to compile MSL shader"));
-                DAWN_TRY(CheckSpvcSuccess(result.GetStringOutput(&msl),
-                                          "Unable to get MSL shader text"));
-            } else {
-                msl = compiler->compile();
-            }
+            std::string msl = compiler.compile();
             // Metal uses Clang to compile the shader as C++14. Disable everything in the -Wall
             // category. -Wunused-variable in particular comes up a lot in generated code, and some
             // (old?) Metal drivers accidentally treat it as a MTLLibraryErrorCompileError instead
@@ -272,13 +203,7 @@
             [library release];
         }
 
-        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-            DAWN_TRY(
-                CheckSpvcSuccess(mSpvcContext.NeedsBufferSizeBuffer(&out->needsStorageBufferLength),
-                                 "Unable to determine if shader needs buffer size buffer"));
-        } else {
-            out->needsStorageBufferLength = compiler->needs_buffer_size_buffer();
-        }
+        out->needsStorageBufferLength = compiler.needs_buffer_size_buffer();
 
         if (GetDevice()->IsToggleEnabled(Toggle::MetalEnableVertexPulling) &&
             GetEntryPoint(functionName, functionStage).usedVertexAttributes.any()) {
@@ -287,26 +212,4 @@
 
         return {};
     }
-
-    shaderc_spvc::CompileOptions ShaderModule::GetMSLCompileOptions(uint32_t sampleMask) {
-        // If these options are changed, the values in DawnSPIRVCrossGLSLFastFuzzer.cpp need to
-        // be updated.
-        shaderc_spvc::CompileOptions options = GetCompileOptions();
-
-        // Disable PointSize builtin for https://bugs.chromium.org/p/dawn/issues/detail?id=146
-        // Because Metal will reject PointSize builtin if the shader is compiled into a render
-        // pipeline that uses a non-point topology.
-        // TODO (hao.x.li@intel.com): Remove this once WebGPU requires there is no
-        // gl_PointSize builtin (https://github.com/gpuweb/gpuweb/issues/332).
-        options.SetMSLEnablePointSizeBuiltIn(false);
-
-        // Always use vertex buffer 30 (the last one in the vertex buffer table) to contain
-        // the shader storage buffer lengths.
-        options.SetMSLBufferSizeBufferIndex(kBufferLengthBufferSlot);
-
-        options.SetMSLAdditionalFixedSampleMask(sampleMask);
-
-        return options;
-    }
-
 }}  // namespace dawn_native::metal
diff --git a/src/dawn_native/null/DeviceNull.cpp b/src/dawn_native/null/DeviceNull.cpp
index 7b86964a..520af6e 100644
--- a/src/dawn_native/null/DeviceNull.cpp
+++ b/src/dawn_native/null/DeviceNull.cpp
@@ -129,27 +129,8 @@
     ResultOrError<ShaderModuleBase*> Device::CreateShaderModuleImpl(
         const ShaderModuleDescriptor* descriptor) {
         Ref<ShaderModule> module = AcquireRef(new ShaderModule(this, descriptor));
-
-        if (IsToggleEnabled(Toggle::UseSpvc)) {
-            shaderc_spvc::CompileOptions options;
-            options.SetValidate(IsValidationEnabled());
-            shaderc_spvc::Context* context = module->GetContext();
-            shaderc_spvc_status status = context->InitializeForGlsl(
-                module->GetSpirv().data(), module->GetSpirv().size(), options);
-            if (status != shaderc_spvc_status_success) {
-                return DAWN_VALIDATION_ERROR("Unable to initialize instance of spvc");
-            }
-
-            spirv_cross::Compiler* compiler;
-            status = context->GetCompiler(reinterpret_cast<void**>(&compiler));
-            if (status != shaderc_spvc_status_success) {
-                return DAWN_VALIDATION_ERROR("Unable to get cross compiler");
-            }
-            DAWN_TRY(module->ExtractSpirvInfo(*compiler));
-        } else {
-            spirv_cross::Compiler compiler(module->GetSpirv());
-            DAWN_TRY(module->ExtractSpirvInfo(compiler));
-        }
+        spirv_cross::Compiler compiler(module->GetSpirv());
+        DAWN_TRY(module->ExtractSpirvInfo(compiler));
         return module.Detach();
     }
     ResultOrError<SwapChainBase*> Device::CreateSwapChainImpl(
diff --git a/src/dawn_native/opengl/ShaderModuleGL.cpp b/src/dawn_native/opengl/ShaderModuleGL.cpp
index 0b02d53..65b5401 100644
--- a/src/dawn_native/opengl/ShaderModuleGL.cpp
+++ b/src/dawn_native/opengl/ShaderModuleGL.cpp
@@ -74,110 +74,47 @@
         DAWN_TRY(InitializeBase());
         const std::vector<uint32_t>& spirv = GetSpirv();
 
-        std::unique_ptr<spirv_cross::CompilerGLSL> compilerImpl;
-        spirv_cross::CompilerGLSL* compiler;
-        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-            // If these options are changed, the values in DawnSPIRVCrossGLSLFastFuzzer.cpp need to
-            // be updated.
-            shaderc_spvc::CompileOptions options = GetCompileOptions();
+        // If these options are changed, the values in DawnSPIRVCrossGLSLFastFuzzer.cpp need to
+        // be updated.
+        spirv_cross::CompilerGLSL::Options options;
 
-            // The range of Z-coordinate in the clipping volume of OpenGL is [-w, w], while it is
-            // [0, w] in D3D12, Metal and Vulkan, so we should normalize it in shaders in all
-            // backends. See the documentation of
-            // spirv_cross::CompilerGLSL::Options::vertex::fixup_clipspace for more details.
-            options.SetFlipVertY(true);
-            options.SetFixupClipspace(true);
+        // The range of Z-coordinate in the clipping volume of OpenGL is [-w, w], while it is
+        // [0, w] in D3D12, Metal and Vulkan, so we should normalize it in shaders in all
+        // backends. See the documentation of
+        // spirv_cross::CompilerGLSL::Options::vertex::fixup_clipspace for more details.
+        options.vertex.flip_vert_y = true;
+        options.vertex.fixup_clipspace = true;
 
-            // TODO(cwallez@chromium.org): discover the backing context version and use that.
+        // TODO(cwallez@chromium.org): discover the backing context version and use that.
 #if defined(DAWN_PLATFORM_APPLE)
-            options.SetGLSLLanguageVersion(410);
+        options.version = 410;
 #else
-            options.SetGLSLLanguageVersion(440);
-#endif
-            DAWN_TRY(CheckSpvcSuccess(
-                mSpvcContext.InitializeForGlsl(spirv.data(), spirv.size(), options),
-                "Unable to initialize instance of spvc"));
-            DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetCompiler(reinterpret_cast<void**>(&compiler)),
-                                      "Unable to get cross compiler"));
-        } else {
-            // If these options are changed, the values in DawnSPIRVCrossGLSLFastFuzzer.cpp need to
-            // be updated.
-            spirv_cross::CompilerGLSL::Options options;
-
-            // The range of Z-coordinate in the clipping volume of OpenGL is [-w, w], while it is
-            // [0, w] in D3D12, Metal and Vulkan, so we should normalize it in shaders in all
-            // backends. See the documentation of
-            // spirv_cross::CompilerGLSL::Options::vertex::fixup_clipspace for more details.
-            options.vertex.flip_vert_y = true;
-            options.vertex.fixup_clipspace = true;
-
-            // TODO(cwallez@chromium.org): discover the backing context version and use that.
-#if defined(DAWN_PLATFORM_APPLE)
-            options.version = 410;
-#else
-            options.version = 440;
+        options.version = 440;
 #endif
 
-            compilerImpl = std::make_unique<spirv_cross::CompilerGLSL>(spirv);
-            compiler = compilerImpl.get();
-            compiler->set_common_options(options);
-        }
+        spirv_cross::CompilerGLSL compiler(spirv);
+        compiler.set_common_options(options);
 
-        DAWN_TRY(ExtractSpirvInfo(*compiler));
+        DAWN_TRY(ExtractSpirvInfo(compiler));
 
         // Extract bindings names so that it can be used to get its location in program.
         // Now translate the separate sampler / textures into combined ones and store their info.
         // We need to do this before removing the set and binding decorations.
-        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-            mSpvcContext.BuildCombinedImageSamplers();
-        } else {
-            compiler->build_combined_image_samplers();
-        }
+        compiler.build_combined_image_samplers();
 
-        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-            std::vector<shaderc_spvc_combined_image_sampler> samplers;
-            mSpvcContext.GetCombinedImageSamplers(&samplers);
-            for (auto sampler : samplers) {
-                mCombinedInfo.emplace_back();
-                auto& info = mCombinedInfo.back();
+        for (const auto& combined : compiler.get_combined_image_samplers()) {
+            mCombinedInfo.emplace_back();
 
-                uint32_t samplerGroup;
-                mSpvcContext.GetDecoration(sampler.sampler_id,
-                                           shaderc_spvc_decoration_descriptorset, &samplerGroup);
-                info.samplerLocation.group = BindGroupIndex(samplerGroup);
-
-                uint32_t samplerBinding;
-                mSpvcContext.GetDecoration(sampler.sampler_id, shaderc_spvc_decoration_binding,
-                                           &samplerBinding);
-                info.samplerLocation.binding = BindingNumber(samplerBinding);
-
-                uint32_t textureGroup;
-                mSpvcContext.GetDecoration(sampler.image_id, shaderc_spvc_decoration_descriptorset,
-                                           &textureGroup);
-                info.textureLocation.group = BindGroupIndex(textureGroup);
-
-                uint32_t textureBinding;
-                mSpvcContext.GetDecoration(sampler.image_id, shaderc_spvc_decoration_binding,
-                                           &textureBinding);
-                info.textureLocation.binding = BindingNumber(textureBinding);
-
-                mSpvcContext.SetName(sampler.combined_id, info.GetName());
-            }
-        } else {
-            for (const auto& combined : compiler->get_combined_image_samplers()) {
-                mCombinedInfo.emplace_back();
-
-                auto& info = mCombinedInfo.back();
-                info.samplerLocation.group = BindGroupIndex(
-                    compiler->get_decoration(combined.sampler_id, spv::DecorationDescriptorSet));
-                info.samplerLocation.binding = BindingNumber(
-                    compiler->get_decoration(combined.sampler_id, spv::DecorationBinding));
-                info.textureLocation.group = BindGroupIndex(
-                    compiler->get_decoration(combined.image_id, spv::DecorationDescriptorSet));
-                info.textureLocation.binding = BindingNumber(
-                    compiler->get_decoration(combined.image_id, spv::DecorationBinding));
-                compiler->set_name(combined.combined_id, info.GetName());
-            }
+            auto& info = mCombinedInfo.back();
+            info.samplerLocation.group = BindGroupIndex(
+                compiler.get_decoration(combined.sampler_id, spv::DecorationDescriptorSet));
+            info.samplerLocation.binding =
+                BindingNumber(compiler.get_decoration(combined.sampler_id, spv::DecorationBinding));
+            info.textureLocation.group = BindGroupIndex(
+                compiler.get_decoration(combined.image_id, spv::DecorationDescriptorSet));
+            info.textureLocation.binding =
+                BindingNumber(compiler.get_decoration(combined.image_id, spv::DecorationBinding));
+            compiler.set_name(combined.combined_id, info.GetName());
         }
 
         const EntryPointMetadata::BindingInfo& bindingInfo =
@@ -205,27 +142,14 @@
                         break;
                 }
 
-                if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-                    mSpvcContext.SetName(resourceId, GetBindingName(group, bindingNumber));
-                    mSpvcContext.UnsetDecoration(info.id, shaderc_spvc_decoration_binding);
-                    mSpvcContext.UnsetDecoration(info.id, shaderc_spvc_decoration_descriptorset);
-                } else {
-                    compiler->set_name(resourceId, GetBindingName(group, bindingNumber));
-                    compiler->unset_decoration(info.id, spv::DecorationBinding);
-                    compiler->unset_decoration(info.id, spv::DecorationDescriptorSet);
-                }
+                compiler.set_name(resourceId, GetBindingName(group, bindingNumber));
+                compiler.unset_decoration(info.id, spv::DecorationBinding);
+                compiler.unset_decoration(info.id, spv::DecorationDescriptorSet);
             }
         }
 
-        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-            shaderc_spvc::CompilationResult result;
-            DAWN_TRY(CheckSpvcSuccess(mSpvcContext.CompileShader(&result),
-                                      "Unable to compile GLSL shader using spvc"));
-            DAWN_TRY(CheckSpvcSuccess(result.GetStringOutput(&mGlslSource),
-                                      "Unable to get GLSL shader text"));
-        } else {
-            mGlslSource = compiler->compile();
-        }
+        mGlslSource = compiler.compile();
+
         return {};
     }
 
diff --git a/src/dawn_native/vulkan/ShaderModuleVk.cpp b/src/dawn_native/vulkan/ShaderModuleVk.cpp
index d76e789..358d9ce 100644
--- a/src/dawn_native/vulkan/ShaderModuleVk.cpp
+++ b/src/dawn_native/vulkan/ShaderModuleVk.cpp
@@ -42,39 +42,16 @@
 
         // Use SPIRV-Cross to extract info from the SPIRV even if Vulkan consumes SPIRV. We want to
         // have a translation step eventually anyway.
-        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-            shaderc_spvc::CompileOptions options = GetCompileOptions();
-
-            DAWN_TRY(CheckSpvcSuccess(
-                mSpvcContext.InitializeForVulkan(spirv.data(), spirv.size(), options),
-                "Unable to initialize instance of spvc"));
-
-            spirv_cross::Compiler* compiler;
-            DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetCompiler(reinterpret_cast<void**>(&compiler)),
-                                      "Unable to get cross compiler"));
-            DAWN_TRY(ExtractSpirvInfo(*compiler));
-        } else {
-            spirv_cross::Compiler compiler(spirv);
-            DAWN_TRY(ExtractSpirvInfo(compiler));
-        }
+        spirv_cross::Compiler compiler(spirv);
+        DAWN_TRY(ExtractSpirvInfo(compiler));
 
         VkShaderModuleCreateInfo createInfo;
         createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
         createInfo.pNext = nullptr;
         createInfo.flags = 0;
         std::vector<uint32_t> vulkanSource;
-        if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
-            shaderc_spvc::CompilationResult result;
-            DAWN_TRY(CheckSpvcSuccess(mSpvcContext.CompileShader(&result),
-                                      "Unable to generate Vulkan shader"));
-            DAWN_TRY(CheckSpvcSuccess(result.GetBinaryOutput(&vulkanSource),
-                                      "Unable to get binary output of Vulkan shader"));
-            createInfo.codeSize = vulkanSource.size() * sizeof(uint32_t);
-            createInfo.pCode = vulkanSource.data();
-        } else {
-            createInfo.codeSize = spirv.size() * sizeof(uint32_t);
-            createInfo.pCode = spirv.data();
-        }
+        createInfo.codeSize = spirv.size() * sizeof(uint32_t);
+        createInfo.pCode = spirv.data();
 
         Device* device = ToBackend(GetDevice());
         return CheckVkSuccess(
diff --git a/src/fuzzers/BUILD.gn b/src/fuzzers/BUILD.gn
index f6400b4..7c8e3dd 100644
--- a/src/fuzzers/BUILD.gn
+++ b/src/fuzzers/BUILD.gn
@@ -74,7 +74,10 @@
     "DawnSPIRVCrossFuzzer.cpp",
     "DawnSPIRVCrossFuzzer.h",
   ]
-  public_deps = [ "${dawn_shaderc_dir}:libshaderc_spvc" ]
+  public_deps = [
+    "${dawn_root}/third_party/gn/spirv_cross:spirv_cross",
+    "${dawn_spirv_tools_dir}:spvtools_val",
+  ]
 }
 
 static_library("dawn_wire_server_fuzzer_common") {
@@ -119,21 +122,6 @@
   asan_options = [ "allow_user_segv_handler=1" ]
 }
 
-dawn_fuzzer_test("dawn_spvc_glsl_fast_fuzzer") {
-  sources = [ "DawnSPVCglslFastFuzzer.cpp" ]
-  deps = [ "${dawn_shaderc_dir}:libshaderc_spvc" ]
-}
-
-dawn_fuzzer_test("dawn_spvc_hlsl_fast_fuzzer") {
-  sources = [ "DawnSPVChlslFastFuzzer.cpp" ]
-  deps = [ "${dawn_shaderc_dir}:libshaderc_spvc" ]
-}
-
-dawn_fuzzer_test("dawn_spvc_msl_fast_fuzzer") {
-  sources = [ "DawnSPVCmslFastFuzzer.cpp" ]
-  deps = [ "${dawn_shaderc_dir}:libshaderc_spvc" ]
-}
-
 dawn_fuzzer_test("dawn_wire_server_and_frontend_fuzzer") {
   sources = [ "DawnWireServerAndFrontendFuzzer.cpp" ]
 
@@ -167,9 +155,6 @@
     ":dawn_spirv_cross_glsl_fast_fuzzer",
     ":dawn_spirv_cross_hlsl_fast_fuzzer",
     ":dawn_spirv_cross_msl_fast_fuzzer",
-    ":dawn_spvc_glsl_fast_fuzzer",
-    ":dawn_spvc_hlsl_fast_fuzzer",
-    ":dawn_spvc_msl_fast_fuzzer",
     ":dawn_wire_server_and_frontend_fuzzer",
     ":dawn_wire_server_and_vulkan_backend_fuzzer",
   ]
diff --git a/src/fuzzers/DawnSPIRVCrossFuzzer.cpp b/src/fuzzers/DawnSPIRVCrossFuzzer.cpp
index 6dbaf06..8ad5711 100644
--- a/src/fuzzers/DawnSPIRVCrossFuzzer.cpp
+++ b/src/fuzzers/DawnSPIRVCrossFuzzer.cpp
@@ -15,9 +15,12 @@
 #include <csetjmp>
 #include <csignal>
 #include <cstdint>
+#include <sstream>
 #include <string>
 #include <vector>
 
+#include <spirv-tools/libspirv.hpp>
+
 #include "DawnSPIRVCrossFuzzer.h"
 
 namespace {
@@ -26,12 +29,8 @@
     void (*old_signal_handler)(int);
 
     // Handler to trap signals, so that it doesn't crash the fuzzer when running
-    // the code under test. Currently the
-    // code being fuzzed uses abort() to report errors like bad input instead of
-    // returning an error code. This will be changing in the future.
-    //
-    // TODO(rharrison): Remove all of this signal trapping once SPIRV-Cross has
-    // been changed to not use abort() for reporting errors.
+    // the code under test. The code being fuzzed uses abort() to report errors
+    // like bad input instead of returning an error code.
     [[noreturn]] static void sigabrt_trap(int sig) {
         std::longjmp(jump_buffer, 1);
     }
@@ -69,6 +68,16 @@
         const uint32_t* u32Data = reinterpret_cast<const uint32_t*>(data);
         std::vector<uint32_t> input(u32Data, u32Data + sizeInU32);
 
+        spvtools::SpirvTools spirvTools(SPV_ENV_VULKAN_1_1);
+        spirvTools.SetMessageConsumer(
+            [](spv_message_level_t, const char*, const spv_position_t&, const char*) {});
+
+        // Dawn is responsible to validating input before it goes into
+        // SPIRV-Cross.
+        if (!spirvTools.Validate(input.data(), input.size())) {
+            return 0;
+        }
+
         if (input.size() != 0) {
             task(input);
         }
diff --git a/src/fuzzers/DawnSPIRVCrossFuzzer.h b/src/fuzzers/DawnSPIRVCrossFuzzer.h
index 49cfc97..82b1ade 100644
--- a/src/fuzzers/DawnSPIRVCrossFuzzer.h
+++ b/src/fuzzers/DawnSPIRVCrossFuzzer.h
@@ -16,13 +16,9 @@
 #include <functional>
 #include <vector>
 
-#include "spvc/spvc.hpp"
-
 namespace DawnSPIRVCrossFuzzer {
 
     using Task = std::function<int(const std::vector<uint32_t>&)>;
-    using TaskWithOptions =
-        std::function<int(const std::vector<uint32_t>&, shaderc_spvc::CompileOptions)>;
 
     // Used to wrap code that may fire a SIGABRT. Do not allocate anything local within |exec|, as
     // it is not guaranteed to return.
diff --git a/src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp b/src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp
index 7a658e0..077ef78 100644
--- a/src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp
+++ b/src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp
@@ -16,29 +16,25 @@
 #include <string>
 #include <vector>
 
+#include <spirv_glsl.hpp>
+
 #include "DawnSPIRVCrossFuzzer.h"
 
 namespace {
     int GLSLFastFuzzTask(const std::vector<uint32_t>& input) {
-        shaderc_spvc::Context context;
-        if (!context.IsValid()) {
-            return 0;
-        }
+        // Values come from ShaderModuleGL.cpp
+        spirv_cross::CompilerGLSL::Options options;
+        options.vertex.flip_vert_y = true;
+        options.vertex.fixup_clipspace = true;
+#if defined(DAWN_PLATFORM_APPLE)
+        options.version = 410;
+#else
+        options.version = 440;
+#endif
 
-        DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&context, &input]() {
-            shaderc_spvc::CompilationResult result;
-            shaderc_spvc::CompileOptions options;
-            options.SetSourceEnvironment(shaderc_target_env_webgpu, shaderc_env_version_webgpu);
-            options.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1);
-
-            // Using the options that are used by Dawn, they appear in ShaderModuleGL.cpp
-            options.SetGLSLLanguageVersion(440);
-            options.SetFixupClipspace(true);
-            if (context.InitializeForGlsl(input.data(), input.size(), options) ==
-                shaderc_spvc_status_success) {
-                context.CompileShader(&result);
-            }
-        });
+        spirv_cross::CompilerGLSL compiler(input);
+        compiler.set_common_options(options);
+        compiler.compile();
 
         return 0;
     }
diff --git a/src/fuzzers/DawnSPIRVCrossHLSLFastFuzzer.cpp b/src/fuzzers/DawnSPIRVCrossHLSLFastFuzzer.cpp
index ac75be1..d6154b5 100644
--- a/src/fuzzers/DawnSPIRVCrossHLSLFastFuzzer.cpp
+++ b/src/fuzzers/DawnSPIRVCrossHLSLFastFuzzer.cpp
@@ -16,40 +16,32 @@
 #include <string>
 #include <vector>
 
+#include <spirv_hlsl.hpp>
+
 #include "DawnSPIRVCrossFuzzer.h"
 
 namespace {
 
     int FuzzTask(const std::vector<uint32_t>& input) {
-        shaderc_spvc::Context context;
-        if (!context.IsValid()) {
-            return 0;
-        }
+        // Values come from ShaderModuleD3D12.cpp
+        spirv_cross::CompilerGLSL::Options options_glsl;
+        // Force all uninitialized variables to be 0, otherwise they will fail to compile
+        // by FXC.
+        options_glsl.force_zero_initialized_variables = true;
 
-        DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&context, &input]() {
-            shaderc_spvc::CompilationResult result;
-            shaderc_spvc::CompileOptions options;
-            options.SetSourceEnvironment(shaderc_target_env_webgpu, shaderc_env_version_webgpu);
-            options.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1);
+        spirv_cross::CompilerHLSL::Options options_hlsl;
+        options_hlsl.shader_model = 51;
+        options_hlsl.point_coord_compat = true;
+        options_hlsl.point_size_compat = true;
+        options_hlsl.nonwritable_uav_texture_as_srv = true;
 
-            // Using the options that are used by Dawn, they appear in ShaderModuleD3D12.cpp
-            options.SetForceZeroInitializedVariables(true);
-            options.SetHLSLShaderModel(51);
-            // TODO (hao.x.li@intel.com): The HLSLPointCoordCompat and HLSLPointSizeCompat are
-            // required temporarily for https://bugs.chromium.org/p/dawn/issues/detail?id=146,
-            // but should be removed once WebGPU requires there is no gl_PointSize builtin.
-            // See https://github.com/gpuweb/gpuweb/issues/332
-            options.SetHLSLPointCoordCompat(true);
-            options.SetHLSLPointSizeCompat(true);
-            if (context.InitializeForHlsl(input.data(), input.size(), options) ==
-                shaderc_spvc_status_success) {
-                context.CompileShader(&result);
-            }
-        });
+        spirv_cross::CompilerHLSL compiler(input);
+        compiler.set_common_options(options_glsl);
+        compiler.set_hlsl_options(options_hlsl);
+        compiler.compile();
 
         return 0;
     }
-
 }  // namespace
 
 extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
diff --git a/src/fuzzers/DawnSPIRVCrossMSLFastFuzzer.cpp b/src/fuzzers/DawnSPIRVCrossMSLFastFuzzer.cpp
index e4ff964..4649d23 100644
--- a/src/fuzzers/DawnSPIRVCrossMSLFastFuzzer.cpp
+++ b/src/fuzzers/DawnSPIRVCrossMSLFastFuzzer.cpp
@@ -16,28 +16,21 @@
 #include <string>
 #include <vector>
 
+#include <spirv_msl.hpp>
+
 #include "DawnSPIRVCrossFuzzer.h"
 
 namespace {
 
     int FuzzTask(const std::vector<uint32_t>& input) {
-        shaderc_spvc::Context context;
-        if (!context.IsValid()) {
-            return 0;
-        }
+        // Values come from ShaderModuleMTL.mm
+        spirv_cross::CompilerMSL::Options options_msl;
+        options_msl.enable_point_size_builtin = false;
+        options_msl.buffer_size_buffer_index = 30;
 
-        DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&context, &input]() {
-            shaderc_spvc::CompilationResult result;
-            shaderc_spvc::CompileOptions options;
-            options.SetSourceEnvironment(shaderc_target_env_webgpu, shaderc_env_version_webgpu);
-            options.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1);
-
-            // Using the options that are used by Dawn, they appear in ShaderModuleMTL.mm
-            if (context.InitializeForMsl(input.data(), input.size(), options) ==
-                shaderc_spvc_status_success) {
-                context.CompileShader(&result);
-            }
-        });
+        spirv_cross::CompilerMSL compiler(input);
+        compiler.set_msl_options(options_msl);
+        compiler.compile();
 
         return 0;
     }
diff --git a/src/fuzzers/DawnSPVCglslFastFuzzer.cpp b/src/fuzzers/DawnSPVCglslFastFuzzer.cpp
deleted file mode 100644
index 6fbaf82..0000000
--- a/src/fuzzers/DawnSPVCglslFastFuzzer.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2019 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.
-
-#include <cstdint>
-#include <string>
-#include <vector>
-
-#include "spvc/spvc.hpp"
-
-extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
-    return 0;
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-    shaderc_spvc::Context context;
-    if (!context.IsValid()) {
-        return 0;
-    }
-
-    shaderc_spvc::CompilationResult result;
-    shaderc_spvc::CompileOptions options;
-    options.SetSourceEnvironment(shaderc_target_env_webgpu, shaderc_env_version_webgpu);
-    options.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1);
-    // Using the options that are used by Dawn, they appear in ShaderModuleGL.cpp
-    // TODO(sarahM0): double check these option after completion of spvc integration
-    options.SetFlipVertY(true);
-    options.SetFixupClipspace(true);
-#if defined(DAWN_PLATFORM_APPLE)
-    options.SetGLSLLanguageVersion(410);
-#else
-    options.SetGLSLLanguageVersion(440);
-#endif
-
-    size_t sizeInU32 = size / sizeof(uint32_t);
-    const uint32_t* u32Data = reinterpret_cast<const uint32_t*>(data);
-    std::vector<uint32_t> input(u32Data, u32Data + sizeInU32);
-
-    if (input.size() != 0) {
-        if (context.InitializeForGlsl(input.data(), input.size(), options) ==
-            shaderc_spvc_status_success) {
-            context.SetUseSpvcParser(true);
-            context.CompileShader(&result);
-        }
-    }
-    return 0;
-}
diff --git a/src/fuzzers/DawnSPVChlslFastFuzzer.cpp b/src/fuzzers/DawnSPVChlslFastFuzzer.cpp
deleted file mode 100644
index 540ac65..0000000
--- a/src/fuzzers/DawnSPVChlslFastFuzzer.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2019 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.
-
-#include <cstdint>
-#include <string>
-#include <vector>
-
-#include "spvc/spvc.hpp"
-
-extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
-    return 0;
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-    shaderc_spvc::Context context;
-    if (!context.IsValid()) {
-        return 0;
-    }
-
-    shaderc_spvc::CompilationResult result;
-    shaderc_spvc::CompileOptions options;
-    options.SetSourceEnvironment(shaderc_target_env_webgpu, shaderc_env_version_webgpu);
-    options.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1);
-
-    // Using the options that are used by Dawn, they appear in ShaderModuleD3D12.cpp
-    // TODO(sarahM0): double check these option after completion of spvc integration
-    options.SetHLSLShaderModel(51);
-    // TODO (hao.x.li@intel.com): The HLSLPointCoordCompat and HLSLPointSizeCompat are
-    // required temporarily for https://bugs.chromium.org/p/dawn/issues/detail?id=146,
-    // but should be removed once WebGPU requires there is no gl_PointSize builtin.
-    // See https://github.com/gpuweb/gpuweb/issues/332
-    options.SetHLSLPointCoordCompat(true);
-    options.SetHLSLPointSizeCompat(true);
-
-    size_t sizeInU32 = size / sizeof(uint32_t);
-    const uint32_t* u32Data = reinterpret_cast<const uint32_t*>(data);
-    std::vector<uint32_t> input(u32Data, u32Data + sizeInU32);
-
-    if (input.size() != 0) {
-        if (context.InitializeForHlsl(input.data(), input.size(), options) ==
-            shaderc_spvc_status_success) {
-            context.CompileShader(&result);
-        }
-    }
-    return 0;
-}
diff --git a/src/fuzzers/DawnSPVCmslFastFuzzer.cpp b/src/fuzzers/DawnSPVCmslFastFuzzer.cpp
deleted file mode 100644
index 70cb21e..0000000
--- a/src/fuzzers/DawnSPVCmslFastFuzzer.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2019 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.
-
-#include <cstdint>
-#include <string>
-#include <vector>
-
-#include "spvc/spvc.hpp"
-
-extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
-    return 0;
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-    shaderc_spvc::Context context;
-    if (!context.IsValid()) {
-        return 0;
-    }
-
-    shaderc_spvc::CompilationResult result;
-    shaderc_spvc::CompileOptions options;
-    options.SetSourceEnvironment(shaderc_target_env_webgpu, shaderc_env_version_webgpu);
-    options.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_1);
-
-    // Using the options that are used by Dawn, they appear in ShaderModuleMTL.mm
-    // TODO(sarahM0): double check these option after completion of spvc integration
-    size_t sizeInU32 = size / sizeof(uint32_t);
-    const uint32_t* u32Data = reinterpret_cast<const uint32_t*>(data);
-    std::vector<uint32_t> input(u32Data, u32Data + sizeInU32);
-
-    if (input.size() != 0) {
-        if (context.InitializeForMsl(input.data(), input.size(), options) ==
-            shaderc_spvc_status_success) {
-            context.CompileShader(&result);
-        }
-    }
-    return 0;
-}
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index dbceb4d..c30ff37 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -39,11 +39,7 @@
     add_subdirectory(${DAWN_GLSLANG_DIR})
 endif()
 
-if (TARGET shaderc)
-    if (NOT TARGET shaderc_spvc)
-        message(FATAL_ERROR "Dawn: If shaderc is configured before Dawn, it must include SPVC")
-    endif()
-else()
+if (NOT TARGET shaderc)
     set(SHADERC_SKIP_TESTS ON CACHE BOOL "" FORCE)
     set(SHADERC_SKIP_INSTALL ON CACHE BOOL "" FORCE)
     set(SHADERC_ENABLE_SPVC ON CACHE BOOL "" FORCE)
@@ -56,10 +52,8 @@
 
     # Let SPVC's CMakeLists.txt deal with configuring SPIRV-Cross
     set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE BOOL "" FORCE)
-    set(SHADERC_SPIRV_CROSS_DIR "${DAWN_SPIRV_CROSS_DIR}" CACHE BOOL "" FORCE)
 
-    message(STATUS "Dawn: using shaderc[_spvc] at ${DAWN_SHADERC_DIR}")
-    message(STATUS "Dawn:  - with SPIRV-Cross at ${DAWN_SPIRV_CROSS_DIR}")
+    message(STATUS "Dawn: using shaderc at ${DAWN_SHADERC_DIR}")
     add_subdirectory(${DAWN_SHADERC_DIR})
 endif()
 
diff --git a/third_party/gn/spirv_cross/BUILD.gn b/third_party/gn/spirv_cross/BUILD.gn
new file mode 100644
index 0000000..e3cfcc3
--- /dev/null
+++ b/third_party/gn/spirv_cross/BUILD.gn
@@ -0,0 +1,70 @@
+# Copyright 2020 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.
+
+import("../../../scripts/dawn_overrides_with_defaults.gni")
+
+import("//build_overrides/build.gni")
+
+# SPIRV_Cross does not have BUILD.gn rules, so implement our own.
+is_msvc = is_win && !is_clang
+
+config("spirv_cross_public") {
+  include_dirs = [
+    "${dawn_spirv_cross_dir}",
+    "${dawn_spirv_cross_dir}/..",
+  ]
+  defines = [ "SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS" ]
+}
+
+config("spirv_cross_internal") {
+  if (!is_msvc) {
+    cflags_cc = [
+      "-Wno-implicit-fallthrough",
+      "-Wno-return-type",
+      "-Wno-sign-compare",
+    ]
+  } else {
+    # Disable "not all control paths return a value" warning.
+    cflags_cc = [ "/wd4715" ]
+  }
+}
+
+source_set("spirv_cross") {
+  public_configs = [ ":spirv_cross_public" ]
+  configs += [ ":spirv_cross_internal" ]
+
+  sources = [
+    "${dawn_spirv_cross_dir}/GLSL.std.450.h",
+    "${dawn_spirv_cross_dir}/spirv.hpp",
+    "${dawn_spirv_cross_dir}/spirv_cfg.cpp",
+    "${dawn_spirv_cross_dir}/spirv_cfg.hpp",
+    "${dawn_spirv_cross_dir}/spirv_common.hpp",
+    "${dawn_spirv_cross_dir}/spirv_cross.cpp",
+    "${dawn_spirv_cross_dir}/spirv_cross.hpp",
+    "${dawn_spirv_cross_dir}/spirv_cross_containers.hpp",
+    "${dawn_spirv_cross_dir}/spirv_cross_error_handling.hpp",
+    "${dawn_spirv_cross_dir}/spirv_cross_parsed_ir.cpp",
+    "${dawn_spirv_cross_dir}/spirv_cross_parsed_ir.hpp",
+    "${dawn_spirv_cross_dir}/spirv_glsl.cpp",
+    "${dawn_spirv_cross_dir}/spirv_glsl.hpp",
+    "${dawn_spirv_cross_dir}/spirv_hlsl.cpp",
+    "${dawn_spirv_cross_dir}/spirv_hlsl.hpp",
+    "${dawn_spirv_cross_dir}/spirv_msl.cpp",
+    "${dawn_spirv_cross_dir}/spirv_msl.hpp",
+    "${dawn_spirv_cross_dir}/spirv_parser.cpp",
+    "${dawn_spirv_cross_dir}/spirv_parser.hpp",
+    "${dawn_spirv_cross_dir}/spirv_reflect.cpp",
+    "${dawn_spirv_cross_dir}/spirv_reflect.hpp",
+  ]
+}