/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/graphite/dawn/DawnBuffer.h"

#include "include/core/SkTraceMemoryDump.h"
#include "include/private/SkAlign.h"
#include "include/private/SkLog.h"
#include "src/gpu/graphite/dawn/DawnAsyncWait.h"
#include "src/gpu/graphite/dawn/DawnSharedContext.h"

namespace skgpu::graphite {
namespace {
#if defined(__EMSCRIPTEN__)
bool is_map_succeeded(WGPUBufferMapAsyncStatus status) {
    return status == WGPUBufferMapAsyncStatus_Success;
}

[[maybe_unused]]
void log_map_error(WGPUBufferMapAsyncStatus status, const char*) {
    const char* statusStr;
    SkLogPriority priority = SkLogPriority::kError;
    switch (status) {
        case WGPUBufferMapAsyncStatus_ValidationError:
            statusStr = "ValidationError";
            break;
        case WGPUBufferMapAsyncStatus_Unknown:
            statusStr = "Unknown";
            break;
        case WGPUBufferMapAsyncStatus_DeviceLost:
            statusStr = "DeviceLost";
            break;
        case WGPUBufferMapAsyncStatus_DestroyedBeforeCallback:
            statusStr = "DestroyedBeforeCallback";
            priority = SkLogPriority::kDebug;
            break;
        case WGPUBufferMapAsyncStatus_UnmappedBeforeCallback:
            statusStr = "UnmappedBeforeCallback";
            priority = SkLogPriority::kDebug;
            break;
        case WGPUBufferMapAsyncStatus_MappingAlreadyPending:
            statusStr = "MappingAlreadyPending";
            break;
        case WGPUBufferMapAsyncStatus_OffsetOutOfRange:
            statusStr = "OffsetOutOfRange";
            break;
        case WGPUBufferMapAsyncStatus_SizeOutOfRange:
            statusStr = "SizeOutOfRange";
            break;
        default:
            statusStr = "<other>";
            break;
    }
    SKIA_LOG(priority, "Buffer async map failed with status %s.", statusStr);
}

#else

bool is_map_succeeded(wgpu::MapAsyncStatus status) {
    return status == wgpu::MapAsyncStatus::Success;
}

void log_map_error(wgpu::MapAsyncStatus status, wgpu::StringView message) {
    const char* statusStr;
    switch (status) {
        case wgpu::MapAsyncStatus::CallbackCancelled:
            statusStr = "CallbackCancelled";
            break;
        case wgpu::MapAsyncStatus::Error:
            statusStr = "Error";
            break;
        case wgpu::MapAsyncStatus::Aborted:
            statusStr = "Aborted";
            break;
        case wgpu::MapAsyncStatus::Success:
            SkDEBUGFAIL("This status is not an error");
            return;
    }
    SKIA_LOG(SkLogPriority::kError,
              "Buffer async map failed with status %s, message '%.*s'.",
              statusStr,
              static_cast<int>(message.length),
              message.data);
}
#endif  // defined(__EMSCRIPTEN__)
}  // namespace

sk_sp<DawnBuffer> DawnBuffer::Make(const DawnSharedContext* sharedContext,
                                   size_t size,
                                   BufferType type,
                                   AccessPattern accessPattern,
                                   std::string_view label) {
    if (size <= 0) {
        return nullptr;
    }

    wgpu::BufferUsage usage = wgpu::BufferUsage::None;

    switch (type) {
        case BufferType::kVertex:
            usage = wgpu::BufferUsage::Vertex | wgpu::BufferUsage::CopyDst;
            break;
        case BufferType::kIndex:
            usage = wgpu::BufferUsage::Index | wgpu::BufferUsage::CopyDst;
            break;
        case BufferType::kXferCpuToGpu:
            usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;
            break;
        case BufferType::kXferGpuToCpu:
            usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead;
            break;
        case BufferType::kUniform:
            usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst;
            break;
        case BufferType::kStorage:
            usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopyDst |
                    wgpu::BufferUsage::CopySrc;
            break;
        case BufferType::kQuery:
            usage = wgpu::BufferUsage::QueryResolve | wgpu::BufferUsage::CopySrc;
            break;
        case BufferType::kIndirect:
            usage = wgpu::BufferUsage::Indirect | wgpu::BufferUsage::Storage |
                    wgpu::BufferUsage::CopyDst;
            break;
        case BufferType::kVertexStorage:
            usage = wgpu::BufferUsage::Vertex | wgpu::BufferUsage::Storage;
            break;
        case BufferType::kIndexStorage:
            usage = wgpu::BufferUsage::Index | wgpu::BufferUsage::Storage;
            break;
    }

    if (sharedContext->caps()->drawBufferCanBeMapped() &&
        accessPattern == AccessPattern::kHostVisible && type != BufferType::kXferGpuToCpu) {
        if (type == BufferType::kQuery) {
            // We can map the query buffer to get the results directly rather than having to copy to
            // a transfer buffer.
            usage |= wgpu::BufferUsage::MapRead;
        } else {
            // If the buffer is intended to be mappable, add MapWrite usage and remove
            // CopyDst.
            // We don't want to allow both CPU and GPU to write to the same buffer.
            usage |= wgpu::BufferUsage::MapWrite;
            usage &= ~wgpu::BufferUsage::CopyDst;
        }
    }

    if (accessPattern == AccessPattern::kGpuOnlyCopySrc) {
        usage |= wgpu::BufferUsage::CopySrc;
    }

    wgpu::BufferDescriptor desc;
    desc.usage = usage;
    desc.size  = size;
    // Specifying mappedAtCreation avoids clearing the buffer on the GPU which can cause MapAsync to
    // be very slow as it waits for GPU execution to complete.
    desc.mappedAtCreation = SkToBool(usage & wgpu::BufferUsage::MapWrite);

    auto buffer = sharedContext->device().CreateBuffer(&desc);
    if (!buffer) {
        return {};
    }

    void* mappedAtCreationPtr = nullptr;
    if (desc.mappedAtCreation) {
        mappedAtCreationPtr = buffer.GetMappedRange();
        SkASSERT(mappedAtCreationPtr);
    }

    return sk_sp<DawnBuffer>(
            new DawnBuffer(sharedContext, size, std::move(buffer), mappedAtCreationPtr, label));
}

DawnBuffer::DawnBuffer(const DawnSharedContext* sharedContext,
                       size_t size,
                       wgpu::Buffer buffer,
                       void* mappedAtCreationPtr,
                       std::string_view label)
        : Buffer(sharedContext,
                 size,
                 Protected::kNo, // Dawn doesn't support protected memory
                 label,
                 /*reusableRequiresPurgeable=*/buffer.GetUsage() & wgpu::BufferUsage::MapWrite,
                 // prepareForReturnToCache only needs to be called for a buffer that is mappable
                 // for writing
                 /* requiresPrepareForReturnToCache= */
                 buffer.GetUsage() & wgpu::BufferUsage::MapWrite)
        , fBuffer(std::move(buffer)) {
    fMapPtr = mappedAtCreationPtr;
    // Update the newly-created underlying GPU object's label to match the Resource's
    this->synchronizeBackendLabel();
}

bool DawnBuffer::prepareForReturnToCache(Resource::TakeRefFunc takeRef, void* takeRefCtx) {
    // This implementation is almost Dawn-agnostic. However, Buffer base class doesn't have any
    // way of distinguishing a buffer that is mappable for writing from one mappable for reading.
    // We only need to re-map the former.
    SkASSERT(fBuffer.GetUsage() & wgpu::BufferUsage::MapWrite);

    // Note that the map state cannot change on another thread when we are here. We got here
    // because there were no UsageRefs on the buffer but async mapping holds a UsageRef until it
    // completes.
    if (this->isMapped()) {
        return false;
    }
    takeRef(takeRefCtx);
    this->asyncMap([](void* ctx, skgpu::CallbackResult result) {
                       sk_sp<DawnBuffer> buffer(static_cast<DawnBuffer*>(ctx));
                       if (result != skgpu::CallbackResult::kSuccess) {
                           buffer->setDeleteASAP();
                       }
                   },
                   this);
    return true;
}

void DawnBuffer::onAsyncMap(GpuFinishedProc proc, GpuFinishedContext ctx) {
    // This function is only useful for Emscripten where we have to use asyncMap().
    SkASSERT(this->sharedContext()->caps()->bufferMapsAreAsync());

    if (proc) {
        SKGPU_ASSERT_SINGLE_OWNER(&fSingleAsyncMapCallbacksOwner)
        if (this->isMapped()) {
            proc(ctx, CallbackResult::kSuccess);
            return;
        }
        fAsyncMapCallbacks.emplace_back(proc, ctx);
    }
    if (this->isUnmappable()) {
        return;
    }
    SkASSERT(fBuffer);
    SkASSERT((fBuffer.GetUsage() & wgpu::BufferUsage::MapRead) ||
             (fBuffer.GetUsage() & wgpu::BufferUsage::MapWrite));
    SkASSERT(fBuffer.GetMapState() == wgpu::BufferMapState::Unmapped);
    bool isWrite = fBuffer.GetUsage() & wgpu::BufferUsage::MapWrite;
    auto buffer = sk_ref_sp(this);

#if defined(__EMSCRIPTEN__)
    fBuffer.MapAsync(
            isWrite ? wgpu::MapMode::Write : wgpu::MapMode::Read,
            0,
            fBuffer.GetSize(),
            [](WGPUBufferMapAsyncStatus s, void* userData) {
                sk_sp<DawnBuffer> buffer(static_cast<DawnBuffer*>(userData));
                buffer->mapCallback(s, /*message=*/nullptr);
            },
            buffer.release());
#else
    // Map with AllowSpontaneous so that if Dawn can trigger the callback immediately
    // if possible,
    fBuffer.MapAsync(
            isWrite ? wgpu::MapMode::Write : wgpu::MapMode::Read,
            0,
            fBuffer.GetSize(),
            wgpu::CallbackMode::AllowSpontaneous,
            [buffer](wgpu::MapAsyncStatus s, wgpu::StringView m) {
                buffer->mapCallback(s, m);
            });
#endif
}

void DawnBuffer::onMap() {
    SKIA_LOG_W("Synchronous buffer mapping not supported in Dawn. Failing map request.");
}

void DawnBuffer::onUnmap() {
    SkASSERT(fBuffer);
    SkASSERT(this->isUnmappable());

    fMapPtr = nullptr;
    fBuffer.Unmap();
}

template <typename StatusT, typename MessageT>
void DawnBuffer::mapCallback(StatusT status, MessageT message) {
    SKGPU_ASSERT_SINGLE_OWNER(&fSingleAsyncMapCallbacksOwner)

    if (is_map_succeeded(status)) {
        if (this->fBuffer.GetUsage() & wgpu::BufferUsage::MapWrite) {
            this->fMapPtr = this->fBuffer.GetMappedRange();
        } else {
            // If buffer is only created with MapRead usage, Dawn only allows returning
            // constant pointer. We need to use const_cast as a workaround here.
            this->fMapPtr = const_cast<void*>(this->fBuffer.GetConstMappedRange());
        }
    } else {
        log_map_error(status, message);
        for (auto& cb : this->fAsyncMapCallbacks) {
            cb.setFailureResult();
        }
    }
    this->fAsyncMapCallbacks.clear();
}

bool DawnBuffer::isUnmappable() const {
    return fBuffer.GetMapState() != wgpu::BufferMapState::Unmapped;
}

void DawnBuffer::freeGpuData() {
    if (fBuffer) {
        // Explicitly destroy the buffer since it might be ref'd by cached bind groups which are
        // not immediately cleaned up. Graphite should already guarantee that all command buffers
        // using this buffer (indirectly via BindGroups) are already completed.
        fBuffer.Destroy();
        fBuffer = nullptr;
    }
}

void DawnBuffer::setBackendLabel(char const* label) {
    SkASSERT(label);
    if (sharedContext()->caps()->setBackendLabels()) {
        fBuffer.SetLabel(label);
    }
}

const wgpu::BindGroup* DawnBuffer::getCachedSingleBufferBindGroup(size_t bindingSize) const {
    for (auto& cachedGroup : fCachedSingleBufferBindGroups) {
        if (cachedGroup.first == bindingSize) {
            return &cachedGroup.second;
        }
    }
    return nullptr;
}
void DawnBuffer::addCachedSingleBufferBindGroup(wgpu::BindGroup bindGroup,
                                                size_t bindingSize) const {
    fCachedSingleBufferBindGroups.push_back({bindingSize, bindGroup});
}

} // namespace skgpu::graphite
