/* Copyright (c) 2015-2024 The Khronos Group Inc.
 * Copyright (C) 2025 Arm Limited.
 *
 * 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 <vulkan/utility/vk_format_utils.h>
#include "stateless/stateless_validation.h"
#include "containers/container_utils.h"
#include "utils/math_utils.h"
#include <cstdint>

namespace stateless {

bool Device::ValidateTensorDescriptionARM(const VkTensorDescriptionARM& description, const Location& description_loc) const {
    bool skip = false;

    if (description.format == VK_FORMAT_UNDEFINED) {
        skip |= LogError("VUID-VkTensorDescriptionARM-format-09735", device, description_loc.dot(Field::format),
                         "is VK_FORMAT_UNDEFINED");
        return skip;
    } else {
        const uint32_t component_count = vkuFormatComponentCount(description.format);
        if (component_count != 1) {
            skip |= LogError("VUID-VkTensorDescriptionARM-format-09735", device, description_loc.dot(Field::format),
                             "(%s) has (%" PRIu32 ") components.", string_VkFormat(description.format), component_count);
        }
    }

    // pStrides can be null
    if (const auto* strides = description.pStrides) {
        if (description.tiling == VK_TENSOR_TILING_OPTIMAL_ARM) {
            skip |= LogError("VUID-VkTensorCreateInfoARM-pDescription-09720", device, description_loc.dot(Field::tiling),
                             "is VK_TENSOR_TILING_OPTIMAL_ARM, but pDescription::pStrides (%p) is not null", description.pStrides);
        }

        const uint32_t texel_block_size = vkuFormatTexelBlockSize(description.format);
        if (strides[description.dimensionCount - 1] != texel_block_size) {
            skip |= LogError("VUID-VkTensorDescriptionARM-pStrides-09736", device,
                             description_loc.dot(Field::pStrides, description.dimensionCount - 1),
                             "(%" PRIi64 ") must equal the size in bytes of a tensor element (%" PRIu32 ")",
                             strides[description.dimensionCount - 1], texel_block_size);
        }
        if (static_cast<uint64_t>(strides[0]) * static_cast<uint64_t>(description.pDimensions[0]) >
            phys_dev_ext_props.tensor_properties.maxTensorSize) {
            skip |= LogError("VUID-VkTensorDescriptionARM-pStrides-09884", device, description_loc.dot(Field::pStrides, 0),
                             "(%" PRId64 ") x pDimensions[0] (%" PRId64
                             ") is greater than VkPhysicalDeviceTensorPropertiesARM::maxTensorSize (%" PRIu64 ").",
                             strides[0], description.pDimensions[0], phys_dev_ext_props.tensor_properties.maxTensorSize);
        }
        for (uint32_t i = 0; i < description.dimensionCount; i++) {
            if (!IsIntegerMultipleOf(strides[i], texel_block_size)) {
                skip |=
                    LogError("VUID-VkTensorDescriptionARM-pStrides-09737", device, description_loc.dot(Field::pStrides, i),
                             "(%" PRIi64 ") must be a multiple of the element size (%" PRIu32 ")", strides[i], texel_block_size);
            }

            if (strides[i] <= 0 || strides[i] > phys_dev_ext_props.tensor_properties.maxTensorStride) {
                skip |= LogError("VUID-VkTensorDescriptionARM-pStrides-09738", device, description_loc.dot(Field::pStrides, i),
                                 "(%" PRIi64 ") is <= 0 or > maxTensorStride (%" PRIu64 ")", strides[i],
                                 phys_dev_ext_props.tensor_properties.maxTensorStride);
            }

            if (i > 0) {
                if (strides[i - 1] < static_cast<int64_t>(strides[i] * description.pDimensions[i])) {
                    skip |=
                        LogError("VUID-VkTensorDescriptionARM-pStrides-09739", device, description_loc.dot(Field::pStrides, i - 1),
                                 "(%" PRIi64 ") < pStrides[%" PRIu32 "] (%" PRIi64 ") * pDimensions[%" PRIu32 "] (%" PRIu64 ")",
                                 strides[i - 1], i, strides[i], i, description.pDimensions[i]);
                }
            }
        }

        if (!enabled_features.tensorNonPacked) {
            int64_t i = description.dimensionCount - 1;
            bool is_packed = strides[i] == vkuFormatTexelBlockSize(description.format);
            while (is_packed && i > 0) {
                if (strides[i - 1] != static_cast<int64_t>(strides[i] * description.pDimensions[i])) {
                    is_packed = false;
                    break;
                }
                i--;
            }
            // if other errors above occurred, i might be zero, but another error will be reported already
            if (!is_packed && i > 0) {
                skip |= LogError("VUID-VkTensorDescriptionARM-None-09740", device, description_loc,
                                 "does not define a packed tensor: pStrides[%" PRIi64 "] (%" PRIi64 ") != pStrides[%" PRIi64
                                 "] (%" PRIi64 ") * pDimensions[%" PRIi64 "] (%" PRIi64 ")",
                                 i - 1, strides[i - 1], i, strides[i], i, description.pDimensions[i]);
            }
        }
    }

    if (description.dimensionCount > phys_dev_ext_props.tensor_properties.maxTensorDimensionCount) {
        skip |= LogError("VUID-VkTensorDescriptionARM-dimensionCount-09733", device, description_loc.dot(Field::dimensionCount),
                         "(%" PRIu32
                         ") must be less than or equal to "
                         "VkPhysicalDeviceTensorPropertiesARM::maxTensorDimensionCount (%" PRIu32 ")",
                         description.dimensionCount, phys_dev_ext_props.tensor_properties.maxTensorDimensionCount);
    }

    {
        int64_t total_elements = 1;
        auto* dims = description.pDimensions;
        auto would_overflow = false;
        for (uint32_t i = 0; i < description.dimensionCount; i++) {
            if (INT64_MAX / total_elements >= dims[i]) {
                total_elements *= dims[i];
            } else {
                would_overflow = true;
            }
            if (dims[i] <= 0) {
                skip |= LogError("VUID-VkTensorDescriptionARM-pDimensions-09734", device,
                                 description_loc.dot(Field::pDimensions, i), "(%" PRIi64 ") must be greater than 0.", dims[i]);
            } else if (static_cast<uint64_t>(dims[i]) > phys_dev_ext_props.tensor_properties.maxPerDimensionTensorElements) {
                skip |=
                    LogError("VUID-VkTensorDescriptionARM-pDimensions-09883", device, description_loc.dot(Field::pDimensions, i),
                             "(%" PRIi64 ") is greater than maxPerDimensionTensorElements (%" PRIu64 ")", dims[i],
                             phys_dev_ext_props.tensor_properties.maxPerDimensionTensorElements);
            }
        }
        if (static_cast<uint64_t>(total_elements) > phys_dev_ext_props.tensor_properties.maxTensorElements || would_overflow) {
            skip |= LogError("VUID-VkTensorCreateInfoARM-tensorElements-09721", device, description_loc.dot(Field::pDimensions),
                             "the total number of elements (%" PRIi64 ") is greater than maxTensorElements (%" PRIu64 ")",
                             total_elements, phys_dev_ext_props.tensor_properties.maxTensorElements);
        }
    }

    bool image_aliasing = (description.usage & VK_TENSOR_USAGE_IMAGE_ALIASING_BIT_ARM) != 0;
    if (description.tiling == VK_TENSOR_TILING_OPTIMAL_ARM && image_aliasing) {
        if (description.pDimensions[description.dimensionCount - 1] > 4) {
            skip |= LogError("VUID-VkTensorDescriptionARM-tiling-09741", device, description_loc.dot(Field::tiling),
                             "is VK_TENSOR_TILING_OPTIMAL_ARM and usage (%s) includes VK_TENSOR_USAGE_IMAGE_ALIASING_BIT_ARM "
                             "but pDimensions[%" PRIu32 "] (%" PRIu64 ") > 4",
                             string_VkTensorUsageFlagsARM(description.usage).c_str(), (description.dimensionCount - 1),
                             description.pDimensions[description.dimensionCount - 1]);
        }
    }
    if (description.tiling == VK_TENSOR_TILING_LINEAR_ARM && image_aliasing) {
        skip |= LogError("VUID-VkTensorDescriptionARM-tiling-09742", device, description_loc.dot(Field::tiling),
                         "is VK_TENSOR_TILING_LINEAR_ARM but usage (%s) includes VK_TENSOR_USAGE_IMAGE_ALIASING_BIT_ARM",
                         string_VkTensorUsageFlagsARM(description.usage).c_str());
    }
    return skip;
}

bool Device::manual_PreCallValidateCreateTensorARM(VkDevice device, const VkTensorCreateInfoARM* pCreateInfo,
                                                   const VkAllocationCallbacks* pAllocator, VkTensorARM* pTensor,
                                                   const Context& context) const {
    bool skip = false;

    if (!enabled_features.tensors) {
        skip |=
            LogError("VUID-vkCreateTensorARM-tensors-09832", device, context.error_obj.location, "tensors feature is not enabled");
    }

    const Location create_info_loc = context.error_obj.location.dot(Field::pCreateInfo);
    ASSERT_AND_RETURN_SKIP(pCreateInfo->pDescription);
    auto description = *pCreateInfo->pDescription;

    skip |= ValidateTensorDescriptionARM(description, create_info_loc.dot(Field::pDescription));

    if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
        if (enabled_features.maintenance11) {
            if (pCreateInfo->queueFamilyIndexCount == 0) {
                skip |= LogError("VUID-VkTensorCreateInfoARM-maintenance11-13358", device, create_info_loc.dot(Field::sharingMode),
                                 "is VK_SHARING_MODE_CONCURRENT, but queueFamilyIndexCount is 0 (needs to be at least 1).");
            }
        } else if (pCreateInfo->queueFamilyIndexCount <= 1) {
            skip |= LogError("VUID-VkTensorCreateInfoARM-sharingMode-09723", device, create_info_loc.dot(Field::sharingMode),
                             "is VK_SHARING_MODE_CONCURRENT, but queueFamilyIndexCount is %" PRIu32
                             " (needs to be at least 2)\nqueueFamilyIndexCount can be 1 if the maintenance11 feature is enabled.",
                             pCreateInfo->queueFamilyIndexCount);
        }

        if (!pCreateInfo->pQueueFamilyIndices) {
            skip |= LogError("VUID-VkTensorCreateInfoARM-sharingMode-09722", device, create_info_loc.dot(Field::sharingMode),
                             "is VK_SHARING_MODE_CONCURRENT, but pQueueFamilyIndices is NULL.");
        }
    }

    if (vku::FindStructInPNextChain<VkOpaqueCaptureDescriptorDataCreateInfoEXT>(pCreateInfo->pNext)) {
        if (!(pCreateInfo->flags & VK_TENSOR_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_ARM)) {
            skip |= LogError("VUID-VkTensorCreateInfoARM-pNext-09727", device, create_info_loc.dot(Field::pNext),
                             "includes a VkOpaqueCaptureDescriptorDataCreateInfoEXT structure, but flags (%s) is "
                             "missing VK_TENSOR_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_ARM",
                             string_VkTensorCreateFlagsARM(pCreateInfo->flags).c_str());
        }
    }

    if ((pCreateInfo->flags & VK_TENSOR_CREATE_PROTECTED_BIT_ARM) != 0) {
        if (!enabled_features.protectedMemory) {
            skip |= LogError("VUID-VkTensorCreateInfoARM-protectedMemory-09729", device, create_info_loc.dot(Field::flags),
                             "%s has the (%s) bit set but the protectedMemory device feature is not enabled.",
                             string_VkTensorCreateFlagsARM(pCreateInfo->flags).c_str(),
                             string_VkTensorCreateFlagsARM(VK_TENSOR_CREATE_PROTECTED_BIT_ARM).c_str());
        }
    }

    if ((pCreateInfo->flags & VK_TENSOR_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_ARM) != 0) {
        if (!enabled_features.descriptorBufferCaptureReplay) {
            skip |= LogError("VUID-VkTensorCreateInfoARM-flags-09726", device, create_info_loc.dot(Field::flags),
                             "(%s) includes (%s), but the descriptorBufferCaptureReplay feature is not enabled.",
                             string_VkTensorCreateFlagsARM(pCreateInfo->flags).c_str(),
                             string_VkTensorCreateFlagsARM(VK_TENSOR_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_ARM).c_str());
        }
    }

    if (IsValueIn(description.tiling, {VK_TENSOR_TILING_BLOCK_U_INTERLEAVED_ARM, VK_TENSOR_TILING_BLOCK_U_INTERLEAVED_64K_ARM}) &&
         description.pDimensions[description.dimensionCount - 1] > 4) {
        skip |= LogError("VUID-VkTensorDescriptionARM-tiling-09842", device,
                         create_info_loc.dot(Field::pDescription).dot(Field::tiling),
                         "(%s) is incompatible with pDimensions[dimensionCount-1] (%" PRIi64 ") > 4\ndimensionCount = %" PRIu32 "",
                         string_VkTensorTilingARM(description.tiling), description.pDimensions[description.dimensionCount - 1],
                         description.dimensionCount);
    }
    if (description.pStrides &&
        IsValueIn(description.tiling,
                  {VK_TENSOR_TILING_BLOCK_U_INTERLEAVED_ARM, VK_TENSOR_TILING_BLOCK_U_INTERLEAVED_64K_ARM,
                   VK_TENSOR_TILING_BRICK_16_WIDE_ARM, VK_TENSOR_TILING_BRICK_8_WIDE_ARM, VK_TENSOR_TILING_BRICK_4_WIDE_ARM})) {
        skip |= LogError(
            "VUID-VkTensorDescriptionARM-tiling-09843", device, create_info_loc.dot(Field::pDescription).dot(Field::tiling),
            "(%s) is incompatible with non-NULL pStrides (%p).",
            string_VkTensorTilingARM(description.tiling), description.pStrides);
    }

    if (auto external_memory_info = vku::FindStructInPNextChain<VkExternalMemoryTensorCreateInfoARM>(pCreateInfo->pNext)) {
        VkPhysicalDeviceExternalTensorInfoARM tensor_info = vku::InitStructHelper();
        tensor_info.pDescription = pCreateInfo->pDescription;
        tensor_info.handleType = static_cast<VkExternalMemoryHandleTypeFlagBits>(external_memory_info->handleTypes);
        VkExternalTensorPropertiesARM properties = vku::InitStructHelper();
        dispatch_instance_->GetPhysicalDeviceExternalTensorPropertiesARM(physical_device, &tensor_info, &properties);
        const auto compatible_types = properties.externalMemoryProperties.compatibleHandleTypes;
        if ((external_memory_info->handleTypes & compatible_types) != external_memory_info->handleTypes) {
            skip |= LogError(
                "VUID-VkTensorCreateInfoARM-pNext-09864", device,
                create_info_loc.pNext(Struct::VkExternalMemoryTensorCreateInfoARM, Field::handleTypes),
                "(%s) is not reported as compatible by vkGetPhysicalDeviceExternalTensorPropertiesARM. Compatible types are: %s",
                string_VkExternalMemoryHandleTypeFlags(external_memory_info->handleTypes).c_str(),
                string_VkExternalMemoryHandleTypeFlags(compatible_types).c_str());
        }
    }

    return skip;
}

}  // namespace stateless
