// Copyright 2025 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 "src/dawn/native/webgpu/DeviceWGPU.h"

#include <string>
#include <utility>

#include "src/dawn/common/Constants.h"
#include "src/dawn/common/StringViewUtils.h"
#include "src/dawn/native/BackendConnection.h"
#include "src/dawn/native/BindGroupLayoutInternal.h"
#include "src/dawn/native/Buffer.h"
#include "src/dawn/native/ChainUtils.h"
#include "src/dawn/native/CommandBuffer.h"
#include "src/dawn/native/CommandEncoder.h"
#include "src/dawn/native/ErrorData.h"
#include "src/dawn/native/Instance.h"
#include "src/dawn/native/PhysicalDevice.h"
#include "src/dawn/native/QuerySet.h"
#include "src/dawn/native/Queue.h"
#include "src/dawn/native/Surface.h"
#include "src/dawn/native/SwapChain.h"
#include "src/dawn/native/Texture.h"
#include "src/dawn/native/webgpu/BackendWGPU.h"
#include "src/dawn/native/webgpu/BindGroupLayoutWGPU.h"
#include "src/dawn/native/webgpu/BindGroupWGPU.h"
#include "src/dawn/native/webgpu/BufferWGPU.h"
#include "src/dawn/native/webgpu/CaptureContext.h"
#include "src/dawn/native/webgpu/CommandBufferWGPU.h"
#include "src/dawn/native/webgpu/ComputePipelineWGPU.h"
#include "src/dawn/native/webgpu/ExternalTextureWGPU.h"
#include "src/dawn/native/webgpu/PhysicalDeviceWGPU.h"
#include "src/dawn/native/webgpu/PipelineLayoutWGPU.h"
#include "src/dawn/native/webgpu/QuerySetWGPU.h"
#include "src/dawn/native/webgpu/QueueWGPU.h"
#include "src/dawn/native/webgpu/RenderBundleWGPU.h"
#include "src/dawn/native/webgpu/RenderPipelineWGPU.h"
#include "src/dawn/native/webgpu/SamplerWGPU.h"
#include "src/dawn/native/webgpu/ShaderModuleWGPU.h"
#include "src/dawn/native/webgpu/SharedFenceWGPU.h"
#include "src/dawn/native/webgpu/SharedTextureMemoryWGPU.h"
#include "src/dawn/native/webgpu/SwapChainWGPU.h"
#include "src/dawn/native/webgpu/TextureWGPU.h"
#include "src/dawn/native/webgpu/ToWGPU.h"
#include "src/utils/log.h"
#include "src/utils/numeric.h"
#include "tint/tint.h"

namespace dawn::native::webgpu {

namespace {

// Toggles in this list are the only ones with ToggleStage::Device that enabled in webgpu::Device.
// Other toggles are only passed down to the inner device.
constexpr Toggle kOuterToggles[] = {
    // Toggles webgpu::Device needs
    Toggle::SkipValidation,
    Toggle::DisableBaseVertex,
    Toggle::DisableBindGroupLayoutEntryArraySize,
    Toggle::EnableImmediateErrorHandling,
    Toggle::EnableTintIRValidationAsserts,

    // Toggles enabled by default for all backend, do not force set them to avoid warnings.
    Toggle::LazyClearResourceOnFirstUse,
    Toggle::TimestampQuantization,
    Toggle::BlobCacheHashValidation,
    Toggle::UseUserDefinedLabelsInBackend,
};

}  // namespace

// static
ResultOrError<Ref<Device>> Device::Create(AdapterBase* adapter,
                                          WGPUAdapter innerAdapter,
                                          const UnpackedPtr<DeviceDescriptor>& descriptor,
                                          const TogglesState& deviceToggles,
                                          Ref<DeviceBase::DeviceLostEvent>&& lostEvent) {
    TogglesState outerDeviceToggles = deviceToggles;

    // For the inner device, we want to enable the toggles if they are enabled in deviceToggles.
    // TogglesState deviceToggles already has them resolved.

    // For outer (this webgpu::Device), we want to disable everything else.
    for (size_t i : deviceToggles.GetEnabledToggles()) {
        Toggle t = static_cast<Toggle>(i);
        const ToggleInfo* info = TogglesInfo::GetToggleInfo(t);

        if (info->stage != ToggleStage::Device) {
            // Bypass any force settings if not a device stage toggle.
            continue;
        }

        bool isOuter = false;
        for (Toggle outer : kOuterToggles) {
            if (t == outer) {
                isOuter = true;
                break;
            }
        }
        if (!isOuter) {
            outerDeviceToggles.ForceSet(t, false);
        }
    }

    Ref<Device> device =
        AcquireRef(new Device(adapter, innerAdapter, descriptor, outerDeviceToggles, deviceToggles,
                              std::move(lostEvent)));
    DAWN_TRY(device->Initialize(descriptor));
    return device;
}

Device::Device(AdapterBase* adapter,
               WGPUAdapter innerAdapter,
               const UnpackedPtr<DeviceDescriptor>& descriptor,
               const TogglesState& deviceToggles,
               const TogglesState& innerDeviceToggles,
               Ref<DeviceBase::DeviceLostEvent>&& lostEvent)
    : DeviceBase(adapter, descriptor, deviceToggles, std::move(lostEvent)),
      ObjectWGPU(ToBackend(adapter->GetPhysicalDevice())->GetFunctions().deviceRelease),
      wgpu(ToBackend(adapter->GetPhysicalDevice())->GetFunctions()) {
    DAWN_ASSERT(adapter->GetPhysicalDevice()->GetBackendType() == wgpu::BackendType::WebGPU);

    WGPUDeviceDescriptor apiDesc = *(ToAPI(*descriptor));
    std::string label = "Inner Device on " + adapter->GetPhysicalDevice()->GetName();
    apiDesc.label = ToOutputStringView(label);

    WGPUDawnTogglesDescriptor apiToggleDescriptor = WGPU_DAWN_TOGGLES_DESCRIPTOR_INIT;

    apiDesc.nextInChain = nullptr;
    auto enabledTogglesName = innerDeviceToggles.GetEnabledToggleNames();
    // enable so we can capture the depth aspect of depth24plus and depth24plusStencil8
    enabledTogglesName.push_back("use_blit_for_depth24plus_texture_to_buffer_copy");
    apiToggleDescriptor.enabledToggleCount = enabledTogglesName.size();
    apiToggleDescriptor.enabledToggles = enabledTogglesName.data();

    auto disabledTogglesName = innerDeviceToggles.GetDisabledToggleNames();
    apiToggleDescriptor.disabledToggleCount = disabledTogglesName.size();
    apiToggleDescriptor.disabledToggles = disabledTogglesName.data();

    apiDesc.nextInChain = &apiToggleDescriptor.chain;

    // Acquire a Ref to the outer webgpu::Device to avoid possible dangling pointer in the callback.
    Ref<Device>* outerDeviceRef = new Ref<Device>(this);
    apiDesc.deviceLostCallbackInfo = {
        nullptr, WGPUCallbackMode_AllowProcessEvents,
        [](WGPUDevice const*, WGPUDeviceLostReason reason, WGPUStringView message, void*,
           void* outerDeviceRef) {
            Ref<Device>* deviceWGPURef = reinterpret_cast<Ref<Device>*>(outerDeviceRef);
            Device* deviceWGPU = deviceWGPURef->Get();
            if (reason == WGPUDeviceLostReason_Unknown) {
                // Internal crash of the implementation device, call device lost callback of the
                // upper DeviceWGPU
                if (!deviceWGPU->IsLost()) {
                    deviceWGPU->APIForceLoss(FromAPI(reason), message);
                }
            }
            delete deviceWGPURef;
        },
        nullptr, reinterpret_cast<void*>(outerDeviceRef)};
    // TODO(crbug.com/413053623): revisit for error scope.
    apiDesc.uncapturedErrorCallbackInfo = {
        nullptr,
        [](WGPUDevice const*, WGPUErrorType errorType, WGPUStringView message, void*,
           void* outerDeviceRef) {
            Ref<Device>* deviceWGPURef = reinterpret_cast<Ref<Device>*>(outerDeviceRef);
            Device* deviceWGPU = deviceWGPURef->Get();
            if (!deviceWGPU || deviceWGPU->IsLost()) {
                return;
            }
            deviceWGPU->EmitLog(wgpu::LoggingType::Error, ToString(message));
        },
        nullptr, reinterpret_cast<void*>(outerDeviceRef)};

    // TODO(crbug.com/413053623): use adapterRequestDevice instead as dawn_wire doesn't support
    // adapterCreateDevice.
    mInnerHandle = wgpu->adapterCreateDevice(innerAdapter, &apiDesc);
}

Device::~Device() {
    Destroy(DestroyReason::CppDestructor);
}

WGPUInstance Device::GetInnerInstance() const {
    return ToBackend(GetPhysicalDevice())->GetBackend()->GetInnerInstance();
}

MaybeError Device::Initialize(const UnpackedPtr<DeviceDescriptor>& descriptor) {
    Ref<Queue> queue;
    DAWN_TRY_ASSIGN(queue, Queue::Create(this, &descriptor->defaultQueue));
    return DeviceBase::Initialize(descriptor, std::move(queue));
}

ResultOrError<Ref<BindGroupBase>> Device::CreateBindGroupImpl(
    const UnpackedPtr<BindGroupDescriptor>& descriptor) {
    return BindGroup::Create(this, descriptor);
}
ResultOrError<Ref<BindGroupLayoutInternalBase>> Device::CreateBindGroupLayoutImpl(
    const UnpackedPtr<BindGroupLayoutDescriptor>& descriptor) {
    return BindGroupLayout::Create(this, descriptor);
}
ResultOrError<Ref<BufferBase>> Device::CreateBufferImpl(
    const UnpackedPtr<BufferDescriptor>& descriptor) {
    return Buffer::Create(this, descriptor);
}

ResultOrUnknownError<Ref<ExternalTextureBase>> Device::CreateExternalTextureImpl(
    const ExternalTextureDescriptor* descriptor) {
    return ExternalTexture::Create(this, descriptor);
}

ResultOrError<Ref<CommandBufferBase>> Device::CreateCommandBuffer(
    CommandEncoder* encoder,
    const CommandBufferDescriptor* descriptor) {
    // This is called by CommandEncoder::Finish
    // TODO(crbug.com/413053623): Store CommandEncoderDescriptor and assign here.
    return CommandBuffer::Create(encoder, descriptor);
}
ResultOrError<Ref<RenderBundleBase>> Device::CreateRenderBundle(
    RenderBundleEncoderBase* encoder,
    const RenderBundleDescriptor* descriptor) {
    return RenderBundle::Create(encoder, descriptor, encoder->AcquireRenderPassUsages(),
                                encoder->AcquireIndirectDrawMetadata());
}
Ref<ComputePipelineBase> Device::CreateUninitializedComputePipelineImpl(
    const UnpackedPtr<ComputePipelineDescriptor>& descriptor) {
    return ComputePipeline::CreateUninitialized(this, descriptor);
}

ResultOrError<Ref<PipelineLayoutBase>> Device::CreatePipelineLayoutImpl(
    const UnpackedPtr<PipelineLayoutDescriptor>& descriptor) {
    return PipelineLayout::Create(this, descriptor);
}

ResultOrError<Ref<QuerySetBase>> Device::CreateQuerySetImpl(const QuerySetDescriptor* descriptor) {
    return QuerySet::Create(this, descriptor);
}

Ref<RenderPipelineBase> Device::CreateUninitializedRenderPipelineImpl(
    const UnpackedPtr<RenderPipelineDescriptor>& descriptor) {
    return RenderPipeline::CreateUninitialized(this, descriptor);
}
ResultOrError<Ref<ResourceTableBase>> Device::CreateResourceTableImpl(
    const ResourceTableDescriptor* descriptor) {
    // TODO(https://issues.chromium.org/473442434): Implement resource tables in WebGPUOnWebGPU.
    return DAWN_UNIMPLEMENTED_ERROR("ResourceTable is not implemented in WebGPUOnWebGPU");
}
ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
    return Sampler::Create(this, descriptor);
}
ResultOrError<Ref<ShaderModuleBase>> Device::CreateShaderModuleImpl(
    const UnpackedPtr<ShaderModuleDescriptor>& descriptor,
    const std::vector<tint::wgsl::Extension>& internalExtensions) {
    return ShaderModule::Create(this, descriptor, internalExtensions);
}
ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(Surface* surface,
                                                              SwapChainBase* previousSwapChain,
                                                              const SurfaceConfiguration* config) {
    return SwapChain::Create(this, surface, previousSwapChain, config);
}
ResultOrError<Ref<TextureBase>> Device::CreateTextureImpl(
    const UnpackedPtr<TextureDescriptor>& descriptor) {
    return Texture::Create(this, descriptor);
}
ResultOrError<Ref<TextureViewBase>> Device::CreateTextureViewImpl(
    TextureBase* texture,
    const UnpackedPtr<TextureViewDescriptor>& descriptor) {
    return TextureView::Create(texture, descriptor);
}

ResultOrUnknownError<Ref<SharedTextureMemoryBase>> Device::ImportSharedTextureMemoryImpl(
    UnpackedPtr<SharedTextureMemoryDescriptor> unpacked) {
    // TODO(crbug.com/483147423): Handle all possible chained structures.
    if (unpacked.Get<SharedTextureMemoryIOSurfaceDescriptor>()) {
        auto feature = Feature::SharedTextureMemoryIOSurface;
        DAWN_INVALID_IF(!HasFeature(feature), "%s is not enabled.", ToCppAPI(feature));
    } else if (unpacked.Get<SharedTextureMemoryAHardwareBufferDescriptor>()) {
        return DAWN_UNIMPLEMENTED_ERROR(
            "SharedTextureMemory in WebGPU backend has "
            "not been implemented for all platforms.");
    } else if (unpacked.Get<SharedTextureMemoryDXGISharedHandleDescriptor>()) {
        return DAWN_UNIMPLEMENTED_ERROR(
            "SharedTextureMemory in WebGPU backend has not been implemented for all platforms.");
    } else if (unpacked.Get<SharedTextureMemoryEGLImageDescriptor>()) {
        return DAWN_UNIMPLEMENTED_ERROR(
            "SharedTextureMemory in WebGPU backend has not been implemented for all platforms.");
    } else if (unpacked.Get<SharedTextureMemoryOpaqueFDDescriptor>()) {
        return DAWN_UNIMPLEMENTED_ERROR(
            "SharedTextureMemory in WebGPU backend has not been implemented for all platforms.");
    } else if (unpacked.Get<SharedTextureMemoryVkDedicatedAllocationDescriptor>()) {
        return DAWN_UNIMPLEMENTED_ERROR(
            "SharedTextureMemory in WebGPU backend has not been implemented for all platforms.");
    } else if (unpacked.Get<SharedTextureMemoryZirconHandleDescriptor>()) {
        return DAWN_UNIMPLEMENTED_ERROR(
            "SharedTextureMemory in WebGPU backend has not been implemented for all platforms.");
    } else if (unpacked.Get<SharedTextureMemoryDmaBufDescriptor>()) {
        return DAWN_UNIMPLEMENTED_ERROR(
            "SharedTextureMemory in WebGPU backend has not been implemented for all platforms.");
    } else {
        return DAWN_VALIDATION_ERROR("SharedTextureMemory chain is missing.");
    }

    // ValidateSubset pass for none, fail for invalid if exists.
    DAWN_TRY((unpacked.ValidateSubset<
              SharedTextureMemoryIOSurfaceDescriptor, SharedTextureMemoryAHardwareBufferDescriptor,
              SharedTextureMemoryDXGISharedHandleDescriptor, SharedTextureMemoryEGLImageDescriptor,
              SharedTextureMemoryOpaqueFDDescriptor,
              SharedTextureMemoryVkDedicatedAllocationDescriptor,
              SharedTextureMemoryZirconHandleDescriptor, SharedTextureMemoryDmaBufDescriptor>()));

    return SharedTextureMemory::Create(this, unpacked);
}

ResultOrUnknownError<Ref<SharedFenceBase>> Device::ImportSharedFenceImpl(
    UnpackedPtr<SharedFenceDescriptor> unpacked) {
    // TODO(crbug.com/483147423): Handle all possible chained structures.
    if (unpacked.Get<SharedFenceMTLSharedEventDescriptor>()) {
        auto feature = Feature::SharedFenceMTLSharedEvent;
        DAWN_INVALID_IF(!HasFeature(feature), "%s is not enabled.", ToCppAPI(feature));
    } else if (unpacked.Get<SharedFenceDXGISharedHandleDescriptor>()) {
        return DAWN_UNIMPLEMENTED_ERROR(
            "SharedFence in WebGPU backend has not been implemented for all platforms.");
    } else if (unpacked.Get<SharedFenceEGLSyncDescriptor>()) {
        return DAWN_UNIMPLEMENTED_ERROR(
            "SharedFence in WebGPU backend has not been implemented for all platforms.");
    } else if (unpacked.Get<SharedFenceSyncFDDescriptor>()) {
        return DAWN_UNIMPLEMENTED_ERROR(
            "SharedFence in WebGPU backend has not been implemented for all platforms.");
    } else if (unpacked.Get<SharedFenceVkSemaphoreOpaqueFDDescriptor>()) {
        return DAWN_UNIMPLEMENTED_ERROR(
            "SharedFence in WebGPU backend has not been implemented for all platforms.");
    } else if (unpacked.Get<SharedFenceVkSemaphoreZirconHandleDescriptor>()) {
        return DAWN_UNIMPLEMENTED_ERROR(
            "SharedFence in WebGPU backend has not been implemented for all platforms.");
    } else {
        return DAWN_VALIDATION_ERROR("SharedFence chain is missing.");
    }

    // ValidateSubset pass for none, fail for invalid if exists.
    DAWN_TRY((
        unpacked.ValidateSubset<SharedFenceMTLSharedEventDescriptor,
                                SharedFenceDXGISharedHandleDescriptor, SharedFenceEGLSyncDescriptor,
                                SharedFenceVkSemaphoreOpaqueFDDescriptor,
                                SharedFenceVkSemaphoreZirconHandleDescriptor>()));

    return SharedFence::Create(this, unpacked);
}

void Device::DestroyImpl(DestroyReason reason) {
    DAWN_ASSERT(GetState() == State::Disconnected);
    // TODO(crbug.com/dawn/831): DestroyImpl is called from two places.
    // - It may be called if the device is explicitly destroyed with APIDestroy.
    //   This case is NOT thread-safe and needs proper synchronization with other
    //   simultaneous uses of the device.
    // - It may be called when the last ref to the device is dropped and the device
    //   is implicitly destroyed. This case is thread-safe because there are no
    //   other threads using the device since there are no other live refs.

    if (ToBackend(GetQueue())->IsCapturing()) {
        EndCapture();
    }

    if (mInnerHandle) {
        wgpu->deviceDestroy(mInnerHandle);
    }
}

void Device::SetLabelImpl() {
    CaptureSetLabel(this, GetLabel());
}

MaybeError Device::CopyFromStagingToBuffer(BufferBase* source,
                                           uint64_t sourceOffset,
                                           BufferBase* destination,
                                           uint64_t destinationOffset,
                                           uint64_t size) {
    wgpu->queueWriteBuffer(
        ToBackend(GetQueue())->GetInnerHandle(), ToBackend(destination)->GetInnerHandle(),
        sourceOffset,
        // The staging buffers in the DynamicUploader are assumed in Dawn to be persistently mapped
        // buffers that always have the mapped pointer accessible. n the WebGPU backend, to use the
        // buffers in a copyB2B we would need to unmap them but the DynamicUploader doesn't support
        // that. Instead keep the buffers mapped and use queueWriteBuffer to read directly from the
        // mapped staging memory.
        wgpu->bufferGetConstMappedRange(ToBackend(source)->GetInnerHandle(), 0,
                                        checked_cast<size_t>(source->GetSize())),
        checked_cast<size_t>(size));
    return {};
}

MaybeError Device::CopyFromStagingToTextureImpl(BufferBase* source,
                                                const TexelCopyBufferLayout& src,
                                                const TextureCopy& dst,
                                                const Extent3D& copySizePixels) {
    WGPUTexelCopyBufferLayout innerSource = ToWGPU(src);
    WGPUTexelCopyTextureInfo innerDestination = ToWGPU(dst);
    size_t bufferSize = checked_cast<size_t>(source->GetSize());
    WGPUExtent3D size = ToWGPU(copySizePixels);
    wgpu->queueWriteTexture(
        ToBackend(GetQueue())->GetInnerHandle(), &innerDestination,
        // The staging buffers in the DynamicUploader are assumed in Dawn to be persistently mapped
        // buffers that always have the mapped pointer accessible. n the WebGPU backend, to use the
        // buffers in a copyB2T we would need to unmap them but the DynamicUploader doesn't support
        // that. Instead keep the buffers mapped and use queueWriteTexture to read directly from the
        // mapped staging memory.
        wgpu->bufferGetConstMappedRange(ToBackend(source)->GetInnerHandle(), 0, bufferSize),
        bufferSize, &innerSource, &size);
    return {};
}

MaybeError Device::TickImpl() {
    wgpu->deviceTick(mInnerHandle);
    return {};
}

uint32_t Device::GetOptimalBytesPerRowAlignment() const {
    return kTextureBytesPerRowAlignment;
}

uint64_t Device::GetOptimalBufferToTextureCopyOffsetAlignment() const {
    return 1;
}

float Device::GetTimestampPeriodInNS() const {
    return 1.0f;
}

bool Device::AreTimestampsQuantized() const {
    return true;
}

bool Device::CanResolveSubRect() const {
    // Related code in src/dawn/native/RenderPassWorkaroundsHelper.cpp
    // WebGPU backend will pass down cmd->resolveRect to the inner layer backend to handle it
    // anyways, so return true and do not apply any workarounds here.
    return true;
}

bool Device::NeedsIndirectGPUValidation() const {
    // WebGPU backend never actually dispatch compute pass to validate indirect draw cmds,
    // since the inner backend will take care of it.
    return false;
}

void Device::StartCapture(CaptureStream& commandStream, CaptureStream& contentStream) {
    MaybeValError result = ToBackend(GetQueue())
                               ->SetCaptureContext(std::unique_ptr<CaptureContext>(
                                   new CaptureContext(this, commandStream, contentStream)));
    std::ignore = ConsumedError(std::move(result), "calling %s.StartCapture()", this);
}

void Device::EndCapture() {
    if (ToBackend(GetQueue())->IsCapturing()) {
        MaybeValError result = ToBackend(GetQueue())->SetCaptureContext(nullptr);
        std::ignore = ConsumedError(std::move(result), "calling %s.EndCapture()", this);
    }
}

}  // namespace dawn::native::webgpu
