blob: 6bac6687880c64bf3331de2a84a191eb42c08e61 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/renderer/backend/metal/vertex_descriptor_mtl.h"
#include "flutter/fml/logging.h"
#include "impeller/base/validation.h"
namespace impeller {
VertexDescriptorMTL::VertexDescriptorMTL() = default;
VertexDescriptorMTL::~VertexDescriptorMTL() = default;
static MTLVertexFormat ReadStageInputFormat(const ShaderStageIOSlot& input) {
if (input.columns != 1) {
// All matrix types are unsupported as vertex inputs.
return MTLVertexFormatInvalid;
}
switch (input.type) {
case ShaderType::kFloat: {
if (input.bit_width == 8 * sizeof(float)) {
switch (input.vec_size) {
case 1:
return MTLVertexFormatFloat;
case 2:
return MTLVertexFormatFloat2;
case 3:
return MTLVertexFormatFloat3;
case 4:
return MTLVertexFormatFloat4;
}
}
return MTLVertexFormatInvalid;
}
case ShaderType::kHalfFloat: {
if (input.bit_width == 8 * sizeof(float) / 2) {
switch (input.vec_size) {
case 1:
return MTLVertexFormatHalf;
case 2:
return MTLVertexFormatHalf2;
case 3:
return MTLVertexFormatHalf3;
case 4:
return MTLVertexFormatHalf4;
}
}
return MTLVertexFormatInvalid;
}
case ShaderType::kDouble: {
// Unsupported.
return MTLVertexFormatInvalid;
}
case ShaderType::kBoolean: {
if (input.bit_width == 8 * sizeof(bool) && input.vec_size == 1) {
return MTLVertexFormatChar;
}
return MTLVertexFormatInvalid;
}
case ShaderType::kSignedByte: {
if (input.bit_width == 8 * sizeof(char)) {
switch (input.vec_size) {
case 1:
return MTLVertexFormatChar;
case 2:
return MTLVertexFormatChar2;
case 3:
return MTLVertexFormatChar3;
case 4:
return MTLVertexFormatChar4;
}
}
return MTLVertexFormatInvalid;
}
case ShaderType::kUnsignedByte: {
if (input.bit_width == 8 * sizeof(char)) {
switch (input.vec_size) {
case 1:
return MTLVertexFormatUChar;
case 2:
return MTLVertexFormatUChar2;
case 3:
return MTLVertexFormatUChar3;
case 4:
return MTLVertexFormatUChar4;
}
}
return MTLVertexFormatInvalid;
}
case ShaderType::kSignedShort: {
if (input.bit_width == 8 * sizeof(short)) {
switch (input.vec_size) {
case 1:
return MTLVertexFormatShort;
case 2:
return MTLVertexFormatShort2;
case 3:
return MTLVertexFormatShort3;
case 4:
return MTLVertexFormatShort4;
}
}
return MTLVertexFormatInvalid;
}
case ShaderType::kUnsignedShort: {
if (input.bit_width == 8 * sizeof(ushort)) {
switch (input.vec_size) {
case 1:
return MTLVertexFormatUShort;
case 2:
return MTLVertexFormatUShort2;
case 3:
return MTLVertexFormatUShort3;
case 4:
return MTLVertexFormatUShort4;
}
}
return MTLVertexFormatInvalid;
}
case ShaderType::kSignedInt: {
if (input.bit_width == 8 * sizeof(int32_t)) {
switch (input.vec_size) {
case 1:
return MTLVertexFormatInt;
case 2:
return MTLVertexFormatInt2;
case 3:
return MTLVertexFormatInt3;
case 4:
return MTLVertexFormatInt4;
}
}
return MTLVertexFormatInvalid;
}
case ShaderType::kUnsignedInt: {
if (input.bit_width == 8 * sizeof(uint32_t)) {
switch (input.vec_size) {
case 1:
return MTLVertexFormatUInt;
case 2:
return MTLVertexFormatUInt2;
case 3:
return MTLVertexFormatUInt3;
case 4:
return MTLVertexFormatUInt4;
}
}
return MTLVertexFormatInvalid;
}
case ShaderType::kSignedInt64: {
// Unsupported.
return MTLVertexFormatInvalid;
}
case ShaderType::kUnsignedInt64: {
// Unsupported.
return MTLVertexFormatInvalid;
}
case ShaderType::kAtomicCounter:
case ShaderType::kStruct:
case ShaderType::kImage:
case ShaderType::kSampledImage:
case ShaderType::kUnknown:
case ShaderType::kVoid:
case ShaderType::kSampler:
return MTLVertexFormatInvalid;
}
}
bool VertexDescriptorMTL::SetStageInputsAndLayout(
const std::vector<ShaderStageIOSlot>& inputs,
const std::vector<ShaderStageBufferLayout>& layouts) {
auto descriptor = descriptor_ = [MTLVertexDescriptor vertexDescriptor];
// TODO(jonahwilliams): its odd that we offset buffers from the max index on
// metal but not on GLES or Vulkan. We should probably consistently start
// these at zero?
for (size_t i = 0; i < inputs.size(); i++) {
const auto& input = inputs[i];
auto vertex_format = ReadStageInputFormat(input);
if (vertex_format == MTLVertexFormatInvalid) {
VALIDATION_LOG << "Format for input " << input.name << " not supported.";
return false;
}
auto attrib = descriptor.attributes[input.location];
attrib.format = vertex_format;
attrib.offset = input.offset;
attrib.bufferIndex =
VertexDescriptor::kReservedVertexBufferIndex - input.binding;
}
for (size_t i = 0; i < layouts.size(); i++) {
const auto& layout = layouts[i];
auto vertex_layout =
descriptor.layouts[VertexDescriptor::kReservedVertexBufferIndex -
layout.binding];
vertex_layout.stride = layout.stride;
vertex_layout.stepRate = 1u;
vertex_layout.stepFunction = MTLVertexStepFunctionPerVertex;
}
return true;
}
MTLVertexDescriptor* VertexDescriptorMTL::GetMTLVertexDescriptor() const {
return descriptor_;
}
} // namespace impeller