// GENERATED FILE - DO NOT EDIT.
// Generated by gen_mtl_internal_shaders.py
//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// C++ string version of Metal default shaders for debug purpose.




constexpr char default_metallib_src[] = R"(
#include <metal_stdlib>
#include <simd/simd.h>
# 1 "master_source.metal"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 376 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "master_source.metal" 2








# 1 "./clear.metal" 1







# 1 "./common.h" 1
# 16 "./common.h"
# 1 "./constants.h" 1
# 11 "./constants.h"
namespace rx
{
namespace mtl_shader
{

enum
{
    kTextureType2D = 0,
    kTextureType2DMultisample = 1,
    kTextureType2DArray = 2,
    kTextureTypeCube = 3,
    kTextureType3D = 4,
    kTextureTypeCount = 5,
};

}
}
# 17 "./common.h" 2







using namespace metal;


constant float2 gCorners[3] = {float2(-1.0f, -1.0f), float2(3.0f, -1.0f), float2(-1.0f, 3.0f)};

fragment float4 dummyFS()
{
    return float4(0, 0, 0, 0);
}
# 9 "./clear.metal" 2

struct ClearParams
{
    float4 clearColor;
    float clearDepth;
};

vertex float4 clearVS(unsigned int vid [[ vertex_id ]],
                      constant ClearParams &clearParams [[buffer(0)]])
{
    return float4(gCorners[vid], clearParams.clearDepth, 1.0);
}

fragment float4 clearFS(constant ClearParams &clearParams [[buffer(0)]])
{
    return clearParams.clearColor;
}
# 10 "master_source.metal" 2
# 1 "./blit.metal" 1
# 10 "./blit.metal"
using namespace rx::mtl_shader;


constant bool kPremultiplyAlpha [[function_constant(4)]];
constant bool kUnmultiplyAlpha [[function_constant(5)]];
constant int kSourceTextureType [[function_constant(6)]];
constant bool kSourceTextureType2D = kSourceTextureType == kTextureType2D;
constant bool kSourceTextureType2DArray = kSourceTextureType == kTextureType2DArray;
constant bool kSourceTextureType2DMS = kSourceTextureType == kTextureType2DMultisample;
constant bool kSourceTextureTypeCube = kSourceTextureType == kTextureTypeCube;
constant bool kSourceTextureType3D = kSourceTextureType == kTextureType3D;

struct BlitParams
{

    float2 srcTexCoords[3];
    int srcLevel;
    int srcLayer;

    bool dstFlipViewportX;
    bool dstFlipViewportY;
    bool dstLuminance;
};

struct BlitVSOut
{
    float4 position [[position]];
    float2 texCoords [[user(locn1)]];
};

vertex BlitVSOut blitVS(unsigned int vid [[vertex_id]], constant BlitParams &options [[buffer(0)]])
{
    BlitVSOut output;
    output.position = float4(gCorners[vid], 0.0, 1.0);
    output.texCoords = options.srcTexCoords[vid];

    if (options.dstFlipViewportX)
    {
        output.position.x = -output.position.x;
    }
    if (!options.dstFlipViewportY)
    {


        output.position.y = -output.position.y;
    }

    return output;
}

static inline float3 cubeTexcoords(float2 texcoords, int face)
{
    texcoords = 2.0 * texcoords - 1.0;
    switch (face)
    {
        case 0:
            return float3(1.0, -texcoords.y, -texcoords.x);
        case 1:
            return float3(-1.0, -texcoords.y, texcoords.x);
        case 2:
            return float3(texcoords.x, 1.0, texcoords.y);
        case 3:
            return float3(texcoords.x, -1.0, -texcoords.y);
        case 4:
            return float3(texcoords.x, -texcoords.y, 1.0);
        case 5:
            return float3(-texcoords.x, -texcoords.y, -1.0);
    }
    return float3(texcoords, 0);
}

template <typename T>
static inline vec<T, 4> blitSampleTextureMS(texture2d_ms<T> srcTexture, float2 texCoords)
{
    uint2 dimens(srcTexture.get_width(), srcTexture.get_height());
    uint2 coords = uint2(texCoords * float2(dimens));

    uint samples = srcTexture.get_num_samples();

    vec<T, 4> output(0);

    for (uint sample = 0; sample < samples; ++sample)
    {
        output += srcTexture.read(coords, sample);
    }

    output = output / samples;

    return output;
}

template <typename T>
static inline vec<T, 4> blitSampleTexture3D(texture3d<T> srcTexture,
                                            sampler textureSampler,
                                            float2 texCoords,
                                            constant BlitParams &options)
{
    uint depth = srcTexture.get_depth(options.srcLevel);
    float zCoord = (float(options.srcLayer) + 0.5) / float(depth);

    return srcTexture.sample(textureSampler, float3(texCoords, zCoord), level(options.srcLevel));
}
# 130 "./blit.metal"
template <typename T>
static inline vec<T, 4> blitReadTexture(BlitVSOut input [[stage_in]], texture2d<T> srcTexture2d [[texture(0), function_constant(kSourceTextureType2D)]], texture2d_array<T> srcTexture2dArray [[texture(0), function_constant(kSourceTextureType2DArray)]], texture2d_ms<T> srcTexture2dMS [[texture(0), function_constant(kSourceTextureType2DMS)]], texturecube<T> srcTextureCube [[texture(0), function_constant(kSourceTextureTypeCube)]], texture3d<T> srcTexture3d [[texture(0), function_constant(kSourceTextureType3D)]], sampler textureSampler [[sampler(0)]], constant BlitParams &options [[buffer(0)]])
{
    vec<T, 4> output;

    switch (kSourceTextureType)
    {
        case kTextureType2D:
            output = srcTexture2d.sample(textureSampler, input.texCoords, level(options.srcLevel));
            break;
        case kTextureType2DArray:
            output = srcTexture2dArray.sample(textureSampler, input.texCoords, options.srcLayer,
                                              level(options.srcLevel));
            break;
        case kTextureType2DMultisample:
            output = blitSampleTextureMS(srcTexture2dMS, input.texCoords);
            break;
        case kTextureTypeCube:
            output = srcTextureCube.sample(textureSampler,
                                           cubeTexcoords(input.texCoords, options.srcLayer),
                                           level(options.srcLevel));
            break;
        case kTextureType3D:
            output = blitSampleTexture3D(srcTexture3d, textureSampler, input.texCoords, options);
            break;
    }

    if (kPremultiplyAlpha)
    {
        output.xyz *= output.a;
    }
    else if (kUnmultiplyAlpha)
    {
        if (output.a != 0.0)
        {
            output.xyz /= output.a;
        }
    }

    if (options.dstLuminance)
    {
        output.g = output.b = output.r;
    }

    return output;
}

fragment float4 blitFS(BlitVSOut input [[stage_in]], texture2d<float> srcTexture2d [[texture(0), function_constant(kSourceTextureType2D)]], texture2d_array<float> srcTexture2dArray [[texture(0), function_constant(kSourceTextureType2DArray)]], texture2d_ms<float> srcTexture2dMS [[texture(0), function_constant(kSourceTextureType2DMS)]], texturecube<float> srcTextureCube [[texture(0), function_constant(kSourceTextureTypeCube)]], texture3d<float> srcTexture3d [[texture(0), function_constant(kSourceTextureType3D)]], sampler textureSampler [[sampler(0)]], constant BlitParams &options [[buffer(0)]])
{
    return blitReadTexture(input, srcTexture2d, srcTexture2dArray, srcTexture2dMS, srcTextureCube, srcTexture3d, textureSampler, options);
}
# 11 "master_source.metal" 2
# 1 "./gen_indices.metal" 1








constant bool kSourceBufferAligned[[function_constant(0)]];
constant bool kSourceIndexIsU8[[function_constant(1)]];
constant bool kSourceIndexIsU16[[function_constant(2)]];
constant bool kSourceIndexIsU32[[function_constant(3)]];
constant bool kSourceBufferUnaligned = !kSourceBufferAligned;
constant bool kUseSourceBufferU8 = kSourceIndexIsU8 || kSourceBufferUnaligned;
constant bool kUseSourceBufferU16 = kSourceIndexIsU16 && kSourceBufferAligned;
constant bool kUseSourceBufferU32 = kSourceIndexIsU32 && kSourceBufferAligned;

struct IndexConversionParams
{
    uint32_t srcOffset;
    uint32_t indexCount;
};



inline ushort getIndexAligned(constant ushort *inputAligned, uint offset, uint idx)
{
    return inputAligned[offset / 2 + idx];
}
inline uint getIndexAligned(constant uint *inputAligned, uint offset, uint idx)
{
    return inputAligned[offset / 4 + idx];
}
inline uchar getIndexAligned(constant uchar *input, uint offset, uint idx)
{
    return input[offset + idx];
}
inline ushort getIndexUnalignedU16(constant uchar *input, uint offset, uint idx)
{
    ushort inputLo = input[offset + 2 * idx];
    ushort inputHi = input[offset + 2 * idx + 1];

    return inputLo | (inputHi << 8);
}
inline uint getIndexUnalignedU32(constant uchar *input, uint offset, uint idx)
{
    uint input0 = input[offset + 4 * idx];
    uint input1 = input[offset + 4 * idx + 1];
    uint input2 = input[offset + 4 * idx + 2];
    uint input3 = input[offset + 4 * idx + 3];

    return input0 | (input1 << 8) | (input2 << 16) | (input3 << 24);
}

kernel void convertIndexU8ToU16(uint idx[[thread_position_in_grid]],
                                constant IndexConversionParams &options[[buffer(0)]],
                                constant uchar *input[[buffer(1)]],
                                device ushort *output[[buffer(2)]])
{
    if (idx >= options.indexCount) { return; };
    output[idx] = getIndexAligned(input, options.srcOffset, idx);
}

kernel void convertIndexU16(
    uint idx[[thread_position_in_grid]],
    constant IndexConversionParams &options[[buffer(0)]],
    constant uchar *input[[ buffer(1), function_constant(kSourceBufferUnaligned) ]],
    constant ushort *inputAligned[[ buffer(1), function_constant(kSourceBufferAligned) ]],
    device ushort *output[[buffer(2)]])
{
    if (idx >= options.indexCount) { return; };

    ushort value;
    if (kSourceBufferAligned)
    {
        value = getIndexAligned(inputAligned, options.srcOffset, idx);
    }
    else
    {
        value = getIndexUnalignedU16(input, options.srcOffset, idx);
    }
    output[idx] = value;
}

kernel void convertIndexU32(
    uint idx[[thread_position_in_grid]],
    constant IndexConversionParams &options[[buffer(0)]],
    constant uchar *input[[ buffer(1), function_constant(kSourceBufferUnaligned) ]],
    constant uint *inputAligned[[ buffer(1), function_constant(kSourceBufferAligned) ]],
    device uint *output[[buffer(2)]])
{
    if (idx >= options.indexCount) { return; };

    uint value;
    if (kSourceBufferAligned)
    {
        value = getIndexAligned(inputAligned, options.srcOffset, idx);
    }
    else
    {
        value = getIndexUnalignedU32(input, options.srcOffset, idx);
    }
    output[idx] = value;
}

struct TriFanArrayParams
{
    uint firstVertex;
    uint vertexCountFrom3rd;
};
kernel void genTriFanIndicesFromArray(uint idx[[thread_position_in_grid]],
                                      constant TriFanArrayParams &options[[buffer(0)]],
                                      device uint *output[[buffer(2)]])
{
    if (idx >= options.vertexCountFrom3rd) { return; };

    uint vertexIdx = options.firstVertex + 2 + idx;

    output[3 * idx] = options.firstVertex;
    output[3 * idx + 1] = vertexIdx - 1;
    output[3 * idx + 2] = vertexIdx;
}

inline uint getIndexU32(uint offset,
                        uint idx,
                        constant uchar *inputU8[[function_constant(kUseSourceBufferU8)]],
                        constant ushort *inputU16[[function_constant(kUseSourceBufferU16)]],
                        constant uint *inputU32[[function_constant(kUseSourceBufferU32)]])
{
    if (kUseSourceBufferU8)
    {
        if (kSourceIndexIsU16)
        {
            return getIndexUnalignedU16(inputU8, offset, idx);
        }
        else if (kSourceIndexIsU32)
        {
            return getIndexUnalignedU32(inputU8, offset, idx);
        }
        return getIndexAligned(inputU8, offset, idx);
    }
    else if (kUseSourceBufferU16)
    {
        return getIndexAligned(inputU16, offset, idx);
    }
    else if (kUseSourceBufferU32)
    {
        return getIndexAligned(inputU32, offset, idx);
    }
    return 0;
}



kernel void genTriFanIndicesFromElements(
    uint idx[[thread_position_in_grid]],
    constant IndexConversionParams &options[[buffer(0)]],
    constant uchar *inputU8[[ buffer(1), function_constant(kUseSourceBufferU8) ]],
    constant ushort *inputU16[[ buffer(1), function_constant(kUseSourceBufferU16) ]],
    constant uint *inputU32[[ buffer(1), function_constant(kUseSourceBufferU32) ]],
    device uint *output[[buffer(2)]])
{
    if (idx >= options.indexCount) { return; };

    uint elemIdx = 2 + idx;

    output[3 * idx] = getIndexU32(options.srcOffset, 0, inputU8, inputU16, inputU32);
    output[3 * idx + 1] = getIndexU32(options.srcOffset, elemIdx - 1, inputU8, inputU16, inputU32);
    output[3 * idx + 2] = getIndexU32(options.srcOffset, elemIdx, inputU8, inputU16, inputU32);
}
# 12 "master_source.metal" 2

)";
