// 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),
                            false,
                            false),
          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)) {
            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(), 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
