// Copyright 2019 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/dawn/native/AttachmentState.h"

#include <bit>

#include "src/dawn/common/Enumerator.h"
#include "src/dawn/native/ChainUtils.h"
#include "src/dawn/native/Device.h"
#include "src/dawn/native/ObjectContentHasher.h"
#include "src/dawn/native/PipelineLayout.h"
#include "src/dawn/native/Texture.h"
#include "src/utils/compiler.h"
#include "src/utils/log.h"
#include "src/utils/span.h"

namespace dawn::native {

AttachmentState::AttachmentState(const RenderBundleEncoderDescriptor* descriptor)
    : mSampleCount(descriptor->sampleCount) {
    DAWN_CHECK(descriptor->colorFormats.size() <= kMaxColorAttachmentsTyped);

    for (auto [i, format] : Enumerate(descriptor->colorFormats)) {
        if (format != wgpu::TextureFormat::Undefined) {
            mColorAttachmentsSet.set(i);
            mColorFormats[i] = format;
        }
    }
    mDepthStencilFormat = descriptor->depthStencilFormat;

    // TODO(dawn:1710): support MSAA render to single sampled in render bundles.
    // TODO(dawn:1710): support LoadOp::ExpandResolveTexture in render bundles.
    // TODO(dawn:1704): support PLS in render bundles.

    SetContentHash(ComputeContentHash());
}

AttachmentState::AttachmentState(const UnpackedPtr<RenderPipelineDescriptor>& descriptor,
                                 const PipelineLayoutBase* layout)
    : mSampleCount(descriptor->multisample.count) {
    if (descriptor->fragment != nullptr) {
        DAWN_CHECK(descriptor->fragment->targets.size() <= kMaxColorAttachmentsTyped);

        for (auto [i, target] : Enumerate(descriptor->fragment->targets)) {
            wgpu::TextureFormat format = target.format;
            if (format != wgpu::TextureFormat::Undefined) {
                mColorAttachmentsSet.set(i);
                mColorFormats[i] = format;

                UnpackedPtr<ColorTargetState> unpackedTarget = Unpack(&target);
                if (auto* expandResolveState =
                        unpackedTarget.Get<ColorTargetStateExpandResolveTextureDawn>()) {
                    mExpandResolveInfo.attachmentsToExpandResolve.set(i,
                                                                      expandResolveState->enabled);
                    // The presence of ColorTargetStateExpandResolveTextureDawn implies that
                    // this color target has a resolve target. Doesn't matter `enabled` is true or
                    // not.
                    mExpandResolveInfo.resolveTargetsMask.set(i);
                }
            }
        }
    }
    if (!mExpandResolveInfo.attachmentsToExpandResolve.any()) {
        // If render pipeline doesn't have any color target using ExpandResolveTexture load op then
        // ignore resolve targets. This is to relax compatibility requirement for common cases
        // where ExpandResolveTexture is not used.
        mExpandResolveInfo.resolveTargetsMask.reset();
    }

    DAWN_CHECK(IsSubset(mExpandResolveInfo.attachmentsToExpandResolve,
                        mExpandResolveInfo.resolveTargetsMask));

    if (descriptor->depthStencil != nullptr) {
        mDepthStencilFormat = descriptor->depthStencil->format;
    }

    mHasPLS = layout->HasPixelLocalStorage();
    mStorageAttachmentSlots = layout->GetStorageAttachmentSlots();

    SetContentHash(ComputeContentHash());
}

AttachmentState::AttachmentState(const UnpackedPtr<RenderPassDescriptor>& descriptor) {
    // Override the sample count with an explicit sample count if provided. This is currently only
    // valid if the MSAARenderToSingleSampled feature is enabled.
    bool msrtssAllowed = false;
    auto* renderPassSampleCount = descriptor.Get<DawnRenderPassSampleCount>();
    if (renderPassSampleCount != nullptr && renderPassSampleCount->sampleCount > 1) {
        mSampleCount = renderPassSampleCount->sampleCount;
        msrtssAllowed = true;
    }

    for (auto [i, colorAttachment] : Enumerate(descriptor->colorAttachments)) {
        TextureViewBase* attachment = colorAttachment.view;
        if (attachment == nullptr) {
            continue;
        }
        mColorAttachmentsSet.set(i);
        mColorFormats[i] = attachment->GetFormat().format;

        uint32_t attachmentSampleCount = attachment->GetTexture()->GetSampleCount();
        if (mSampleCount == 0) {
            mSampleCount = attachmentSampleCount;
        } else {
            // Attachment sample counts are allowed to either match the sample count for the pass
            // or, if MSAARenderToSingleSampled is enabled, be 1.
            DAWN_CHECK(mSampleCount == attachmentSampleCount ||
                       (msrtssAllowed && attachmentSampleCount == 1));
        }

        if (colorAttachment.loadOp == wgpu::LoadOp::ExpandResolveTexture) {
            mExpandResolveInfo.attachmentsToExpandResolve.set(i);
        }
        mExpandResolveInfo.resolveTargetsMask.set(i, colorAttachment.resolveTarget != nullptr);
    }

    // Gather the depth-stencil information.
    if (descriptor->depthStencilAttachment != nullptr) {
        TextureViewBase* attachment = descriptor->depthStencilAttachment->view;
        mDepthStencilFormat = attachment->GetFormat().format;
        if (mSampleCount == 0) {
            mSampleCount = attachment->GetTexture()->GetSampleCount();
        } else {
            DAWN_CHECK(mSampleCount == attachment->GetTexture()->GetSampleCount());
        }
    }

    if (!mExpandResolveInfo.attachmentsToExpandResolve.any()) {
        // If render pass doesn't have any color attachment using ExpandResolveTexture load op then
        // ignore resolve targets. This is to relax compatibility requirement for common cases
        // where ExpandResolveTexture is not used.
        mExpandResolveInfo.resolveTargetsMask.reset();
    }
    DAWN_CHECK(IsSubset(mExpandResolveInfo.attachmentsToExpandResolve,
                        mExpandResolveInfo.resolveTargetsMask));

    // Gather the PLS information.
    if (auto* pls = descriptor.Get<RenderPassPixelLocalStorage>()) {
        mHasPLS = true;
        mStorageAttachmentSlots = std::vector<wgpu::TextureFormat>(
            pls->totalPixelLocalStorageSize / kPLSSlotByteSize, wgpu::TextureFormat::Undefined);
        for (const RenderPassStorageAttachment& attachment : pls->storageAttachments) {
            size_t slot = attachment.offset / kPLSSlotByteSize;
            const TextureViewBase* storage = attachment.storage;

            mStorageAttachmentSlots[slot] = storage->GetFormat().format;
            if (mSampleCount == 0) {
                mSampleCount = storage->GetTexture()->GetSampleCount();
            } else {
                DAWN_CHECK(mSampleCount == storage->GetTexture()->GetSampleCount());
            }
        }
    }

    DAWN_CHECK(mSampleCount > 0);
    SetContentHash(ComputeContentHash());
}

AttachmentState::AttachmentState(const AttachmentState& blueprint) {
    mColorAttachmentsSet = blueprint.mColorAttachmentsSet;
    mColorFormats = blueprint.mColorFormats;
    mDepthStencilFormat = blueprint.mDepthStencilFormat;
    mSampleCount = blueprint.mSampleCount;
    mExpandResolveInfo = blueprint.mExpandResolveInfo;
    mHasPLS = blueprint.mHasPLS;
    mStorageAttachmentSlots = blueprint.mStorageAttachmentSlots;
    DAWN_CHECK(IsSubset(mExpandResolveInfo.attachmentsToExpandResolve,
                        mExpandResolveInfo.resolveTargetsMask));
    SetContentHash(blueprint.GetContentHash());
}

void AttachmentState::DeleteThis() {
    Uncache();
    RefCounted::DeleteThis();
}

bool AttachmentState::EqualityFunc::operator()(const AttachmentState* a,
                                               const AttachmentState* b) const {
    // Check set attachments
    if (a->mColorAttachmentsSet != b->mColorAttachmentsSet) {
        return false;
    }

    // Check color formats
    for (auto i : a->mColorAttachmentsSet) {
        if (a->mColorFormats[i] != b->mColorFormats[i]) {
            return false;
        }
    }

    // Check depth stencil format
    if (a->mDepthStencilFormat != b->mDepthStencilFormat) {
        return false;
    }

    // Check sample count
    if (a->mSampleCount != b->mSampleCount) {
        return false;
    }

    // Both attachment state must have the same `ExpandResolveTexture` load ops.
    if (a->mExpandResolveInfo.attachmentsToExpandResolve !=
        b->mExpandResolveInfo.attachmentsToExpandResolve) {
        return false;
    }

    if (a->mExpandResolveInfo.resolveTargetsMask != b->mExpandResolveInfo.resolveTargetsMask) {
        return false;
    }

    // Check PLS
    if (a->mHasPLS != b->mHasPLS) {
        return false;
    }
    if (a->mStorageAttachmentSlots.size() != b->mStorageAttachmentSlots.size()) {
        return false;
    }
    for (size_t i = 0; i < a->mStorageAttachmentSlots.size(); i++) {
        if (a->mStorageAttachmentSlots[i] != b->mStorageAttachmentSlots[i]) {
            return false;
        }
    }

    return true;
}

size_t AttachmentState::ComputeContentHash() {
    size_t hash = 0;

    // Hash color formats
    HashCombine(&hash, mColorAttachmentsSet);
    for (auto i : mColorAttachmentsSet) {
        HashCombine(&hash, mColorFormats[i]);
    }

    // Hash depth stencil attachment
    HashCombine(&hash, mDepthStencilFormat);

    // Hash sample count
    HashCombine(&hash, mSampleCount);

    // Hash expand resolve load op bits
    HashCombine(&hash, mExpandResolveInfo.attachmentsToExpandResolve);
    HashCombine(&hash, mExpandResolveInfo.resolveTargetsMask);

    // Hash the PLS state
    HashCombine(&hash, mHasPLS);
    for (wgpu::TextureFormat slotFormat : mStorageAttachmentSlots) {
        HashCombine(&hash, slotFormat);
    }

    return hash;
}

ColorAttachmentMask AttachmentState::GetColorAttachmentsMask() const {
    return mColorAttachmentsSet;
}

wgpu::TextureFormat AttachmentState::GetColorAttachmentFormat(ColorAttachmentIndex index) const {
    DAWN_CHECK(mColorAttachmentsSet[index]);
    return mColorFormats[index];
}

bool AttachmentState::HasDepthStencilAttachment() const {
    return mDepthStencilFormat != wgpu::TextureFormat::Undefined;
}

wgpu::TextureFormat AttachmentState::GetDepthStencilFormat() const {
    DAWN_CHECK(HasDepthStencilAttachment());
    return mDepthStencilFormat;
}

uint32_t AttachmentState::GetSampleCount() const {
    return mSampleCount;
}

const AttachmentState::ExpandResolveInfo& AttachmentState::GetExpandResolveInfo() const {
    return mExpandResolveInfo;
}

bool AttachmentState::HasPixelLocalStorage() const {
    return mHasPLS;
}

const std::vector<wgpu::TextureFormat>& AttachmentState::GetStorageAttachmentSlots() const {
    return mStorageAttachmentSlots;
}

std::vector<ColorAttachmentIndex>
AttachmentState::ComputeStorageAttachmentPackingInColorAttachments() const {
    // TODO(dawn:1704): Consider caching this on AttachmentState creation, but does it become part
    // of the hashing and comparison operators? Fill with garbage data to more easily detect cases
    // where an incorrect slot is accessed.
    std::vector<ColorAttachmentIndex> result(mStorageAttachmentSlots.size(),
                                             kMaxColorAttachmentsTyped.PlusOne());

    // Iterate over the empty bits of mColorAttachmentsSet to pack storage attachment in them.
    auto availableSlots = ~mColorAttachmentsSet;
    for (size_t i = 0; i < mStorageAttachmentSlots.size(); i++) {
        DAWN_CHECK(!availableSlots.none());
        auto slot = ColorAttachmentIndex(static_cast<uint8_t>(
            std::countr_zero(static_cast<uint32_t>(availableSlots.to_ulong()))));
        availableSlots.reset(slot);
        result[i] = slot;
    }

    return result;
}

}  // namespace dawn::native
