blob: e077be715ff5070d982ae60fa400f66e072c882a [file] [log] [blame]
Tony Barbour2f18b292016-02-25 15:44:10 -07001/*
2 * Copyright (C) 2016 Google, Inc.
3 *
Jon Ashburn43b53e82016-04-19 11:30:31 -06004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Tony Barbour2f18b292016-02-25 15:44:10 -07007 *
Jon Ashburn43b53e82016-04-19 11:30:31 -06008 * http://www.apache.org/licenses/LICENSE-2.0
Tony Barbour2f18b292016-02-25 15:44:10 -07009 *
Jon Ashburn43b53e82016-04-19 11:30:31 -060010 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Tony Barbour2f18b292016-02-25 15:44:10 -070015 */
16
17#include <cassert>
18#include <cmath>
19#include <cstring>
20#include <array>
21#include <unordered_map>
22
23#include "Helpers.h"
24#include "Meshes.h"
25
26namespace {
27
28class Mesh {
Mark Lobodzinskicc7c3052017-01-26 13:34:13 -070029 public:
Tony Barbour2f18b292016-02-25 15:44:10 -070030 struct Position {
31 float x;
32 float y;
33 float z;
34 };
35
36 struct Normal {
37 float x;
38 float y;
39 float z;
40 };
41
42 struct Face {
43 int v0;
44 int v1;
45 int v2;
46 };
47
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -070048 static uint32_t vertex_stride() {
Tony Barbour2f18b292016-02-25 15:44:10 -070049 // Position + Normal
50 const int comp_count = 6;
51
52 return sizeof(float) * comp_count;
53 }
54
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -070055 static VkVertexInputBindingDescription vertex_input_binding() {
Tony Barbour2f18b292016-02-25 15:44:10 -070056 VkVertexInputBindingDescription vi_binding = {};
57 vi_binding.binding = 0;
58 vi_binding.stride = vertex_stride();
59 vi_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
60
61 return vi_binding;
62 }
63
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -070064 static std::vector<VkVertexInputAttributeDescription> vertex_input_attributes() {
Tony Barbour2f18b292016-02-25 15:44:10 -070065 std::vector<VkVertexInputAttributeDescription> vi_attrs(2);
66 // Position
67 vi_attrs[0].location = 0;
68 vi_attrs[0].binding = 0;
69 vi_attrs[0].format = VK_FORMAT_R32G32B32_SFLOAT;
70 vi_attrs[0].offset = 0;
71 // Normal
72 vi_attrs[1].location = 1;
73 vi_attrs[1].binding = 0;
74 vi_attrs[1].format = VK_FORMAT_R32G32B32_SFLOAT;
75 vi_attrs[1].offset = sizeof(float) * 3;
76
77 return vi_attrs;
78 }
79
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -070080 static VkIndexType index_type() { return VK_INDEX_TYPE_UINT32; }
Tony Barbour2f18b292016-02-25 15:44:10 -070081
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -070082 static VkPipelineInputAssemblyStateCreateInfo input_assembly_state() {
Tony Barbour2f18b292016-02-25 15:44:10 -070083 VkPipelineInputAssemblyStateCreateInfo ia_info = {};
84 ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
85 ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
86 ia_info.primitiveRestartEnable = false;
87 return ia_info;
88 }
89
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -070090 void build(const std::vector<std::array<float, 6>> &vertices, const std::vector<std::array<int, 3>> &faces) {
Tony Barbour2f18b292016-02-25 15:44:10 -070091 positions_.reserve(vertices.size());
92 normals_.reserve(vertices.size());
93 for (const auto &v : vertices) {
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -070094 positions_.emplace_back(Position{v[0], v[1], v[2]});
95 normals_.emplace_back(Normal{v[3], v[4], v[5]});
Tony Barbour2f18b292016-02-25 15:44:10 -070096 }
97
98 faces_.reserve(faces.size());
Mark Lobodzinskicc7c3052017-01-26 13:34:13 -070099 for (const auto &f : faces) faces_.emplace_back(Face{f[0], f[1], f[2]});
Tony Barbour2f18b292016-02-25 15:44:10 -0700100 }
101
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700102 uint32_t vertex_count() const { return static_cast<uint32_t>(positions_.size()); }
Tony Barbour2f18b292016-02-25 15:44:10 -0700103
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700104 VkDeviceSize vertex_buffer_size() const { return vertex_stride() * vertex_count(); }
Tony Barbour2f18b292016-02-25 15:44:10 -0700105
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700106 void vertex_buffer_write(void *data) const {
Tony Barbour2f18b292016-02-25 15:44:10 -0700107 float *dst = reinterpret_cast<float *>(data);
108 for (size_t i = 0; i < positions_.size(); i++) {
109 const Position &pos = positions_[i];
110 const Normal &normal = normals_[i];
111 dst[0] = pos.x;
112 dst[1] = pos.y;
113 dst[2] = pos.z;
114 dst[3] = normal.x;
115 dst[4] = normal.y;
116 dst[5] = normal.z;
117 dst += 6;
118 }
119 }
120
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700121 uint32_t index_count() const { return static_cast<uint32_t>(faces_.size()) * 3; }
Tony Barbour2f18b292016-02-25 15:44:10 -0700122
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700123 VkDeviceSize index_buffer_size() const { return sizeof(uint32_t) * index_count(); }
Tony Barbour2f18b292016-02-25 15:44:10 -0700124
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700125 void index_buffer_write(void *data) const {
Tony Barbour2f18b292016-02-25 15:44:10 -0700126 uint32_t *dst = reinterpret_cast<uint32_t *>(data);
127 for (const auto &face : faces_) {
128 dst[0] = face.v0;
129 dst[1] = face.v1;
130 dst[2] = face.v2;
131 dst += 3;
132 }
133 }
134
135 std::vector<Position> positions_;
136 std::vector<Normal> normals_;
137 std::vector<Face> faces_;
138};
139
140class BuildPyramid {
Mark Lobodzinskicc7c3052017-01-26 13:34:13 -0700141 public:
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700142 BuildPyramid(Mesh &mesh) {
Tony Barbour2f18b292016-02-25 15:44:10 -0700143 const std::vector<std::array<float, 6>> vertices = {
144 // position normal
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700145 {{0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f}}, {{-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}},
146 {{1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f}}, {{1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f}},
147 {{-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f}},
Tony Barbour2f18b292016-02-25 15:44:10 -0700148 };
149
150 const std::vector<std::array<int, 3>> faces = {
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700151 {{0, 1, 2}}, {{0, 2, 3}}, {{0, 3, 4}}, {{0, 4, 1}}, {{1, 4, 3}}, {{1, 3, 2}},
Tony Barbour2f18b292016-02-25 15:44:10 -0700152 };
153
154 mesh.build(vertices, faces);
155 }
156};
157
158class BuildIcosphere {
Mark Lobodzinskicc7c3052017-01-26 13:34:13 -0700159 public:
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700160 BuildIcosphere(Mesh &mesh) : mesh_(mesh), radius_(1.0f) {
Tony Barbour2f18b292016-02-25 15:44:10 -0700161 const int tessellate_level = 2;
162
163 build_icosahedron();
Mark Lobodzinskicc7c3052017-01-26 13:34:13 -0700164 for (int i = 0; i < tessellate_level; i++) tessellate();
Tony Barbour2f18b292016-02-25 15:44:10 -0700165 }
166
Mark Lobodzinskicc7c3052017-01-26 13:34:13 -0700167 private:
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700168 void build_icosahedron() {
Tony Barbour2f18b292016-02-25 15:44:10 -0700169 // https://en.wikipedia.org/wiki/Regular_icosahedron
170 const float l1 = std::sqrt(2.0f / (5.0f + std::sqrt(5.0f))) * radius_;
171 const float l2 = std::sqrt(2.0f / (5.0f - std::sqrt(5.0f))) * radius_;
172 // vertices are from three golden rectangles
173 const std::vector<std::array<float, 6>> icosahedron_vertices = {
174 // position normal
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700175 {{
176 -l1, -l2, 0.0f, -l1, -l2, 0.0f,
177 }},
178 {{
179 l1, -l2, 0.0f, l1, -l2, 0.0f,
180 }},
181 {{
182 l1, l2, 0.0f, l1, l2, 0.0f,
183 }},
184 {{
185 -l1, l2, 0.0f, -l1, l2, 0.0f,
186 }},
Tony Barbour2f18b292016-02-25 15:44:10 -0700187
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700188 {{
189 -l2, 0.0f, -l1, -l2, 0.0f, -l1,
190 }},
191 {{
192 l2, 0.0f, -l1, l2, 0.0f, -l1,
193 }},
194 {{
195 l2, 0.0f, l1, l2, 0.0f, l1,
196 }},
197 {{
198 -l2, 0.0f, l1, -l2, 0.0f, l1,
199 }},
Tony Barbour2f18b292016-02-25 15:44:10 -0700200
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700201 {{
202 0.0f, -l1, -l2, 0.0f, -l1, -l2,
203 }},
204 {{
205 0.0f, l1, -l2, 0.0f, l1, -l2,
206 }},
207 {{
208 0.0f, l1, l2, 0.0f, l1, l2,
209 }},
210 {{
211 0.0f, -l1, l2, 0.0f, -l1, l2,
212 }},
Tony Barbour2f18b292016-02-25 15:44:10 -0700213 };
214 const std::vector<std::array<int, 3>> icosahedron_faces = {
215 // triangles sharing vertex 0
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700216 {{0, 1, 11}},
217 {{0, 11, 7}},
218 {{0, 7, 4}},
219 {{0, 4, 8}},
220 {{0, 8, 1}},
Tony Barbour2f18b292016-02-25 15:44:10 -0700221 // adjacent triangles
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700222 {{11, 1, 6}},
223 {{7, 11, 10}},
224 {{4, 7, 3}},
225 {{8, 4, 9}},
226 {{1, 8, 5}},
Tony Barbour2f18b292016-02-25 15:44:10 -0700227 // triangles sharing vertex 2
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700228 {{2, 3, 10}},
229 {{2, 10, 6}},
230 {{2, 6, 5}},
231 {{2, 5, 9}},
232 {{2, 9, 3}},
Tony Barbour2f18b292016-02-25 15:44:10 -0700233 // adjacent triangles
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700234 {{10, 3, 7}},
235 {{6, 10, 11}},
236 {{5, 6, 1}},
237 {{9, 5, 8}},
238 {{3, 9, 4}},
Tony Barbour2f18b292016-02-25 15:44:10 -0700239 };
240
241 mesh_.build(icosahedron_vertices, icosahedron_faces);
242 }
243
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700244 void tessellate() {
Tony Barbour2f18b292016-02-25 15:44:10 -0700245 size_t middle_point_count = mesh_.faces_.size() * 3 / 2;
246 size_t final_face_count = mesh_.faces_.size() * 4;
247
248 std::vector<Mesh::Face> faces;
249 faces.reserve(final_face_count);
250
251 middle_points_.clear();
252 middle_points_.reserve(middle_point_count);
253
254 mesh_.positions_.reserve(mesh_.vertex_count() + middle_point_count);
255 mesh_.normals_.reserve(mesh_.vertex_count() + middle_point_count);
256
257 for (const auto &f : mesh_.faces_) {
258 int v0 = f.v0;
259 int v1 = f.v1;
260 int v2 = f.v2;
261
262 int v01 = add_middle_point(v0, v1);
263 int v12 = add_middle_point(v1, v2);
264 int v20 = add_middle_point(v2, v0);
265
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700266 faces.emplace_back(Mesh::Face{v0, v01, v20});
267 faces.emplace_back(Mesh::Face{v1, v12, v01});
268 faces.emplace_back(Mesh::Face{v2, v20, v12});
269 faces.emplace_back(Mesh::Face{v01, v12, v20});
Tony Barbour2f18b292016-02-25 15:44:10 -0700270 }
271
272 mesh_.faces_.swap(faces);
273 }
274
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700275 int add_middle_point(int a, int b) {
276 uint64_t key = (a < b) ? ((uint64_t)a << 32 | b) : ((uint64_t)b << 32 | a);
Tony Barbour2f18b292016-02-25 15:44:10 -0700277 auto it = middle_points_.find(key);
Mark Lobodzinskicc7c3052017-01-26 13:34:13 -0700278 if (it != middle_points_.end()) return it->second;
Tony Barbour2f18b292016-02-25 15:44:10 -0700279
280 const Mesh::Position &pos_a = mesh_.positions_[a];
281 const Mesh::Position &pos_b = mesh_.positions_[b];
282 Mesh::Position pos_mid = {
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700283 (pos_a.x + pos_b.x) / 2.0f, (pos_a.y + pos_b.y) / 2.0f, (pos_a.z + pos_b.z) / 2.0f,
Tony Barbour2f18b292016-02-25 15:44:10 -0700284 };
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700285 float scale = radius_ / std::sqrt(pos_mid.x * pos_mid.x + pos_mid.y * pos_mid.y + pos_mid.z * pos_mid.z);
Tony Barbour2f18b292016-02-25 15:44:10 -0700286 pos_mid.x *= scale;
287 pos_mid.y *= scale;
288 pos_mid.z *= scale;
289
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700290 Mesh::Normal normal_mid = {pos_mid.x, pos_mid.y, pos_mid.z};
Tony Barbour2f18b292016-02-25 15:44:10 -0700291 normal_mid.x /= radius_;
292 normal_mid.y /= radius_;
293 normal_mid.z /= radius_;
294
295 mesh_.positions_.emplace_back(pos_mid);
296 mesh_.normals_.emplace_back(normal_mid);
297
298 int mid = mesh_.vertex_count() - 1;
299 middle_points_.emplace(std::make_pair(key, mid));
300
301 return mid;
302 }
303
304 Mesh &mesh_;
305 const float radius_;
306 std::unordered_map<uint64_t, uint32_t> middle_points_;
307};
308
309class BuildTeapot {
Mark Lobodzinskicc7c3052017-01-26 13:34:13 -0700310 public:
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700311 BuildTeapot(Mesh &mesh) {
Tony Barbour2f18b292016-02-25 15:44:10 -0700312#include "Meshes.teapot.h"
313 const int position_count = sizeof(teapot_positions) / sizeof(teapot_positions[0]);
314 const int index_count = sizeof(teapot_indices) / sizeof(teapot_indices[0]);
315 assert(position_count % 3 == 0 && index_count % 3 == 0);
316
317 Mesh::Position translate;
318 float scale;
319 get_transform(teapot_positions, position_count, translate, scale);
320
321 for (int i = 0; i < position_count; i += 3) {
322 mesh.positions_.emplace_back(Mesh::Position{
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700323 (teapot_positions[i + 0] + translate.x) * scale, (teapot_positions[i + 1] + translate.y) * scale,
Tony Barbour2f18b292016-02-25 15:44:10 -0700324 (teapot_positions[i + 2] + translate.z) * scale,
325 });
326
327 mesh.normals_.emplace_back(Mesh::Normal{
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700328 teapot_normals[i + 0], teapot_normals[i + 1], teapot_normals[i + 2],
Tony Barbour2f18b292016-02-25 15:44:10 -0700329 });
330 }
331
332 for (int i = 0; i < index_count; i += 3) {
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700333 mesh.faces_.emplace_back(Mesh::Face{teapot_indices[i + 0], teapot_indices[i + 1], teapot_indices[i + 2]});
Tony Barbour2f18b292016-02-25 15:44:10 -0700334 }
335 }
336
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700337 void get_transform(const float *positions, int position_count, Mesh::Position &translate, float &scale) {
Tony Barbour2f18b292016-02-25 15:44:10 -0700338 float min[3] = {
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700339 positions[0], positions[1], positions[2],
Tony Barbour2f18b292016-02-25 15:44:10 -0700340 };
341 float max[3] = {
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700342 positions[0], positions[1], positions[2],
Tony Barbour2f18b292016-02-25 15:44:10 -0700343 };
344 for (int i = 3; i < position_count; i += 3) {
345 for (int j = 0; j < 3; j++) {
Mark Lobodzinskicc7c3052017-01-26 13:34:13 -0700346 if (min[j] > positions[i + j]) min[j] = positions[i + j];
347 if (max[j] < positions[i + j]) max[j] = positions[i + j];
Tony Barbour2f18b292016-02-25 15:44:10 -0700348 }
349 }
350
351 translate.x = -(min[0] + max[0]) / 2.0f;
352 translate.y = -(min[1] + max[1]) / 2.0f;
353 translate.z = -(min[2] + max[2]) / 2.0f;
354
355 float extents[3] = {
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700356 max[0] + translate.x, max[1] + translate.y, max[2] + translate.z,
Tony Barbour2f18b292016-02-25 15:44:10 -0700357 };
358
359 float max_extent = extents[0];
Mark Lobodzinskicc7c3052017-01-26 13:34:13 -0700360 if (max_extent < extents[1]) max_extent = extents[1];
361 if (max_extent < extents[2]) max_extent = extents[2];
Tony Barbour2f18b292016-02-25 15:44:10 -0700362
363 scale = 1.0f / max_extent;
364 }
365};
366
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700367void build_meshes(std::array<Mesh, Meshes::MESH_COUNT> &meshes) {
Tony Barbour2f18b292016-02-25 15:44:10 -0700368 BuildPyramid build_pyramid(meshes[Meshes::MESH_PYRAMID]);
369 BuildIcosphere build_icosphere(meshes[Meshes::MESH_ICOSPHERE]);
370 BuildTeapot build_teapot(meshes[Meshes::MESH_TEAPOT]);
371}
372
Mark Lobodzinskicc7c3052017-01-26 13:34:13 -0700373} // namespace
Tony Barbour2f18b292016-02-25 15:44:10 -0700374
375Meshes::Meshes(VkDevice dev, const std::vector<VkMemoryPropertyFlags> &mem_flags)
Mark Lobodzinskicc7c3052017-01-26 13:34:13 -0700376 : dev_(dev),
377 vertex_input_binding_(Mesh::vertex_input_binding()),
378 vertex_input_attrs_(Mesh::vertex_input_attributes()),
379 vertex_input_state_(),
380 input_assembly_state_(Mesh::input_assembly_state()),
381 index_type_(Mesh::index_type()) {
Tony Barbour2f18b292016-02-25 15:44:10 -0700382 vertex_input_state_.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
383 vertex_input_state_.vertexBindingDescriptionCount = 1;
384 vertex_input_state_.pVertexBindingDescriptions = &vertex_input_binding_;
385 vertex_input_state_.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertex_input_attrs_.size());
386 vertex_input_state_.pVertexAttributeDescriptions = vertex_input_attrs_.data();
387
388 std::array<Mesh, MESH_COUNT> meshes;
389 build_meshes(meshes);
390
391 draw_commands_.reserve(meshes.size());
392 uint32_t first_index = 0;
393 int32_t vertex_offset = 0;
394 VkDeviceSize vb_size = 0;
395 VkDeviceSize ib_size = 0;
396 for (const auto &mesh : meshes) {
397 VkDrawIndexedIndirectCommand draw = {};
398 draw.indexCount = mesh.index_count();
399 draw.instanceCount = 1;
400 draw.firstIndex = first_index;
401 draw.vertexOffset = vertex_offset;
402 draw.firstInstance = 0;
403
404 draw_commands_.push_back(draw);
405
406 first_index += mesh.index_count();
407 vertex_offset += mesh.vertex_count();
408 vb_size += mesh.vertex_buffer_size();
409 ib_size += mesh.index_buffer_size();
410 }
411
412 allocate_resources(vb_size, ib_size, mem_flags);
413
414 uint8_t *vb_data, *ib_data;
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700415 vk::assert_success(vk::MapMemory(dev_, mem_, 0, VK_WHOLE_SIZE, 0, reinterpret_cast<void **>(&vb_data)));
Tony Barbour2f18b292016-02-25 15:44:10 -0700416 ib_data = vb_data + ib_mem_offset_;
417
418 for (const auto &mesh : meshes) {
419 mesh.vertex_buffer_write(vb_data);
420 mesh.index_buffer_write(ib_data);
421 vb_data += mesh.vertex_buffer_size();
422 ib_data += mesh.index_buffer_size();
423 }
424
425 vk::UnmapMemory(dev_, mem_);
426}
427
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700428Meshes::~Meshes() {
Tony Barbour2f18b292016-02-25 15:44:10 -0700429 vk::FreeMemory(dev_, mem_, nullptr);
430 vk::DestroyBuffer(dev_, vb_, nullptr);
431 vk::DestroyBuffer(dev_, ib_, nullptr);
432}
433
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700434void Meshes::cmd_bind_buffers(VkCommandBuffer cmd) const {
Tony Barbour2f18b292016-02-25 15:44:10 -0700435 const VkDeviceSize vb_offset = 0;
436 vk::CmdBindVertexBuffers(cmd, 0, 1, &vb_, &vb_offset);
437
438 vk::CmdBindIndexBuffer(cmd, ib_, 0, index_type_);
439}
440
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700441void Meshes::cmd_draw(VkCommandBuffer cmd, Type type) const {
Tony Barbour2f18b292016-02-25 15:44:10 -0700442 const auto &draw = draw_commands_[type];
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700443 vk::CmdDrawIndexed(cmd, draw.indexCount, draw.instanceCount, draw.firstIndex, draw.vertexOffset, draw.firstInstance);
Tony Barbour2f18b292016-02-25 15:44:10 -0700444}
445
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700446void Meshes::allocate_resources(VkDeviceSize vb_size, VkDeviceSize ib_size, const std::vector<VkMemoryPropertyFlags> &mem_flags) {
Tony Barbour2f18b292016-02-25 15:44:10 -0700447 VkBufferCreateInfo buf_info = {};
448 buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
449 buf_info.size = vb_size;
450 buf_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
451 buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
452 vk::CreateBuffer(dev_, &buf_info, nullptr, &vb_);
453
454 buf_info.size = ib_size;
455 buf_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
456 vk::CreateBuffer(dev_, &buf_info, nullptr, &ib_);
457
458 VkMemoryRequirements vb_mem_reqs, ib_mem_reqs;
459 vk::GetBufferMemoryRequirements(dev_, vb_, &vb_mem_reqs);
460 vk::GetBufferMemoryRequirements(dev_, ib_, &ib_mem_reqs);
461
462 // indices follow vertices
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700463 ib_mem_offset_ = vb_mem_reqs.size + (ib_mem_reqs.alignment - (vb_mem_reqs.size % ib_mem_reqs.alignment));
Tony Barbour2f18b292016-02-25 15:44:10 -0700464
465 VkMemoryAllocateInfo mem_info = {};
466 mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
467 mem_info.allocationSize = ib_mem_offset_ + ib_mem_reqs.size;
468
469 // find any supported and mappable memory type
470 uint32_t mem_types = (vb_mem_reqs.memoryTypeBits & ib_mem_reqs.memoryTypeBits);
471 for (uint32_t idx = 0; idx < mem_flags.size(); idx++) {
Mark Lobodzinskibc9caa52017-01-26 12:16:30 -0700472 if ((mem_types & (1 << idx)) && (mem_flags[idx] & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) &&
Tony Barbour2f18b292016-02-25 15:44:10 -0700473 (mem_flags[idx] & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
474 // TODO this may not be reachable
475 mem_info.memoryTypeIndex = idx;
476 break;
477 }
478 }
479
480 vk::AllocateMemory(dev_, &mem_info, nullptr, &mem_);
481
482 vk::BindBufferMemory(dev_, vb_, mem_, 0);
483 vk::BindBufferMemory(dev_, ib_, mem_, ib_mem_offset_);
484}