138 lines
4.9 KiB
C++
138 lines
4.9 KiB
C++
#include "hk_model.hpp"
|
|
|
|
#include <cassert>
|
|
#include <cstring>
|
|
|
|
namespace hk{
|
|
Model::Model(Device &device, const Builder &builder)
|
|
: m_device{device}
|
|
{
|
|
createVertexBuffers(builder.vertices);
|
|
createIndexBuffers(builder.indices);
|
|
}
|
|
|
|
Model::~Model()
|
|
{
|
|
vkDestroyBuffer(m_device.device(), m_vertexBuffer, nullptr);
|
|
vkFreeMemory(m_device.device(), m_vertexBufferMemory, nullptr);
|
|
vkDestroyBuffer(m_device.device(), m_indexBuffer, nullptr);
|
|
vkFreeMemory(m_device.device(), m_indexBufferMemory, nullptr);
|
|
}
|
|
|
|
void Model::createVertexBuffers(const std::vector<Vertex> &vertices)
|
|
{
|
|
m_vertexCount = static_cast<uint32_t>(vertices.size());
|
|
assert(m_vertexCount >= 3 && "Vertex count must be at least 3");
|
|
VkDeviceSize bufferSize = sizeof(vertices[0]) * m_vertexCount;
|
|
|
|
VkBuffer stagingBuffer;
|
|
VkDeviceMemory stagingBufferMemory;
|
|
m_device.createBuffer(
|
|
bufferSize,
|
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
|
stagingBuffer,
|
|
stagingBufferMemory
|
|
);
|
|
void *data;
|
|
vkMapMemory(m_device.device(), stagingBufferMemory, 0, bufferSize, 0, &data);
|
|
memcpy(data, vertices.data(), static_cast<size_t>(bufferSize));
|
|
vkUnmapMemory(m_device.device(), stagingBufferMemory);
|
|
|
|
m_device.createBuffer(
|
|
bufferSize,
|
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
m_vertexBuffer,
|
|
m_vertexBufferMemory
|
|
);
|
|
m_device.copyBuffer(stagingBuffer, m_vertexBuffer, bufferSize);
|
|
|
|
vkDestroyBuffer(m_device.device(), stagingBuffer, nullptr);
|
|
vkFreeMemory(m_device.device(), stagingBufferMemory, nullptr);
|
|
}
|
|
|
|
void Model::createIndexBuffers(const std::vector<uint32_t> &indices)
|
|
{
|
|
m_indexCount = static_cast<uint32_t>(indices.size());
|
|
m_hasIndexBuffer = m_indexCount > 0;
|
|
|
|
if (!m_hasIndexBuffer)
|
|
return;
|
|
|
|
VkDeviceSize bufferSize = sizeof(indices[0]) * m_indexCount;
|
|
|
|
VkBuffer stagingBuffer;
|
|
VkDeviceMemory stagingBufferMemory;
|
|
m_device.createBuffer(
|
|
bufferSize,
|
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
|
stagingBuffer,
|
|
stagingBufferMemory
|
|
);
|
|
void *data;
|
|
vkMapMemory(m_device.device(), stagingBufferMemory, 0, bufferSize, 0, &data);
|
|
memcpy(data, indices.data(), static_cast<size_t>(bufferSize));
|
|
vkUnmapMemory(m_device.device(), stagingBufferMemory);
|
|
|
|
m_device.createBuffer(
|
|
bufferSize,
|
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
m_indexBuffer,
|
|
m_indexBufferMemory
|
|
);
|
|
m_device.copyBuffer(stagingBuffer, m_indexBuffer, bufferSize);
|
|
|
|
vkDestroyBuffer(m_device.device(), stagingBuffer, nullptr);
|
|
vkFreeMemory(m_device.device(), stagingBufferMemory, nullptr);
|
|
}
|
|
|
|
void Model::bind(VkCommandBuffer commandBuffer)
|
|
{
|
|
VkBuffer buffers[] = {m_vertexBuffer};
|
|
VkDeviceSize offsets[] = {0};
|
|
vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
|
|
|
|
if (m_hasIndexBuffer)
|
|
{
|
|
vkCmdBindIndexBuffer(commandBuffer, m_indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
|
}
|
|
}
|
|
void Model::draw(VkCommandBuffer commandBuffer)
|
|
{
|
|
if (m_hasIndexBuffer)
|
|
{
|
|
vkCmdDrawIndexed(commandBuffer, m_indexCount, 1, 0, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
vkCmdDraw(commandBuffer, m_vertexCount, 1, 0, 0);
|
|
}
|
|
}
|
|
|
|
std::vector<VkVertexInputBindingDescription> Model::Vertex::getBindingDescriptions()
|
|
{
|
|
std::vector<VkVertexInputBindingDescription> bindingDescriptions(1);
|
|
bindingDescriptions[0].binding = 0;
|
|
bindingDescriptions[0].stride = sizeof(Vertex);
|
|
bindingDescriptions[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
return bindingDescriptions;
|
|
}
|
|
std::vector<VkVertexInputAttributeDescription> Model::Vertex::getAttributeDescriptions()
|
|
{
|
|
std::vector<VkVertexInputAttributeDescription> attributeDescriptions(2);
|
|
attributeDescriptions[0].binding = 0;
|
|
attributeDescriptions[0].location = 0;
|
|
attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
|
|
attributeDescriptions[0].offset = offsetof(Vertex, position);
|
|
|
|
attributeDescriptions[1].binding = 0;
|
|
attributeDescriptions[1].location = 1;
|
|
attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
|
|
attributeDescriptions[1].offset = offsetof(Vertex, color);
|
|
|
|
return attributeDescriptions;
|
|
}
|
|
} |