// 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
