// 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 <d3dcompiler.h>

#include <map>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include "dawn/common/Assert.h"
#include "dawn/common/BitSetIterator.h"
#include "dawn/common/Log.h"
#include "dawn/common/WindowsUtils.h"
#include "dawn/native/CacheKey.h"
#include "dawn/native/CacheRequest.h"
#include "dawn/native/Pipeline.h"
#include "dawn/native/TintUtils.h"
#include "dawn/native/d3d12/AdapterD3D12.h"
#include "dawn/native/d3d12/BackendD3D12.h"
#include "dawn/native/d3d12/BindGroupLayoutD3D12.h"
#include "dawn/native/d3d12/BlobD3D12.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 "dawn/native/stream/BlobSource.h"
#include "dawn/native/stream/ByteVectorSink.h"
#include "dawn/platform/DawnPlatform.h"
#include "dawn/platform/tracing/TraceEvent.h"

#include "tint/tint.h"

namespace dawn::native::stream {

// Define no-op serializations for pD3DCompile, IDxcLibrary, and IDxcCompiler.
// These are output-only interfaces used to generate bytecode.
template <>
void Stream<IDxcLibrary*>::Write(Sink*, IDxcLibrary* const&) {}
template <>
void Stream<IDxcCompiler*>::Write(Sink*, IDxcCompiler* const&) {}
template <>
void Stream<pD3DCompile>::Write(Sink*, pD3DCompile const&) {}

}  // namespace dawn::native::stream

namespace dawn::native::d3d12 {

namespace {

// 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::Override::Type dawnType,
                               const OverrideScalar* entry,
                               double value = 0) {
    switch (dawnType) {
        case EntryPointMetadata::Override::Type::Boolean:
            return std::to_string(entry ? entry->b : static_cast<int32_t>(value));
        case EntryPointMetadata::Override::Type::Float32:
            return FloatToStringWithPrecision(entry ? entry->f32 : static_cast<float>(value));
        case EntryPointMetadata::Override::Type::Int32:
            return std::to_string(entry ? entry->i32 : static_cast<int32_t>(value));
        case EntryPointMetadata::Override::Type::Uint32:
            return std::to_string(entry ? entry->u32 : static_cast<uint32_t>(value));
        default:
            UNREACHABLE();
    }
}

constexpr char kSpecConstantPrefix[] = "WGSL_SPEC_CONSTANT_";

using DefineStrings = std::vector<std::pair<std::string, std::string>>;

DefineStrings GetOverridableConstantsDefines(
    const PipelineConstantEntries& pipelineConstantEntries,
    const EntryPointMetadata::OverridesMap& shaderEntryPointConstants) {
    DefineStrings defineStrings;
    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));
    }
    return defineStrings;
}

enum class Compiler { FXC, DXC };

#define HLSL_COMPILATION_REQUEST_MEMBERS(X)                                     \
    X(const tint::Program*, inputProgram)                                       \
    X(std::string_view, entryPointName)                                         \
    X(SingleShaderStage, stage)                                                 \
    X(uint32_t, shaderModel)                                                    \
    X(uint32_t, compileFlags)                                                   \
    X(Compiler, compiler)                                                       \
    X(uint64_t, compilerVersion)                                                \
    X(std::wstring_view, dxcShaderProfile)                                      \
    X(std::string_view, fxcShaderProfile)                                       \
    X(pD3DCompile, d3dCompile)                                                  \
    X(IDxcLibrary*, dxcLibrary)                                                 \
    X(IDxcCompiler*, dxcCompiler)                                               \
    X(uint32_t, firstIndexOffsetShaderRegister)                                 \
    X(uint32_t, firstIndexOffsetRegisterSpace)                                  \
    X(bool, usesNumWorkgroups)                                                  \
    X(uint32_t, numWorkgroupsShaderRegister)                                    \
    X(uint32_t, numWorkgroupsRegisterSpace)                                     \
    X(DefineStrings, defineStrings)                                             \
    X(tint::transform::MultiplanarExternalTexture::BindingsMap, newBindingsMap) \
    X(tint::writer::ArrayLengthFromUniformOptions, arrayLengthFromUniform)      \
    X(tint::transform::BindingRemapper::BindingPoints, remappedBindingPoints)   \
    X(tint::transform::BindingRemapper::AccessControls, remappedAccessControls) \
    X(bool, disableSymbolRenaming)                                              \
    X(bool, isRobustnessEnabled)                                                \
    X(bool, disableWorkgroupInit)                                               \
    X(bool, dumpShaders)

#define D3D_BYTECODE_COMPILATION_REQUEST_MEMBERS(X) \
    X(bool, hasShaderFloat16Feature)                \
    X(uint32_t, compileFlags)                       \
    X(Compiler, compiler)                           \
    X(uint64_t, compilerVersion)                    \
    X(std::wstring_view, dxcShaderProfile)          \
    X(std::string_view, fxcShaderProfile)           \
    X(pD3DCompile, d3dCompile)                      \
    X(IDxcLibrary*, dxcLibrary)                     \
    X(IDxcCompiler*, dxcCompiler)                   \
    X(DefineStrings, defineStrings)

DAWN_SERIALIZABLE(struct, HlslCompilationRequest, HLSL_COMPILATION_REQUEST_MEMBERS){};
#undef HLSL_COMPILATION_REQUEST_MEMBERS

DAWN_SERIALIZABLE(struct,
                  D3DBytecodeCompilationRequest,
                  D3D_BYTECODE_COMPILATION_REQUEST_MEMBERS){};
#undef D3D_BYTECODE_COMPILATION_REQUEST_MEMBERS

#define D3D_COMPILATION_REQUEST_MEMBERS(X)     \
    X(HlslCompilationRequest, hlsl)            \
    X(D3DBytecodeCompilationRequest, bytecode) \
    X(CacheKey::UnsafeUnkeyedValue<dawn::platform::Platform*>, tracePlatform)

DAWN_MAKE_CACHE_REQUEST(D3DCompilationRequest, D3D_COMPILATION_REQUEST_MEMBERS);
#undef D3D_COMPILATION_REQUEST_MEMBERS

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(const D3DBytecodeCompilationRequest& r,
                                                 const std::string& entryPointName,
                                                 const std::string& hlslSource) {
    ComPtr<IDxcBlobEncoding> sourceBlob;
    DAWN_TRY(CheckHRESULT(r.dxcLibrary->CreateBlobWithEncodingFromPinned(
                              hlslSource.c_str(), hlslSource.length(), CP_UTF8, &sourceBlob),
                          "DXC create blob"));

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

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

    // Build defines for overridable constants
    std::vector<std::pair<std::wstring, std::wstring>> defineStrings;
    defineStrings.reserve(r.defineStrings.size());
    for (const auto& [name, value] : r.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(
        r.dxcCompiler->Compile(sourceBlob.Get(), nullptr, entryPointW.c_str(),
                               r.dxcShaderProfile.data(), 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_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 D3DBytecodeCompilationRequest& r,
                                                 const std::string& entryPointName,
                                                 const std::string& hlslSource) {
    ComPtr<ID3DBlob> compiledShader;
    ComPtr<ID3DBlob> errors;

    // Build defines for overridable constants
    const D3D_SHADER_MACRO* pDefines = nullptr;
    std::vector<D3D_SHADER_MACRO> fxcDefines;
    if (r.defineStrings.size() > 0) {
        fxcDefines.reserve(r.defineStrings.size() + 1);
        for (const auto& [name, value] : r.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(r.d3dCompile(hlslSource.c_str(), hlslSource.length(), nullptr, pDefines,
                                        nullptr, entryPointName.c_str(), r.fxcShaderProfile.data(),
                                        r.compileFlags, 0, &compiledShader, &errors)),
                    "D3D compile failed with: %s", static_cast<char*>(errors->GetBufferPointer()));

    return std::move(compiledShader);
}

ResultOrError<std::string> TranslateToHLSL(
    HlslCompilationRequest r,
    CacheKey::UnsafeUnkeyedValue<dawn::platform::Platform*> tracePlatform,
    std::string* remappedEntryPointName,
    bool* usesVertexOrInstanceIndex) {
    std::ostringstream errorStream;
    errorStream << "Tint HLSL failure:" << std::endl;

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

    if (!r.newBindingsMap.empty()) {
        transformManager.Add<tint::transform::MultiplanarExternalTexture>();
        transformInputs.Add<tint::transform::MultiplanarExternalTexture::NewBindingPoints>(
            std::move(r.newBindingsMap));
    }

    if (r.stage == SingleShaderStage::Vertex) {
        transformManager.Add<tint::transform::FirstIndexOffset>();
        transformInputs.Add<tint::transform::FirstIndexOffset::BindingPoint>(
            r.firstIndexOffsetShaderRegister, r.firstIndexOffsetRegisterSpace);
    }

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

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

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

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

    if (r.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(r.remappedBindingPoints), std::move(r.remappedAccessControls), mayCollide);

    tint::Program transformedProgram;
    tint::transform::DataMap transformOutputs;
    {
        TRACE_EVENT0(tracePlatform.UnsafeGetValue(), General, "RunTransforms");
        DAWN_TRY_ASSIGN(transformedProgram,
                        RunTransforms(&transformManager, r.inputProgram, transformInputs,
                                      &transformOutputs, nullptr));
    }

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

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

    if (r.stage == SingleShaderStage::Vertex) {
        if (auto* data = transformOutputs.Get<tint::transform::FirstIndexOffset::Data>()) {
            *usesVertexOrInstanceIndex = data->has_vertex_or_instance_index;
        } else {
            return DAWN_VALIDATION_ERROR("Transform output missing first index offset data.");
        }
    }

    tint::writer::hlsl::Options options;
    options.disable_workgroup_init = r.disableWorkgroupInit;
    if (r.usesNumWorkgroups) {
        options.root_constant_binding_point =
            tint::sem::BindingPoint{r.numWorkgroupsRegisterSpace, r.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 = r.arrayLengthFromUniform;
    TRACE_EVENT0(tracePlatform.UnsafeGetValue(), General, "tint::writer::hlsl::Generate");
    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);
}

ResultOrError<CompiledShader> CompileShader(D3DCompilationRequest r) {
    CompiledShader compiledShader;
    // Compile the source shader to HLSL.
    std::string remappedEntryPoint;
    DAWN_TRY_ASSIGN(compiledShader.hlslSource,
                    TranslateToHLSL(std::move(r.hlsl), r.tracePlatform, &remappedEntryPoint,
                                    &compiledShader.usesVertexOrInstanceIndex));

    switch (r.bytecode.compiler) {
        case Compiler::DXC: {
            TRACE_EVENT0(r.tracePlatform.UnsafeGetValue(), General, "CompileShaderDXC");
            ComPtr<IDxcBlob> compiledDXCShader;
            DAWN_TRY_ASSIGN(compiledDXCShader, CompileShaderDXC(r.bytecode, remappedEntryPoint,
                                                                compiledShader.hlslSource));
            compiledShader.shaderBlob = CreateBlob(std::move(compiledDXCShader));
            break;
        }
        case Compiler::FXC: {
            TRACE_EVENT0(r.tracePlatform.UnsafeGetValue(), General, "CompileShaderFXC");
            ComPtr<ID3DBlob> compiledFXCShader;
            DAWN_TRY_ASSIGN(compiledFXCShader, CompileShaderFXC(r.bytecode, remappedEntryPoint,
                                                                compiledShader.hlslSource));
            compiledShader.shaderBlob = CreateBlob(std::move(compiledFXCShader));
            break;
        }
    }

    // If dumpShaders is false, we don't need the HLSL for logging. Clear the contents so it
    // isn't stored into the cache.
    if (!r.hlsl.dumpShaders) {
        compiledShader.hlslSource = "";
    }
    return compiledShader;
}

}  // anonymous namespace

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

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

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

ResultOrError<CompiledShader> ShaderModule::Compile(const ProgrammableStage& programmableStage,
                                                    SingleShaderStage stage,
                                                    const PipelineLayout* layout,
                                                    uint32_t compileFlags) {
    Device* device = ToBackend(GetDevice());
    TRACE_EVENT0(device->GetPlatform(), General, "ShaderModuleD3D12::Compile");
    ASSERT(!IsError());

    ScopedTintICEHandler scopedICEHandler(device);
    const EntryPointMetadata& entryPoint = GetEntryPoint(programmableStage.entryPoint);

    D3DCompilationRequest req = {};
    req.tracePlatform = UnsafeUnkeyedValue(device->GetPlatform());
    req.hlsl.shaderModel = device->GetDeviceInfo().shaderModel;
    req.hlsl.disableSymbolRenaming = device->IsToggleEnabled(Toggle::DisableSymbolRenaming);
    req.hlsl.isRobustnessEnabled = device->IsRobustnessEnabled();
    req.hlsl.disableWorkgroupInit = device->IsToggleEnabled(Toggle::DisableWorkgroupInit);
    req.hlsl.dumpShaders = device->IsToggleEnabled(Toggle::DumpShaders);

    req.bytecode.hasShaderFloat16Feature = device->IsFeatureEnabled(Feature::ShaderFloat16);
    req.bytecode.compileFlags = compileFlags;
    req.bytecode.defineStrings =
        GetOverridableConstantsDefines(programmableStage.constants, entryPoint.overrides);
    if (device->IsToggleEnabled(Toggle::UseDXC)) {
        req.bytecode.compiler = Compiler::DXC;
        req.bytecode.dxcLibrary = device->GetDxcLibrary().Get();
        req.bytecode.dxcCompiler = device->GetDxcCompiler().Get();
        DAWN_TRY_ASSIGN(req.bytecode.compilerVersion,
                        ToBackend(device->GetAdapter())->GetBackend()->GetDXCompilerVersion());
        req.bytecode.dxcShaderProfile = device->GetDeviceInfo().shaderProfiles[stage];
    } else {
        req.bytecode.compiler = Compiler::FXC;
        req.bytecode.d3dCompile = device->GetFunctions()->d3dCompile;
        req.bytecode.compilerVersion = D3D_COMPILER_VERSION;
        switch (stage) {
            case SingleShaderStage::Vertex:
                req.bytecode.fxcShaderProfile = "vs_5_1";
                break;
            case SingleShaderStage::Fragment:
                req.bytecode.fxcShaderProfile = "ps_5_1";
                break;
            case SingleShaderStage::Compute:
                req.bytecode.fxcShaderProfile = "cs_5_1";
                break;
        }
    }

    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);
            }
        }
    }

    req.hlsl.inputProgram = GetTintProgram();
    req.hlsl.entryPointName = programmableStage.entryPoint.c_str();
    req.hlsl.stage = stage;
    req.hlsl.firstIndexOffsetShaderRegister = layout->GetFirstIndexOffsetShaderRegister();
    req.hlsl.firstIndexOffsetRegisterSpace = layout->GetFirstIndexOffsetRegisterSpace();
    req.hlsl.usesNumWorkgroups = entryPoint.usesNumWorkgroups;
    req.hlsl.numWorkgroupsShaderRegister = layout->GetNumWorkgroupsShaderRegister();
    req.hlsl.numWorkgroupsRegisterSpace = layout->GetNumWorkgroupsRegisterSpace();
    req.hlsl.remappedBindingPoints = std::move(remappedBindingPoints);
    req.hlsl.remappedAccessControls = std::move(remappedAccessControls);
    req.hlsl.newBindingsMap = BuildExternalTextureTransformBindings(layout);
    req.hlsl.arrayLengthFromUniform = std::move(arrayLengthFromUniform);

    CacheResult<CompiledShader> compiledShader;
    DAWN_TRY_LOAD_OR_RUN(compiledShader, device, std::move(req), CompiledShader::FromBlob,
                         CompileShader);

    if (device->IsToggleEnabled(Toggle::DumpShaders)) {
        std::ostringstream dumpedMsg;
        dumpedMsg << "/* Dumped generated HLSL */" << std::endl
                  << compiledShader->hlslSource << std::endl;
        device->EmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str());

        if (device->IsToggleEnabled(Toggle::UseDXC)) {
            dumpedMsg << "/* Dumped disassembled DXIL */" << std::endl;
            D3D12_SHADER_BYTECODE code = compiledShader->GetD3D12ShaderBytecode();
            ComPtr<IDxcBlobEncoding> dxcBlob;
            ComPtr<IDxcBlobEncoding> disassembly;
            if (FAILED(device->GetDxcLibrary()->CreateBlobWithEncodingFromPinned(
                    code.pShaderBytecode, code.BytecodeLength, 0, &dxcBlob)) ||
                FAILED(device->GetDxcCompiler()->Disassemble(dxcBlob.Get(), &disassembly))) {
                dumpedMsg << "DXC disassemble failed" << std::endl;
            } else {
                dumpedMsg << std::string_view(
                    static_cast<const char*>(disassembly->GetBufferPointer()),
                    disassembly->GetBufferSize());
            }
        } else {
            dumpedMsg << "/* FXC compile flags */ " << std::endl
                      << CompileFlagsToStringFXC(compileFlags) << std::endl;
            dumpedMsg << "/* Dumped disassembled DXBC */" << std::endl;
            ComPtr<ID3DBlob> disassembly;
            D3D12_SHADER_BYTECODE code = compiledShader->GetD3D12ShaderBytecode();
            if (FAILED(device->GetFunctions()->d3dDisassemble(
                    code.pShaderBytecode, code.BytecodeLength, 0, nullptr, &disassembly))) {
                dumpedMsg << "D3D disassemble failed" << std::endl;
            } else {
                dumpedMsg << std::string_view(
                    static_cast<const char*>(disassembly->GetBufferPointer()),
                    disassembly->GetBufferSize());
            }
        }
        device->EmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str());
    }

    if (BlobCache* cache = device->GetBlobCache()) {
        cache->EnsureStored(compiledShader);
    }

    // Clear the hlslSource. It is only used for logging and should not be used
    // outside of the compilation.
    CompiledShader result = compiledShader.Acquire();
    result.hlslSource = "";
    return result;
}

D3D12_SHADER_BYTECODE CompiledShader::GetD3D12ShaderBytecode() const {
    return {shaderBlob.Data(), shaderBlob.Size()};
}

}  // namespace dawn::native::d3d12
