Flutter Impeller
vertex_descriptor_mtl.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
7 #include "flutter/fml/logging.h"
9 
10 namespace impeller {
11 
13 
15 
16 static MTLVertexFormat ReadStageInputFormat(const ShaderStageIOSlot& input) {
17  if (input.columns != 1) {
18  // All matrix types are unsupported as vertex inputs.
19  return MTLVertexFormatInvalid;
20  }
21 
22  switch (input.type) {
23  case ShaderType::kFloat: {
24  if (input.bit_width == 8 * sizeof(float)) {
25  switch (input.vec_size) {
26  case 1:
27  return MTLVertexFormatFloat;
28  case 2:
29  return MTLVertexFormatFloat2;
30  case 3:
31  return MTLVertexFormatFloat3;
32  case 4:
33  return MTLVertexFormatFloat4;
34  }
35  }
36  return MTLVertexFormatInvalid;
37  }
39  if (input.bit_width == 8 * sizeof(float) / 2) {
40  switch (input.vec_size) {
41  case 1:
42  return MTLVertexFormatHalf;
43  case 2:
44  return MTLVertexFormatHalf2;
45  case 3:
46  return MTLVertexFormatHalf3;
47  case 4:
48  return MTLVertexFormatHalf4;
49  }
50  }
51  return MTLVertexFormatInvalid;
52  }
53  case ShaderType::kDouble: {
54  // Unsupported.
55  return MTLVertexFormatInvalid;
56  }
57  case ShaderType::kBoolean: {
58  if (input.bit_width == 8 * sizeof(bool) && input.vec_size == 1) {
59  return MTLVertexFormatChar;
60  }
61  return MTLVertexFormatInvalid;
62  }
64  if (input.bit_width == 8 * sizeof(char)) {
65  switch (input.vec_size) {
66  case 1:
67  return MTLVertexFormatChar;
68  case 2:
69  return MTLVertexFormatChar2;
70  case 3:
71  return MTLVertexFormatChar3;
72  case 4:
73  return MTLVertexFormatChar4;
74  }
75  }
76  return MTLVertexFormatInvalid;
77  }
79  if (input.bit_width == 8 * sizeof(char)) {
80  switch (input.vec_size) {
81  case 1:
82  return MTLVertexFormatUChar;
83  case 2:
84  return MTLVertexFormatUChar2;
85  case 3:
86  return MTLVertexFormatUChar3;
87  case 4:
88  return MTLVertexFormatUChar4;
89  }
90  }
91  return MTLVertexFormatInvalid;
92  }
94  if (input.bit_width == 8 * sizeof(short)) {
95  switch (input.vec_size) {
96  case 1:
97  return MTLVertexFormatShort;
98  case 2:
99  return MTLVertexFormatShort2;
100  case 3:
101  return MTLVertexFormatShort3;
102  case 4:
103  return MTLVertexFormatShort4;
104  }
105  }
106  return MTLVertexFormatInvalid;
107  }
109  if (input.bit_width == 8 * sizeof(ushort)) {
110  switch (input.vec_size) {
111  case 1:
112  return MTLVertexFormatUShort;
113  case 2:
114  return MTLVertexFormatUShort2;
115  case 3:
116  return MTLVertexFormatUShort3;
117  case 4:
118  return MTLVertexFormatUShort4;
119  }
120  }
121  return MTLVertexFormatInvalid;
122  }
123  case ShaderType::kSignedInt: {
124  if (input.bit_width == 8 * sizeof(int32_t)) {
125  switch (input.vec_size) {
126  case 1:
127  return MTLVertexFormatInt;
128  case 2:
129  return MTLVertexFormatInt2;
130  case 3:
131  return MTLVertexFormatInt3;
132  case 4:
133  return MTLVertexFormatInt4;
134  }
135  }
136  return MTLVertexFormatInvalid;
137  }
139  if (input.bit_width == 8 * sizeof(uint32_t)) {
140  switch (input.vec_size) {
141  case 1:
142  return MTLVertexFormatUInt;
143  case 2:
144  return MTLVertexFormatUInt2;
145  case 3:
146  return MTLVertexFormatUInt3;
147  case 4:
148  return MTLVertexFormatUInt4;
149  }
150  }
151  return MTLVertexFormatInvalid;
152  }
154  // Unsupported.
155  return MTLVertexFormatInvalid;
156  }
158  // Unsupported.
159  return MTLVertexFormatInvalid;
160  }
162  case ShaderType::kStruct:
163  case ShaderType::kImage:
166  case ShaderType::kVoid:
168  return MTLVertexFormatInvalid;
169  }
170 }
171 
173  const std::vector<ShaderStageIOSlot>& inputs,
174  const std::vector<ShaderStageBufferLayout>& layouts) {
175  auto descriptor = descriptor_ = [MTLVertexDescriptor vertexDescriptor];
176 
177  // TODO(jonahwilliams): its odd that we offset buffers from the max index on
178  // metal but not on GLES or Vulkan. We should probably consistently start
179  // these at zero?
180  for (size_t i = 0; i < inputs.size(); i++) {
181  const auto& input = inputs[i];
182  auto vertex_format = ReadStageInputFormat(input);
183  if (vertex_format == MTLVertexFormatInvalid) {
184  VALIDATION_LOG << "Format for input " << input.name << " not supported.";
185  return false;
186  }
187  auto attrib = descriptor.attributes[input.location];
188  attrib.format = vertex_format;
189  attrib.offset = input.offset;
190  attrib.bufferIndex =
192  }
193 
194  for (size_t i = 0; i < layouts.size(); i++) {
195  const auto& layout = layouts[i];
196  auto vertex_layout =
198  layout.binding];
199  vertex_layout.stride = layout.stride;
200  vertex_layout.stepRate = 1u;
201  vertex_layout.stepFunction = MTLVertexStepFunctionPerVertex;
202  }
203  return true;
204 }
205 
206 MTLVertexDescriptor* VertexDescriptorMTL::GetMTLVertexDescriptor() const {
207  return descriptor_;
208 }
209 
210 } // namespace impeller
static constexpr size_t kReservedVertexBufferIndex
bool SetStageInputsAndLayout(const std::vector< ShaderStageIOSlot > &inputs, const std::vector< ShaderStageBufferLayout > &layouts)
MTLVertexDescriptor * GetMTLVertexDescriptor() const
static MTLVertexFormat ReadStageInputFormat(const ShaderStageIOSlot &input)
#define VALIDATION_LOG
Definition: validation.h:91