// Copyright 2017 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 "dawn_native/d3d12/ShaderModuleD3D12.h"

#include "common/Assert.h"
#include "common/BitSetIterator.h"
#include "common/Log.h"
#include "common/WindowsUtils.h"
#include "dawn_native/Pipeline.h"
#include "dawn_native/TintUtils.h"
#include "dawn_native/d3d12/BindGroupLayoutD3D12.h"
#include "dawn_native/d3d12/D3D12Error.h"
#include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/PipelineLayoutD3D12.h"
#include "dawn_native/d3d12/PlatformFunctions.h"
#include "dawn_native/d3d12/UtilsD3D12.h"

#include <d3dcompiler.h>

#include <tint/tint.h>
#include <map>
#include <sstream>
#include <unordered_map>

namespace dawn_native { namespace d3d12 {

    namespace {
        ResultOrError<uint64_t> GetDXCompilerVersion(ComPtr<IDxcValidator> dxcValidator) {
            ComPtr<IDxcVersionInfo> versionInfo;
            DAWN_TRY(CheckHRESULT(dxcValidator.As(&versionInfo),
                                  "D3D12 QueryInterface IDxcValidator to IDxcVersionInfo"));

            uint32_t compilerMajor, compilerMinor;
            DAWN_TRY(CheckHRESULT(versionInfo->GetVersion(&compilerMajor, &compilerMinor),
                                  "IDxcVersionInfo::GetVersion"));

            // Pack both into a single version number.
            return (uint64_t(compilerMajor) << uint64_t(32)) + compilerMinor;
        }

        uint64_t GetD3DCompilerVersion() {
            return D3D_COMPILER_VERSION;
        }

        struct CompareBindingPoint {
            constexpr bool operator()(const tint::transform::BindingPoint& lhs,
                                      const tint::transform::BindingPoint& rhs) const {
                if (lhs.group != rhs.group) {
                    return lhs.group < rhs.group;
                } else {
                    return lhs.binding < rhs.binding;
                }
            }
        };

        void Serialize(std::stringstream& output, const tint::ast::Access& access) {
            output << access;
        }

        void Serialize(std::stringstream& output,
                       const tint::transform::BindingPoint& binding_point) {
            output << "(BindingPoint";
            output << " group=" << binding_point.group;
            output << " binding=" << binding_point.binding;
            output << ")";
        }

        template <typename T,
                  typename = typename std::enable_if<std::is_fundamental<T>::value>::type>
        void Serialize(std::stringstream& output, const T& val) {
            output << val;
        }

        template <typename T>
        void Serialize(std::stringstream& output,
                       const std::unordered_map<tint::transform::BindingPoint, T>& map) {
            output << "(map";

            std::map<tint::transform::BindingPoint, T, CompareBindingPoint> sorted(map.begin(),
                                                                                   map.end());
            for (auto& [bindingPoint, value] : sorted) {
                output << " ";
                Serialize(output, bindingPoint);
                output << "=";
                Serialize(output, value);
            }
            output << ")";
        }

        void Serialize(std::stringstream& output,
                       const tint::writer::ArrayLengthFromUniformOptions& arrayLengthFromUniform) {
            output << "(ArrayLengthFromUniformOptions";
            output << " ubo_binding=";
            Serialize(output, arrayLengthFromUniform.ubo_binding);
            output << " bindpoint_to_size_index=";
            Serialize(output, arrayLengthFromUniform.bindpoint_to_size_index);
            output << ")";
        }

        // 32 bit float has 7 decimal digits of precision so setting n to 8 should be enough
        std::string FloatToStringWithPrecision(float v, std::streamsize n = 8) {
            std::ostringstream out;
            out.precision(n);
            out << std::fixed << v;
            return out.str();
        }

        std::string GetHLSLValueString(EntryPointMetadata::OverridableConstant::Type dawnType,
                                       const OverridableConstantScalar* entry,
                                       double value = 0) {
            switch (dawnType) {
                case EntryPointMetadata::OverridableConstant::Type::Boolean:
                    return std::to_string(entry ? entry->b : static_cast<int32_t>(value));
                case EntryPointMetadata::OverridableConstant::Type::Float32:
                    return FloatToStringWithPrecision(entry ? entry->f32
                                                            : static_cast<float>(value));
                case EntryPointMetadata::OverridableConstant::Type::Int32:
                    return std::to_string(entry ? entry->i32 : static_cast<int32_t>(value));
                case EntryPointMetadata::OverridableConstant::Type::Uint32:
                    return std::to_string(entry ? entry->u32 : static_cast<uint32_t>(value));
                default:
                    UNREACHABLE();
            }
        }

        constexpr char kSpecConstantPrefix[] = "WGSL_SPEC_CONSTANT_";

        void GetOverridableConstantsDefines(
            std::vector<std::pair<std::string, std::string>>* defineStrings,
            const PipelineConstantEntries* pipelineConstantEntries,
            const EntryPointMetadata::OverridableConstantsMap* shaderEntryPointConstants) {
            std::unordered_set<std::string> overriddenConstants;

            // Set pipeline overridden values
            for (const auto& [name, value] : *pipelineConstantEntries) {
                overriddenConstants.insert(name);

                // This is already validated so `name` must exist
                const auto& moduleConstant = shaderEntryPointConstants->at(name);

                defineStrings->emplace_back(
                    kSpecConstantPrefix + std::to_string(static_cast<int32_t>(moduleConstant.id)),
                    GetHLSLValueString(moduleConstant.type, nullptr, value));
            }

            // Set shader initialized default values
            for (const auto& iter : *shaderEntryPointConstants) {
                const std::string& name = iter.first;
                if (overriddenConstants.count(name) != 0) {
                    // This constant already has overridden value
                    continue;
                }

                const auto& moduleConstant = shaderEntryPointConstants->at(name);

                // Uninitialized default values are okay since they ar only defined to pass
                // compilation but not used
                defineStrings->emplace_back(
                    kSpecConstantPrefix + std::to_string(static_cast<int32_t>(moduleConstant.id)),
                    GetHLSLValueString(moduleConstant.type, &moduleConstant.defaultValue));
            }
        }

        // The inputs to a shader compilation. These have been intentionally isolated from the
        // device to help ensure that the pipeline cache key contains all inputs for compilation.
        struct ShaderCompilationRequest {
            enum Compiler { FXC, DXC };

            // Common inputs
            Compiler compiler;
            const tint::Program* program;
            const char* entryPointName;
            SingleShaderStage stage;
            uint32_t compileFlags;
            bool disableSymbolRenaming;
            tint::transform::BindingRemapper::BindingPoints remappedBindingPoints;
            tint::transform::BindingRemapper::AccessControls remappedAccessControls;
            bool isRobustnessEnabled;
            bool usesNumWorkgroups;
            uint32_t numWorkgroupsRegisterSpace;
            uint32_t numWorkgroupsShaderRegister;
            tint::writer::ArrayLengthFromUniformOptions arrayLengthFromUniform;
            std::vector<std::pair<std::string, std::string>> defineStrings;

            // FXC/DXC common inputs
            bool disableWorkgroupInit;

            // FXC inputs
            uint64_t fxcVersion;

            // DXC inputs
            uint64_t dxcVersion;
            const D3D12DeviceInfo* deviceInfo;
            bool hasShaderFloat16Feature;

            static ResultOrError<ShaderCompilationRequest> Create(
                const char* entryPointName,
                SingleShaderStage stage,
                const PipelineLayout* layout,
                uint32_t compileFlags,
                const Device* device,
                const tint::Program* program,
                const EntryPointMetadata& entryPoint,
                const ProgrammableStage& programmableStage) {
                Compiler compiler;
                uint64_t dxcVersion = 0;
                if (device->IsToggleEnabled(Toggle::UseDXC)) {
                    compiler = Compiler::DXC;
                    DAWN_TRY_ASSIGN(dxcVersion, GetDXCompilerVersion(device->GetDxcValidator()));
                } else {
                    compiler = Compiler::FXC;
                }

                using tint::transform::BindingPoint;
                using tint::transform::BindingRemapper;

                BindingRemapper::BindingPoints remappedBindingPoints;
                BindingRemapper::AccessControls remappedAccessControls;

                tint::writer::ArrayLengthFromUniformOptions arrayLengthFromUniform;
                arrayLengthFromUniform.ubo_binding = {
                    layout->GetDynamicStorageBufferLengthsRegisterSpace(),
                    layout->GetDynamicStorageBufferLengthsShaderRegister()};

                const BindingInfoArray& moduleBindingInfo = entryPoint.bindings;
                for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
                    const BindGroupLayout* bgl = ToBackend(layout->GetBindGroupLayout(group));
                    const auto& groupBindingInfo = moduleBindingInfo[group];

                    // d3d12::BindGroupLayout packs the bindings per HLSL register-space. We modify
                    // the Tint AST to make the "bindings" decoration match the offset chosen by
                    // d3d12::BindGroupLayout so that Tint produces HLSL with the correct registers
                    // assigned to each interface variable.
                    for (const auto& [binding, bindingInfo] : groupBindingInfo) {
                        BindingIndex bindingIndex = bgl->GetBindingIndex(binding);
                        BindingPoint srcBindingPoint{static_cast<uint32_t>(group),
                                                     static_cast<uint32_t>(binding)};
                        BindingPoint dstBindingPoint{static_cast<uint32_t>(group),
                                                     bgl->GetShaderRegister(bindingIndex)};
                        if (srcBindingPoint != dstBindingPoint) {
                            remappedBindingPoints.emplace(srcBindingPoint, dstBindingPoint);
                        }

                        // Declaring a read-only storage buffer in HLSL but specifying a storage
                        // buffer in the BGL produces the wrong output. Force read-only storage
                        // buffer bindings to be treated as UAV instead of SRV. Internal storage
                        // buffer is a storage buffer used in the internal pipeline.
                        const bool forceStorageBufferAsUAV =
                            (bindingInfo.buffer.type == wgpu::BufferBindingType::ReadOnlyStorage &&
                             (bgl->GetBindingInfo(bindingIndex).buffer.type ==
                                  wgpu::BufferBindingType::Storage ||
                              bgl->GetBindingInfo(bindingIndex).buffer.type ==
                                  kInternalStorageBufferBinding));
                        if (forceStorageBufferAsUAV) {
                            remappedAccessControls.emplace(srcBindingPoint,
                                                           tint::ast::Access::kReadWrite);
                        }
                    }

                    // Add arrayLengthFromUniform options
                    {
                        for (const auto& bindingAndRegisterOffset :
                             layout->GetDynamicStorageBufferLengthInfo()[group]
                                 .bindingAndRegisterOffsets) {
                            BindingNumber binding = bindingAndRegisterOffset.binding;
                            uint32_t registerOffset = bindingAndRegisterOffset.registerOffset;

                            BindingPoint bindingPoint{static_cast<uint32_t>(group),
                                                      static_cast<uint32_t>(binding)};
                            // Get the renamed binding point if it was remapped.
                            auto it = remappedBindingPoints.find(bindingPoint);
                            if (it != remappedBindingPoints.end()) {
                                bindingPoint = it->second;
                            }

                            arrayLengthFromUniform.bindpoint_to_size_index.emplace(bindingPoint,
                                                                                   registerOffset);
                        }
                    }
                }

                ShaderCompilationRequest request;
                request.compiler = compiler;
                request.program = program;
                request.entryPointName = entryPointName;
                request.stage = stage;
                request.compileFlags = compileFlags;
                request.disableSymbolRenaming =
                    device->IsToggleEnabled(Toggle::DisableSymbolRenaming);
                request.remappedBindingPoints = std::move(remappedBindingPoints);
                request.remappedAccessControls = std::move(remappedAccessControls);
                request.isRobustnessEnabled = device->IsRobustnessEnabled();
                request.disableWorkgroupInit =
                    device->IsToggleEnabled(Toggle::DisableWorkgroupInit);
                request.usesNumWorkgroups = entryPoint.usesNumWorkgroups;
                request.numWorkgroupsShaderRegister = layout->GetNumWorkgroupsShaderRegister();
                request.numWorkgroupsRegisterSpace = layout->GetNumWorkgroupsRegisterSpace();
                request.arrayLengthFromUniform = std::move(arrayLengthFromUniform);
                request.fxcVersion = compiler == Compiler::FXC ? GetD3DCompilerVersion() : 0;
                request.dxcVersion = compiler == Compiler::DXC ? dxcVersion : 0;
                request.deviceInfo = &device->GetDeviceInfo();
                request.hasShaderFloat16Feature = device->IsFeatureEnabled(Feature::ShaderFloat16);

                GetOverridableConstantsDefines(
                    &request.defineStrings, &programmableStage.constants,
                    &programmableStage.module->GetEntryPoint(programmableStage.entryPoint)
                         .overridableConstants);

                return std::move(request);
            }

            ResultOrError<PersistentCacheKey> CreateCacheKey() const {
                // Generate the WGSL from the Tint program so it's normalized.
                // TODO(tint:1180): Consider using a binary serialization of the tint AST for a more
                // compact representation.
                auto result = tint::writer::wgsl::Generate(program, tint::writer::wgsl::Options{});
                if (!result.success) {
                    std::ostringstream errorStream;
                    errorStream << "Tint WGSL failure:" << std::endl;
                    errorStream << "Generator: " << result.error << std::endl;
                    return DAWN_INTERNAL_ERROR(errorStream.str().c_str());
                }

                std::stringstream stream;

                // Prefix the key with the type to avoid collisions from another type that could
                // have the same key.
                stream << static_cast<uint32_t>(PersistentKeyType::Shader);
                stream << "\n";

                stream << result.wgsl.length();
                stream << "\n";

                stream << result.wgsl;
                stream << "\n";

                stream << "(ShaderCompilationRequest";
                stream << " compiler=" << compiler;
                stream << " entryPointName=" << entryPointName;
                stream << " stage=" << uint32_t(stage);
                stream << " compileFlags=" << compileFlags;
                stream << " disableSymbolRenaming=" << disableSymbolRenaming;

                stream << " remappedBindingPoints=";
                Serialize(stream, remappedBindingPoints);

                stream << " remappedAccessControls=";
                Serialize(stream, remappedAccessControls);

                stream << " useNumWorkgroups=" << usesNumWorkgroups;
                stream << " numWorkgroupsRegisterSpace=" << numWorkgroupsRegisterSpace;
                stream << " numWorkgroupsShaderRegister=" << numWorkgroupsShaderRegister;

                stream << " arrayLengthFromUniform=";
                Serialize(stream, arrayLengthFromUniform);

                stream << " shaderModel=" << deviceInfo->shaderModel;
                stream << " disableWorkgroupInit=" << disableWorkgroupInit;
                stream << " isRobustnessEnabled=" << isRobustnessEnabled;
                stream << " fxcVersion=" << fxcVersion;
                stream << " dxcVersion=" << dxcVersion;
                stream << " hasShaderFloat16Feature=" << hasShaderFloat16Feature;

                stream << " defines={";
                for (const auto& [name, value] : defineStrings) {
                    stream << " <" << name << "," << value << ">";
                }
                stream << " }";

                stream << ")";
                stream << "\n";

                return PersistentCacheKey(std::istreambuf_iterator<char>{stream},
                                          std::istreambuf_iterator<char>{});
            }
        };

        std::vector<const wchar_t*> GetDXCArguments(uint32_t compileFlags, bool enable16BitTypes) {
            std::vector<const wchar_t*> arguments;
            if (compileFlags & D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY) {
                arguments.push_back(L"/Gec");
            }
            if (compileFlags & D3DCOMPILE_IEEE_STRICTNESS) {
                arguments.push_back(L"/Gis");
            }
            constexpr uint32_t d3dCompileFlagsBits = D3DCOMPILE_OPTIMIZATION_LEVEL2;
            if (compileFlags & d3dCompileFlagsBits) {
                switch (compileFlags & D3DCOMPILE_OPTIMIZATION_LEVEL2) {
                    case D3DCOMPILE_OPTIMIZATION_LEVEL0:
                        arguments.push_back(L"/O0");
                        break;
                    case D3DCOMPILE_OPTIMIZATION_LEVEL2:
                        arguments.push_back(L"/O2");
                        break;
                    case D3DCOMPILE_OPTIMIZATION_LEVEL3:
                        arguments.push_back(L"/O3");
                        break;
                }
            }
            if (compileFlags & D3DCOMPILE_DEBUG) {
                arguments.push_back(L"/Zi");
            }
            if (compileFlags & D3DCOMPILE_PACK_MATRIX_ROW_MAJOR) {
                arguments.push_back(L"/Zpr");
            }
            if (compileFlags & D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR) {
                arguments.push_back(L"/Zpc");
            }
            if (compileFlags & D3DCOMPILE_AVOID_FLOW_CONTROL) {
                arguments.push_back(L"/Gfa");
            }
            if (compileFlags & D3DCOMPILE_PREFER_FLOW_CONTROL) {
                arguments.push_back(L"/Gfp");
            }
            if (compileFlags & D3DCOMPILE_RESOURCES_MAY_ALIAS) {
                arguments.push_back(L"/res_may_alias");
            }

            if (enable16BitTypes) {
                // enable-16bit-types are only allowed in -HV 2018 (default)
                arguments.push_back(L"/enable-16bit-types");
            }

            arguments.push_back(L"-HV");
            arguments.push_back(L"2018");

            return arguments;
        }

        ResultOrError<ComPtr<IDxcBlob>> CompileShaderDXC(IDxcLibrary* dxcLibrary,
                                                         IDxcCompiler* dxcCompiler,
                                                         const ShaderCompilationRequest& request,
                                                         const std::string& hlslSource) {
            ComPtr<IDxcBlobEncoding> sourceBlob;
            DAWN_TRY(
                CheckHRESULT(dxcLibrary->CreateBlobWithEncodingOnHeapCopy(
                                 hlslSource.c_str(), hlslSource.length(), CP_UTF8, &sourceBlob),
                             "DXC create blob"));

            std::wstring entryPointW;
            DAWN_TRY_ASSIGN(entryPointW, ConvertStringToWstring(request.entryPointName));

            std::vector<const wchar_t*> arguments =
                GetDXCArguments(request.compileFlags, request.hasShaderFloat16Feature);

            // Build defines for overridable constants
            std::vector<std::pair<std::wstring, std::wstring>> defineStrings;
            defineStrings.reserve(request.defineStrings.size());
            for (const auto& [name, value] : request.defineStrings) {
                defineStrings.emplace_back(UTF8ToWStr(name.c_str()), UTF8ToWStr(value.c_str()));
            }

            std::vector<DxcDefine> dxcDefines;
            dxcDefines.reserve(defineStrings.size());
            for (const auto& [name, value] : defineStrings) {
                dxcDefines.push_back({name.c_str(), value.c_str()});
            }

            ComPtr<IDxcOperationResult> result;
            DAWN_TRY(CheckHRESULT(
                dxcCompiler->Compile(sourceBlob.Get(), nullptr, entryPointW.c_str(),
                                     request.deviceInfo->shaderProfiles[request.stage].c_str(),
                                     arguments.data(), arguments.size(), dxcDefines.data(),
                                     dxcDefines.size(), nullptr, &result),
                "DXC compile"));

            HRESULT hr;
            DAWN_TRY(CheckHRESULT(result->GetStatus(&hr), "DXC get status"));

            if (FAILED(hr)) {
                ComPtr<IDxcBlobEncoding> errors;
                DAWN_TRY(CheckHRESULT(result->GetErrorBuffer(&errors), "DXC get error buffer"));

                return DAWN_FORMAT_VALIDATION_ERROR("DXC compile failed with: %s",
                                                    static_cast<char*>(errors->GetBufferPointer()));
            }

            ComPtr<IDxcBlob> compiledShader;
            DAWN_TRY(CheckHRESULT(result->GetResult(&compiledShader), "DXC get result"));
            return std::move(compiledShader);
        }

        std::string CompileFlagsToStringFXC(uint32_t compileFlags) {
            struct Flag {
                uint32_t value;
                const char* name;
            };
            constexpr Flag flags[] = {
            // Populated from d3dcompiler.h
#define F(f) Flag{f, #f}
                F(D3DCOMPILE_DEBUG),
                F(D3DCOMPILE_SKIP_VALIDATION),
                F(D3DCOMPILE_SKIP_OPTIMIZATION),
                F(D3DCOMPILE_PACK_MATRIX_ROW_MAJOR),
                F(D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR),
                F(D3DCOMPILE_PARTIAL_PRECISION),
                F(D3DCOMPILE_FORCE_VS_SOFTWARE_NO_OPT),
                F(D3DCOMPILE_FORCE_PS_SOFTWARE_NO_OPT),
                F(D3DCOMPILE_NO_PRESHADER),
                F(D3DCOMPILE_AVOID_FLOW_CONTROL),
                F(D3DCOMPILE_PREFER_FLOW_CONTROL),
                F(D3DCOMPILE_ENABLE_STRICTNESS),
                F(D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY),
                F(D3DCOMPILE_IEEE_STRICTNESS),
                F(D3DCOMPILE_RESERVED16),
                F(D3DCOMPILE_RESERVED17),
                F(D3DCOMPILE_WARNINGS_ARE_ERRORS),
                F(D3DCOMPILE_RESOURCES_MAY_ALIAS),
                F(D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES),
                F(D3DCOMPILE_ALL_RESOURCES_BOUND),
                F(D3DCOMPILE_DEBUG_NAME_FOR_SOURCE),
                F(D3DCOMPILE_DEBUG_NAME_FOR_BINARY),
#undef F
            };

            std::string result;
            for (const Flag& f : flags) {
                if ((compileFlags & f.value) != 0) {
                    result += f.name + std::string("\n");
                }
            }

            // Optimization level must be handled separately as two bits are used, and the values
            // don't map neatly to 0-3.
            constexpr uint32_t d3dCompileFlagsBits = D3DCOMPILE_OPTIMIZATION_LEVEL2;
            switch (compileFlags & d3dCompileFlagsBits) {
                case D3DCOMPILE_OPTIMIZATION_LEVEL0:
                    result += "D3DCOMPILE_OPTIMIZATION_LEVEL0";
                    break;
                case D3DCOMPILE_OPTIMIZATION_LEVEL1:
                    result += "D3DCOMPILE_OPTIMIZATION_LEVEL1";
                    break;
                case D3DCOMPILE_OPTIMIZATION_LEVEL2:
                    result += "D3DCOMPILE_OPTIMIZATION_LEVEL2";
                    break;
                case D3DCOMPILE_OPTIMIZATION_LEVEL3:
                    result += "D3DCOMPILE_OPTIMIZATION_LEVEL3";
                    break;
            }
            result += std::string("\n");

            return result;
        }

        ResultOrError<ComPtr<ID3DBlob>> CompileShaderFXC(const PlatformFunctions* functions,
                                                         const ShaderCompilationRequest& request,
                                                         const std::string& hlslSource) {
            const char* targetProfile = nullptr;
            switch (request.stage) {
                case SingleShaderStage::Vertex:
                    targetProfile = "vs_5_1";
                    break;
                case SingleShaderStage::Fragment:
                    targetProfile = "ps_5_1";
                    break;
                case SingleShaderStage::Compute:
                    targetProfile = "cs_5_1";
                    break;
            }

            ComPtr<ID3DBlob> compiledShader;
            ComPtr<ID3DBlob> errors;

            // Build defines for overridable constants
            const D3D_SHADER_MACRO* pDefines = nullptr;
            std::vector<D3D_SHADER_MACRO> fxcDefines;
            if (request.defineStrings.size() > 0) {
                fxcDefines.reserve(request.defineStrings.size() + 1);
                for (const auto& [name, value] : request.defineStrings) {
                    fxcDefines.push_back({name.c_str(), value.c_str()});
                }
                // d3dCompile D3D_SHADER_MACRO* pDefines is a nullptr terminated array
                fxcDefines.push_back({nullptr, nullptr});
                pDefines = fxcDefines.data();
            }

            DAWN_INVALID_IF(FAILED(functions->d3dCompile(
                                hlslSource.c_str(), hlslSource.length(), nullptr, pDefines, nullptr,
                                request.entryPointName, targetProfile, request.compileFlags, 0,
                                &compiledShader, &errors)),
                            "D3D compile failed with: %s",
                            static_cast<char*>(errors->GetBufferPointer()));

            return std::move(compiledShader);
        }

        ResultOrError<std::string> TranslateToHLSL(const ShaderCompilationRequest& request,
                                                   std::string* remappedEntryPointName) {
            std::ostringstream errorStream;
            errorStream << "Tint HLSL failure:" << std::endl;

            tint::transform::Manager transformManager;
            tint::transform::DataMap transformInputs;

            if (request.isRobustnessEnabled) {
                transformManager.Add<tint::transform::Robustness>();
            }

            transformManager.Add<tint::transform::BindingRemapper>();

            transformManager.Add<tint::transform::SingleEntryPoint>();
            transformInputs.Add<tint::transform::SingleEntryPoint::Config>(request.entryPointName);

            transformManager.Add<tint::transform::Renamer>();

            if (request.disableSymbolRenaming) {
                // We still need to rename HLSL reserved keywords
                transformInputs.Add<tint::transform::Renamer::Config>(
                    tint::transform::Renamer::Target::kHlslKeywords);
            }

            // D3D12 registers like `t3` and `c3` have the same bindingOffset number in
            // the remapping but should not be considered a collision because they have
            // different types.
            const bool mayCollide = true;
            transformInputs.Add<tint::transform::BindingRemapper::Remappings>(
                std::move(request.remappedBindingPoints), std::move(request.remappedAccessControls),
                mayCollide);

            tint::Program transformedProgram;
            tint::transform::DataMap transformOutputs;
            DAWN_TRY_ASSIGN(transformedProgram,
                            RunTransforms(&transformManager, request.program, transformInputs,
                                          &transformOutputs, nullptr));

            if (auto* data = transformOutputs.Get<tint::transform::Renamer::Data>()) {
                auto it = data->remappings.find(request.entryPointName);
                if (it != data->remappings.end()) {
                    *remappedEntryPointName = it->second;
                } else {
                    DAWN_INVALID_IF(!request.disableSymbolRenaming,
                                    "Could not find remapped name for entry point.");

                    *remappedEntryPointName = request.entryPointName;
                }
            } else {
                return DAWN_FORMAT_VALIDATION_ERROR("Transform output missing renamer data.");
            }

            tint::writer::hlsl::Options options;
            options.disable_workgroup_init = request.disableWorkgroupInit;
            if (request.usesNumWorkgroups) {
                options.root_constant_binding_point.group = request.numWorkgroupsRegisterSpace;
                options.root_constant_binding_point.binding = request.numWorkgroupsShaderRegister;
            }
            // TODO(dawn:549): HLSL generation outputs the indices into the
            // array_length_from_uniform buffer that were actually used. When the blob cache can
            // store more than compiled shaders, we should reflect these used indices and store
            // them as well. This would allow us to only upload root constants that are actually
            // read by the shader.
            options.array_length_from_uniform = request.arrayLengthFromUniform;
            auto result = tint::writer::hlsl::Generate(&transformedProgram, options);
            DAWN_INVALID_IF(!result.success, "An error occured while generating HLSL: %s",
                            result.error);

            return std::move(result.hlsl);
        }

        template <typename F>
        MaybeError CompileShader(const PlatformFunctions* functions,
                                 IDxcLibrary* dxcLibrary,
                                 IDxcCompiler* dxcCompiler,
                                 ShaderCompilationRequest&& request,
                                 bool dumpShaders,
                                 F&& DumpShadersEmitLog,
                                 CompiledShader* compiledShader) {
            // Compile the source shader to HLSL.
            std::string hlslSource;
            std::string remappedEntryPoint;
            DAWN_TRY_ASSIGN(hlslSource, TranslateToHLSL(request, &remappedEntryPoint));
            if (dumpShaders) {
                std::ostringstream dumpedMsg;
                dumpedMsg << "/* Dumped generated HLSL */" << std::endl << hlslSource;
                DumpShadersEmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str());
            }
            request.entryPointName = remappedEntryPoint.c_str();
            switch (request.compiler) {
                case ShaderCompilationRequest::Compiler::DXC:
                    DAWN_TRY_ASSIGN(compiledShader->compiledDXCShader,
                                    CompileShaderDXC(dxcLibrary, dxcCompiler, request, hlslSource));
                    break;
                case ShaderCompilationRequest::Compiler::FXC:
                    DAWN_TRY_ASSIGN(compiledShader->compiledFXCShader,
                                    CompileShaderFXC(functions, request, hlslSource));
                    break;
            }

            if (dumpShaders && request.compiler == ShaderCompilationRequest::Compiler::FXC) {
                std::ostringstream dumpedMsg;
                dumpedMsg << "/* FXC compile flags */ " << std::endl
                          << CompileFlagsToStringFXC(request.compileFlags) << std::endl;

                dumpedMsg << "/* Dumped disassembled DXBC */" << std::endl;

                ComPtr<ID3DBlob> disassembly;
                if (FAILED(functions->d3dDisassemble(
                        compiledShader->compiledFXCShader->GetBufferPointer(),
                        compiledShader->compiledFXCShader->GetBufferSize(), 0, nullptr,
                        &disassembly))) {
                    dumpedMsg << "D3D disassemble failed" << std::endl;
                } else {
                    dumpedMsg << reinterpret_cast<const char*>(disassembly->GetBufferPointer());
                }
                DumpShadersEmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str());
            }

            return {};
        }

    }  // anonymous namespace

    // static
    ResultOrError<Ref<ShaderModule>> ShaderModule::Create(Device* device,
                                                          const ShaderModuleDescriptor* descriptor,
                                                          ShaderModuleParseResult* parseResult) {
        Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor));
        DAWN_TRY(module->Initialize(parseResult));
        return module;
    }

    ShaderModule::ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor)
        : ShaderModuleBase(device, descriptor) {
    }

    MaybeError ShaderModule::Initialize(ShaderModuleParseResult* parseResult) {
        ScopedTintICEHandler scopedICEHandler(GetDevice());
        return InitializeBase(parseResult);
    }

    ResultOrError<CompiledShader> ShaderModule::Compile(const ProgrammableStage& programmableStage,
                                                        SingleShaderStage stage,
                                                        PipelineLayout* layout,
                                                        uint32_t compileFlags) {
        ASSERT(!IsError());
        ScopedTintICEHandler scopedICEHandler(GetDevice());

        Device* device = ToBackend(GetDevice());

        CompiledShader compiledShader = {};

        tint::transform::Manager transformManager;
        tint::transform::DataMap transformInputs;

        const tint::Program* program;
        tint::Program programAsValue;
        if (stage == SingleShaderStage::Vertex) {
            transformManager.Add<tint::transform::FirstIndexOffset>();
            transformInputs.Add<tint::transform::FirstIndexOffset::BindingPoint>(
                layout->GetFirstIndexOffsetShaderRegister(),
                layout->GetFirstIndexOffsetRegisterSpace());

            tint::transform::DataMap transformOutputs;
            DAWN_TRY_ASSIGN(programAsValue,
                            RunTransforms(&transformManager, GetTintProgram(), transformInputs,
                                          &transformOutputs, nullptr));

            if (auto* data = transformOutputs.Get<tint::transform::FirstIndexOffset::Data>()) {
                // TODO(dawn:549): Consider adding this information to the pipeline cache once we
                // can store more than the shader blob in it.
                compiledShader.firstOffsetInfo.usesVertexIndex = data->has_vertex_index;
                if (compiledShader.firstOffsetInfo.usesVertexIndex) {
                    compiledShader.firstOffsetInfo.vertexIndexOffset = data->first_vertex_offset;
                }
                compiledShader.firstOffsetInfo.usesInstanceIndex = data->has_instance_index;
                if (compiledShader.firstOffsetInfo.usesInstanceIndex) {
                    compiledShader.firstOffsetInfo.instanceIndexOffset =
                        data->first_instance_offset;
                }
            }

            program = &programAsValue;
        } else {
            program = GetTintProgram();
        }

        ShaderCompilationRequest request;
        DAWN_TRY_ASSIGN(
            request, ShaderCompilationRequest::Create(
                         programmableStage.entryPoint.c_str(), stage, layout, compileFlags, device,
                         program, GetEntryPoint(programmableStage.entryPoint), programmableStage));

        PersistentCacheKey shaderCacheKey;
        DAWN_TRY_ASSIGN(shaderCacheKey, request.CreateCacheKey());

        DAWN_TRY_ASSIGN(
            compiledShader.cachedShader,
            device->GetPersistentCache()->GetOrCreate(
                shaderCacheKey, [&](auto doCache) -> MaybeError {
                    DAWN_TRY(CompileShader(
                        device->GetFunctions(),
                        device->IsToggleEnabled(Toggle::UseDXC) ? device->GetDxcLibrary().Get()
                                                                : nullptr,
                        device->IsToggleEnabled(Toggle::UseDXC) ? device->GetDxcCompiler().Get()
                                                                : nullptr,
                        std::move(request), device->IsToggleEnabled(Toggle::DumpShaders),
                        [&](WGPULoggingType loggingType, const char* message) {
                            GetDevice()->EmitLog(loggingType, message);
                        },
                        &compiledShader));
                    const D3D12_SHADER_BYTECODE shader = compiledShader.GetD3D12ShaderBytecode();
                    doCache(shader.pShaderBytecode, shader.BytecodeLength);
                    return {};
                }));

        return std::move(compiledShader);
    }

    D3D12_SHADER_BYTECODE CompiledShader::GetD3D12ShaderBytecode() const {
        if (cachedShader.buffer != nullptr) {
            return {cachedShader.buffer.get(), cachedShader.bufferSize};
        } else if (compiledFXCShader != nullptr) {
            return {compiledFXCShader->GetBufferPointer(), compiledFXCShader->GetBufferSize()};
        } else if (compiledDXCShader != nullptr) {
            return {compiledDXCShader->GetBufferPointer(), compiledDXCShader->GetBufferSize()};
        }
        UNREACHABLE();
        return {};
    }
}}  // namespace dawn_native::d3d12
