blob: eb8a7bd8beadceea7a75c5d7c22d3d63fbeb1b96 [file] [log] [blame]
// Copyright 2019 The Amber Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/vulkan/vertex_buffer.h"
#include <utility>
#include "amber/value.h"
#include "gtest/gtest.h"
#include "src/format.h"
#include "src/make_unique.h"
#include "src/type_parser.h"
#include "src/vulkan/command_buffer.h"
#include "src/vulkan/command_pool.h"
#include "src/vulkan/device.h"
namespace amber {
namespace vulkan {
namespace {
class DummyDevice : public Device {
public:
DummyDevice()
: Device(VkInstance(),
VkPhysicalDevice(),
0u,
VkDevice(this),
VkQueue()) {
memory_.resize(64);
dummyPtrs_.vkCreateBuffer = vkCreateBuffer;
dummyPtrs_.vkGetBufferMemoryRequirements = vkGetBufferMemoryRequirements;
dummyPtrs_.vkAllocateMemory = vkAllocateMemory;
dummyPtrs_.vkBindBufferMemory = vkBindBufferMemory;
dummyPtrs_.vkMapMemory = vkMapMemory;
dummyPtrs_.vkCmdPipelineBarrier = vkCmdPipelineBarrier;
dummyPtrs_.vkAllocateCommandBuffers = vkAllocateCommandBuffers;
dummyPtrs_.vkCreateFence = vkCreateFence;
dummyPtrs_.vkDestroyBufferView = vkDestroyBufferView;
dummyPtrs_.vkFreeMemory = vkFreeMemory;
dummyPtrs_.vkDestroyBuffer = vkDestroyBuffer;
}
~DummyDevice() override {}
const VulkanPtrs* GetPtrs() const override { return &dummyPtrs_; }
bool HasMemoryFlags(uint32_t, const VkMemoryPropertyFlags) const override {
return true;
}
void* GetMemoryPtr() { return memory_.data(); }
private:
VulkanPtrs dummyPtrs_;
std::vector<uint8_t> memory_;
static VkResult vkCreateBuffer(VkDevice,
const VkBufferCreateInfo*,
const VkAllocationCallbacks*,
VkBuffer* pBuffer) {
*pBuffer = VkBuffer(1);
return VK_SUCCESS;
}
static void vkGetBufferMemoryRequirements(
VkDevice,
VkBuffer,
VkMemoryRequirements* pMemoryRequirements) {
pMemoryRequirements->alignment = 0;
pMemoryRequirements->size = 0;
pMemoryRequirements->memoryTypeBits = 0xffffffff;
}
static VkResult vkAllocateMemory(VkDevice,
const VkMemoryAllocateInfo*,
const VkAllocationCallbacks*,
VkDeviceMemory*) {
return VK_SUCCESS;
}
static VkResult vkBindBufferMemory(VkDevice,
VkBuffer,
VkDeviceMemory,
VkDeviceSize) {
return VK_SUCCESS;
}
static VkResult vkMapMemory(VkDevice device,
VkDeviceMemory,
VkDeviceSize,
VkDeviceSize,
VkMemoryMapFlags,
void** ppData) {
DummyDevice* devicePtr = reinterpret_cast<DummyDevice*>(device);
*ppData = devicePtr->GetMemoryPtr();
return VK_SUCCESS;
}
static void vkCmdPipelineBarrier(VkCommandBuffer,
VkPipelineStageFlags,
VkPipelineStageFlags,
VkDependencyFlags,
uint32_t,
const VkMemoryBarrier*,
uint32_t,
const VkBufferMemoryBarrier*,
uint32_t,
const VkImageMemoryBarrier*) {}
static VkResult vkAllocateCommandBuffers(VkDevice,
const VkCommandBufferAllocateInfo*,
VkCommandBuffer*) {
return VK_SUCCESS;
}
static VkResult vkCreateFence(VkDevice,
const VkFenceCreateInfo*,
const VkAllocationCallbacks*,
VkFence*) {
return VK_SUCCESS;
}
static void vkDestroyBufferView(VkDevice,
VkBufferView,
const VkAllocationCallbacks*) {}
static void vkFreeMemory(VkDevice,
VkDeviceMemory,
const VkAllocationCallbacks*) {}
static void vkDestroyBuffer(VkDevice,
VkBuffer,
const VkAllocationCallbacks*) {}
};
class VertexBufferTest : public testing::Test {
public:
VertexBufferTest()
: device_(MakeUnique<DummyDevice>()),
commandPool_(MakeUnique<CommandPool>(device_.get())),
commandBuffer_(
MakeUnique<CommandBuffer>(device_.get(), commandPool_.get())),
vertex_buffer_(MakeUnique<VertexBuffer>(device_.get())) {
commandBuffer_->Initialize();
}
~VertexBufferTest() override { vertex_buffer_.reset(); }
Result SetData(uint8_t location, Format* format, std::vector<Value> values) {
auto buffer = MakeUnique<Buffer>();
buffer->SetFormat(format);
buffer->SetData(std::move(values));
vertex_buffer_->SetData(location, buffer.get(), InputRate::kVertex, format,
0, format->SizeInBytes());
return vertex_buffer_->SendVertexData(commandBuffer_.get());
}
const void* GetVkBufferPtr() { return device_->GetMemoryPtr(); }
private:
std::unique_ptr<DummyDevice> device_;
std::unique_ptr<CommandPool> commandPool_;
std::unique_ptr<CommandBuffer> commandBuffer_;
std::unique_ptr<VertexBuffer> vertex_buffer_;
};
} // namespace
TEST_F(VertexBufferTest, R8G8B8A8_UINT) {
std::vector<Value> values(4);
values[0].SetIntValue(55);
values[1].SetIntValue(3);
values[2].SetIntValue(27);
values[3].SetIntValue(255);
TypeParser parser;
auto type = parser.Parse("R8G8B8A8_UINT");
Format fmt(type.get());
Result r = SetData(0, &fmt, values);
const uint8_t* ptr = static_cast<const uint8_t*>(GetVkBufferPtr());
EXPECT_EQ(55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
EXPECT_EQ(27, ptr[2]);
EXPECT_EQ(255, ptr[3]);
}
TEST_F(VertexBufferTest, R16G16B16A16_UINT) {
std::vector<Value> values(4);
values[0].SetIntValue(55);
values[1].SetIntValue(3);
values[2].SetIntValue(27);
values[3].SetIntValue(255);
TypeParser parser;
auto type = parser.Parse("R16G16B16A16_UINT");
Format fmt(type.get());
Result r = SetData(0, &fmt, values);
const uint16_t* ptr = static_cast<const uint16_t*>(GetVkBufferPtr());
EXPECT_EQ(55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
EXPECT_EQ(27, ptr[2]);
EXPECT_EQ(255, ptr[3]);
}
TEST_F(VertexBufferTest, R32G32B32A32_UINT) {
std::vector<Value> values(4);
values[0].SetIntValue(55);
values[1].SetIntValue(3);
values[2].SetIntValue(27);
values[3].SetIntValue(255);
TypeParser parser;
auto type = parser.Parse("R32G32B32A32_UINT");
Format fmt(type.get());
Result r = SetData(0, &fmt, values);
const uint32_t* ptr = static_cast<const uint32_t*>(GetVkBufferPtr());
EXPECT_EQ(55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
EXPECT_EQ(27, ptr[2]);
EXPECT_EQ(255, ptr[3]);
}
TEST_F(VertexBufferTest, R64G64B64A64_UINT) {
std::vector<Value> values(4);
values[0].SetIntValue(55);
values[1].SetIntValue(3);
values[2].SetIntValue(27);
values[3].SetIntValue(255);
TypeParser parser;
auto type = parser.Parse("R64G64B64A64_UINT");
Format fmt(type.get());
Result r = SetData(0, &fmt, values);
const uint64_t* ptr = static_cast<const uint64_t*>(GetVkBufferPtr());
EXPECT_EQ(55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
EXPECT_EQ(27, ptr[2]);
EXPECT_EQ(255, ptr[3]);
}
TEST_F(VertexBufferTest, R8G8B8A8_SNORM) {
std::vector<Value> values(4);
values[0].SetIntValue(static_cast<uint64_t>(-55));
values[1].SetIntValue(3);
values[2].SetIntValue(static_cast<uint64_t>(-128));
values[3].SetIntValue(127);
TypeParser parser;
auto type = parser.Parse("R8G8B8A8_SNORM");
Format fmt(type.get());
Result r = SetData(0, &fmt, values);
const int8_t* ptr = static_cast<const int8_t*>(GetVkBufferPtr());
EXPECT_EQ(-55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
EXPECT_EQ(-128, ptr[2]);
EXPECT_EQ(127, ptr[3]);
}
TEST_F(VertexBufferTest, R16G16B16A16_SNORM) {
std::vector<Value> values(4);
values[0].SetIntValue(static_cast<uint64_t>(-55));
values[1].SetIntValue(3);
values[2].SetIntValue(static_cast<uint64_t>(-27));
values[3].SetIntValue(255);
TypeParser parser;
auto type = parser.Parse("R16G16B16A16_SNORM");
Format fmt(type.get());
Result r = SetData(0, &fmt, values);
const int16_t* ptr = static_cast<const int16_t*>(GetVkBufferPtr());
EXPECT_EQ(-55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
EXPECT_EQ(-27, ptr[2]);
EXPECT_EQ(255, ptr[3]);
}
TEST_F(VertexBufferTest, R32G32B32A32_SINT) {
std::vector<Value> values(4);
values[0].SetIntValue(static_cast<uint64_t>(-55));
values[1].SetIntValue(3);
values[2].SetIntValue(static_cast<uint64_t>(-27));
values[3].SetIntValue(255);
TypeParser parser;
auto type = parser.Parse("R32G32B32A32_SINT");
Format fmt(type.get());
Result r = SetData(0, &fmt, values);
const int32_t* ptr = static_cast<const int32_t*>(GetVkBufferPtr());
EXPECT_EQ(-55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
EXPECT_EQ(-27, ptr[2]);
EXPECT_EQ(255, ptr[3]);
}
TEST_F(VertexBufferTest, R64G64B64A64_SINT) {
std::vector<Value> values(4);
values[0].SetIntValue(static_cast<uint64_t>(-55));
values[1].SetIntValue(3);
values[2].SetIntValue(static_cast<uint64_t>(-27));
values[3].SetIntValue(255);
TypeParser parser;
auto type = parser.Parse("R64G64B64A64_SINT");
Format fmt(type.get());
Result r = SetData(0, &fmt, values);
const int64_t* ptr = static_cast<const int64_t*>(GetVkBufferPtr());
EXPECT_EQ(-55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
EXPECT_EQ(-27, ptr[2]);
EXPECT_EQ(255, ptr[3]);
}
TEST_F(VertexBufferTest, R32G32B32_SFLOAT) {
std::vector<Value> values(3);
values[0].SetDoubleValue(-6.0);
values[1].SetDoubleValue(14.0);
values[2].SetDoubleValue(0.1171875);
TypeParser parser;
auto type = parser.Parse("R32G32B32_SFLOAT");
Format fmt(type.get());
Result r = SetData(0, &fmt, values);
const float* ptr = static_cast<const float*>(GetVkBufferPtr());
EXPECT_FLOAT_EQ(-6.0f, ptr[0]);
EXPECT_FLOAT_EQ(14.0f, ptr[1]);
EXPECT_FLOAT_EQ(0.1171875f, ptr[2]);
}
TEST_F(VertexBufferTest, R64G64B64_SFLOAT) {
std::vector<Value> values(3);
values[0].SetDoubleValue(-6.0);
values[1].SetDoubleValue(14.0);
values[2].SetDoubleValue(0.1171875);
TypeParser parser;
auto type = parser.Parse("R64G64B64_SFLOAT");
Format fmt(type.get());
Result r = SetData(0, &fmt, values);
const double* ptr = static_cast<const double*>(GetVkBufferPtr());
EXPECT_DOUBLE_EQ(-6.0, ptr[0]);
EXPECT_DOUBLE_EQ(14.0, ptr[1]);
EXPECT_DOUBLE_EQ(0.1171875, ptr[2]);
}
} // namespace vulkan
} // namespace amber