Add basic functionality to draw instances
Allows creation of instances of meshes and drawing all of them with single draw call. Instances can have their own transformation data (location, rotation and scale).
This commit is contained in:
1 parent
6a09350902
commit
c4734e99c2
8 files changed
+343
-37
No files matched your search
@@ -1,15 +1,15 @@
|
||||
#include "vulkan_buffers.hpp"
|
||||
|
||||
#include "vulkan_errors.hpp"
|
||||
|
||||
#include "locale_vulkan.hpp"
|
||||
#include "utilities/logger.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include "vulkan_errors.hpp"
|
||||
#include "locale_vulkan.hpp"
|
||||
#include "utilities/logger.hpp"
|
||||
#include "mesh_controller.hpp"
|
||||
|
||||
namespace rse::graphics::vulkanbase
|
||||
{
|
||||
@@ -17,21 +17,20 @@ namespace rse::graphics::vulkanbase
|
||||
|
||||
using namespace locale::vulkan;
|
||||
|
||||
// FIXME: Temporary array of vertices, for testing purposes
|
||||
const std::vector<Vertex> vertices = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}},
|
||||
{{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 1.0f}},
|
||||
{{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}},
|
||||
{{-0.5f, 0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}}};
|
||||
// // FIXME: Temporary array of vertices, for testing purposes
|
||||
// const std::vector<Vertex> vertices = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}},
|
||||
// {{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 1.0f}},
|
||||
// {{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}},
|
||||
// {{-0.5f, 0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}}};
|
||||
|
||||
// FIXME: Temporary array of vertices, for testing purposes
|
||||
std::vector<uint16_t> indices = {0, 1, 2, 2, 3, 0};
|
||||
// // FIXME: Temporary array of vertices, for testing purposes
|
||||
// std::vector<uint16_t> indices = {0, 1, 2, 2, 3, 0};
|
||||
|
||||
/* GPU visible buffer */
|
||||
Buffer gVertexBuffer = {};
|
||||
/* CPU visible buffer. TODO: Do we need this global? */
|
||||
Buffer gVertexStagingBuffer = {};
|
||||
Buffer gIndexBuffer = {};
|
||||
Buffer gIndexStagingBuffer = {};
|
||||
Buffer gInstancesBuffer = {};
|
||||
/* CPU visible buffer. TODO: Do we need this global? */
|
||||
|
||||
VkCommandPool gCommandPool = VK_NULL_HANDLE;
|
||||
|
||||
@@ -184,12 +183,15 @@ uint8_t createVertexBuffer(VulkanState& vulkan_state)
|
||||
{
|
||||
void* mappedData;
|
||||
VkDeviceSize bufferSize;
|
||||
Buffer staging_buffer;
|
||||
|
||||
auto vertices = rse::graphics::mesh::get_mesh_vertices(0);
|
||||
|
||||
bufferSize = sizeof(vertices[0]) * vertices.size();
|
||||
|
||||
/* Creating staging buffer*/
|
||||
if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, gVertexStagingBuffer)) {
|
||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, staging_buffer)) {
|
||||
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||
}
|
||||
@@ -203,14 +205,16 @@ uint8_t createVertexBuffer(VulkanState& vulkan_state)
|
||||
}
|
||||
|
||||
/* Fill staging buffer */
|
||||
if (VK_SUCCESS != vmaMapMemory(vulkan_state.allocator, gVertexStagingBuffer.allocation, &mappedData)) {
|
||||
if (VK_SUCCESS != vmaMapMemory(vulkan_state.allocator, staging_buffer.allocation, &mappedData)) {
|
||||
LOGF << vulkanErrorMesssages[VULKAN_VERTEX_BUFFER_MAPPING_FAILED];
|
||||
return VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED;
|
||||
}
|
||||
memcpy(mappedData, vertices.data(), sizeof(Vertex) * vertices.size());
|
||||
vmaUnmapMemory(vulkan_state.allocator, gVertexStagingBuffer.allocation);
|
||||
vmaUnmapMemory(vulkan_state.allocator, staging_buffer.allocation);
|
||||
|
||||
copyBuffer(vulkan_state, gVertexStagingBuffer.buffer, gVertexBuffer.buffer, bufferSize);
|
||||
copyBuffer(vulkan_state, staging_buffer.buffer, gVertexBuffer.buffer, bufferSize);
|
||||
|
||||
vmaDestroyBuffer(vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation);
|
||||
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
}
|
||||
@@ -225,12 +229,15 @@ uint8_t createIndexBuffer(VulkanState& vulkan_state)
|
||||
{
|
||||
void* mappedData;
|
||||
VkDeviceSize bufferSize;
|
||||
Buffer staging_buffer;
|
||||
|
||||
auto indices = rse::graphics::mesh::get_mesh_indices(0);
|
||||
|
||||
bufferSize = sizeof(indices[0]) * indices.size();
|
||||
|
||||
/* Creating staging buffer*/
|
||||
if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, gIndexStagingBuffer)) {
|
||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, staging_buffer)) {
|
||||
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||
}
|
||||
@@ -244,18 +251,59 @@ uint8_t createIndexBuffer(VulkanState& vulkan_state)
|
||||
}
|
||||
|
||||
/* Fill staging buffer */
|
||||
if (VK_SUCCESS != vmaMapMemory(vulkan_state.allocator, gIndexStagingBuffer.allocation, &mappedData)) {
|
||||
if (VK_SUCCESS != vmaMapMemory(vulkan_state.allocator, staging_buffer.allocation, &mappedData)) {
|
||||
LOGF << vulkanErrorMesssages[VULKAN_VERTEX_BUFFER_MAPPING_FAILED];
|
||||
return VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED;
|
||||
}
|
||||
memcpy(mappedData, indices.data(), static_cast<size_t>(bufferSize));
|
||||
vmaUnmapMemory(vulkan_state.allocator, gIndexStagingBuffer.allocation);
|
||||
vmaUnmapMemory(vulkan_state.allocator, staging_buffer.allocation);
|
||||
|
||||
copyBuffer(vulkan_state, gIndexStagingBuffer.buffer, gIndexBuffer.buffer, bufferSize);
|
||||
copyBuffer(vulkan_state, staging_buffer.buffer, gIndexBuffer.buffer, bufferSize);
|
||||
vmaDestroyBuffer(vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation);
|
||||
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
uint8_t createInstancesBuffer(VulkanState& vulkan_state)
|
||||
{
|
||||
void* mappedData;
|
||||
VkDeviceSize bufferSize;
|
||||
Buffer staging_buffer;
|
||||
|
||||
auto instances = rse::graphics::mesh::get_instance_data_for_mesh(0);
|
||||
|
||||
bufferSize = sizeof(instances[0]) * instances.size();
|
||||
|
||||
/* Creating staging buffer*/
|
||||
if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, staging_buffer)) {
|
||||
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||
}
|
||||
|
||||
/* Create Vertex Buffer*/
|
||||
if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, /* Will not be mapped with vmaMapMemory */
|
||||
gInstancesBuffer)) {
|
||||
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||
}
|
||||
|
||||
/* Fill staging buffer */
|
||||
if (VK_SUCCESS != vmaMapMemory(vulkan_state.allocator, staging_buffer.allocation, &mappedData)) {
|
||||
LOGF << vulkanErrorMesssages[VULKAN_VERTEX_BUFFER_MAPPING_FAILED];
|
||||
return VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED;
|
||||
}
|
||||
memcpy(mappedData, instances.data(), static_cast<size_t>(bufferSize));
|
||||
vmaUnmapMemory(vulkan_state.allocator, staging_buffer.allocation);
|
||||
|
||||
copyBuffer(vulkan_state, staging_buffer.buffer, gInstancesBuffer.buffer, bufferSize);
|
||||
vmaDestroyBuffer(vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation);
|
||||
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a Uniform Buffers
|
||||
*
|
||||
@@ -309,6 +357,7 @@ uint8_t allocateCommandBuffers(VulkanState& vulkan_state)
|
||||
void updateUniformBuffer(VulkanState& vulkan_state)
|
||||
{
|
||||
UniformBufferObject ubo{};
|
||||
// ubo.model = glm::translate(glm::mat4(1.0f), glm::vec3(1.0f, 0.0f, 0.0f)) * glm::rotate(glm::mat4(1.0f), glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f)) * glm::scale(glm::mat4(1.0f), glm::vec3(2, 1, 1));
|
||||
ubo.model = glm::mat4(1.0f);
|
||||
ubo.view = glm::lookAt(glm::vec3(0.0f, 0.0f, 5.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
ubo.proj =
|
||||
@@ -334,8 +383,12 @@ uint8_t recordCommandBuffer(VulkanState& vulkan_state, uint32_t imageIndex)
|
||||
VkViewport viewport{};
|
||||
VkRect2D scissor{};
|
||||
VkBuffer vertexBuffers[] = {gVertexBuffer.buffer};
|
||||
VkBuffer instanceBuffers[] = {gInstancesBuffer.buffer};
|
||||
VkDeviceSize offsets[] = {0};
|
||||
|
||||
auto indices = rse::graphics::mesh::get_mesh_indices(0);
|
||||
auto instances = rse::graphics::mesh::get_instance_data_for_mesh(0);
|
||||
|
||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
beginInfo.flags = 0;
|
||||
beginInfo.pInheritanceInfo = nullptr;
|
||||
@@ -369,11 +422,12 @@ uint8_t recordCommandBuffer(VulkanState& vulkan_state, uint32_t imageIndex)
|
||||
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
|
||||
vkCmdBindVertexBuffers(commandBuffer, 1, 1, instanceBuffers, offsets);
|
||||
vkCmdBindIndexBuffer(commandBuffer, gIndexBuffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_state.pipelineLayout, 0, 1,
|
||||
&vulkan_state.descriptorSets[vulkan_state.currentFrame], 0, nullptr);
|
||||
|
||||
vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(indices.size()), 1, 0, 0, 0);
|
||||
vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(indices.size()), instances.size(), 0, 0, 0);
|
||||
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
|
||||
@@ -392,6 +446,7 @@ uint8_t create_buffers(VulkanState& vulkan_state)
|
||||
STATUS_CHECK(createCommandPools(vulkan_state));
|
||||
STATUS_CHECK(createVertexBuffer(vulkan_state));
|
||||
STATUS_CHECK(createIndexBuffer(vulkan_state));
|
||||
STATUS_CHECK(createInstancesBuffer(vulkan_state));
|
||||
STATUS_CHECK(createUniformBuffers(vulkan_state));
|
||||
STATUS_CHECK(allocateCommandBuffers(vulkan_state));
|
||||
|
||||
@@ -410,9 +465,8 @@ void destroy_buffers(VulkanState& vulkan_state)
|
||||
}
|
||||
|
||||
vmaDestroyBuffer(vulkan_state.allocator, gVertexBuffer.buffer, gVertexBuffer.allocation);
|
||||
vmaDestroyBuffer(vulkan_state.allocator, gVertexStagingBuffer.buffer, gVertexStagingBuffer.allocation);
|
||||
vmaDestroyBuffer(vulkan_state.allocator, gIndexBuffer.buffer, gIndexBuffer.allocation);
|
||||
vmaDestroyBuffer(vulkan_state.allocator, gIndexStagingBuffer.buffer, gIndexStagingBuffer.allocation);
|
||||
vmaDestroyBuffer(vulkan_state.allocator, gInstancesBuffer.buffer, gInstancesBuffer.allocation);
|
||||
vkDestroyCommandPool(vulkan_state.device, gCommandPool, nullptr);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user