/* Copyright (c) 2019-2021 The Khronos Group Inc.
 * Copyright (c) 2019-2021 Valve Corporation
 * Copyright (c) 2019-2021 LunarG, Inc.
 * Copyright (C) 2019-2021 Google Inc.
 *
 * 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.
 *
 * John Zulauf <jzulauf@lunarg.com>
 *
 */
#include <cassert>
#include "subresource_adapter.h"
#include "vk_format_utils.h"
#include <cmath>
#include "image_state.h"
#include "layer_chassis_dispatch.h"

namespace subresource_adapter {
Subresource::Subresource(const RangeEncoder& encoder, const VkImageSubresource& subres)
    : VkImageSubresource({0, subres.mipLevel, subres.arrayLayer}), aspect_index() {
    aspect_index = encoder.LowerBoundFromMask(subres.aspectMask);
    aspectMask = encoder.AspectBit(aspect_index);
}

IndexType RangeEncoder::Encode1AspectArrayOnly(const Subresource& pos) const { return pos.arrayLayer; }
IndexType RangeEncoder::Encode1AspectMipArray(const Subresource& pos) const { return pos.arrayLayer + pos.mipLevel * mip_size_; }
IndexType RangeEncoder::Encode1AspectMipOnly(const Subresource& pos) const { return pos.mipLevel; }

IndexType RangeEncoder::EncodeAspectArrayOnly(const Subresource& pos) const {
    return pos.arrayLayer + aspect_base_[pos.aspect_index];
}
IndexType RangeEncoder::EncodeAspectMipArray(const Subresource& pos) const {
    return pos.arrayLayer + pos.mipLevel * mip_size_ + aspect_base_[pos.aspect_index];
}
IndexType RangeEncoder::EncodeAspectMipOnly(const Subresource& pos) const { return pos.mipLevel + aspect_base_[pos.aspect_index]; }

uint32_t RangeEncoder::LowerBoundImpl1(VkImageAspectFlags aspect_mask) const {
    assert(aspect_mask & aspect_bits_[0]);
    return 0;
}
uint32_t RangeEncoder::LowerBoundWithStartImpl1(VkImageAspectFlags aspect_mask, uint32_t start) const {
    assert(start == 0);
    if (aspect_mask & aspect_bits_[0]) {
        return 0;
    }
    return limits_.aspect_index;
}

uint32_t RangeEncoder::LowerBoundImpl2(VkImageAspectFlags aspect_mask) const {
    if (aspect_mask & aspect_bits_[0]) {
        return 0;
    }
    assert(aspect_mask & aspect_bits_[1]);
    return 1;
}
uint32_t RangeEncoder::LowerBoundWithStartImpl2(VkImageAspectFlags aspect_mask, uint32_t start) const {
    switch (start) {
        case 0:
            if (aspect_mask & aspect_bits_[0]) {
                return 0;
            }
            // no break
        case 1:
            if (aspect_mask & aspect_bits_[1]) {
                return 1;
            }
            break;
        default:
            break;
    }
    return limits_.aspect_index;
}

uint32_t RangeEncoder::LowerBoundImpl3(VkImageAspectFlags aspect_mask) const {
    if (aspect_mask & aspect_bits_[0]) {
        return 0;
    } else if (aspect_mask & aspect_bits_[1]) {
        return 1;
    } else {
        assert(aspect_mask & aspect_bits_[2]);
        return 2;
    }
}

uint32_t RangeEncoder::LowerBoundWithStartImpl3(VkImageAspectFlags aspect_mask, uint32_t start) const {
    switch (start) {
        case 0:
            if (aspect_mask & aspect_bits_[0]) {
                return 0;
            }
            // no break
        case 1:
            if ((aspect_mask & aspect_bits_[1])) {
                return 1;
            }
            // no break
        case 2:
            if ((aspect_mask & aspect_bits_[2])) {
                return 2;
            }
            break;
        default:
            break;
    }
    return limits_.aspect_index;
}

void RangeEncoder::PopulateFunctionPointers() {
    // Select the encode/decode specialists
    if (limits_.aspect_index == 1) {
        // One aspect use simplified encode/decode math
        if (limits_.arrayLayer == 1) {  // Same as mip_size_ == 1
            encode_function_ = &RangeEncoder::Encode1AspectMipOnly;
            decode_function_ = &RangeEncoder::DecodeAspectMipOnly<1>;
        } else if (limits_.mipLevel == 1) {
            encode_function_ = &RangeEncoder::Encode1AspectArrayOnly;
            decode_function_ = &RangeEncoder::DecodeAspectArrayOnly<1>;
        } else {
            encode_function_ = &RangeEncoder::Encode1AspectMipArray;
            decode_function_ = &RangeEncoder::DecodeAspectMipArray<1>;
        }
        lower_bound_function_ = &RangeEncoder::LowerBoundImpl1;
        lower_bound_with_start_function_ = &RangeEncoder::LowerBoundWithStartImpl1;
    } else if (limits_.aspect_index == 2) {
        // Two aspect use simplified encode/decode math
        if (limits_.arrayLayer == 1) {  // Same as mip_size_ == 1
            encode_function_ = &RangeEncoder::EncodeAspectMipOnly;
            decode_function_ = &RangeEncoder::DecodeAspectMipOnly<2>;
        } else if (limits_.mipLevel == 1) {
            encode_function_ = &RangeEncoder::EncodeAspectArrayOnly;
            decode_function_ = &RangeEncoder::DecodeAspectArrayOnly<2>;
        } else {
            encode_function_ = &RangeEncoder::EncodeAspectMipArray;
            decode_function_ = &RangeEncoder::DecodeAspectMipArray<2>;
        }
        lower_bound_function_ = &RangeEncoder::LowerBoundImpl2;
        lower_bound_with_start_function_ = &RangeEncoder::LowerBoundWithStartImpl2;
    } else {
        encode_function_ = &RangeEncoder::EncodeAspectMipArray;
        decode_function_ = &RangeEncoder::DecodeAspectMipArray<3>;
        lower_bound_function_ = &RangeEncoder::LowerBoundImpl3;
        lower_bound_with_start_function_ = &RangeEncoder::LowerBoundWithStartImpl3;
    }

    // Initialize the offset array
    aspect_base_[0] = 0;
    for (uint32_t i = 1; i < limits_.aspect_index; ++i) {
        aspect_base_[i] = aspect_base_[i - 1] + aspect_size_;
    }
}

RangeEncoder::RangeEncoder(const VkImageSubresourceRange& full_range, const AspectParameters* param)
    : limits_(param->AspectMask(), full_range.levelCount, full_range.layerCount, param->AspectCount()),
      full_range_(full_range),
      mip_size_(full_range.layerCount),
      aspect_size_(mip_size_ * full_range.levelCount),
      aspect_bits_(param->AspectBits()),
      mask_index_function_(param->MaskToIndexFunction()),
      encode_function_(nullptr),
      decode_function_(nullptr) {
    // Only valid to create an encoder for a *whole* image (i.e. base must be zero, and the specified limits_.selected_aspects
    // *must* be equal to the traits aspect mask. (Encoder range assumes zero bases)
    assert(full_range.aspectMask == limits_.aspectMask);
    assert(full_range.baseArrayLayer == 0);
    assert(full_range.baseMipLevel == 0);
    // TODO: should be some static assert
    assert(param->AspectCount() <= kMaxSupportedAspect);
    PopulateFunctionPointers();
}

#ifndef NDEBUG
static bool IsValid(const RangeEncoder& encoder, const VkImageSubresourceRange& bounds) {
    const auto& limits = encoder.Limits();
    return (((bounds.aspectMask & limits.aspectMask) == bounds.aspectMask) &&
            (bounds.baseMipLevel + bounds.levelCount <= limits.mipLevel) &&
            (bounds.baseArrayLayer + bounds.layerCount <= limits.arrayLayer));
}
#endif

// Create an iterator like "generator" that for each increment produces the next index range matching the
// next contiguous (in index space) section of the VkImageSubresourceRange
// Ranges will always span the layerCount layers, and if the layerCount is the full range of the image (as known by
// the encoder) will span the levelCount mip levels as weill.
RangeGenerator::RangeGenerator(const RangeEncoder& encoder, const VkImageSubresourceRange& subres_range)
    : encoder_(&encoder), isr_pos_(encoder, subres_range), pos_(), aspect_base_() {
    assert((((isr_pos_.Limits()).aspectMask & (encoder.Limits()).aspectMask) == (isr_pos_.Limits()).aspectMask));
    assert((isr_pos_.Limits()).baseMipLevel + (isr_pos_.Limits()).levelCount <= (encoder.Limits()).mipLevel);
    assert((isr_pos_.Limits()).baseArrayLayer + (isr_pos_.Limits()).layerCount <= (encoder.Limits()).arrayLayer);

    // To see if we have a full range special case, need to compare the subres_range against the *encoders* limits
    const auto& limits = encoder.Limits();
    if ((subres_range.baseArrayLayer == 0 && subres_range.layerCount == limits.arrayLayer)) {
        if ((subres_range.baseMipLevel == 0) && (subres_range.levelCount == limits.mipLevel)) {
            if (subres_range.aspectMask == limits.aspectMask) {
                // Full range
                pos_.begin = 0;
                pos_.end = encoder.AspectSize() * limits.aspect_index;
                aspect_count_ = 1;  // Flag this to never advance aspects.
            } else {
                // All mips all layers but not all aspect
                pos_.begin = encoder.AspectBase(isr_pos_.aspect_index);
                pos_.end = pos_.begin + encoder.AspectSize();
                aspect_count_ = limits.aspect_index;
            }
        } else {
            // All array layers, but not all levels
            pos_.begin = encoder.AspectBase(isr_pos_.aspect_index) + subres_range.baseMipLevel * encoder.MipSize();
            pos_.end = pos_.begin + subres_range.levelCount * encoder.MipSize();
            aspect_count_ = limits.aspect_index;
        }

        // Full set of array layers at a time, thus we can span across all selected mip levels
        mip_count_ = 1;  // we don't ever advance across mips, as we do all of then in one range
    } else {
        // Each range covers all included array_layers for each selected mip_level for each given selected aspect
        // so we'll use the general purpose encode and smallest range size
        pos_.begin = encoder.Encode(isr_pos_);
        pos_.end = pos_.begin + subres_range.layerCount;

        // we do have to traverse across mips, though (other than Encode abover), we don't have to know which one we are on.
        mip_count_ = subres_range.levelCount;
        aspect_count_ = limits.aspect_index;
    }

    // To get to the next aspect range we offset from the last base
    aspect_base_ = pos_;
    mip_index_ = 0;
    aspect_index_ = isr_pos_.aspect_index;
}

RangeGenerator& RangeGenerator::operator++() {
    mip_index_++;
    // NOTE: If all selected mip levels are done at once, mip_count_ is set to one, not the number of selected mip_levels
    if (mip_index_ >= mip_count_) {
        const auto last_aspect_index = aspect_index_;
        // Seek the next value aspect (if any)
        aspect_index_ = encoder_->LowerBoundFromMask(isr_pos_.Limits().aspectMask, aspect_index_ + 1);
        if (aspect_index_ < aspect_count_) {
            // Force isr_pos to the beginning of this found aspect
            isr_pos_.SeekAspect(aspect_index_);
            // SubresourceGenerator should never be at tombstones we we aren't
            assert(isr_pos_.aspectMask != 0);

            // Offset by the distance between the last start of aspect and *this* start of aspect
            aspect_base_ += (encoder_->AspectBase(isr_pos_.aspect_index) - encoder_->AspectBase(last_aspect_index));
            pos_ = aspect_base_;
            mip_index_ = 0;
        } else {
            // Tombstone both index range and subresource positions to "At end" convention
            pos_ = {0, 0};
            isr_pos_.aspectMask = 0;
        }
    } else {
        // Note: for the layerCount < full_range.layerCount case, because the generated ranges per mip_level are discontinuous
        // we have to do each individual array of ranges
        pos_ += encoder_->MipSize();
        isr_pos_.SeekMip(isr_pos_.Limits().baseMipLevel + mip_index_);
    }
    return *this;
}

ImageRangeEncoder::ImageRangeEncoder(const IMAGE_STATE& image)
    : ImageRangeEncoder(image, AspectParameters::Get(image.full_range.aspectMask)) {}

ImageRangeEncoder::ImageRangeEncoder(const IMAGE_STATE& image, const AspectParameters* param)
    : RangeEncoder(image.full_range, param), image_(&image), total_size_(0U) {
    if (image_->createInfo.extent.depth > 1) {
        limits_.arrayLayer = image_->createInfo.extent.depth;
    }
    VkSubresourceLayout layout = {};
    VkImageSubresource subres = {};
    VkImageSubresourceLayers subres_layers = {limits_.aspectMask, 0, 0, limits_.arrayLayer};
    linear_image_ = false;

    // WORKAROUND for dev_sim and mock_icd not containing valid VkSubresourceLayout yet. Treat it as optimal image.
    if (image_->createInfo.tiling == VK_IMAGE_TILING_LINEAR) {
        subres = {static_cast<VkImageAspectFlags>(AspectBit(0)), 0, 0};
        DispatchGetImageSubresourceLayout(image_->store_device_as_workaround, image_->image(), &subres, &layout);
        if (layout.size > 0) {
            linear_image_ = true;
        }
    }

    is_compressed_ = FormatIsCompressed(image.createInfo.format);
    texel_extent_ = FormatTexelBlockExtent(image.createInfo.format);

    is_3_d_ = image_->createInfo.imageType == VK_IMAGE_TYPE_3D;
    y_interleave_ = false;
    for (uint32_t aspect_index = 0; aspect_index < limits_.aspect_index; ++aspect_index) {
        subres.aspectMask = static_cast<VkImageAspectFlags>(AspectBit(aspect_index));
        subres_layers.aspectMask = subres.aspectMask;
        texel_sizes_.push_back(FormatTexelSize(image.createInfo.format, subres.aspectMask));
        IndexType aspect_size = 0;
        for (uint32_t mip_index = 0; mip_index < limits_.mipLevel; ++mip_index) {
            subres_layers.mipLevel = mip_index;
            subres.mipLevel = mip_index;
            auto subres_extent = image_->GetSubresourceExtent(subres_layers);

            if (linear_image_) {
                DispatchGetImageSubresourceLayout(image_->store_device_as_workaround, image_->image(), &subres, &layout);
                if (is_3_d_) {
                    if ((layout.depthPitch == 0) && (subres_extent.depth == 1)) {
                        layout.depthPitch = layout.size;  // Certain implmentations don't supply pitches when size is 1
                    }
                    y_interleave_ = y_interleave_ || (layout.rowPitch > layout.depthPitch);
                } else {
                    if ((layout.arrayPitch == 0) && (limits_.arrayLayer == 1)) {
                        layout.arrayPitch = layout.size;  // Certain implmentations don't supply pitches when size is 1
                    }
                    y_interleave_ = y_interleave_ || (layout.rowPitch > layout.arrayPitch);
                }
            } else {
                layout.offset += layout.size;
                layout.rowPitch = static_cast<VkDeviceSize>(floor(subres_extent.width * texel_sizes_[aspect_index]));
                layout.arrayPitch = layout.rowPitch * subres_extent.height;
                layout.depthPitch = layout.arrayPitch;
                if (is_3_d_) {
                    layout.size = layout.depthPitch * subres_extent.depth;
                } else {
                    // 2D arrays are not affected by MIP level extent reductions.
                    layout.size = layout.arrayPitch * limits_.arrayLayer;
                }
            }
            subres_info_.emplace_back(layout, subres_extent, texel_extent_, texel_sizes_[aspect_index]);
            aspect_size += layout.size;
            total_size_ += layout.size;
        }
        aspect_sizes_.emplace_back(aspect_size);
    }
}

IndexType ImageRangeEncoder::Encode2D(const VkSubresourceLayout& layout, uint32_t layer, uint32_t aspect_index,
                                      const VkOffset3D& offset) const {
    assert(offset.z == 0U);
    return layout.offset + layer * layout.arrayPitch + offset.y * layout.rowPitch +
           (offset.x ? static_cast<IndexType>(floor(offset.x * texel_sizes_[aspect_index])) : 0U);
}

IndexType ImageRangeEncoder::Encode3D(const VkSubresourceLayout& layout, uint32_t aspect_index, const VkOffset3D& offset) const {
    return layout.offset + offset.z * layout.depthPitch + offset.y * layout.rowPitch +
           (offset.x ? static_cast<IndexType>(floor(offset.x * texel_sizes_[aspect_index])) : 0U);
}

void ImageRangeEncoder::Decode(const VkImageSubresource& subres, const IndexType& encode, uint32_t& out_layer,
                               VkOffset3D& out_offset) const {
    uint32_t subres_index = GetSubresourceIndex(LowerBoundFromMask(subres.aspectMask), subres.mipLevel);
    const auto& subres_layout = GetSubresourceInfo(subres_index).layout;
    IndexType decode = encode - subres_layout.offset;
    out_layer = static_cast<uint32_t>(decode / subres_layout.arrayPitch);
    decode -= (out_layer * subres_layout.arrayPitch);
    out_offset.z = static_cast<int32_t>(decode / subres_layout.depthPitch);
    decode -= (out_offset.z * subres_layout.depthPitch);
    out_offset.y = static_cast<int32_t>(decode / subres_layout.rowPitch);
    decode -= (out_offset.y * subres_layout.rowPitch);
    out_offset.x = static_cast<int32_t>(static_cast<double>(decode) / texel_sizes_[LowerBoundFromMask(subres.aspectMask)]);
}


inline VkImageSubresourceRange GetRemaining(const VkImageSubresourceRange& full_range, VkImageSubresourceRange subres_range) {
    if (subres_range.levelCount == VK_REMAINING_MIP_LEVELS) {
        subres_range.levelCount = full_range.levelCount - subres_range.baseMipLevel;
    }
    if (subres_range.layerCount == VK_REMAINING_ARRAY_LAYERS) {
        subres_range.layerCount = full_range.layerCount - subres_range.baseArrayLayer;
    }
    return subres_range;
}
inline bool CoversAllLayers(const VkImageSubresourceRange& full_range, VkImageSubresourceRange subres_range) {
    return (subres_range.baseArrayLayer == 0) && (subres_range.layerCount == full_range.layerCount);
}
inline bool CoversAllLevels(const VkImageSubresourceRange& full_range, VkImageSubresourceRange subres_range) {
    return (subres_range.baseMipLevel == 0) && (subres_range.layerCount == full_range.levelCount);
}
inline bool CoversAllAspects(const VkImageSubresourceRange& full_range, VkImageSubresourceRange subres_range) {
    return full_range.aspectMask == subres_range.aspectMask;
}

static bool SubresourceRangeIsEmpty(const VkImageSubresourceRange& range) {
    return (0 == range.aspectMask) || (0 == range.levelCount) || (0 == range.layerCount);
}
static bool ExtentIsEmpty(const VkExtent3D& extent) { return (0 == extent.width) || (0 == extent.height) || (0 == extent.width); }

void ImageRangeGenerator::SetInitialPosFullOffset(uint32_t layer, uint32_t aspect_index) {
    const bool is_3D = encoder_->Is3D();
    const auto& subres_layout = subres_info_->layout;
    const IndexType encode_base = is_3D ? encoder_->Encode3D(subres_layout, aspect_index, offset_)
                                        : encoder_->Encode2D(subres_layout, layer, aspect_index, offset_);
    const IndexType base = base_address_ + encode_base;
    // To deal with compressed formats the span must cover the y-extent of lines (something we resmember in the y_step)
    const IndexType span = static_cast<IndexType>(floor(encoder_->TexelSize(aspect_index) * (extent_.width * incr_state_.y_step)));

    const uint32_t z_count = is_3D ? extent_.depth : subres_range_.layerCount;
    const IndexType z_pitch = is_3D ? subres_info_->z_step_pitch : subres_layout.arrayPitch;
    incr_state_.Set(extent_.height, z_count, base, span, subres_info_->y_step_pitch, z_pitch);
}

void ImageRangeGenerator::SetInitialPosFullWidth(uint32_t layer, uint32_t aspect_index) {
    assert(!encoder_->IsInterleaveY() && (offset_.x == 0));
    const bool is_3D = encoder_->Is3D();
    const auto& subres_layout = subres_info_->layout;
    const IndexType encode_base = is_3D ? encoder_->Encode3D(subres_layout, aspect_index, offset_)
                                        : encoder_->Encode2D(subres_layout, layer, aspect_index, offset_);
    const IndexType base = base_address_ + encode_base;
    // Height must be in multiples of y_step (the texel dimension)... validated elsewhere
    const IndexType span = subres_layout.rowPitch * extent_.height;

    const uint32_t z_count = is_3D ? extent_.depth : subres_range_.layerCount;
    const IndexType z_pitch = is_3D ? subres_info_->z_step_pitch : subres_layout.arrayPitch;
    incr_state_.Set(1U, z_count, base, span, subres_info_->y_step_pitch, z_pitch);
}

void ImageRangeGenerator::SetInitialPosFullHeight(uint32_t layer, uint32_t aspect_index) {
    assert(!encoder_->Is3D() && (offset_.x == 0) && (offset_.y == 0));
    const auto& subres_layout = subres_info_->layout;
    const IndexType base = base_address_ + subres_layout.offset + subres_range_.baseArrayLayer * subres_layout.arrayPitch;
    const IndexType span = subres_info_->layer_span;
    const IndexType z_step = subres_layout.arrayPitch;

    incr_state_.Set(1, subres_range_.layerCount, base, span, span, z_step);
}

void ImageRangeGenerator::SetInitialPosSomeDepth(uint32_t layer, uint32_t aspect_index) {
    assert(encoder_->Is3D() && (offset_.x == 0) && (offset_.y == 0) && (layer == 0));
    const auto& subres_layout = subres_info_->layout;
    const IndexType encode_base = encoder_->Encode3D(subres_layout, aspect_index, offset_);
    const IndexType base = base_address_ + encode_base;
    // Height must be in multiples of z_step (the texel dimension)... validated elsewhere
    const IndexType span = subres_layout.depthPitch * extent_.depth;

    incr_state_.Set(1, 1, base, span, span, subres_layout.size);
}

void ImageRangeGenerator::SetInitialPosFullDepth(uint32_t layer, uint32_t aspect_index) {
    assert(encoder_->Is3D() && (offset_.x == 0) && (offset_.y == 0) && (offset_.z == 0) && (layer == 0));
    const auto& subres_layout = subres_info_->layout;
    const IndexType base = base_address_ + subres_layout.offset;
    const IndexType span = subres_layout.depthPitch * extent_.depth;

    incr_state_.Set(1, 1, base, span, span, span);
}

void ImageRangeGenerator::SetInitialPosSomeLayers(uint32_t layer, uint32_t aspect_index) {
    assert(!encoder_->Is3D() && (offset_.x == 0) && (offset_.y == 0) && (offset_.z == 0));
    const auto& subres_layout = subres_info_->layout;
    const IndexType base = base_address_ + subres_layout.offset + layer * subres_layout.arrayPitch;
    const IndexType span = subres_layout.arrayPitch * subres_range_.layerCount;
    const IndexType z_step = subres_layout.arrayPitch * encoder_->Limits().arrayLayer;
    incr_state_.Set(1, 1, base, span, span, z_step);
}

void ImageRangeGenerator::SetInitialPosAllLayers(uint32_t layer, uint32_t aspect_index) {
    assert(!encoder_->Is3D() && (offset_.x == 0) && (offset_.y == 0) && (offset_.z == 0) &&
           (layer == 0));
    const auto& subres_layout = subres_info_->layout;
    const IndexType base = base_address_ + subres_layout.offset;
    const IndexType span = subres_layout.arrayPitch * subres_range_.layerCount;
    incr_state_.Set(1, 1, base, span, span, span);
}

void ImageRangeGenerator::SetInitialPosOneAspect(uint32_t layer, uint32_t aspect_index) {
    assert(!encoder_->IsLinearImage());  // Requires the major minor of "idealized/non-linear" images
    const auto& subres_layout = subres_info_->layout;
    const IndexType base = base_address_ + subres_layout.offset;
    IndexType span = 0;
    if (subres_range_.levelCount == encoder_->Limits().mipLevel) {
        span = encoder_->GetAspectSize(aspect_index);
    } else {
        // Add up the mip sizes...
        // Assumes subres_info is pointing to index(baseMipLevel, aspect_index)
        // Assumes mip major order...
        for (uint32_t level = 0; level < subres_range_.levelCount; level++) {
            span += subres_info_[level].layout.size;
        }
    }
    incr_mip_ = subres_range_.levelCount;
    incr_state_.Set(1, 1, base, span, span, span);
}

void ImageRangeGenerator::SetInitialPosAllSubres(uint32_t layer, uint32_t aspect_index) {
    assert(!encoder_->IsLinearImage());
    const IndexType base = base_address_;
    const IndexType span = encoder_->TotalSize();

    // Just one range... everything, ++ will short circuit to "end"
    single_full_size_range_ = true;
    // We don't need to set up the rest of the incrementer, just the starting position
    incr_state_.y_base = {base, base + span};
}

bool ImageRangeGenerator::Convert2DCompatibleTo3D() {
    if (encoder_->Is3D()) {
        if ((subres_range_.levelCount == 1) && ((subres_range_.baseArrayLayer > 0) || (subres_range_.layerCount > 1))) {
            // This only valid for 2D compatible 3D images
            // Touch up the extent and the subres to make this look like a depth extent
            offset_.z = subres_range_.baseArrayLayer;
            subres_range_.baseArrayLayer = 0;
            extent_.depth = subres_range_.layerCount;
            subres_range_.layerCount = 1;
            return true;
        }
    }
    return false;
}
ImageRangeGenerator::ImageRangeGenerator(const ImageRangeEncoder& encoder, const VkImageSubresourceRange& subres_range,
                                         VkDeviceSize base_address)
    : encoder_(&encoder),
      subres_range_(GetRemaining(encoder.FullRange(), subres_range)),
      offset_(),
      extent_(),
      base_address_(base_address) {
#ifndef NDEBUG
    assert(IsValid(*encoder_, subres_range_));
#endif
    if (SubresourceRangeIsEmpty(subres_range)) {
        // Not robust to empty ranges, so for to "at end" condition.
        pos_ = {0, 0};
        return;
    }

    SetUpSubresInfo();
    extent_ = subres_info_->extent;
    const bool converted = Convert2DCompatibleTo3D();
    SetUpIncrementerDefaults();
    if (converted && (extent_.depth != subres_info_->extent.depth)) {
        SetUpIncrementer(true, true, false);
    } else {
        SetUpSubresIncrementer();
    }
    SetInitialPos(subres_range_.baseArrayLayer, aspect_index_);
    pos_ = incr_state_.y_base;
}

ImageRangeGenerator::ImageRangeGenerator(const ImageRangeEncoder& encoder, const VkImageSubresourceRange& subres_range,
                                         const VkOffset3D& offset, const VkExtent3D& extent, VkDeviceSize base_address)
    : encoder_(&encoder),
      subres_range_(GetRemaining(encoder.FullRange(), subres_range)),
      offset_(offset),
      extent_(extent),
      base_address_(base_address) {
#ifndef NDEBUG
    assert(IsValid(*encoder_, subres_range_));
#endif

    assert(subres_range_.levelCount == 1);
    if (SubresourceRangeIsEmpty(subres_range)) {
        // Empty range forces empty position -- no operations other than deref for empty check are valid
        pos_ = {0, 0};
        return;
    }

    // When passing in an offset and extent, *must* only specify *one* mip level
    SetUpSubresInfo();
    Convert2DCompatibleTo3D();

    const VkExtent3D& subres_extent = subres_info_->extent;
    if (ExtentIsEmpty(extent_) || ((extent_.width + offset_.x) > subres_extent.width) ||
        ((extent_.height + offset_.y) > subres_extent.height) || ((extent_.depth + offset_.z) > subres_extent.depth)) {
        // Empty range forces empty position -- no operations other than deref for empty check are valid
        pos_ = {0, 0};
        return;
    }

    const bool all_width = (offset.x == 0) && (extent_.width == subres_extent.width);
    const bool all_height = (offset.y == 0) && (extent_.height == subres_extent.height);
    const bool all_depth = !encoder_->Is3D() || ((offset.z == 0) && (extent_.depth == subres_extent.depth));

    SetUpIncrementerDefaults();
    SetUpIncrementer(all_width, all_height, all_depth);
    SetInitialPos(subres_range_.baseArrayLayer, aspect_index_);
    pos_ = incr_state_.y_base;
}

void ImageRangeGenerator::SetUpSubresInfo() {
    mip_index_ = 0;
    aspect_index_ = encoder_->LowerBoundFromMask(subres_range_.aspectMask);
    subres_index_ = encoder_->GetSubresourceIndex(aspect_index_, subres_range_.baseMipLevel);
    subres_info_ = &encoder_->GetSubresourceInfo(subres_index_);
}

void ImageRangeGenerator::SetUpIncrementerDefaults() {
    // These are safe defaults that most SetInitialPos* will use.  Those that need to change them, do.
    incr_state_.y_step = encoder_->TexelExtent().height;
    incr_state_.layer_z_step = encoder_->Is3D() ? encoder_->TexelExtent().depth : 1U;
    incr_mip_ = 1;
    single_full_size_range_ = false;
}

// Assumes full extent in width/height/depth(if present)
void ImageRangeGenerator::SetUpSubresIncrementer() {
    const auto& full_range = encoder_->FullRange();
    const bool linear_image = encoder_->IsLinearImage();
    const bool is_3d = encoder_->Is3D();
    const bool layers_interleave = linear_image && (subres_info_->layout.arrayPitch > subres_info_->layout.size);
    if (layers_interleave) {
        // The implementation can interleave arrays, aspects, and mips arbitrarily
        if (encoder_->Is3D()) {
            set_initial_pos_fn_ = &ImageRangeGenerator::SetInitialPosFullDepth;
        } else {
            set_initial_pos_fn_ = &ImageRangeGenerator::SetInitialPosFullHeight;
        }
    } else if (is_3d || CoversAllLayers(full_range, subres_range_)) {
        if (!linear_image) {
            // Linear images are defined by the implementation and so we can't assume the ordering we use here
            bool all_mips = (subres_range_.baseMipLevel == 0) && (subres_range_.levelCount == full_range.levelCount);
            bool all_aspects = subres_range_.aspectMask == full_range.aspectMask;
            if (all_aspects && all_mips) {
                set_initial_pos_fn_ = &ImageRangeGenerator::SetInitialPosAllSubres;
            } else {
                set_initial_pos_fn_ = &ImageRangeGenerator::SetInitialPosOneAspect;
            }
        } else if (is_3d) {
            // 3D implies CoversAllLayers
            set_initial_pos_fn_ = &ImageRangeGenerator::SetInitialPosFullDepth;
        } else {
            set_initial_pos_fn_ = &ImageRangeGenerator::SetInitialPosAllLayers;
        }
    } else {
        set_initial_pos_fn_ = &ImageRangeGenerator::SetInitialPosSomeLayers;
    }
}

void ImageRangeGenerator::SetUpIncrementer(bool all_width, bool all_height, bool all_depth) {
    if (!all_width || encoder_->IsInterleaveY()) {
        // Dimensional majority is not guaranteed for Linear images except in X
        // For tiled images we can use "idealized" addresses
        set_initial_pos_fn_ = &ImageRangeGenerator::SetInitialPosFullOffset;
    } else if (!all_height) {
        set_initial_pos_fn_ = &ImageRangeGenerator::SetInitialPosFullWidth;
    } else if (encoder_->Is3D() && !all_depth) {
        set_initial_pos_fn_ = &ImageRangeGenerator::SetInitialPosSomeDepth;
    } else {
        SetUpSubresIncrementer();
    }
}

ImageRangeGenerator& ImageRangeGenerator::operator++() {
    // Short circuit
    if (single_full_size_range_) {
        // Advance directly to end
        pos_ = {0, 0};
        return *this;
    }

    incr_state_.y_index += incr_state_.y_step;
    if (incr_state_.y_index < incr_state_.y_count) {
        incr_state_.y_base += incr_state_.incr_y;
        pos_ = incr_state_.y_base;
    } else {
        incr_state_.layer_z_index += incr_state_.layer_z_step;
        if (incr_state_.layer_z_index < incr_state_.layer_z_count) {
            incr_state_.layer_z_base += incr_state_.incr_layer_z;
            incr_state_.y_base = incr_state_.layer_z_base;
            pos_ = incr_state_.y_base;
        } else {
            // For aspects and mips we need to move to a new subresource layer info
            mip_index_ += incr_mip_;
            if (mip_index_ < subres_range_.levelCount) {
                // NOTE: This means that ImageRangeGenerator is relying on the major/minor ordering of mip and aspect in the
                subres_index_ += incr_mip_;
                extent_ = subres_info_->extent;  // Overwrites input extent, but > 1 MIP isn't valid with input extent
            } else {
                const auto next_aspect_index = encoder_->LowerBoundFromMask(subres_range_.aspectMask, aspect_index_ + 1);
                if (next_aspect_index < encoder_->Limits().aspect_index) {
                    //       SubresourceLayout info in ImageRangeEncoder... it's a cheat, but it was a hotspot.
                    aspect_index_ = next_aspect_index;
                    mip_index_ = 0;
                    subres_index_ = encoder_->GetSubresourceIndex(aspect_index_, subres_range_.baseMipLevel);
                } else {
                    // At End
                    pos_ = {0, 0};
                    return *this;
                }
            }

            subres_info_ = &encoder_->GetSubresourceInfo(subres_index_);
            SetInitialPos(subres_range_.baseArrayLayer, aspect_index_);
            pos_ = incr_state_.y_base;
        }
    }

    return *this;
}

template <typename AspectTraits>
class AspectParametersImpl : public AspectParameters {
  public:
    VkImageAspectFlags AspectMask() const override { return AspectTraits::kAspectMask; }
    MaskIndexFunc MaskToIndexFunction() const override { return &AspectTraits::MaskIndex; }
    uint32_t AspectCount() const override { return AspectTraits::kAspectCount; };
    const VkImageAspectFlagBits* AspectBits() const override { return AspectTraits::AspectBits().data(); }
};

struct NullAspectTraits {
    static constexpr uint32_t kAspectCount = 0;
    static constexpr VkImageAspectFlags kAspectMask = 0;
    static uint32_t MaskIndex(VkImageAspectFlags mask) { return 0; };
    static const std::array<VkImageAspectFlagBits, kAspectCount>& AspectBits() {
        static std::array<VkImageAspectFlagBits, kAspectCount> k_aspect_bits{};
        return k_aspect_bits;
    }
};

struct ColorAspectTraits {
    static constexpr uint32_t kAspectCount = 1;
    static constexpr VkImageAspectFlags kAspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    static uint32_t MaskIndex(VkImageAspectFlags mask) { return 0; };
    static const std::array<VkImageAspectFlagBits, kAspectCount>& AspectBits() {
        static std::array<VkImageAspectFlagBits, kAspectCount> k_aspect_bits{{VK_IMAGE_ASPECT_COLOR_BIT}};
        return k_aspect_bits;
    }
};

struct DepthAspectTraits {
    static constexpr uint32_t kAspectCount = 1;
    static constexpr VkImageAspectFlags kAspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
    static uint32_t MaskIndex(VkImageAspectFlags mask) { return 0; };
    static const std::array<VkImageAspectFlagBits, kAspectCount>& AspectBits() {
        static std::array<VkImageAspectFlagBits, kAspectCount> k_aspect_bits{{VK_IMAGE_ASPECT_DEPTH_BIT}};
        return k_aspect_bits;
    }
};

struct StencilAspectTraits {
    static constexpr uint32_t kAspectCount = 1;
    static constexpr VkImageAspectFlags kAspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
    static uint32_t MaskIndex(VkImageAspectFlags mask) { return 0; };
    static const std::array<VkImageAspectFlagBits, kAspectCount>& AspectBits() {
        static std::array<VkImageAspectFlagBits, kAspectCount> k_aspect_bits{{VK_IMAGE_ASPECT_STENCIL_BIT}};
        return k_aspect_bits;
    }
};

struct DepthStencilAspectTraits {
    // VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002,  >> 1 -> 1 -1 -> 0
    // VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004, >> 1 -> 2 -1 = 1
    static constexpr uint32_t kAspectCount = 2;
    static constexpr VkImageAspectFlags kAspectMask = (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
    static uint32_t MaskIndex(VkImageAspectFlags mask) {
        uint32_t index = (mask >> 1) - 1;
        assert((index == 0) || (index == 1));
        return index;
    };
    static const std::array<VkImageAspectFlagBits, kAspectCount>& AspectBits() {
        static std::array<VkImageAspectFlagBits, kAspectCount> k_aspect_bits{
            {VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_ASPECT_STENCIL_BIT}};
        return k_aspect_bits;
    }
};

struct Multiplane2AspectTraits {
    // VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010, >> 4 - 1 -> 0
    // VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020, >> 4 - 1 -> 1
    static constexpr uint32_t kAspectCount = 2;
    static constexpr VkImageAspectFlags kAspectMask = (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT);
    static uint32_t MaskIndex(VkImageAspectFlags mask) {
        uint32_t index = (mask >> 4) - 1;
        assert((index == 0) || (index == 1));
        return index;
    };
    static const std::array<VkImageAspectFlagBits, kAspectCount>& AspectBits() {
        static std::array<VkImageAspectFlagBits, kAspectCount> k_aspect_bits{
            {VK_IMAGE_ASPECT_PLANE_0_BIT, VK_IMAGE_ASPECT_PLANE_1_BIT}};
        return k_aspect_bits;
    }
};

struct Multiplane3AspectTraits {
    // VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010, >> 4 - 1 -> 0
    // VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020, >> 4 - 1 -> 1
    // VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040, >> 4 - 1 -> 3
    static constexpr uint32_t kAspectCount = 3;
    static constexpr VkImageAspectFlags kAspectMask =
        (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT);
    static uint32_t MaskIndex(VkImageAspectFlags mask) {
        uint32_t index = (mask >> 4) - 1;
        index = index > 2 ? 2 : index;
        assert((index == 0) || (index == 1) || (index == 2));
        return index;
    };
    static const std::array<VkImageAspectFlagBits, kAspectCount>& AspectBits() {
        static std::array<VkImageAspectFlagBits, kAspectCount> k_aspect_bits{
            {VK_IMAGE_ASPECT_PLANE_0_BIT, VK_IMAGE_ASPECT_PLANE_1_BIT, VK_IMAGE_ASPECT_PLANE_2_BIT}};
        return k_aspect_bits;
    }
};

// Create the encoder parameter suitable to the full range aspect mask (*must* be canonical)
const AspectParameters* AspectParameters::Get(VkImageAspectFlags aspect_mask) {
    // We need a persitent instance of each specialist containing only a VTABLE each
    static const AspectParametersImpl<ColorAspectTraits> k_color_param;
    static const AspectParametersImpl<DepthAspectTraits> k_depth_param;
    static const AspectParametersImpl<StencilAspectTraits> k_stencil_param;
    static const AspectParametersImpl<DepthStencilAspectTraits> k_depth_stencil_param;
    static const AspectParametersImpl<Multiplane2AspectTraits> k_mutliplane2_param;
    static const AspectParametersImpl<Multiplane3AspectTraits> k_mutliplane3_param;
    static const AspectParametersImpl<NullAspectTraits> k_null_aspect;

    const AspectParameters* param;
    switch (aspect_mask) {
        case ColorAspectTraits::kAspectMask:
            param = &k_color_param;
            break;
        case DepthAspectTraits::kAspectMask:
            param = &k_depth_param;
            break;
        case StencilAspectTraits::kAspectMask:
            param = &k_stencil_param;
            break;
        case DepthStencilAspectTraits::kAspectMask:
            param = &k_depth_stencil_param;
            break;
        case Multiplane2AspectTraits::kAspectMask:
            param = &k_mutliplane2_param;
            break;
        case Multiplane3AspectTraits::kAspectMask:
            param = &k_mutliplane3_param;
            break;
        default:
            assert(false);
            param = &k_null_aspect;
    }
    return param;
}

inline ImageRangeEncoder::SubresInfo::SubresInfo(const VkSubresourceLayout& layout_, const VkExtent3D& extent_,
                                                 const VkExtent3D& texel_extent, double texel_size)
    : layout(layout_),
      extent(extent_),
      y_step_pitch(layout.rowPitch * texel_extent.height),
      z_step_pitch(layout.depthPitch * texel_extent.depth),
      layer_span(layout.rowPitch * extent_.height) {}

void ImageRangeGenerator::IncrementerState::Set(uint32_t y_count_, uint32_t layer_z_count_, IndexType base, IndexType span,
                                                IndexType y_step, IndexType z_step) {
    y_count = y_count_;
    layer_z_count = layer_z_count_;
    y_index = 0;
    layer_z_index = 0;
    y_base.begin = base;
    y_base.end = base + span;
    layer_z_base = y_base;
    incr_y = y_step;
    incr_layer_z = z_step;
}

};  // namespace subresource_adapter
