// 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,
                            &mBundleEncodingContext,
                            device->GetOrCreateAttachmentState(descriptor),
                            descriptor->depthReadOnly,
                            descriptor->stencilReadOnly),
          mBundleEncodingContext(device, this) {
    }

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

    // 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 Finish(%s).",
                                       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
