// Copyright 2017 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/Buffer.h"

#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <utility>

#include "absl/container/flat_hash_map.h"
#include "absl/strings/str_format.h"
#include "dawn/common/Alloc.h"
#include "dawn/common/Assert.h"
#include "dawn/native/Adapter.h"
#include "dawn/native/CallbackTaskManager.h"
#include "dawn/native/ChainUtils.h"
#include "dawn/native/Commands.h"
#include "dawn/native/Device.h"
#include "dawn/native/DynamicUploader.h"
#include "dawn/native/ErrorData.h"
#include "dawn/native/EventManager.h"
#include "dawn/native/Instance.h"
#include "dawn/native/ObjectType_autogen.h"
#include "dawn/native/PhysicalDevice.h"
#include "dawn/native/Queue.h"
#include "dawn/native/SystemEvent.h"
#include "dawn/native/ValidationUtils_autogen.h"
#include "dawn/platform/DawnPlatform.h"
#include "dawn/platform/tracing/TraceEvent.h"
#include "partition_alloc/pointers/raw_ptr.h"

namespace dawn::native {

namespace {
struct MapRequestTask : TrackTaskCallback {
    MapRequestTask(dawn::platform::Platform* platform, Ref<BufferBase> buffer, MapRequestID id)
        : TrackTaskCallback(platform), buffer(std::move(buffer)), id(id) {}
    ~MapRequestTask() override = default;

  private:
    void FinishImpl() override {
        {
            // This is called from a callback, and no lock will be held by default. Hence, we need
            // to lock the mutex now because mSerial might be changed by another thread.
            auto deviceLock(buffer->GetDevice()->GetScopedLock());
            DAWN_ASSERT(mSerial != kMaxExecutionSerial);
            TRACE_EVENT1(mPlatform, General, "Buffer::TaskInFlight::Finished", "serial",
                         uint64_t(mSerial));
        }
        buffer->CallbackOnMapRequestCompleted(id, WGPUBufferMapAsyncStatus_Success);
    }
    void HandleDeviceLossImpl() override {
        buffer->CallbackOnMapRequestCompleted(id, WGPUBufferMapAsyncStatus_DeviceLost);
    }
    void HandleShutDownImpl() override {
        buffer->CallbackOnMapRequestCompleted(id, WGPUBufferMapAsyncStatus_DestroyedBeforeCallback);
    }

    Ref<BufferBase> buffer;
    MapRequestID id;
};

class ErrorBuffer final : public BufferBase {
  public:
    ErrorBuffer(DeviceBase* device, const BufferDescriptor* descriptor)
        : BufferBase(device, descriptor, ObjectBase::kError) {
        if (descriptor->mappedAtCreation) {
            // Check that the size can be used to allocate an mFakeMappedData. A malloc(0)
            // is invalid, and on 32bit systems we should avoid a narrowing conversion that
            // would make size = 1 << 32 + 1 allocate one byte.
            bool isValidSize = descriptor->size != 0 &&
                               descriptor->size < uint64_t(std::numeric_limits<size_t>::max());

            if (isValidSize) {
                mFakeMappedData =
                    std::unique_ptr<uint8_t[]>(AllocNoThrow<uint8_t>(descriptor->size));
            }
            // Since error buffers in this case may allocate memory, we need to track them
            // for destruction on the device.
            GetObjectTrackingList()->Track(this);
        }
    }

  private:
    bool IsCPUWritableAtCreation() const override { DAWN_UNREACHABLE(); }

    MaybeError MapAtCreationImpl() override { DAWN_UNREACHABLE(); }

    MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override {
        DAWN_UNREACHABLE();
    }

    void* GetMappedPointer() override { return mFakeMappedData.get(); }

    void UnmapImpl() override { mFakeMappedData.reset(); }

    std::unique_ptr<uint8_t[]> mFakeMappedData;
};

wgpu::BufferUsage AddInternalUsages(const DeviceBase* device, wgpu::BufferUsage usage) {
    // Add readonly storage usage if the buffer has a storage usage. The validation rules in
    // ValidateSyncScopeResourceUsage will make sure we don't use both at the same time.
    if (usage & wgpu::BufferUsage::Storage) {
        usage |= kReadOnlyStorageBuffer;
    }

    // The query resolve buffer need to be used as a storage buffer in the internal compute
    // pipeline which does timestamp uint conversion for timestamp query, it requires the buffer
    // has Storage usage in the binding group. Implicitly add an InternalStorage usage which is
    // only compatible with InternalStorageBuffer binding type in BGL. It shouldn't be
    // compatible with StorageBuffer binding type and the query resolve buffer cannot be bound
    // as storage buffer if it's created without Storage usage.
    if (usage & wgpu::BufferUsage::QueryResolve) {
        usage |= kInternalStorageBuffer;
    }

    // We also add internal storage usage for Indirect buffers for some transformations before
    // DispatchIndirect calls on the backend (e.g. validations, support of [[num_workgroups]] on
    // D3D12), since these transformations involve binding them as storage buffers for use in a
    // compute pass.
    if (usage & wgpu::BufferUsage::Indirect) {
        usage |= kInternalStorageBuffer;
    }

    if (usage & wgpu::BufferUsage::CopyDst) {
        const bool useComputeForT2B =
            device->IsToggleEnabled(Toggle::UseBlitForDepth16UnormTextureToBufferCopy) ||
            device->IsToggleEnabled(Toggle::UseBlitForDepth32FloatTextureToBufferCopy) ||
            device->IsToggleEnabled(Toggle::UseBlitForStencilTextureToBufferCopy) ||
            device->IsToggleEnabled(Toggle::UseBlitForSnormTextureToBufferCopy) ||
            device->IsToggleEnabled(Toggle::UseBlitForBGRA8UnormTextureToBufferCopy) ||
            device->IsToggleEnabled(Toggle::UseBlitForRGB9E5UfloatTextureCopy) ||
            device->IsToggleEnabled(Toggle::UseBlitForT2B);
        if (useComputeForT2B) {
            if (!(usage & (kMappableBufferUsages | wgpu::BufferUsage::Uniform)) ||
                !device->PreferNotUsingMappableOrUniformBufferAsStorage()) {
                // If buffer doesn't have mapping nor Uniform usage, or backend is ok with using
                // this kind of buffer as storage buffer, we can add Storage usage in order to write
                // to it in compute shader.
                usage |= kInternalStorageBuffer;
            }

            // We also need CopySrc usage in order to copy to a temporary buffer.
            // The temporary buffer is needed in cases when offset doesn't satisfy certain
            // conditions. Or if it's not possible to add kInternalStorageBuffer usage to the
            // buffer.
            usage |= kInternalCopySrcBuffer;
        }
    }

    return usage;
}

// GetMappedRange on a zero-sized buffer returns a pointer to this value.
static uint32_t sZeroSizedMappingData = 0xCAFED00D;

}  // anonymous namespace

struct BufferBase::MapAsyncEvent : public EventManager::TrackedEvent {
    MapAsyncEvent(wgpu::CallbackMode mode, QueueBase* queue, ExecutionSerial serial)
        : TrackedEvent(mode, queue, serial) {}
    // TODO(crbug.com/42241006): Note that currently this constructor is used for errors because a
    // dropped device can result in failure when trying to get the queue. While using this fixes the
    // problem, it causes an unintentional side-effect where it is possible to run into a
    // UnsupportedMixedSource error on WaitAny even if we are only using a single device with
    // MapAsync calls. This will be fixed once we correctly implement mixed sources.
    explicit MapAsyncEvent(wgpu::CallbackMode mode)
        : TrackedEvent(mode, SystemEvent::CreateSignaled()) {}

    virtual void UnmapEarly(wgpu::BufferMapAsyncStatus status) = 0;
};

struct BufferBase::MapAsyncEvent1 final : public BufferBase::MapAsyncEvent {
    // MapAsyncEvent stores a raw pointer to the buffer so that it can
    // update the buffer's map state when it completes.
    // If the map completes early (error, unmap, destroy), then the buffer
    // is no longer needed and we store the early status instead.
    // The raw pointer is safe because the early status is set to destroyed
    // before the buffer is dropped.
    // Note: this could be an atomic + spin lock on a sentinel enum if the mutex
    // cost is high.
    MutexProtected<std::variant<BufferBase*, wgpu::BufferMapAsyncStatus>> mBufferOrEarlyStatus;

    WGPUBufferMapCallback mCallback;
    raw_ptr<void> mUserdata;

    // Create an event backed by the given queue execution serial.
    MapAsyncEvent1(DeviceBase* device,
                   BufferBase* buffer,
                   const BufferMapCallbackInfo& callbackInfo,
                   ExecutionSerial serial)
        : MapAsyncEvent(callbackInfo.mode, device->GetQueue(), serial),
          mBufferOrEarlyStatus(buffer),
          mCallback(callbackInfo.callback),
          mUserdata(callbackInfo.userdata) {
        TRACE_EVENT_ASYNC_BEGIN0(device->GetPlatform(), General, "Buffer::APIMapAsync",
                                 uint64_t(serial));
    }

    // Create an event that's ready at creation (for errors, etc.)
    MapAsyncEvent1(DeviceBase* device,
                   const BufferMapCallbackInfo& callbackInfo,
                   wgpu::BufferMapAsyncStatus earlyStatus)
        : MapAsyncEvent(callbackInfo.mode, device->GetQueue(), kBeginningOfGPUTime),
          mBufferOrEarlyStatus(earlyStatus),
          mCallback(callbackInfo.callback),
          mUserdata(callbackInfo.userdata) {
        TRACE_EVENT_ASYNC_BEGIN0(device->GetPlatform(), General, "Buffer::APIMapAsync",
                                 uint64_t(kBeginningOfGPUTime));
    }

    ~MapAsyncEvent1() override { EnsureComplete(EventCompletionType::Shutdown); }

    void Complete(EventCompletionType completionType) override {
        if (const auto* queueAndSerial = std::get_if<QueueAndSerial>(&GetCompletionData())) {
            TRACE_EVENT_ASYNC_END0(queueAndSerial->queue->GetDevice()->GetPlatform(), General,
                                   "Buffer::APIMapAsync",
                                   uint64_t(queueAndSerial->completionSerial));
        }

        if (completionType == EventCompletionType::Shutdown) {
            mCallback(ToAPI(wgpu::BufferMapAsyncStatus::InstanceDropped), mUserdata);
            return;
        }

        wgpu::BufferMapAsyncStatus status = wgpu::BufferMapAsyncStatus::Success;
        Ref<MapAsyncEvent> pendingMapEvent;

        // Lock the buffer / early status. This may race with UnmapEarly which occurs
        // when the buffer is unmapped or destroyed.
        mBufferOrEarlyStatus.Use([&](auto bufferOrEarlyStatus) {
            if (auto* earlyStatus =
                    std::get_if<wgpu::BufferMapAsyncStatus>(&*bufferOrEarlyStatus)) {
                // Assign the early status, if it was set.
                status = *earlyStatus;
            } else if (auto** buffer = std::get_if<BufferBase*>(&*bufferOrEarlyStatus)) {
                // Set the buffer state to Mapped if this pending map succeeded.
                // TODO(crbug.com/dawn/831): in order to be thread safe, mutation of the
                // state and pending map event needs to be atomic w.r.t. UnmapInternal.
                DAWN_ASSERT((*buffer)->mState == BufferState::PendingMap);
                (*buffer)->mState = BufferState::Mapped;

                pendingMapEvent = std::move((*buffer)->mPendingMapEvent);
            }
        });
        mCallback(ToAPI(status), mUserdata);
    }

    // Set the buffer early status because it was unmapped early due to Unmap or Destroy.
    // This can race with Complete such that the early status is ignored, but this is OK
    // because we will still unmap the buffer. It will be as-if the application called
    // Unmap/Destroy just after the map event completed.
    void UnmapEarly(wgpu::BufferMapAsyncStatus status) override {
        mBufferOrEarlyStatus.Use([&](auto bufferOrEarlyStatus) { *bufferOrEarlyStatus = status; });
    }
};

struct BufferBase::MapAsyncEvent2 final : public BufferBase::MapAsyncEvent {
    // MapAsyncEvent stores a raw pointer to the buffer so that it can update the buffer's map state
    // when it completes. If the map completes early (error, unmap, destroy), then the buffer is no
    // longer needed and we store the early status instead. The raw pointer is safe because the
    // early status is set to destroyed before the buffer is dropped. Note: this could be an atomic
    // + spin lock on a sentinel enum if the mutex cost is high.
    struct BufferErrorData {
        WGPUMapAsyncStatus status;
        std::string message;
    };
    MutexProtected<std::variant<BufferBase*, BufferErrorData>> mBufferOrError;

    WGPUBufferMapCallback2 mCallback;
    raw_ptr<void> mUserdata1;
    raw_ptr<void> mUserdata2;

    // Create an event backed by the given queue execution serial.
    MapAsyncEvent2(DeviceBase* device,
                   BufferBase* buffer,
                   const WGPUBufferMapCallbackInfo2& callbackInfo,
                   ExecutionSerial serial)
        : MapAsyncEvent(static_cast<wgpu::CallbackMode>(callbackInfo.mode),
                        device->GetQueue(),
                        serial),
          mBufferOrError(buffer),
          mCallback(callbackInfo.callback),
          mUserdata1(callbackInfo.userdata1),
          mUserdata2(callbackInfo.userdata2) {
        TRACE_EVENT_ASYNC_BEGIN0(device->GetPlatform(), General, "Buffer::APIMapAsync",
                                 uint64_t(serial));
    }

    // Create an event that's ready at creation (for errors, etc.)
    MapAsyncEvent2(DeviceBase* device,
                   const WGPUBufferMapCallbackInfo2& callbackInfo,
                   const std::string& message)
        : MapAsyncEvent(static_cast<wgpu::CallbackMode>(callbackInfo.mode)),
          mBufferOrError(BufferErrorData{WGPUMapAsyncStatus_Error, message}),
          mCallback(callbackInfo.callback),
          mUserdata1(callbackInfo.userdata1),
          mUserdata2(callbackInfo.userdata2) {
        TRACE_EVENT_ASYNC_BEGIN0(device->GetPlatform(), General, "Buffer::APIMapAsync",
                                 uint64_t(kBeginningOfGPUTime));
    }

    ~MapAsyncEvent2() override { EnsureComplete(EventCompletionType::Shutdown); }

    void Complete(EventCompletionType completionType) override {
        if (const auto* queueAndSerial = std::get_if<QueueAndSerial>(&GetCompletionData())) {
            TRACE_EVENT_ASYNC_END0(queueAndSerial->queue->GetDevice()->GetPlatform(), General,
                                   "Buffer::APIMapAsync",
                                   uint64_t(queueAndSerial->completionSerial));
        }

        void* userdata1 = mUserdata1.ExtractAsDangling();
        void* userdata2 = mUserdata2.ExtractAsDangling();

        if (completionType == EventCompletionType::Shutdown) {
            mCallback(WGPUMapAsyncStatus_InstanceDropped,
                      "A valid external Instance reference no longer exists.", userdata1,
                      userdata2);
            return;
        }

        bool error = false;
        BufferErrorData pendingErrorData;
        Ref<MapAsyncEvent> pendingMapEvent;

        // Lock the buffer / error. This may race with UnmapEarly which occurs when the buffer is
        // unmapped or destroyed.
        mBufferOrError.Use([&](auto bufferOrError) {
            if (auto* errorData = std::get_if<BufferErrorData>(&*bufferOrError)) {
                // Assign the early error, if it was set.
                pendingErrorData = *errorData;
                error = true;
            } else if (auto** buffer = std::get_if<BufferBase*>(&*bufferOrError)) {
                // Set the buffer state to Mapped if this pending map succeeded.
                // TODO(crbug.com/dawn/831): in order to be thread safe, mutation of the
                // state and pending map event needs to be atomic w.r.t. UnmapInternal.
                DAWN_ASSERT((*buffer)->mState == BufferState::PendingMap);
                (*buffer)->mState = BufferState::Mapped;

                pendingMapEvent = std::move((*buffer)->mPendingMapEvent);
            }
        });
        if (error) {
            DAWN_ASSERT(!pendingErrorData.message.empty());
            mCallback(pendingErrorData.status, pendingErrorData.message.c_str(), userdata1,
                      userdata2);
        } else {
            mCallback(WGPUMapAsyncStatus_Success, nullptr, userdata1, userdata2);
        }
    }

    // Set the buffer early status because it was unmapped early due to Unmap or Destroy.
    // This can race with Complete such that the early status is ignored, but this is OK
    // because we will still unmap the buffer. It will be as-if the application called
    // Unmap/Destroy just after the map event completed.
    void UnmapEarly(wgpu::BufferMapAsyncStatus status) override {
        auto StatusToMessage = [](wgpu::BufferMapAsyncStatus status) {
            switch (status) {
                case wgpu::BufferMapAsyncStatus::DeviceLost:
                    return "Device was lost.";
                case wgpu::BufferMapAsyncStatus::DestroyedBeforeCallback:
                    return "Buffer was destroyed before mapping was resolved.";
                case wgpu::BufferMapAsyncStatus::UnmappedBeforeCallback:
                    return "Buffer was unmapped before mapping was resolved.";
                default:
                    DAWN_UNREACHABLE();
            }
        };
        mBufferOrError.Use([&](auto bufferOrError) {
            *bufferOrError = BufferErrorData{WGPUMapAsyncStatus_Aborted, StatusToMessage(status)};
        });
    }
};

ResultOrError<UnpackedPtr<BufferDescriptor>> ValidateBufferDescriptor(
    DeviceBase* device,
    const BufferDescriptor* descriptor) {
    UnpackedPtr<BufferDescriptor> unpacked;
    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(descriptor));

    DAWN_TRY(ValidateBufferUsage(descriptor->usage));

    if (const auto* hostMappedDesc = unpacked.Get<BufferHostMappedPointer>()) {
        // TODO(crbug.com/dawn/2018): Properly expose this limit.
        uint32_t requiredAlignment = 4096;
        if (device->GetAdapter()->GetPhysicalDevice()->GetBackendType() ==
            wgpu::BackendType::D3D12) {
            requiredAlignment = 65536;
        }

        DAWN_INVALID_IF(!device->HasFeature(Feature::HostMappedPointer), "%s requires %s.",
                        hostMappedDesc->sType, ToAPI(Feature::HostMappedPointer));
        DAWN_INVALID_IF(!IsAligned(descriptor->size, requiredAlignment),
                        "Buffer size (%u) wrapping host-mapped memory was not aligned to %u.",
                        descriptor->size, requiredAlignment);
        DAWN_INVALID_IF(!IsPtrAligned(hostMappedDesc->pointer, requiredAlignment),
                        "Host-mapped memory pointer (%p) was not aligned to %u.",
                        hostMappedDesc->pointer, requiredAlignment);

        // TODO(dawn:2018) consider allowing the host-mapped buffers to be mapped through WebGPU.
        DAWN_INVALID_IF(
            descriptor->mappedAtCreation,
            "Buffer created from host-mapped pointer requires mappedAtCreation to be false.");
    }

    wgpu::BufferUsage usage = descriptor->usage;

    DAWN_INVALID_IF(usage == wgpu::BufferUsage::None, "Buffer usages must not be 0.");

    if (!device->HasFeature(Feature::BufferMapExtendedUsages)) {
        const wgpu::BufferUsage kMapWriteAllowedUsages =
            wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
        DAWN_INVALID_IF(
            usage & wgpu::BufferUsage::MapWrite && !IsSubset(usage, kMapWriteAllowedUsages),
            "Buffer usages (%s) is invalid. If a buffer usage contains %s the only other allowed "
            "usage is %s.",
            usage, wgpu::BufferUsage::MapWrite, wgpu::BufferUsage::CopySrc);

        const wgpu::BufferUsage kMapReadAllowedUsages =
            wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
        DAWN_INVALID_IF(
            usage & wgpu::BufferUsage::MapRead && !IsSubset(usage, kMapReadAllowedUsages),
            "Buffer usages (%s) is invalid. If a buffer usage contains %s the only other allowed "
            "usage is %s.",
            usage, wgpu::BufferUsage::MapRead, wgpu::BufferUsage::CopyDst);
    }

    DAWN_INVALID_IF(descriptor->mappedAtCreation && descriptor->size % 4 != 0,
                    "Buffer is mapped at creation but its size (%u) is not a multiple of 4.",
                    descriptor->size);

    DAWN_INVALID_IF(descriptor->size > device->GetLimits().v1.maxBufferSize,
                    "Buffer size (%u) exceeds the max buffer size limit (%u).", descriptor->size,
                    device->GetLimits().v1.maxBufferSize);

    return unpacked;
}

// Buffer

BufferBase::BufferBase(DeviceBase* device, const UnpackedPtr<BufferDescriptor>& descriptor)
    : SharedResource(device, descriptor->label),
      mSize(descriptor->size),
      mUsage(AddInternalUsages(device, descriptor->usage)),
      mState(descriptor.Get<BufferHostMappedPointer>() ? BufferState::HostMappedPersistent
                                                       : BufferState::Unmapped) {
    GetObjectTrackingList()->Track(this);
}

BufferBase::BufferBase(DeviceBase* device,
                       const BufferDescriptor* descriptor,
                       ObjectBase::ErrorTag tag)
    : SharedResource(device, tag, descriptor->label),
      mSize(descriptor->size),
      mUsage(descriptor->usage),
      mState(descriptor->mappedAtCreation ? BufferState::MappedAtCreation : BufferState::Unmapped) {
    if (descriptor->mappedAtCreation) {
        mMapOffset = 0;
        mMapSize = mSize;
    }
}

BufferBase::~BufferBase() {
    DAWN_ASSERT(mState == BufferState::Unmapped || mState == BufferState::Destroyed);
}

void BufferBase::DestroyImpl() {
    // TODO(crbug.com/dawn/831): DestroyImpl is called from two places.
    // - It may be called if the buffer is explicitly destroyed with APIDestroy.
    //   This case is NOT thread-safe and needs proper synchronization with other
    //   simultaneous uses of the buffer.
    // - It may be called when the last ref to the buffer is dropped and the buffer
    //   is implicitly destroyed. This case is thread-safe because there are no
    //   other threads using the buffer since there are no other live refs.
    if (mState == BufferState::Mapped || mState == BufferState::PendingMap) {
        UnmapInternal(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback);
    } else if (mState == BufferState::MappedAtCreation) {
        if (mStagingBuffer != nullptr) {
            mStagingBuffer = nullptr;
        } else if (mSize != 0) {
            UnmapInternal(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback);
        }
    }

    mState = BufferState::Destroyed;
}

// static
Ref<BufferBase> BufferBase::MakeError(DeviceBase* device, const BufferDescriptor* descriptor) {
    return AcquireRef(new ErrorBuffer(device, descriptor));
}

ObjectType BufferBase::GetType() const {
    return ObjectType::Buffer;
}

uint64_t BufferBase::GetSize() const {
    DAWN_ASSERT(!IsError());
    return mSize;
}

uint64_t BufferBase::GetAllocatedSize() const {
    DAWN_ASSERT(!IsError());
    // The backend must initialize this value.
    DAWN_ASSERT(mAllocatedSize != 0);
    return mAllocatedSize;
}

wgpu::BufferUsage BufferBase::GetUsage() const {
    DAWN_ASSERT(!IsError());
    return mUsage;
}

wgpu::BufferUsage BufferBase::GetUsageExternalOnly() const {
    DAWN_ASSERT(!IsError());
    return GetUsage() & ~kAllInternalBufferUsages;
}

wgpu::BufferUsage BufferBase::APIGetUsage() const {
    return mUsage & ~kAllInternalBufferUsages;
}

wgpu::BufferMapState BufferBase::APIGetMapState() const {
    switch (mState) {
        case BufferState::Mapped:
        case BufferState::MappedAtCreation:
            return wgpu::BufferMapState::Mapped;
        case BufferState::PendingMap:
            return wgpu::BufferMapState::Pending;
        case BufferState::Unmapped:
        case BufferState::Destroyed:
        case BufferState::SharedMemoryNoAccess:
            return wgpu::BufferMapState::Unmapped;
        default:
            DAWN_UNREACHABLE();
            return wgpu::BufferMapState::Unmapped;
    }
}

MaybeError BufferBase::MapAtCreation() {
    DAWN_TRY(MapAtCreationInternal());

    void* ptr;
    size_t size;
    if (mSize == 0) {
        return {};
    } else if (mStagingBuffer != nullptr) {
        // If there is a staging buffer for initialization, clear its contents directly.
        // It should be exactly as large as the buffer allocation.
        ptr = mStagingBuffer->GetMappedPointer();
        size = mStagingBuffer->GetSize();
        DAWN_ASSERT(size == GetAllocatedSize());
    } else {
        // Otherwise, the buffer is directly mappable on the CPU.
        ptr = GetMappedPointer();
        size = GetAllocatedSize();
    }

    DeviceBase* device = GetDevice();
    if (device->IsToggleEnabled(Toggle::LazyClearResourceOnFirstUse) &&
        !device->IsToggleEnabled(Toggle::DisableLazyClearForMappedAtCreationBuffer)) {
        memset(ptr, uint8_t(0u), size);
        device->IncrementLazyClearCountForTesting();
    } else if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
        memset(ptr, uint8_t(1u), size);
    }
    // Mark the buffer as initialized since we don't want to later clear it using the GPU since that
    // would overwrite what the client wrote using the CPU.
    SetInitialized(true);

    return {};
}

MaybeError BufferBase::MapAtCreationInternal() {
    DAWN_ASSERT(!IsError());
    mMapOffset = 0;
    mMapSize = mSize;

    // 0-sized buffers are not supposed to be written to. Return back any non-null pointer.
    // Skip handling 0-sized buffers so we don't try to map them in the backend.
    if (mSize != 0) {
        // Mappable buffers don't use a staging buffer and are just as if mapped through
        // MapAsync.
        if (IsCPUWritableAtCreation()) {
            DAWN_TRY(MapAtCreationImpl());
        } else {
            // If any of these fail, the buffer will be deleted and replaced with an error
            // buffer. The staging buffer is used to return mappable data to inititalize the
            // buffer contents. Allocate one as large as the real buffer size so that every byte
            // is initialized.
            // TODO(crbug.com/dawn/828): Suballocate and reuse memory from a larger staging
            // buffer so we don't create many small buffers.
            BufferDescriptor stagingBufferDesc = {};
            stagingBufferDesc.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;
            stagingBufferDesc.size = Align(GetAllocatedSize(), 4);
            stagingBufferDesc.mappedAtCreation = true;
            stagingBufferDesc.label = "Dawn_MappedAtCreationStaging";

            IgnoreLazyClearCountScope scope(GetDevice());
            DAWN_TRY_ASSIGN(mStagingBuffer, GetDevice()->CreateBuffer(&stagingBufferDesc));
        }
    }

    // Only set the state to mapped at creation if we did no fail any point in this helper.
    // Otherwise, if we override the default unmapped state before succeeding to create a
    // staging buffer, we will have issues when we try to destroy the buffer.
    mState = BufferState::MappedAtCreation;
    return {};
}

MaybeError BufferBase::ValidateCanUseOnQueueNow() const {
    DAWN_ASSERT(!IsError());

    switch (mState) {
        case BufferState::Destroyed:
            return DAWN_VALIDATION_ERROR("%s used in submit while destroyed.", this);
        case BufferState::Mapped:
        case BufferState::MappedAtCreation:
            return DAWN_VALIDATION_ERROR("%s used in submit while mapped.", this);
        case BufferState::PendingMap:
            return DAWN_VALIDATION_ERROR("%s used in submit while pending map.", this);
        case BufferState::SharedMemoryNoAccess:
            return DAWN_VALIDATION_ERROR("%s used in submit without shared memory access.", this);
        case BufferState::HostMappedPersistent:
        case BufferState::Unmapped:
            return {};
    }
    DAWN_UNREACHABLE();
}

std::function<void()> BufferBase::PrepareMappingCallback(MapRequestID mapID,
                                                         WGPUBufferMapAsyncStatus status) {
    DAWN_ASSERT(!IsError());

    if (mMapCallback != nullptr && mapID == mLastMapID) {
        auto callback = std::move(mMapCallback);
        void* userdata = std::move(mMapUserdata);
        WGPUBufferMapAsyncStatus actualStatus;
        if (GetDevice()->IsLost()) {
            actualStatus = WGPUBufferMapAsyncStatus_DeviceLost;
        } else {
            actualStatus = status;
        }

        // Tag the callback as fired before firing it, otherwise it could fire a second time if
        // for example buffer.Unmap() is called before the MapRequestTask completes.
        mMapCallback = nullptr;
        mMapUserdata = nullptr;

        return std::bind(callback, actualStatus, userdata);
    }

    return [] {};
}

void BufferBase::APIMapAsync(wgpu::MapMode mode,
                             size_t offset,
                             size_t size,
                             WGPUBufferMapCallback callback,
                             void* userdata) {
    GetInstance()->EmitDeprecationWarning(
        "Old MapAsync APIs are deprecated. If using C please pass a CallbackInfo "
        "struct that has two userdatas. Otherwise, if using C++, please use templated helpers.");

    // Check for an existing pending map first because it just
    // rejects the callback and doesn't produce a validation error.
    if (mState == BufferState::PendingMap) {
        if (callback) {
            GetDevice()->GetCallbackTaskManager()->AddCallbackTask(
                callback, WGPUBufferMapAsyncStatus_MappingAlreadyPending, userdata);
        }
        return;
    }

    // Handle the defaulting of size required by WebGPU, even if in webgpu_cpp.h it is not
    // possible to default the function argument (because there is the callback later in the
    // argument list)
    if ((size == wgpu::kWholeMapSize) && (offset <= mSize)) {
        size = mSize - offset;
    }

    WGPUBufferMapAsyncStatus status;
    if (GetDevice()->ConsumedError(ValidateMapAsync(mode, offset, size, &status),
                                   "calling %s.MapAsync(%s, %u, %u, ...).", this, mode, offset,
                                   size)) {
        if (callback) {
            GetDevice()->GetCallbackTaskManager()->AddCallbackTask(callback, status, userdata);
        }
        return;
    }
    DAWN_ASSERT(!IsError());

    mLastMapID++;
    mMapMode = mode;
    mMapOffset = offset;
    mMapSize = size;
    mMapCallback = callback;
    mMapUserdata = userdata;
    mState = BufferState::PendingMap;

    if (GetDevice()->ConsumedError(MapAsyncImpl(mode, offset, size))) {
        GetDevice()->GetCallbackTaskManager()->AddCallbackTask(
            PrepareMappingCallback(mLastMapID, WGPUBufferMapAsyncStatus_DeviceLost));
        return;
    }
    std::unique_ptr<MapRequestTask> request =
        std::make_unique<MapRequestTask>(GetDevice()->GetPlatform(), this, mLastMapID);
    TRACE_EVENT1(GetDevice()->GetPlatform(), General, "Buffer::APIMapAsync", "serial",
                 uint64_t(mLastUsageSerial));
    GetDevice()->GetQueue()->TrackTask(std::move(request), mLastUsageSerial);
}

Future BufferBase::APIMapAsyncF(wgpu::MapMode mode,
                                size_t offset,
                                size_t size,
                                const BufferMapCallbackInfo& callbackInfo) {
    GetInstance()->EmitDeprecationWarning(
        "Old MapAsync APIs are deprecated. If using C please pass a CallbackInfo "
        "struct that has two userdatas. Otherwise, if using C++, please use templated helpers.");

    // TODO(crbug.com/dawn/2052): Once we always return a future, change this to log to the instance
    // (note, not raise a validation error to the device) and return the null future.
    DAWN_ASSERT(callbackInfo.nextInChain == nullptr);

    Ref<EventManager::TrackedEvent> event;
    std::optional<wgpu::BufferMapAsyncStatus> earlyStatus;
    {
        // TODO(crbug.com/dawn/831) Manually acquire device lock instead of relying on code-gen for
        // re-entrancy.
        auto deviceLock(GetDevice()->GetScopedLock());

        // Handle the defaulting of size required by WebGPU, even if in webgpu_cpp.h it is not
        // possible to default the function argument (because there is the callback later in the
        // argument list)
        if ((size == wgpu::kWholeMapSize) && (offset <= mSize)) {
            size = mSize - offset;
        }

        earlyStatus = [&]() -> std::optional<wgpu::BufferMapAsyncStatus> {
            if (mState == BufferState::PendingMap) {
                return wgpu::BufferMapAsyncStatus::MappingAlreadyPending;
            }
            WGPUBufferMapAsyncStatus status;
            if (GetDevice()->ConsumedError(ValidateMapAsync(mode, offset, size, &status),
                                           "calling %s.MapAsync(%s, %u, %u, ...).", this, mode,
                                           offset, size)) {
                return static_cast<wgpu::BufferMapAsyncStatus>(status);
            }
            if (GetDevice()->ConsumedError(MapAsyncImpl(mode, offset, size))) {
                return wgpu::BufferMapAsyncStatus::DeviceLost;
            }
            return std::nullopt;
        }();

        if (earlyStatus) {
            event = AcquireRef(new MapAsyncEvent1(GetDevice(), callbackInfo, *earlyStatus));
        } else {
            mMapMode = mode;
            mMapOffset = offset;
            mMapSize = size;
            mState = BufferState::PendingMap;
            mPendingMapEvent =
                AcquireRef(new MapAsyncEvent1(GetDevice(), this, callbackInfo, mLastUsageSerial));
            event = mPendingMapEvent;
        }
    }

    FutureID futureID = GetInstance()->GetEventManager()->TrackEvent(std::move(event));
    return {futureID};
}

Future BufferBase::APIMapAsync2(wgpu::MapMode mode,
                                size_t offset,
                                size_t size,
                                const WGPUBufferMapCallbackInfo2& callbackInfo) {
    // TODO(crbug.com/dawn/2052): Once we always return a future, change this to log to the instance
    // (note, not raise a validation error to the device) and return the null future.
    DAWN_ASSERT(callbackInfo.nextInChain == nullptr);

    Ref<EventManager::TrackedEvent> event;
    {
        // TODO(crbug.com/dawn/831) Manually acquire device lock instead of relying on code-gen for
        // re-entrancy.
        auto deviceLock(GetDevice()->GetScopedLock());

        // Handle the defaulting of size required by WebGPU, even if in webgpu_cpp.h it is not
        // possible to default the function argument (because there is the callback later in the
        // argument list)
        if ((size == wgpu::kWholeMapSize) && (offset <= mSize)) {
            size = mSize - offset;
        }

        MaybeError maybeError = [&]() -> MaybeError {
            DAWN_INVALID_IF(mState == BufferState::PendingMap,
                            "%s already has an outstanding map pending.", this);
            WGPUBufferMapAsyncStatus status;
            DAWN_TRY(ValidateMapAsync(mode, offset, size, &status));
            DAWN_TRY(MapAsyncImpl(mode, offset, size));
            return {};
        }();

        if (maybeError.IsError()) {
            auto error = maybeError.AcquireError();
            event = AcquireRef(new MapAsyncEvent2(GetDevice(), callbackInfo, error->GetMessage()));
            [[maybe_unused]] bool hadError = GetDevice()->ConsumedError(
                std::move(error), "calling %s.MapAsync(%s, %u, %u, ...).", this, mode, offset,
                size);
        } else {
            mMapMode = mode;
            mMapOffset = offset;
            mMapSize = size;
            mState = BufferState::PendingMap;
            mPendingMapEvent =
                AcquireRef(new MapAsyncEvent2(GetDevice(), this, callbackInfo, mLastUsageSerial));
            event = mPendingMapEvent;
        }
    }

    FutureID futureID = GetInstance()->GetEventManager()->TrackEvent(std::move(event));
    return {futureID};
}

void* BufferBase::APIGetMappedRange(size_t offset, size_t size) {
    return GetMappedRange(offset, size, true);
}

const void* BufferBase::APIGetConstMappedRange(size_t offset, size_t size) {
    return GetMappedRange(offset, size, false);
}

void* BufferBase::GetMappedRange(size_t offset, size_t size, bool writable) {
    if (!CanGetMappedRange(writable, offset, size)) {
        return nullptr;
    }

    if (mStagingBuffer != nullptr) {
        return static_cast<uint8_t*>(mStagingBuffer->GetMappedPointer()) + offset;
    }
    if (mSize == 0) {
        return &sZeroSizedMappingData;
    }
    uint8_t* start = static_cast<uint8_t*>(GetMappedPointer());
    return start == nullptr ? nullptr : start + offset;
}

void BufferBase::APIDestroy() {
    Destroy();
}

uint64_t BufferBase::APIGetSize() const {
    return mSize;
}

MaybeError BufferBase::CopyFromStagingBuffer() {
    DAWN_ASSERT(mStagingBuffer != nullptr && mSize != 0);

    DAWN_TRY(
        GetDevice()->CopyFromStagingToBuffer(mStagingBuffer.Get(), 0, this, 0, GetAllocatedSize()));

    DynamicUploader* uploader = GetDevice()->GetDynamicUploader();
    uploader->ReleaseStagingBuffer(std::move(mStagingBuffer));

    return {};
}

void BufferBase::APIUnmap() {
    if (GetDevice()->ConsumedError(ValidateUnmap(), "calling %s.Unmap().", this)) {
        return;
    }
    [[maybe_unused]] bool hadError =
        GetDevice()->ConsumedError(Unmap(), "calling %s.Unmap().", this);
}

MaybeError BufferBase::Unmap() {
    if (mState == BufferState::Destroyed) {
        return {};
    }

    // Make sure writes are now visibile to the GPU if we used a staging buffer.
    if (mState == BufferState::MappedAtCreation && mStagingBuffer != nullptr) {
        DAWN_TRY(CopyFromStagingBuffer());
    }
    UnmapInternal(WGPUBufferMapAsyncStatus_UnmappedBeforeCallback);
    return {};
}

void BufferBase::UnmapInternal(WGPUBufferMapAsyncStatus callbackStatus) {
    // Unmaps resources on the backend.
    if (mState == BufferState::PendingMap) {
        // TODO(crbug.com/dawn/831): in order to be thread safe, mutation of the
        // state and pending map event needs to be atomic w.r.t. MapAsyncEvent::Complete.
        Ref<MapAsyncEvent> pendingMapEvent = std::move(mPendingMapEvent);
        if (pendingMapEvent != nullptr) {
            pendingMapEvent->UnmapEarly(static_cast<wgpu::BufferMapAsyncStatus>(callbackStatus));
            GetInstance()->GetEventManager()->SetFutureReady(pendingMapEvent.Get());
        } else {
            GetDevice()->GetCallbackTaskManager()->AddCallbackTask(
                PrepareMappingCallback(mLastMapID, callbackStatus));
        }
        UnmapImpl();
    } else if (mState == BufferState::Mapped) {
        UnmapImpl();
    } else if (mState == BufferState::MappedAtCreation) {
        if (!IsError() && mSize != 0 && IsCPUWritableAtCreation()) {
            UnmapImpl();
        }
    }

    mState = BufferState::Unmapped;
}

MaybeError BufferBase::ValidateMapAsync(wgpu::MapMode mode,
                                        size_t offset,
                                        size_t size,
                                        WGPUBufferMapAsyncStatus* status) const {
    *status = WGPUBufferMapAsyncStatus_DeviceLost;
    DAWN_TRY(GetDevice()->ValidateIsAlive());

    *status = WGPUBufferMapAsyncStatus_ValidationError;
    DAWN_TRY(GetDevice()->ValidateObject(this));

    DAWN_INVALID_IF(uint64_t(offset) > mSize,
                    "Mapping offset (%u) is larger than the size (%u) of %s.", offset, mSize, this);

    DAWN_INVALID_IF(offset % 8 != 0, "Offset (%u) must be a multiple of 8.", offset);
    DAWN_INVALID_IF(size % 4 != 0, "Size (%u) must be a multiple of 4.", size);

    DAWN_INVALID_IF(uint64_t(size) > mSize - uint64_t(offset),
                    "Mapping range (offset:%u, size: %u) doesn't fit in the size (%u) of %s.",
                    offset, size, mSize, this);

    switch (mState) {
        case BufferState::Mapped:
        case BufferState::MappedAtCreation:
            return DAWN_VALIDATION_ERROR("%s is already mapped.", this);
        case BufferState::PendingMap:
            DAWN_UNREACHABLE();
        case BufferState::Destroyed:
            return DAWN_VALIDATION_ERROR("%s is destroyed.", this);
        case BufferState::HostMappedPersistent:
            return DAWN_VALIDATION_ERROR("Host-mapped %s cannot be mapped again.", this);
        case BufferState::SharedMemoryNoAccess:
            return DAWN_VALIDATION_ERROR("%s used without shared memory access.", this);
        case BufferState::Unmapped:
            break;
    }

    bool isReadMode = mode & wgpu::MapMode::Read;
    bool isWriteMode = mode & wgpu::MapMode::Write;
    DAWN_INVALID_IF(!(isReadMode ^ isWriteMode), "Map mode (%s) is not one of %s or %s.", mode,
                    wgpu::MapMode::Write, wgpu::MapMode::Read);

    if (mode & wgpu::MapMode::Read) {
        DAWN_INVALID_IF(!(mUsage & wgpu::BufferUsage::MapRead),
                        "The buffer usages (%s) do not contain %s.", mUsage,
                        wgpu::BufferUsage::MapRead);
    } else {
        DAWN_ASSERT(mode & wgpu::MapMode::Write);
        DAWN_INVALID_IF(!(mUsage & wgpu::BufferUsage::MapWrite),
                        "The buffer usages (%s) do not contain %s.", mUsage,
                        wgpu::BufferUsage::MapWrite);
    }

    *status = WGPUBufferMapAsyncStatus_Success;
    return {};
}

bool BufferBase::CanGetMappedRange(bool writable, size_t offset, size_t size) const {
    if (offset % 8 != 0 || offset < mMapOffset || offset > mSize) {
        return false;
    }

    size_t rangeSize = size == WGPU_WHOLE_MAP_SIZE ? mSize - offset : size;

    if (rangeSize % 4 != 0 || rangeSize > mMapSize) {
        return false;
    }

    size_t offsetInMappedRange = offset - mMapOffset;
    if (offsetInMappedRange > mMapSize - rangeSize) {
        return false;
    }

    // Note that:
    //
    //   - We don't check that the device is alive because the application can ask for the
    //     mapped pointer before it knows, and even Dawn knows, that the device was lost, and
    //     still needs to work properly.
    //   - We don't check that the object is alive because we need to return mapped pointers
    //     for error buffers too.

    switch (mState) {
        // It is never valid to call GetMappedRange on a host-mapped buffer.
        // TODO(crbug.com/dawn/2018): consider returning the same pointer here.
        case BufferState::HostMappedPersistent:
            return false;

        // Writeable Buffer::GetMappedRange is always allowed when mapped at creation.
        case BufferState::MappedAtCreation:
            return true;

        case BufferState::Mapped:
            DAWN_ASSERT(bool{mMapMode & wgpu::MapMode::Read} ^
                        bool{mMapMode & wgpu::MapMode::Write});
            return !writable || (mMapMode & wgpu::MapMode::Write);

        case BufferState::PendingMap:
        case BufferState::Unmapped:
        case BufferState::SharedMemoryNoAccess:
        case BufferState::Destroyed:
            return false;
    }
    DAWN_UNREACHABLE();
}

MaybeError BufferBase::ValidateUnmap() const {
    DAWN_TRY(GetDevice()->ValidateIsAlive());
    DAWN_INVALID_IF(mState == BufferState::HostMappedPersistent,
                    "Persistently mapped buffer cannot be unmapped.");
    return {};
}

void BufferBase::CallbackOnMapRequestCompleted(MapRequestID mapID,
                                               WGPUBufferMapAsyncStatus status) {
    {
        // This is called from a callback, and no lock will be held by default. Hence, we need to
        // lock the mutex now because this will modify the buffer's states.
        auto deviceLock(GetDevice()->GetScopedLock());
        if (mapID == mLastMapID && status == WGPUBufferMapAsyncStatus_Success &&
            mState == BufferState::PendingMap) {
            mState = BufferState::Mapped;
        }
    }

    auto cb = PrepareMappingCallback(mapID, status);
    cb();
}

bool BufferBase::NeedsInitialization() const {
    return !mIsDataInitialized && GetDevice()->IsToggleEnabled(Toggle::LazyClearResourceOnFirstUse);
}

void BufferBase::MarkUsedInPendingCommands() {
    ExecutionSerial serial = GetDevice()->GetQueue()->GetPendingCommandSerial();
    DAWN_ASSERT(serial >= mLastUsageSerial);
    mLastUsageSerial = serial;
}

ExecutionSerial BufferBase::GetLastUsageSerial() const {
    return mLastUsageSerial;
}

MaybeError BufferBase::UploadData(uint64_t bufferOffset, const void* data, size_t size) {
    if (size == 0) {
        return {};
    }

    DeviceBase* device = GetDevice();

    UploadHandle uploadHandle;
    DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
                                      size, device->GetQueue()->GetPendingCommandSerial(),
                                      kCopyBufferToBufferOffsetAlignment));
    DAWN_ASSERT(uploadHandle.mappedBuffer != nullptr);

    memcpy(uploadHandle.mappedBuffer, data, size);

    return device->CopyFromStagingToBuffer(uploadHandle.stagingBuffer, uploadHandle.startOffset,
                                           this, bufferOffset, size);
}

ExecutionSerial BufferBase::OnEndAccess() {
    mState = BufferState::SharedMemoryNoAccess;
    ExecutionSerial lastUsageSerial = mLastUsageSerial;
    mLastUsageSerial = kBeginningOfGPUTime;
    return lastUsageSerial;
}

void BufferBase::OnBeginAccess() {
    mState = BufferState::Unmapped;
}

bool BufferBase::HasAccess() const {
    return mState != BufferState::SharedMemoryNoAccess;
}

bool BufferBase::IsDestroyed() const {
    return mState == BufferState::Destroyed;
}

void BufferBase::SetInitialized(bool initialized) {
    mIsDataInitialized = initialized;
}

bool BufferBase::IsInitialized() const {
    return mIsDataInitialized;
}

bool BufferBase::IsFullBufferRange(uint64_t offset, uint64_t size) const {
    return offset == 0 && size == GetSize();
}

void BufferBase::DumpMemoryStatistics(MemoryDump* dump, const char* prefix) const {
    // Do not emit for destroyed buffers.
    if (!IsAlive()) {
        return;
    }
    std::string name = absl::StrFormat("%s/buffer_%p", prefix, static_cast<const void*>(this));
    dump->AddScalar(name.c_str(), MemoryDump::kNameSize, MemoryDump::kUnitsBytes,
                    GetAllocatedSize());
    dump->AddString(name.c_str(), "label", GetLabel());
    dump->AddString(name.c_str(), "usage", absl::StrFormat("%s", GetUsage()));
}

}  // namespace dawn::native
