// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn/native/RenderBundleEncoder.h"

#include <utility>

#include "dawn/native/CommandValidation.h"
#include "dawn/native/Commands.h"
#include "dawn/native/Device.h"
#include "dawn/native/Format.h"
#include "dawn/native/ObjectType_autogen.h"
#include "dawn/native/RenderPipeline.h"
#include "dawn/native/ValidationUtils_autogen.h"
#include "dawn/platform/DawnPlatform.h"
#include "dawn/platform/tracing/TraceEvent.h"

namespace dawn::native {

MaybeError ValidateColorAttachmentFormat(const DeviceBase* device,
                                         wgpu::TextureFormat textureFormat) {
    DAWN_TRY(ValidateTextureFormat(textureFormat));
    const Format* format = nullptr;
    DAWN_TRY_ASSIGN(format, device->GetInternalFormat(textureFormat));
    DAWN_INVALID_IF(!format->IsColor() || !format->isRenderable,
                    "Texture format %s is not color renderable.", textureFormat);
    return {};
}

MaybeError ValidateDepthStencilAttachmentFormat(const DeviceBase* device,
                                                wgpu::TextureFormat textureFormat,
                                                bool depthReadOnly,
                                                bool stencilReadOnly) {
    DAWN_TRY(ValidateTextureFormat(textureFormat));
    const Format* format = nullptr;
    DAWN_TRY_ASSIGN(format, device->GetInternalFormat(textureFormat));
    DAWN_INVALID_IF(!format->HasDepthOrStencil() || !format->isRenderable,
                    "Texture format %s is not depth/stencil renderable.", textureFormat);

    DAWN_INVALID_IF(
        format->HasDepth() && format->HasStencil() && depthReadOnly != stencilReadOnly,
        "depthReadOnly (%u) and stencilReadOnly (%u) must be the same when format %s has "
        "both depth and stencil aspects.",
        depthReadOnly, stencilReadOnly, textureFormat);

    return {};
}

MaybeError ValidateRenderBundleEncoderDescriptor(const DeviceBase* device,
                                                 const RenderBundleEncoderDescriptor* descriptor) {
    DAWN_INVALID_IF(!IsValidSampleCount(descriptor->sampleCount),
                    "Sample count (%u) is not supported.", descriptor->sampleCount);

    uint32_t maxColorAttachments = device->GetLimits().v1.maxColorAttachments;
    DAWN_INVALID_IF(descriptor->colorFormatsCount > maxColorAttachments,
                    "Color formats count (%u) exceeds maximum number of color attachements (%u).",
                    descriptor->colorFormatsCount, maxColorAttachments);

    bool allColorFormatsUndefined = true;
    for (uint32_t i = 0; i < descriptor->colorFormatsCount; ++i) {
        wgpu::TextureFormat format = descriptor->colorFormats[i];
        if (format != wgpu::TextureFormat::Undefined) {
            DAWN_TRY_CONTEXT(ValidateColorAttachmentFormat(device, format),
                             "validating colorFormats[%u]", i);
            allColorFormatsUndefined = false;
        }
    }

    if (descriptor->depthStencilFormat != wgpu::TextureFormat::Undefined) {
        DAWN_TRY_CONTEXT(ValidateDepthStencilAttachmentFormat(
                             device, descriptor->depthStencilFormat, descriptor->depthReadOnly,
                             descriptor->stencilReadOnly),
                         "validating depthStencilFormat");
    } else {
        DAWN_INVALID_IF(
            allColorFormatsUndefined,
            "No color or depthStencil attachments specified. At least one is required.");
    }

    return {};
}

RenderBundleEncoder::RenderBundleEncoder(DeviceBase* device,
                                         const RenderBundleEncoderDescriptor* descriptor)
    : RenderEncoderBase(device,
                        descriptor->label,
                        &mBundleEncodingContext,
                        device->GetOrCreateAttachmentState(descriptor),
                        descriptor->depthReadOnly,
                        descriptor->stencilReadOnly),
      mBundleEncodingContext(device, this) {
    GetObjectTrackingList()->Track(this);
}

RenderBundleEncoder::RenderBundleEncoder(DeviceBase* device, ErrorTag errorTag)
    : RenderEncoderBase(device, &mBundleEncodingContext, errorTag),
      mBundleEncodingContext(device, this) {}

void RenderBundleEncoder::DestroyImpl() {
    RenderEncoderBase::DestroyImpl();
    mBundleEncodingContext.Destroy();
}

// static
Ref<RenderBundleEncoder> RenderBundleEncoder::Create(
    DeviceBase* device,
    const RenderBundleEncoderDescriptor* descriptor) {
    return AcquireRef(new RenderBundleEncoder(device, descriptor));
}

// static
RenderBundleEncoder* RenderBundleEncoder::MakeError(DeviceBase* device) {
    return new RenderBundleEncoder(device, ObjectBase::kError);
}

ObjectType RenderBundleEncoder::GetType() const {
    return ObjectType::RenderBundleEncoder;
}

CommandIterator RenderBundleEncoder::AcquireCommands() {
    return mBundleEncodingContext.AcquireCommands();
}

RenderBundleBase* RenderBundleEncoder::APIFinish(const RenderBundleDescriptor* descriptor) {
    RenderBundleBase* result = nullptr;

    if (GetDevice()->ConsumedError(FinishImpl(descriptor), &result, "calling %s.Finish(%s).", this,
                                   descriptor)) {
        return RenderBundleBase::MakeError(GetDevice());
    }

    return result;
}

ResultOrError<RenderBundleBase*> RenderBundleEncoder::FinishImpl(
    const RenderBundleDescriptor* descriptor) {
    // Even if mBundleEncodingContext.Finish() validation fails, calling it will mutate the
    // internal state of the encoding context. Subsequent calls to encode commands will generate
    // errors.
    DAWN_TRY(mBundleEncodingContext.Finish());

    RenderPassResourceUsage usages = mUsageTracker.AcquireResourceUsage();
    if (IsValidationEnabled()) {
        DAWN_TRY(GetDevice()->ValidateObject(this));
        DAWN_TRY(ValidateProgrammableEncoderEnd());
        DAWN_TRY(ValidateFinish(usages));
    }

    return new RenderBundleBase(this, descriptor, AcquireAttachmentState(), IsDepthReadOnly(),
                                IsStencilReadOnly(), std::move(usages),
                                std::move(mIndirectDrawMetadata));
}

MaybeError RenderBundleEncoder::ValidateFinish(const RenderPassResourceUsage& usages) const {
    TRACE_EVENT0(GetDevice()->GetPlatform(), Validation, "RenderBundleEncoder::ValidateFinish");
    DAWN_TRY(GetDevice()->ValidateObject(this));
    DAWN_TRY(ValidateSyncScopeResourceUsage(usages));
    return {};
}

}  // namespace dawn::native
