// Copyright 2023 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dawn/native/d3d11/PhysicalDeviceD3D11.h"

#include <algorithm>
#include <string>
#include <utility>

#include "dawn/common/Constants.h"
#include "dawn/common/GPUInfo.h"
#include "dawn/native/ChainUtils.h"
#include "dawn/native/Instance.h"
#include "dawn/native/d3d/D3DError.h"
#include "dawn/native/d3d11/BackendD3D11.h"
#include "dawn/native/d3d11/DeviceD3D11.h"
#include "dawn/native/d3d11/PlatformFunctionsD3D11.h"
#include "dawn/native/d3d11/UtilsD3D11.h"
#include "dawn/platform/DawnPlatform.h"

namespace dawn::native::d3d11 {

PhysicalDevice::PhysicalDevice(Backend* backend,
                               ComPtr<IDXGIAdapter3> hardwareAdapter,
                               ComPtr<ID3D11Device> d3d11Device)
    : Base(backend, std::move(hardwareAdapter), wgpu::BackendType::D3D11),
      mIsSharedD3D11Device(!!d3d11Device),
      mD3D11Device(std::move(d3d11Device)) {}

PhysicalDevice::~PhysicalDevice() = default;

bool PhysicalDevice::SupportsExternalImages() const {
    return true;
}

bool PhysicalDevice::SupportsFeatureLevel(wgpu::FeatureLevel featureLevel,
                                          InstanceBase* instance) const {
    // TODO(dawn:1820): compare D3D11 feature levels with Dawn feature levels.
    switch (featureLevel) {
        case wgpu::FeatureLevel::Core: {
            return mFeatureLevel >= D3D_FEATURE_LEVEL_11_1;
        }
        case wgpu::FeatureLevel::Compatibility: {
            return mFeatureLevel >= D3D_FEATURE_LEVEL_11_0;
        }
        case wgpu::FeatureLevel::Undefined:
            break;
    }
    DAWN_UNREACHABLE();
}

const DeviceInfo& PhysicalDevice::GetDeviceInfo() const {
    return mDeviceInfo;
}

ResultOrError<ComPtr<ID3D11Device>> PhysicalDevice::CreateD3D11Device(bool enableDebugLayer) {
    if (mIsSharedD3D11Device) {
        DAWN_ASSERT(mD3D11Device);
        return ComPtr<ID3D11Device>(mD3D11Device);
    }

    // If there mD3D11Device which is used for collecting GPU info is not null, try to use it.
    if (mD3D11Device) {
        // Backend validation level doesn't match, recreate the d3d11 device.
        if (enableDebugLayer == IsDebugLayerEnabled(mD3D11Device)) {
            return std::move(mD3D11Device);
        }
        mD3D11Device = nullptr;
    }

    const PlatformFunctions* functions = static_cast<Backend*>(GetBackend())->GetFunctions();
    const D3D_FEATURE_LEVEL featureLevels[] = {D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0};

    ComPtr<ID3D11Device> d3d11Device;

    if (enableDebugLayer) {
        // Try create d3d11 device with debug layer.
        HRESULT hr = functions->d3d11CreateDevice(
            GetHardwareAdapter(), D3D_DRIVER_TYPE_UNKNOWN,
            /*Software=*/nullptr, D3D11_CREATE_DEVICE_DEBUG, featureLevels,
            std::size(featureLevels), D3D11_SDK_VERSION, &d3d11Device,
            /*pFeatureLevel=*/nullptr, /*[out] ppImmediateContext=*/nullptr);

        if (SUCCEEDED(hr)) {
            DAWN_ASSERT(IsDebugLayerEnabled(d3d11Device));
            return d3d11Device;
        }
    }

    DAWN_TRY(CheckHRESULT(functions->d3d11CreateDevice(
                              GetHardwareAdapter(), D3D_DRIVER_TYPE_UNKNOWN,
                              /*Software=*/nullptr, /*Flags=*/0, featureLevels,
                              std::size(featureLevels), D3D11_SDK_VERSION, &d3d11Device,
                              /*pFeatureLevel=*/nullptr, /*[out] ppImmediateContext=*/nullptr),
                          "D3D11CreateDevice failed"));

    return d3d11Device;
}

MaybeError PhysicalDevice::InitializeImpl() {
    DAWN_TRY(Base::InitializeImpl());
    // D3D11 cannot check for feature support without a device.
    // Create the device to populate the adapter properties then reuse it when needed for actual
    // rendering.
    if (!mIsSharedD3D11Device) {
        DAWN_TRY_ASSIGN(mD3D11Device, CreateD3D11Device(/*enableDebugLayers=*/false));
    }

    mFeatureLevel = mD3D11Device->GetFeatureLevel();
    DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(GetHardwareAdapter(), mD3D11Device));

    // Base::InitializeImpl() cannot distinguish between discrete and integrated GPUs, so we need to
    // overwrite it.
    if (mAdapterType == wgpu::AdapterType::DiscreteGPU && mDeviceInfo.isUMA) {
        mAdapterType = wgpu::AdapterType::IntegratedGPU;
    }

    return {};
}

void PhysicalDevice::InitializeSupportedFeaturesImpl() {
    EnableFeature(Feature::Depth32FloatStencil8);
    EnableFeature(Feature::DepthClipControl);
    EnableFeature(Feature::TextureCompressionBC);
    EnableFeature(Feature::TextureCompressionBCSliced3D);
    EnableFeature(Feature::D3D11MultithreadProtected);
    EnableFeature(Feature::Float32Filterable);
    EnableFeature(Feature::Float32Blendable);
    EnableFeature(Feature::DualSourceBlending);
    EnableFeature(Feature::ClipDistances);
    EnableFeature(Feature::Unorm16TextureFormats);
    EnableFeature(Feature::Unorm16Filterable);
    EnableFeature(Feature::Unorm16FormatsForExternalTexture);
    EnableFeature(Feature::AdapterPropertiesMemoryHeaps);
    EnableFeature(Feature::AdapterPropertiesD3D);
    EnableFeature(Feature::ShaderModuleCompilationOptions);
    EnableFeature(Feature::DawnLoadResolveTexture);
    EnableFeature(Feature::DawnPartialLoadResolveTexture);
    EnableFeature(Feature::RG11B10UfloatRenderable);
    EnableFeature(Feature::TextureFormatsTier1);
    EnableFeature(Feature::PrimitiveIndex);

    if (mDeviceInfo.isUMA && mDeviceInfo.supportsMapNoOverwriteDynamicBuffers) {
        // With UMA we should allow mapping usages on more type of buffers.
        EnableFeature(Feature::BufferMapExtendedUsages);
    }

    // Multi planar formats are always supported since Feature Level 11.0
    // https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/format-support-for-direct3d-11-0-feature-level-hardware
    EnableFeature(Feature::DawnMultiPlanarFormats);
    EnableFeature(Feature::MultiPlanarFormatP010);
    EnableFeature(Feature::MultiPlanarRenderTargets);

    if (mDeviceInfo.supportsROV) {
        EnableFeature(Feature::PixelLocalStorageCoherent);
    }

    EnableFeature(Feature::SharedTextureMemoryD3D11Texture2D);
    EnableFeature(Feature::SharedTextureMemoryDXGISharedHandle);

    if (mDeviceInfo.supportsMonitoredFence || mDeviceInfo.supportsNonMonitoredFence) {
        EnableFeature(Feature::SharedFenceDXGISharedHandle);
    }

    UINT formatSupport = 0;
    HRESULT hr = mD3D11Device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport);
    DAWN_ASSERT(SUCCEEDED(hr));
    if (formatSupport & D3D11_FORMAT_SUPPORT_TYPED_UNORDERED_ACCESS_VIEW) {
        EnableFeature(Feature::BGRA8UnormStorage);
    }

    EnableFeature(Feature::DawnTexelCopyBufferRowAlignment);
    EnableFeature(Feature::FlexibleTextureViews);
}

MaybeError PhysicalDevice::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
    GetDefaultLimitsForSupportedFeatureLevel(limits);

    // // https://docs.microsoft.com/en-us/windows/win32/direct3d12/hardware-feature-levels

    // Limits that are the same across D3D feature levels
    limits->v1.maxTextureDimension1D = D3D11_REQ_TEXTURE1D_U_DIMENSION;
    limits->v1.maxTextureDimension2D = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
    limits->v1.maxTextureDimension3D = D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
    limits->v1.maxTextureArrayLayers = D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
    // Slot values can be 0-15, inclusive:
    // https://docs.microsoft.com/en-ca/windows/win32/api/d3d11/ns-d3d11-d3d11_input_element_desc
    limits->v1.maxVertexBuffers = 16;
    // Both SV_VertexID and SV_InstanceID will consume vertex input slots.
    limits->v1.maxVertexAttributes = D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT - 2;

    uint32_t maxUAVsAllStages;
    uint32_t maxUAVsPerStage;

    if (mFeatureLevel >= D3D_FEATURE_LEVEL_11_1) {
        // In D3D 11.1, max UAV slots are shared between fragment & vertex stage so divide it by 2
        // to get per stage limit.
        maxUAVsAllStages = D3D11_1_UAV_SLOT_COUNT;
        maxUAVsPerStage = maxUAVsAllStages / 2;
    } else {
        // We don't support feature level < 11.0
        DAWN_INVALID_IF(mFeatureLevel < D3D_FEATURE_LEVEL_11_0, "Unsupported D3D feature level %u",
                        mFeatureLevel);
        // In D3D 11.0, only fragment and compute have UAVs. Vertex doesn't have UAV so we don't
        // need to divide the slot count between fragment & vertex.
        maxUAVsAllStages = D3D11_PS_CS_UAV_REGISTER_COUNT;
        maxUAVsPerStage = maxUAVsAllStages;
    }
    mUAVSlotCount = maxUAVsAllStages;

    // Reserve one slot for builtin constants.
    constexpr uint32_t kReservedCBVSlots = 1;
    limits->v1.maxUniformBuffersPerShaderStage =
        D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - kReservedCBVSlots;

    // Allocate half of the UAVs to storage buffers, and half to storage textures.
    limits->v1.maxStorageTexturesPerShaderStage = maxUAVsPerStage / 2;
    limits->v1.maxStorageBuffersPerShaderStage = maxUAVsPerStage / 2;
    limits->compat.maxStorageTexturesInFragmentStage = limits->v1.maxStorageTexturesPerShaderStage;
    limits->compat.maxStorageBuffersInFragmentStage = limits->v1.maxStorageBuffersPerShaderStage;
    // If the device only has feature level 11.0, technically, vertex stage doesn't have any UAV
    // slot (writable storage buffers). However, since Dawn spec requires that storage buffers must
    // be readonly in VS, it's safe to advertise that we have storage buffers in VS. Readonly
    // storage buffers will use SRV slots which are available in all stages.
    // The same for read-only storage textures in VS.
    limits->compat.maxStorageTexturesInVertexStage = limits->v1.maxStorageTexturesPerShaderStage;
    limits->compat.maxStorageBuffersInVertexStage = limits->v1.maxStorageBuffersPerShaderStage;
    limits->v1.maxSampledTexturesPerShaderStage = D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT;
    limits->v1.maxSamplersPerShaderStage = D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
    limits->v1.maxColorAttachments = D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
    // This is maxColorAttachments times 16, the color format with the largest cost.
    limits->v1.maxColorAttachmentBytesPerSample = D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT * 16;

    limits->v1.maxDynamicUniformBuffersPerPipelineLayout =
        limits->v1.maxUniformBuffersPerShaderStage;
    limits->v1.maxDynamicStorageBuffersPerPipelineLayout =
        limits->v1.maxStorageBuffersPerShaderStage;

    // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-attributes-numthreads
    limits->v1.maxComputeWorkgroupSizeX = D3D11_CS_THREAD_GROUP_MAX_X;
    limits->v1.maxComputeWorkgroupSizeY = D3D11_CS_THREAD_GROUP_MAX_Y;
    limits->v1.maxComputeWorkgroupSizeZ = D3D11_CS_THREAD_GROUP_MAX_Z;
    limits->v1.maxComputeInvocationsPerWorkgroup = D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;

    // https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-dispatch
    limits->v1.maxComputeWorkgroupsPerDimension = D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;

    // https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-downlevel-compute-shaders
    // Thread Group Shared Memory is limited to 16Kb on downlevel hardware. This is less than
    // the 32Kb that is available to Direct3D 11 hardware. D3D12 is also 32kb.
    limits->v1.maxComputeWorkgroupStorageSize = 32768;

    // Max number of "constants" where each constant is a 16-byte float4
    limits->v1.maxUniformBufferBindingSize = D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16;

    if (gpu_info::IsQualcommACPI(GetVendorId()) &&
        gpu_info::GetQualcommACPIGen(GetVendorId(), GetDeviceId()) <
            gpu_info::QualcommACPIGen::Adreno8xx) {
        // Due to hardware limitation, Raw Buffers can only address 2^28 bytes instead of the
        // guaranteed 2^31 bytes.
        limits->v1.maxStorageBufferBindingSize = 1 << 28;
    } else {
        limits->v1.maxStorageBufferBindingSize = kAssumedMaxBufferSize;
    }

    // D3D11 has no documented limit on the buffer size.
    limits->v1.maxBufferSize = kAssumedMaxBufferSize;

    // 1 for SV_Position and 1 for (SV_IsFrontFace OR SV_SampleIndex).
    // See the discussions in https://github.com/gpuweb/gpuweb/issues/1962 for more details.
    limits->v1.maxInterStageShaderVariables = D3D11_PS_INPUT_REGISTER_COUNT - 2;

    // D3D11 uses internal uniform buffers to support immediate data. The space is enough for
    // 64 bytes.
    limits->v1.maxImmediateSize = kMaxImmediateDataBytes;

    // The BlitTextureToBuffer helper requires the alignment to be 4.
    limits->texelCopyBufferRowAlignmentLimits.minTexelCopyBufferRowAlignment = 4;

    // D3D11 Debug layer enforces that when creating a RAW Shader Resource View, the offset of the
    // first element from the start of the buffer must be a multiple of 16 bytes. There is no
    // official document about it but we have to adhere to the debug layer. So set SSBO alignment
    // to 16.
    limits->v1.minStorageBufferOffsetAlignment = 16;

    return {};
}

FeatureValidationResult PhysicalDevice::ValidateFeatureSupportedWithTogglesImpl(
    wgpu::FeatureName feature,
    const TogglesState& toggles) const {
    return {};
}

void PhysicalDevice::SetupBackendAdapterToggles(dawn::platform::Platform* platform,
                                                TogglesState* adapterToggles) const {
    // D3D11 must use FXC, not DXC.
    adapterToggles->ForceSet(Toggle::UseDXC, false);
}

void PhysicalDevice::SetupBackendDeviceToggles(dawn::platform::Platform* platform,
                                               TogglesState* deviceToggles) const {
    // D3D11 can only clear RTV with float values.
    deviceToggles->Default(Toggle::ApplyClearBigIntegerColorValueWithDraw, true);
    deviceToggles->Default(Toggle::UseBlitForBufferToStencilTextureCopy, true);
    if (!mDeviceInfo.supportsMonitoredFence) {
        deviceToggles->Default(Toggle::D3D11UseUnmonitoredFence,
                               mDeviceInfo.supportsNonMonitoredFence);
        deviceToggles->ForceSet(Toggle::D3D11DisableFence, !mDeviceInfo.supportsNonMonitoredFence);
    }
    deviceToggles->Default(Toggle::UseBlitForT2B, true);
    deviceToggles->Default(Toggle::UseBlitForB2T, true);

    auto deviceId = GetDeviceId();
    auto vendorId = GetVendorId();
    // D3D11 ClearRenderTargetView() could be buggy with some old driver or GPUs. Intel Gen12+ GPUs
    // don't have the problem.
    // https://crbug.com/329702368
    //
    // The workaround still can't cover lazy clear,
    // TODO(crbug.com/364834368): Move handling of workaround at command submission time instead of
    // recording time.
    if (gpu_info::IsIntel(vendorId) &&
        gpu_info::GetIntelGen(vendorId, deviceId) <= gpu_info::IntelGen::Gen11) {
        deviceToggles->Default(Toggle::ClearColorWithDraw, true);
    }

    // TODO(crbug.com/458062283): older intel drivers seems to produce buggy shaders. Especially if
    // they are very complex. Current workaround is disable FXC optimizations.
    if (gpu_info::IsIntel(vendorId) &&
        gpu_info::GetIntelGen(vendorId, deviceId) <= gpu_info::IntelGen::Gen9) {
        const gpu_info::IntelWindowsDriverVersion kKnownGoodDriverVersion = {31, 0, 101, 2121};
        if (gpu_info::IntelWindowsDriverVersion(GetDriverVersion()) < kKnownGoodDriverVersion) {
            deviceToggles->Default(Toggle::D3DSkipShaderOptimizations, true);
        }
    }

    // Enable the integer range analysis for shader robustness by default if the corresponding
    // platform feature is enabled.
    deviceToggles->Default(
        Toggle::EnableIntegerRangeAnalysisInRobustness,
        platform->IsFeatureEnabled(platform::Features::kWebGPUEnableRangeAnalysisForRobustness));

    // TODO(crbug.com/454782021): hang on Qualcomm Adreno X1.
    if (gpu_info::IsQualcommACPI(vendorId)) {
        deviceToggles->ForceSet(Toggle::D3D11DelayFlushToGPU, false);
    }
}

ResultOrError<Ref<DeviceBase>> PhysicalDevice::CreateDeviceImpl(
    AdapterBase* adapter,
    const UnpackedPtr<DeviceDescriptor>& descriptor,
    const TogglesState& deviceToggles,
    Ref<DeviceBase::DeviceLostEvent>&& lostEvent) {
    return Device::Create(adapter, descriptor, deviceToggles, std::move(lostEvent));
}

// Resets the backend device and creates a new one. If any D3D11 objects belonging to the
// current ID3D11Device have not been destroyed, a non-zero value will be returned upon Reset()
// and the subequent call to CreateDevice will return a handle the existing device instead of
// creating a new one.
MaybeError PhysicalDevice::ResetInternalDeviceForTestingImpl() {
    [[maybe_unused]] auto refCount = mD3D11Device.Reset();
    DAWN_ASSERT(refCount == 0);
    DAWN_TRY(Initialize());

    return {};
}

void PhysicalDevice::PopulateBackendProperties(UnpackedPtr<AdapterInfo>& info,
                                               const TogglesState&) const {
    if (auto* memoryHeapProperties = info.Get<AdapterPropertiesMemoryHeaps>()) {
        // https://microsoft.github.io/DirectX-Specs/d3d/D3D12GPUUploadHeaps.html describes
        // the properties of D3D12 Default/Upload/Readback heaps. The assumption is that these are
        // roughly how D3D11 allocates memory has well.
        if (mDeviceInfo.isUMA) {
            auto* heapInfo = new MemoryHeapInfo[1];
            memoryHeapProperties->heapCount = 1;
            memoryHeapProperties->heapInfo = heapInfo;

            heapInfo[0].size =
                std::max(mDeviceInfo.dedicatedVideoMemory, mDeviceInfo.sharedSystemMemory);
            heapInfo[0].properties =
                wgpu::HeapProperty::DeviceLocal | wgpu::HeapProperty::HostVisible |
                wgpu::HeapProperty::HostUncached | wgpu::HeapProperty::HostCached;
        } else {
            auto* heapInfo = new MemoryHeapInfo[2];
            memoryHeapProperties->heapCount = 2;
            memoryHeapProperties->heapInfo = heapInfo;

            heapInfo[0].size = mDeviceInfo.dedicatedVideoMemory;
            heapInfo[0].properties = wgpu::HeapProperty::DeviceLocal;

            heapInfo[1].size = mDeviceInfo.sharedSystemMemory;
            heapInfo[1].properties =
                wgpu::HeapProperty::HostVisible | wgpu::HeapProperty::HostCoherent |
                wgpu::HeapProperty::HostUncached | wgpu::HeapProperty::HostCached;
        }
    }
    if (auto* d3dProperties = info.Get<AdapterPropertiesD3D>()) {
        d3dProperties->shaderModel = GetDeviceInfo().shaderModel;
    }
}

}  // namespace dawn::native::d3d11
