<commit_before>// Copyright (c) 2013-2016 mogemimi. Distributed under the MIT license.

#include "PipelineStateMetal.hpp"
#include "MetalFormatHelper.hpp"
#include "Pomdog/Graphics/DepthFormat.hpp"
#include "Pomdog/Graphics/PipelineStateDescription.hpp"
#include "Pomdog/Utility/Assert.hpp"
#include "Pomdog/Utility/Exception.hpp"
#include "Pomdog/Utility/StringHelper.hpp"
#include "ShaderMetal.hpp"
#import <Metal/MTLVertexDescriptor.h>

namespace Pomdog {
namespace Detail {
namespace Metal {
namespace {

MTLVertexStepFunction ToVertexStepFunction(InputClassification classification) noexcept
{
    switch (classification) {
    case InputClassification::InputPerVertex:
        return MTLVertexStepFunctionPerVertex;
    case InputClassification::InputPerInstance:
        return MTLVertexStepFunctionPerInstance;
    }
}

MTLVertexFormat ToVertexFormat(InputElementFormat format) noexcept
{
    switch (format) {
    case InputElementFormat::Float: return MTLVertexFormatFloat;
    case InputElementFormat::Float2: return MTLVertexFormatFloat2;
    case InputElementFormat::Float3: return MTLVertexFormatFloat3;
    case InputElementFormat::Float4: return MTLVertexFormatFloat4;
    case InputElementFormat::Int4: return MTLVertexFormatInt4;
    case InputElementFormat::Byte4: return MTLVertexFormatUChar4;
    case InputElementFormat::HalfFloat2: return MTLVertexFormatHalf2;
    case InputElementFormat::HalfFloat4: return MTLVertexFormatHalf4;
    }
}

MTLVertexDescriptor* ToVertexDescriptor(const InputLayoutDescription& inputLayout)
{
    MTLVertexDescriptor* vertexDescriptor = [MTLVertexDescriptor new];

    int bufferIndex = 0;
    for (auto & element : inputLayout.InputElements) {
        auto bufferLayout = vertexDescriptor.layouts[bufferIndex];
        bufferLayout.stride = element.ByteOffset;
        bufferLayout.stepRate = element.InstanceStepRate;
        bufferLayout.stepFunction = ToVertexStepFunction(element.InputSlotClass);

        auto attribute = vertexDescriptor.attributes[bufferIndex];
        attribute.format = ToVertexFormat(element.Format);
        attribute.offset = element.ByteOffset;
        attribute.bufferIndex = bufferIndex;
        ++bufferIndex;
    }

    return vertexDescriptor;
}

MTLBlendOperation ToBlendOperation(BlendOperation blendOperation) noexcept
{
    switch (blendOperation) {
    case BlendOperation::Add: return MTLBlendOperationAdd;
    case BlendOperation::Subtract: return MTLBlendOperationSubtract;
    case BlendOperation::ReverseSubtract: return MTLBlendOperationReverseSubtract;
    case BlendOperation::Min: return MTLBlendOperationMin;
    case BlendOperation::Max: return MTLBlendOperationMax;
    }
}

MTLBlendFactor ToBlendFactor(Blend blend)
{
    switch (blend) {
    case Blend::Zero: return MTLBlendFactorZero;
    case Blend::One: return MTLBlendFactorOne;
    case Blend::SourceColor: return MTLBlendFactorSourceColor;
    case Blend::InverseSourceColor: return MTLBlendFactorOneMinusSourceColor;
    case Blend::SourceAlpha: return MTLBlendFactorSourceAlpha;
    case Blend::InverseSourceAlpha: return MTLBlendFactorOneMinusSourceAlpha;
    case Blend::DestinationAlpha: return MTLBlendFactorDestinationAlpha;
    case Blend::InverseDestinationAlpha: return MTLBlendFactorOneMinusDestinationAlpha;
    case Blend::DestinationColor: return MTLBlendFactorDestinationColor;
    case Blend::InverseDestinationColor: return MTLBlendFactorOneMinusDestinationColor;
    case Blend::SourceAlphaSaturation: return MTLBlendFactorSourceAlphaSaturated;
    case Blend::Source1Color: return MTLBlendFactorBlendColor;<commit_msg>Fix MTLVertexDescriptor bug<commit_after>// Copyright (c) 2013-2016 mogemimi. Distributed under the MIT license.

#include "PipelineStateMetal.hpp"
#include "MetalFormatHelper.hpp"
#include "../RenderSystem/BufferHelper.hpp"
#include "Pomdog/Graphics/DepthFormat.hpp"
#include "Pomdog/Graphics/PipelineStateDescription.hpp"
#include "Pomdog/Utility/Assert.hpp"
#include "Pomdog/Utility/Exception.hpp"
#include "Pomdog/Utility/StringHelper.hpp"
#include "ShaderMetal.hpp"
#import <Metal/MTLVertexDescriptor.h>

namespace Pomdog {
namespace Detail {
namespace Metal {
namespace {

MTLVertexStepFunction ToVertexStepFunction(InputClassification classification) noexcept
{
    switch (classification) {
    case InputClassification::InputPerVertex:
        return MTLVertexStepFunctionPerVertex;
    case InputClassification::InputPerInstance:
        return MTLVertexStepFunctionPerInstance;
    }
}

MTLVertexFormat ToVertexFormat(InputElementFormat format) noexcept
{
    switch (format) {
    case InputElementFormat::Float: return MTLVertexFormatFloat;
    case InputElementFormat::Float2: return MTLVertexFormatFloat2;
    case InputElementFormat::Float3: return MTLVertexFormatFloat3;
    case InputElementFormat::Float4: return MTLVertexFormatFloat4;
    case InputElementFormat::Int4: return MTLVertexFormatInt4;
    case InputElementFormat::Byte4: return MTLVertexFormatUChar4;
    case InputElementFormat::HalfFloat2: return MTLVertexFormatHalf2;
    case InputElementFormat::HalfFloat4: return MTLVertexFormatHalf4;
    }
}

MTLVertexDescriptor* ToVertexDescriptor(const InputLayoutDescription& inputLayout)
{
    MTLVertexDescriptor* vertexDescriptor = [MTLVertexDescriptor new];

    int attributeIndex = 0;
    for (auto & element : inputLayout.InputElements) {
        auto bufferLayout = vertexDescriptor.layouts[element.InputSlot];
        bufferLayout.stride = element.ByteOffset + BufferHelper::ToByteSize(element.Format);
        bufferLayout.stepFunction = ToVertexStepFunction(element.InputSlotClass);
        bufferLayout.stepRate = element.InstanceStepRate;
        if (element.InputSlotClass == InputClassification::InputPerVertex) {
            // NOTE: `stepRate` must be one if stepFunction is MTLVertexStepFunctionPerVertex.
            bufferLayout.stepRate = 1;
        }

        auto attribute = vertexDescriptor.attributes[attributeIndex];
        attribute.format = ToVertexFormat(element.Format);
        attribute.offset = element.ByteOffset;
        attribute.bufferIndex = element.InputSlot;
        ++attributeIndex;
    }

    return vertexDescriptor;
}

MTLBlendOperation ToBlendOperation(BlendOperation blendOperation) noexcept
{
    switch (blendOperation) {
    case BlendOperation::Add: return MTLBlendOperationAdd;
    case BlendOperation::Subtract: return MTLBlendOperationSubtract;
    case BlendOperation::ReverseSubtract: return MTLBlendOperationReverseSubtract;
    case BlendOperation::Min: return MTLBlendOperationMin;
    case BlendOperation::Max: return MTLBlendOperationMax;
    }
}

MTLBlendFactor ToBlendFactor(Blend blend)
{
    switch (blend) {
    case Blend::Zero: return MTLBlendFactorZero;
    case Blend::One: return MTLBlendFactorOne;
    case Blend::SourceColor: return MTLBlendFactorSourceColor;
    case Blend::InverseSourceColor: return MTLBlendFactorOneMinusSourceColor;
    case Blend::SourceAlpha: return MTLBlendFactorSourceAlpha;
    case Blend::InverseSourceAlpha: return MTLBlendFactorOneMinusSourceAlpha;
    case Blend::DestinationAlpha: return MTLBlendFactorDestinationAlpha;
    case Blend::InverseDestinationAlpha: return MTLBlendFactorOneMinusDestinationAlpha;
    case Blend::DestinationColor: return MTLBlendFactorDestinationColor;
    case Blend::InverseDestinationColor: return MTLBlendFactorOneMinusDestinationColor;
    case Blend::SourceAlphaSaturation: return MTLBlendFactorSourceAlphaSaturated;
    case Blend::Source1Color: return MTLBlendFactorBlendColor;
{'fraction_non_alphanumeric': 0.07336776585882665, 'fraction_numerical': 0.00648920672758575, 'mean_word_length': 5.653744493392071, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6710228', 'n_tokens_mistral': 2126, 'n_tokens_neox': 2103, 'n_words': 422}