1 // Copyright 2019 The Amber Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/vulkan/vertex_buffer.h"
16
17 #include <utility>
18
19 #include "amber/value.h"
20 #include "gtest/gtest.h"
21 #include "src/format.h"
22 #include "src/make_unique.h"
23 #include "src/type_parser.h"
24 #include "src/vulkan/command_buffer.h"
25 #include "src/vulkan/command_pool.h"
26 #include "src/vulkan/device.h"
27
28 namespace amber {
29 namespace vulkan {
30 namespace {
31
32 class DummyDevice : public Device {
33 public:
DummyDevice()34 DummyDevice()
35 : Device(VkInstance(),
36 VkPhysicalDevice(),
37 0u,
38 VkDevice(this),
39 VkQueue(),
40 nullptr) {
41 memory_.resize(64);
42 dummyPtrs_.vkCreateBuffer = vkCreateBuffer;
43 dummyPtrs_.vkGetBufferMemoryRequirements = vkGetBufferMemoryRequirements;
44 dummyPtrs_.vkAllocateMemory = vkAllocateMemory;
45 dummyPtrs_.vkBindBufferMemory = vkBindBufferMemory;
46 dummyPtrs_.vkMapMemory = vkMapMemory;
47 dummyPtrs_.vkCmdPipelineBarrier = vkCmdPipelineBarrier;
48 dummyPtrs_.vkAllocateCommandBuffers = vkAllocateCommandBuffers;
49 dummyPtrs_.vkCreateFence = vkCreateFence;
50 dummyPtrs_.vkDestroyBufferView = vkDestroyBufferView;
51 dummyPtrs_.vkFreeMemory = vkFreeMemory;
52 dummyPtrs_.vkDestroyBuffer = vkDestroyBuffer;
53 }
~DummyDevice()54 ~DummyDevice() override {}
55
GetPtrs() const56 const VulkanPtrs* GetPtrs() const override { return &dummyPtrs_; }
57
HasMemoryFlags(uint32_t,const VkMemoryPropertyFlags) const58 bool HasMemoryFlags(uint32_t, const VkMemoryPropertyFlags) const override {
59 return true;
60 }
61
GetMemoryPtr()62 void* GetMemoryPtr() { return memory_.data(); }
63
64 private:
65 VulkanPtrs dummyPtrs_;
66 std::vector<uint8_t> memory_;
67
vkCreateBuffer(VkDevice,const VkBufferCreateInfo *,const VkAllocationCallbacks *,VkBuffer * pBuffer)68 static VkResult vkCreateBuffer(VkDevice,
69 const VkBufferCreateInfo*,
70 const VkAllocationCallbacks*,
71 VkBuffer* pBuffer) {
72 *pBuffer = VkBuffer(1);
73 return VK_SUCCESS;
74 }
vkGetBufferMemoryRequirements(VkDevice,VkBuffer,VkMemoryRequirements * pMemoryRequirements)75 static void vkGetBufferMemoryRequirements(
76 VkDevice,
77 VkBuffer,
78 VkMemoryRequirements* pMemoryRequirements) {
79 pMemoryRequirements->alignment = 0;
80 pMemoryRequirements->size = 0;
81 pMemoryRequirements->memoryTypeBits = 0xffffffff;
82 }
vkAllocateMemory(VkDevice,const VkMemoryAllocateInfo *,const VkAllocationCallbacks *,VkDeviceMemory *)83 static VkResult vkAllocateMemory(VkDevice,
84 const VkMemoryAllocateInfo*,
85 const VkAllocationCallbacks*,
86 VkDeviceMemory*) {
87 return VK_SUCCESS;
88 }
vkBindBufferMemory(VkDevice,VkBuffer,VkDeviceMemory,VkDeviceSize)89 static VkResult vkBindBufferMemory(VkDevice,
90 VkBuffer,
91 VkDeviceMemory,
92 VkDeviceSize) {
93 return VK_SUCCESS;
94 }
vkMapMemory(VkDevice device,VkDeviceMemory,VkDeviceSize,VkDeviceSize,VkMemoryMapFlags,void ** ppData)95 static VkResult vkMapMemory(VkDevice device,
96 VkDeviceMemory,
97 VkDeviceSize,
98 VkDeviceSize,
99 VkMemoryMapFlags,
100 void** ppData) {
101 DummyDevice* devicePtr = reinterpret_cast<DummyDevice*>(device);
102 *ppData = devicePtr->GetMemoryPtr();
103 return VK_SUCCESS;
104 }
vkCmdPipelineBarrier(VkCommandBuffer,VkPipelineStageFlags,VkPipelineStageFlags,VkDependencyFlags,uint32_t,const VkMemoryBarrier *,uint32_t,const VkBufferMemoryBarrier *,uint32_t,const VkImageMemoryBarrier *)105 static void vkCmdPipelineBarrier(VkCommandBuffer,
106 VkPipelineStageFlags,
107 VkPipelineStageFlags,
108 VkDependencyFlags,
109 uint32_t,
110 const VkMemoryBarrier*,
111 uint32_t,
112 const VkBufferMemoryBarrier*,
113 uint32_t,
114 const VkImageMemoryBarrier*) {}
vkAllocateCommandBuffers(VkDevice,const VkCommandBufferAllocateInfo *,VkCommandBuffer *)115 static VkResult vkAllocateCommandBuffers(VkDevice,
116 const VkCommandBufferAllocateInfo*,
117 VkCommandBuffer*) {
118 return VK_SUCCESS;
119 }
vkCreateFence(VkDevice,const VkFenceCreateInfo *,const VkAllocationCallbacks *,VkFence *)120 static VkResult vkCreateFence(VkDevice,
121 const VkFenceCreateInfo*,
122 const VkAllocationCallbacks*,
123 VkFence*) {
124 return VK_SUCCESS;
125 }
vkDestroyBufferView(VkDevice,VkBufferView,const VkAllocationCallbacks *)126 static void vkDestroyBufferView(VkDevice,
127 VkBufferView,
128 const VkAllocationCallbacks*) {}
vkFreeMemory(VkDevice,VkDeviceMemory,const VkAllocationCallbacks *)129 static void vkFreeMemory(VkDevice,
130 VkDeviceMemory,
131 const VkAllocationCallbacks*) {}
vkDestroyBuffer(VkDevice,VkBuffer,const VkAllocationCallbacks *)132 static void vkDestroyBuffer(VkDevice,
133 VkBuffer,
134 const VkAllocationCallbacks*) {}
135 };
136
137 class VertexBufferTest : public testing::Test {
138 public:
VertexBufferTest()139 VertexBufferTest()
140 : device_(MakeUnique<DummyDevice>()),
141 commandPool_(MakeUnique<CommandPool>(device_.get())),
142 commandBuffer_(
143 MakeUnique<CommandBuffer>(device_.get(), commandPool_.get())),
144 vertex_buffer_(MakeUnique<VertexBuffer>(device_.get())) {
145 commandBuffer_->Initialize();
146 }
147
~VertexBufferTest()148 ~VertexBufferTest() override { vertex_buffer_.reset(); }
149
SetData(uint8_t location,Format * format,std::vector<Value> values)150 Result SetData(uint8_t location, Format* format, std::vector<Value> values) {
151 auto buffer = MakeUnique<Buffer>();
152 buffer->SetFormat(format);
153 buffer->SetData(std::move(values));
154
155 vertex_buffer_->SetData(location, buffer.get(), InputRate::kVertex, format,
156 0, format->SizeInBytes());
157 return vertex_buffer_->SendVertexData(commandBuffer_.get());
158 }
159
GetVkBufferPtr()160 const void* GetVkBufferPtr() { return device_->GetMemoryPtr(); }
161
162 private:
163 std::unique_ptr<DummyDevice> device_;
164 std::unique_ptr<CommandPool> commandPool_;
165 std::unique_ptr<CommandBuffer> commandBuffer_;
166 std::unique_ptr<VertexBuffer> vertex_buffer_;
167 };
168
169 } // namespace
170
TEST_F(VertexBufferTest,R8G8B8A8_UINT)171 TEST_F(VertexBufferTest, R8G8B8A8_UINT) {
172 std::vector<Value> values(4);
173 values[0].SetIntValue(55);
174 values[1].SetIntValue(3);
175 values[2].SetIntValue(27);
176 values[3].SetIntValue(255);
177
178 TypeParser parser;
179 auto type = parser.Parse("R8G8B8A8_UINT");
180 Format fmt(type.get());
181 Result r = SetData(0, &fmt, values);
182
183 const uint8_t* ptr = static_cast<const uint8_t*>(GetVkBufferPtr());
184 EXPECT_EQ(55, ptr[0]);
185 EXPECT_EQ(3, ptr[1]);
186 EXPECT_EQ(27, ptr[2]);
187 EXPECT_EQ(255, ptr[3]);
188 }
189
TEST_F(VertexBufferTest,R16G16B16A16_UINT)190 TEST_F(VertexBufferTest, R16G16B16A16_UINT) {
191 std::vector<Value> values(4);
192 values[0].SetIntValue(55);
193 values[1].SetIntValue(3);
194 values[2].SetIntValue(27);
195 values[3].SetIntValue(255);
196
197 TypeParser parser;
198 auto type = parser.Parse("R16G16B16A16_UINT");
199 Format fmt(type.get());
200 Result r = SetData(0, &fmt, values);
201
202 const uint16_t* ptr = static_cast<const uint16_t*>(GetVkBufferPtr());
203 EXPECT_EQ(55, ptr[0]);
204 EXPECT_EQ(3, ptr[1]);
205 EXPECT_EQ(27, ptr[2]);
206 EXPECT_EQ(255, ptr[3]);
207 }
208
TEST_F(VertexBufferTest,R32G32B32A32_UINT)209 TEST_F(VertexBufferTest, R32G32B32A32_UINT) {
210 std::vector<Value> values(4);
211 values[0].SetIntValue(55);
212 values[1].SetIntValue(3);
213 values[2].SetIntValue(27);
214 values[3].SetIntValue(255);
215
216 TypeParser parser;
217 auto type = parser.Parse("R32G32B32A32_UINT");
218 Format fmt(type.get());
219 Result r = SetData(0, &fmt, values);
220
221 const uint32_t* ptr = static_cast<const uint32_t*>(GetVkBufferPtr());
222 EXPECT_EQ(55, ptr[0]);
223 EXPECT_EQ(3, ptr[1]);
224 EXPECT_EQ(27, ptr[2]);
225 EXPECT_EQ(255, ptr[3]);
226 }
227
TEST_F(VertexBufferTest,R64G64B64A64_UINT)228 TEST_F(VertexBufferTest, R64G64B64A64_UINT) {
229 std::vector<Value> values(4);
230 values[0].SetIntValue(55);
231 values[1].SetIntValue(3);
232 values[2].SetIntValue(27);
233 values[3].SetIntValue(255);
234
235 TypeParser parser;
236 auto type = parser.Parse("R64G64B64A64_UINT");
237 Format fmt(type.get());
238 Result r = SetData(0, &fmt, values);
239
240 const uint64_t* ptr = static_cast<const uint64_t*>(GetVkBufferPtr());
241 EXPECT_EQ(55, ptr[0]);
242 EXPECT_EQ(3, ptr[1]);
243 EXPECT_EQ(27, ptr[2]);
244 EXPECT_EQ(255, ptr[3]);
245 }
246
TEST_F(VertexBufferTest,R8G8B8A8_SNORM)247 TEST_F(VertexBufferTest, R8G8B8A8_SNORM) {
248 std::vector<Value> values(4);
249 values[0].SetIntValue(static_cast<uint64_t>(-55));
250 values[1].SetIntValue(3);
251 values[2].SetIntValue(static_cast<uint64_t>(-128));
252 values[3].SetIntValue(127);
253
254 TypeParser parser;
255 auto type = parser.Parse("R8G8B8A8_SNORM");
256 Format fmt(type.get());
257 Result r = SetData(0, &fmt, values);
258 const int8_t* ptr = static_cast<const int8_t*>(GetVkBufferPtr());
259
260 EXPECT_EQ(-55, ptr[0]);
261 EXPECT_EQ(3, ptr[1]);
262 EXPECT_EQ(-128, ptr[2]);
263 EXPECT_EQ(127, ptr[3]);
264 }
265
TEST_F(VertexBufferTest,R16G16B16A16_SNORM)266 TEST_F(VertexBufferTest, R16G16B16A16_SNORM) {
267 std::vector<Value> values(4);
268 values[0].SetIntValue(static_cast<uint64_t>(-55));
269 values[1].SetIntValue(3);
270 values[2].SetIntValue(static_cast<uint64_t>(-27));
271 values[3].SetIntValue(255);
272
273 TypeParser parser;
274 auto type = parser.Parse("R16G16B16A16_SNORM");
275 Format fmt(type.get());
276 Result r = SetData(0, &fmt, values);
277
278 const int16_t* ptr = static_cast<const int16_t*>(GetVkBufferPtr());
279 EXPECT_EQ(-55, ptr[0]);
280 EXPECT_EQ(3, ptr[1]);
281 EXPECT_EQ(-27, ptr[2]);
282 EXPECT_EQ(255, ptr[3]);
283 }
284
TEST_F(VertexBufferTest,R32G32B32A32_SINT)285 TEST_F(VertexBufferTest, R32G32B32A32_SINT) {
286 std::vector<Value> values(4);
287 values[0].SetIntValue(static_cast<uint64_t>(-55));
288 values[1].SetIntValue(3);
289 values[2].SetIntValue(static_cast<uint64_t>(-27));
290 values[3].SetIntValue(255);
291
292 TypeParser parser;
293 auto type = parser.Parse("R32G32B32A32_SINT");
294 Format fmt(type.get());
295 Result r = SetData(0, &fmt, values);
296
297 const int32_t* ptr = static_cast<const int32_t*>(GetVkBufferPtr());
298 EXPECT_EQ(-55, ptr[0]);
299 EXPECT_EQ(3, ptr[1]);
300 EXPECT_EQ(-27, ptr[2]);
301 EXPECT_EQ(255, ptr[3]);
302 }
303
TEST_F(VertexBufferTest,R64G64B64A64_SINT)304 TEST_F(VertexBufferTest, R64G64B64A64_SINT) {
305 std::vector<Value> values(4);
306 values[0].SetIntValue(static_cast<uint64_t>(-55));
307 values[1].SetIntValue(3);
308 values[2].SetIntValue(static_cast<uint64_t>(-27));
309 values[3].SetIntValue(255);
310
311 TypeParser parser;
312 auto type = parser.Parse("R64G64B64A64_SINT");
313 Format fmt(type.get());
314 Result r = SetData(0, &fmt, values);
315
316 const int64_t* ptr = static_cast<const int64_t*>(GetVkBufferPtr());
317 EXPECT_EQ(-55, ptr[0]);
318 EXPECT_EQ(3, ptr[1]);
319 EXPECT_EQ(-27, ptr[2]);
320 EXPECT_EQ(255, ptr[3]);
321 }
322
TEST_F(VertexBufferTest,R32G32B32_SFLOAT)323 TEST_F(VertexBufferTest, R32G32B32_SFLOAT) {
324 std::vector<Value> values(3);
325 values[0].SetDoubleValue(-6.0);
326 values[1].SetDoubleValue(14.0);
327 values[2].SetDoubleValue(0.1171875);
328
329 TypeParser parser;
330 auto type = parser.Parse("R32G32B32_SFLOAT");
331 Format fmt(type.get());
332 Result r = SetData(0, &fmt, values);
333
334 const float* ptr = static_cast<const float*>(GetVkBufferPtr());
335 EXPECT_FLOAT_EQ(-6.0f, ptr[0]);
336 EXPECT_FLOAT_EQ(14.0f, ptr[1]);
337 EXPECT_FLOAT_EQ(0.1171875f, ptr[2]);
338 }
339
TEST_F(VertexBufferTest,R64G64B64_SFLOAT)340 TEST_F(VertexBufferTest, R64G64B64_SFLOAT) {
341 std::vector<Value> values(3);
342 values[0].SetDoubleValue(-6.0);
343 values[1].SetDoubleValue(14.0);
344 values[2].SetDoubleValue(0.1171875);
345
346 TypeParser parser;
347 auto type = parser.Parse("R64G64B64_SFLOAT");
348 Format fmt(type.get());
349 Result r = SetData(0, &fmt, values);
350
351 const double* ptr = static_cast<const double*>(GetVkBufferPtr());
352 EXPECT_DOUBLE_EQ(-6.0, ptr[0]);
353 EXPECT_DOUBLE_EQ(14.0, ptr[1]);
354 EXPECT_DOUBLE_EQ(0.1171875, ptr[2]);
355 }
356
357 } // namespace vulkan
358 } // namespace amber
359