1 /* 2 * Copyright © 2017 Collabora Ltd. 3 * 4 * This file is part of vkmark. 5 * 6 * vkmark is free software: you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation, either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * vkmark is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with vkmark. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * Authors: 20 * Alexandros Frantzis <alexandros.frantzis@collabora.com> 21 */ 22 23 #include "src/mesh.h" 24 25 #include "catch.hpp" 26 27 #include <vulkan/vulkan.hpp> 28 #include <glm/glm.hpp> 29 #include <memory> 30 #include <numeric> 31 32 using namespace Catch::Matchers; 33 34 SCENARIO("mesh object construction", "") 35 { 36 GIVEN("Unsupported formats") 37 { 38 std::vector<vk::Format> const unsupported_formats{ 39 vk::Format::eR32G32B32Sint, 40 vk::Format::eR64G64B64Sfloat}; 41 42 WHEN("constructing a mesh") 43 { 44 THEN("the construction throws") 45 { 46 for (auto const f : unsupported_formats) 47 { 48 std::vector<vk::Format> formats{vk::Format::eR32G32B32A32Sfloat, f}; 49 REQUIRE_THROWS(Mesh{formats}); 50 } 51 } 52 } 53 } 54 55 GIVEN("Supported formats") 56 { 57 std::vector<vk::Format> const supported_formats{ 58 vk::Format::eR32G32Sfloat, 59 vk::Format::eR32G32B32Sfloat, 60 vk::Format::eR32G32B32A32Sfloat}; 61 62 WHEN("constructing a mesh") 63 { 64 THEN("the construction succeeeds") 65 { 66 Mesh mesh{supported_formats}; 67 } 68 } 69 } 70 } 71 72 SCENARIO("mesh creation", "") 73 { 74 std::vector<vk::Format> const formats{ 75 vk::Format::eR32Sfloat, 76 vk::Format::eR32G32Sfloat, 77 vk::Format::eR32G32B32Sfloat, 78 vk::Format::eR32G32B32A32Sfloat}; 79 size_t const num_vertex_floats = 10; 80 81 Mesh mesh{formats}; 82 83 GIVEN("A mesh") 84 { 85 WHEN("setting vertex attribute with incorrectly sized data") 86 { 87 mesh.next_vertex(); 88 89 THEN("setting the attributes throws") 90 { 91 REQUIRE_THROWS(mesh.set_attribute(0, glm::vec2{1, 2})); 92 REQUIRE_THROWS(mesh.set_attribute(1, glm::vec3{1, 2, 3})); 93 REQUIRE_THROWS(mesh.set_attribute(2, glm::vec2{1, 2})); 94 REQUIRE_THROWS(mesh.set_attribute(3, glm::vec3{1, 2, 3})); 95 } 96 } 97 98 WHEN("setting vertex attributes with correctly sized data") 99 { 100 mesh.next_vertex(); 101 102 THEN("setting the attributes works") 103 { 104 mesh.set_attribute(0, 0); 105 mesh.set_attribute(1, glm::vec2{1, 2}); 106 mesh.set_attribute(2, glm::vec3{1, 2, 3}); 107 mesh.set_attribute(3, glm::vec4{1, 2, 3, 4}); 108 } 109 } 110 } 111 112 GIVEN("A mesh with vertices") 113 { 114 for (int i = 0; i < 5; ++i) 115 { 116 auto const v = i * num_vertex_floats; 117 mesh.next_vertex(); 118 mesh.set_attribute(0, v); 119 mesh.set_attribute(1, glm::vec2{v + 1, v + 2}); 120 mesh.set_attribute(2, glm::vec3{v + 3, v + 4, v + 5}); 121 mesh.set_attribute(3, glm::vec4{v + 6, v + 7, v + 8, v + 9}); 122 } 123 124 WHEN("interleave is true") 125 { 126 mesh.set_interleave(true); 127 128 THEN("the copied vertex data is interleaved") 129 { 130 std::vector<float> data(mesh.vertex_data_size() / sizeof(float)); 131 mesh.copy_vertex_data_to(data.data()); 132 133 std::vector<float> expected(num_vertex_floats * 5); 134 std::iota(expected.begin(), expected.end(), 0); 135 136 REQUIRE_THAT(data, Equals(expected)); 137 } 138 139 THEN("binding descriptions are interleaved") 140 { 141 auto const binding_descs = mesh.binding_descriptions(); 142 143 REQUIRE(binding_descs.size() == 1); 144 REQUIRE(binding_descs[0].binding == 0); 145 REQUIRE(binding_descs[0].stride == num_vertex_floats * sizeof(float)); 146 REQUIRE(binding_descs[0].inputRate == vk::VertexInputRate::eVertex); 147 } 148 149 THEN("attribute descriptions are interleaved") 150 { 151 auto const attrib_descs = mesh.attribute_descriptions(); 152 153 REQUIRE(attrib_descs.size() == formats.size()); 154 for (size_t i = 0; i < attrib_descs.size(); ++i) 155 { 156 REQUIRE(attrib_descs[i].binding == 0); 157 REQUIRE(attrib_descs[i].location == i); 158 } 159 REQUIRE(attrib_descs[0].offset == 0 * sizeof(float)); 160 REQUIRE(attrib_descs[1].offset == 1 * sizeof(float)); 161 REQUIRE(attrib_descs[2].offset == 3 * sizeof(float)); 162 REQUIRE(attrib_descs[3].offset == 6 * sizeof(float)); 163 } 164 } 165 166 WHEN("interleave is false") 167 { 168 mesh.set_interleave(false); 169 170 THEN("the copied vertex data is not interleaved") 171 { 172 std::vector<float> data(mesh.vertex_data_size() / sizeof(float)); 173 mesh.copy_vertex_data_to(data.data()); 174 175 std::vector<float> expected; 176 for (int i = 0; i < 5; ++i) 177 { 178 expected.push_back(i * num_vertex_floats); 179 } 180 for (int i = 0; i < 5; ++i) 181 { 182 for (int j = 0; j < 2; ++j) 183 expected.push_back(i * num_vertex_floats + 1 + j); 184 } 185 for (int i = 0; i < 5; ++i) 186 { 187 for (int j = 0; j < 3; ++j) 188 expected.push_back(i * num_vertex_floats + 3 + j); 189 } 190 for (int i = 0; i < 5; ++i) 191 { 192 for (int j = 0; j < 4; ++j) 193 expected.push_back(i * num_vertex_floats + 6 + j); 194 } 195 196 REQUIRE_THAT(data, Equals(expected)); 197 } 198 199 THEN("binding descriptions are not interleaved") 200 { 201 auto const binding_descs = mesh.binding_descriptions(); 202 203 REQUIRE(binding_descs.size() == formats.size()); 204 for (size_t i = 0; i < binding_descs.size(); ++i) 205 { 206 REQUIRE(binding_descs[i].binding == i); 207 // format[i] corresponds to a float vector of size i + 1 208 REQUIRE(binding_descs[i].stride == (i + 1) * sizeof(float)); 209 REQUIRE(binding_descs[i].inputRate == vk::VertexInputRate::eVertex); 210 } 211 } 212 213 THEN("attribute descriptions are not interleaved") 214 { 215 auto const attrib_descs = mesh.attribute_descriptions(); 216 217 REQUIRE(attrib_descs.size() == formats.size()); 218 for (size_t i = 0; i < attrib_descs.size(); ++i) 219 { 220 REQUIRE(attrib_descs[i].binding == i); 221 REQUIRE(attrib_descs[i].location == i); 222 REQUIRE(attrib_descs[i].offset == 0); 223 } 224 } 225 } 226 } 227 } 228