// 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 "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);

        DAWN_INVALID_IF(
            descriptor->colorFormatsCount > kMaxColorAttachments,
            "Color formats count (%u) exceeds maximum number of color attachements (%u).",
            descriptor->colorFormatsCount, kMaxColorAttachments);

        DAWN_INVALID_IF(descriptor->colorFormatsCount == 0 &&
                            descriptor->depthStencilFormat == wgpu::TextureFormat::Undefined,
                        "No color or depth/stencil attachment formats specified.");

        for (uint32_t i = 0; i < descriptor->colorFormatsCount; ++i) {
            DAWN_TRY_CONTEXT(ValidateColorAttachmentFormat(device, descriptor->colorFormats[i]),
                             "validating colorFormats[%u]", i);
        }

        if (descriptor->depthStencilFormat != wgpu::TextureFormat::Undefined) {
            DAWN_TRY_CONTEXT(ValidateDepthStencilAttachmentFormat(
                                 device, descriptor->depthStencilFormat, descriptor->depthReadOnly,
                                 descriptor->stencilReadOnly),
                             "validating depthStencilFormat");
        }

        return {};
    }

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

    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
