// Copyright 2020 The Tint 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 "src/tint/reader/spirv/enum_converter.h"

namespace tint::reader::spirv {

EnumConverter::EnumConverter(const FailStream& fs) : fail_stream_(fs) {}

EnumConverter::~EnumConverter() = default;

ast::PipelineStage EnumConverter::ToPipelineStage(SpvExecutionModel model) {
    switch (model) {
        case SpvExecutionModelVertex:
            return ast::PipelineStage::kVertex;
        case SpvExecutionModelFragment:
            return ast::PipelineStage::kFragment;
        case SpvExecutionModelGLCompute:
            return ast::PipelineStage::kCompute;
        default:
            break;
    }

    Fail() << "unknown SPIR-V execution model: " << uint32_t(model);
    return ast::PipelineStage::kNone;
}

ast::StorageClass EnumConverter::ToStorageClass(const SpvStorageClass sc) {
    switch (sc) {
        case SpvStorageClassInput:
            return ast::StorageClass::kIn;
        case SpvStorageClassOutput:
            return ast::StorageClass::kOut;
        case SpvStorageClassUniform:
            return ast::StorageClass::kUniform;
        case SpvStorageClassWorkgroup:
            return ast::StorageClass::kWorkgroup;
        case SpvStorageClassUniformConstant:
            return ast::StorageClass::kNone;
        case SpvStorageClassStorageBuffer:
            return ast::StorageClass::kStorage;
        case SpvStorageClassPrivate:
            return ast::StorageClass::kPrivate;
        case SpvStorageClassFunction:
            return ast::StorageClass::kFunction;
        default:
            break;
    }

    Fail() << "unknown SPIR-V storage class: " << uint32_t(sc);
    return ast::StorageClass::kInvalid;
}

ast::BuiltinValue EnumConverter::ToBuiltin(SpvBuiltIn b) {
    switch (b) {
        case SpvBuiltInPosition:
            return ast::BuiltinValue::kPosition;
        case SpvBuiltInVertexIndex:
            return ast::BuiltinValue::kVertexIndex;
        case SpvBuiltInInstanceIndex:
            return ast::BuiltinValue::kInstanceIndex;
        case SpvBuiltInFrontFacing:
            return ast::BuiltinValue::kFrontFacing;
        case SpvBuiltInFragCoord:
            return ast::BuiltinValue::kPosition;
        case SpvBuiltInFragDepth:
            return ast::BuiltinValue::kFragDepth;
        case SpvBuiltInLocalInvocationId:
            return ast::BuiltinValue::kLocalInvocationId;
        case SpvBuiltInLocalInvocationIndex:
            return ast::BuiltinValue::kLocalInvocationIndex;
        case SpvBuiltInGlobalInvocationId:
            return ast::BuiltinValue::kGlobalInvocationId;
        case SpvBuiltInWorkgroupId:
            return ast::BuiltinValue::kWorkgroupId;
        case SpvBuiltInSampleId:
            return ast::BuiltinValue::kSampleIndex;
        case SpvBuiltInSampleMask:
            return ast::BuiltinValue::kSampleMask;
        default:
            break;
    }

    Fail() << "unknown SPIR-V builtin: " << uint32_t(b);
    return ast::BuiltinValue::kInvalid;
}

ast::TextureDimension EnumConverter::ToDim(SpvDim dim, bool arrayed) {
    if (arrayed) {
        switch (dim) {
            case SpvDim2D:
                return ast::TextureDimension::k2dArray;
            case SpvDimCube:
                return ast::TextureDimension::kCubeArray;
            default:
                break;
        }
        Fail() << "arrayed dimension must be 2D or Cube. Got " << int(dim);
        return ast::TextureDimension::kNone;
    }
    // Assume non-arrayed
    switch (dim) {
        case SpvDim1D:
            return ast::TextureDimension::k1d;
        case SpvDim2D:
            return ast::TextureDimension::k2d;
        case SpvDim3D:
            return ast::TextureDimension::k3d;
        case SpvDimCube:
            return ast::TextureDimension::kCube;
        default:
            break;
    }
    Fail() << "invalid dimension: " << int(dim);
    return ast::TextureDimension::kNone;
}

ast::TexelFormat EnumConverter::ToTexelFormat(SpvImageFormat fmt) {
    switch (fmt) {
        case SpvImageFormatUnknown:
            return ast::TexelFormat::kInvalid;

        // 8 bit channels
        case SpvImageFormatRgba8:
            return ast::TexelFormat::kRgba8Unorm;
        case SpvImageFormatRgba8Snorm:
            return ast::TexelFormat::kRgba8Snorm;
        case SpvImageFormatRgba8ui:
            return ast::TexelFormat::kRgba8Uint;
        case SpvImageFormatRgba8i:
            return ast::TexelFormat::kRgba8Sint;

        // 16 bit channels
        case SpvImageFormatRgba16ui:
            return ast::TexelFormat::kRgba16Uint;
        case SpvImageFormatRgba16i:
            return ast::TexelFormat::kRgba16Sint;
        case SpvImageFormatRgba16f:
            return ast::TexelFormat::kRgba16Float;

        // 32 bit channels
        case SpvImageFormatR32ui:
            return ast::TexelFormat::kR32Uint;
        case SpvImageFormatR32i:
            return ast::TexelFormat::kR32Sint;
        case SpvImageFormatR32f:
            return ast::TexelFormat::kR32Float;
        case SpvImageFormatRg32ui:
            return ast::TexelFormat::kRg32Uint;
        case SpvImageFormatRg32i:
            return ast::TexelFormat::kRg32Sint;
        case SpvImageFormatRg32f:
            return ast::TexelFormat::kRg32Float;
        case SpvImageFormatRgba32ui:
            return ast::TexelFormat::kRgba32Uint;
        case SpvImageFormatRgba32i:
            return ast::TexelFormat::kRgba32Sint;
        case SpvImageFormatRgba32f:
            return ast::TexelFormat::kRgba32Float;
        default:
            break;
    }
    Fail() << "invalid image format: " << int(fmt);
    return ast::TexelFormat::kInvalid;
}

}  // namespace tint::reader::spirv
