Enable multiple buffers
Enables creation of multiple mesh objects in a single buffer. This is still WIP.
This commit is contained in:
1 parent
c4734e99c2
commit
e06288320d
6 files changed
+188
-123
No files matched your search
@@ -4,6 +4,8 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "vulkan_buffers.hpp"
|
||||||
|
|
||||||
namespace rse::graphics::mesh
|
namespace rse::graphics::mesh
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -12,7 +14,9 @@ std::queue<uint16_t> free_ids;
|
|||||||
|
|
||||||
std::map<uint16_t, std::queue<uint16_t>> instance_free_ids;
|
std::map<uint16_t, std::queue<uint16_t>> instance_free_ids;
|
||||||
|
|
||||||
uint16_t create_mesh(std::vector<rse::graphics::vulkanbase::Vertex> vertices, std::vector<uint16_t> indices)
|
uint16_t create_mesh(rse::graphics::vulkanbase::VulkanState& vulkan_state,
|
||||||
|
std::vector<rse::graphics::vulkanbase::Vertex> vertices,
|
||||||
|
std::vector<uint16_t> indices)
|
||||||
{
|
{
|
||||||
static uint16_t last_id = 0U;
|
static uint16_t last_id = 0U;
|
||||||
uint16_t assignable_id = 0U;
|
uint16_t assignable_id = 0U;
|
||||||
@@ -30,10 +34,14 @@ uint16_t create_mesh(std::vector<rse::graphics::vulkanbase::Vertex> vertices, st
|
|||||||
indices
|
indices
|
||||||
));
|
));
|
||||||
|
|
||||||
|
rse::graphics::vulkanbase::update_mesh_buffers(vulkan_state, vertices, indices);
|
||||||
|
|
||||||
return assignable_id;
|
return assignable_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_mesh_instance(uint16_t mesh_id, InstanceData instance_data)
|
void create_mesh_instance(rse::graphics::vulkanbase::VulkanState& vulkan_state,
|
||||||
|
uint16_t mesh_id,
|
||||||
|
InstanceData instance_data)
|
||||||
{
|
{
|
||||||
uint16_t instance_id = 0U;
|
uint16_t instance_id = 0U;
|
||||||
auto& instances = g_meshes[mesh_id].instances;
|
auto& instances = g_meshes[mesh_id].instances;
|
||||||
@@ -50,6 +58,8 @@ void create_mesh_instance(uint16_t mesh_id, InstanceData instance_data)
|
|||||||
instance_id,
|
instance_id,
|
||||||
instance_data
|
instance_data
|
||||||
);
|
);
|
||||||
|
|
||||||
|
rse::graphics::vulkanbase::update_mesh_instances(vulkan_state, instance_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Replace with something else. It will take to much time to do this each time we draw frame for all the objects
|
//TODO: Replace with something else. It will take to much time to do this each time we draw frame for all the objects
|
||||||
|
|||||||
@@ -17,8 +17,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
#include "vulkan_commons.hpp"
|
#include "vulkan_commons.hpp"
|
||||||
|
|
||||||
namespace rse::graphics::mesh
|
namespace rse::graphics::mesh
|
||||||
@@ -27,12 +25,6 @@ namespace rse::graphics::mesh
|
|||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
struct MeshInstance;
|
struct MeshInstance;
|
||||||
|
|
||||||
struct InstanceData {
|
|
||||||
glm::vec3 pos;
|
|
||||||
glm::vec3 rot;
|
|
||||||
float scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MeshInstance
|
struct MeshInstance
|
||||||
{
|
{
|
||||||
uint32_t instance_id;
|
uint32_t instance_id;
|
||||||
@@ -55,7 +47,9 @@ struct Mesh
|
|||||||
* @param indices indices for mesh
|
* @param indices indices for mesh
|
||||||
* @return uint16_t Mesh identifier. Can be useful for getting vertices, indices and instances
|
* @return uint16_t Mesh identifier. Can be useful for getting vertices, indices and instances
|
||||||
*/
|
*/
|
||||||
uint16_t create_mesh(std::vector<rse::graphics::vulkanbase::Vertex> vertices, std::vector<uint16_t> indices);
|
uint16_t create_mesh(rse::graphics::vulkanbase::VulkanState& vulkan_state,
|
||||||
|
std::vector<rse::graphics::vulkanbase::Vertex> vertices,
|
||||||
|
std::vector<uint16_t> indices);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a instance for the selected mesh. Instance can have its own location, rotation and scale
|
* @brief Create a instance for the selected mesh. Instance can have its own location, rotation and scale
|
||||||
@@ -63,7 +57,9 @@ uint16_t create_mesh(std::vector<rse::graphics::vulkanbase::Vertex> vertices, st
|
|||||||
* @param mesh_id Mesh id
|
* @param mesh_id Mesh id
|
||||||
* @param instance_data Transformation info
|
* @param instance_data Transformation info
|
||||||
*/
|
*/
|
||||||
void create_mesh_instance(uint16_t mesh_id, InstanceData instance_data);
|
void create_mesh_instance(rse::graphics::vulkanbase::VulkanState& vulkan_state,
|
||||||
|
uint16_t mesh_id,
|
||||||
|
InstanceData instance_data);
|
||||||
|
|
||||||
std::vector<rse::graphics::vulkanbase::Vertex> get_mesh_vertices(uint16_t mesh_id);
|
std::vector<rse::graphics::vulkanbase::Vertex> get_mesh_vertices(uint16_t mesh_id);
|
||||||
std::vector<uint16_t> get_mesh_indices(uint16_t mesh_id);
|
std::vector<uint16_t> get_mesh_indices(uint16_t mesh_id);
|
||||||
|
|||||||
@@ -34,6 +34,11 @@ uint8_t RseGraphics::graphics_run(void)
|
|||||||
|
|
||||||
window::windowInit();
|
window::windowInit();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (0 != vulkanbase::initVulkan(vulkan_state))
|
||||||
|
return -1;
|
||||||
|
|
||||||
// FIXME: Temporary array of vertices, for testing purposes
|
// FIXME: Temporary array of vertices, for testing purposes
|
||||||
const std::vector<rse::graphics::vulkanbase::Vertex> vertices = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}},
|
const std::vector<rse::graphics::vulkanbase::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, 1.0f, 1.0f}},
|
||||||
@@ -43,21 +48,18 @@ uint8_t RseGraphics::graphics_run(void)
|
|||||||
// FIXME: Temporary array of vertices, for testing purposes
|
// FIXME: Temporary array of vertices, for testing purposes
|
||||||
std::vector<uint16_t> indices = {0, 1, 2, 2, 3, 0};
|
std::vector<uint16_t> indices = {0, 1, 2, 2, 3, 0};
|
||||||
|
|
||||||
uint16_t mesh_id = rse::graphics::mesh::create_mesh(vertices, indices);
|
uint16_t mesh_id = rse::graphics::mesh::create_mesh(vulkan_state, vertices, indices);
|
||||||
rse::graphics::mesh::create_mesh_instance(mesh_id, rse::graphics::mesh::InstanceData(
|
rse::graphics::mesh::create_mesh_instance(vulkan_state, mesh_id, rse::graphics::mesh::InstanceData(
|
||||||
glm::vec3(0.0f, 0.0f, 0.0f),
|
glm::vec3(0.0f, 0.0f, 0.0f),
|
||||||
glm::vec3(0.0f, 0.0f, glm::radians(45.0f)),
|
glm::vec3(0.0f, 0.0f, glm::radians(45.0f)),
|
||||||
1.0f
|
1.0f
|
||||||
));
|
));
|
||||||
|
|
||||||
rse::graphics::mesh::create_mesh_instance(mesh_id, rse::graphics::mesh::InstanceData(
|
// rse::graphics::mesh::create_mesh_instance(vulkan_state, mesh_id, rse::graphics::mesh::InstanceData(
|
||||||
glm::vec3(-1.0f, 0.0f, 0.0f),
|
// glm::vec3(-1.0f, 0.0f, 0.0f),
|
||||||
glm::vec3(0.0f, 0.0f, 0.0f),
|
// glm::vec3(0.0f, 0.0f, 0.0f),
|
||||||
1.0f
|
// 1.0f
|
||||||
));
|
// ));
|
||||||
|
|
||||||
if (0 != vulkanbase::initVulkan(vulkan_state))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
window::windowLoop(vulkan_state);
|
window::windowLoop(vulkan_state);
|
||||||
|
|
||||||
|
|||||||
+141
-101
@@ -14,6 +14,7 @@
|
|||||||
namespace rse::graphics::vulkanbase
|
namespace rse::graphics::vulkanbase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#define MAX_VERTEX_BUFFER_SIZE 33554432 /* 32 MB*/
|
||||||
|
|
||||||
using namespace locale::vulkan;
|
using namespace locale::vulkan;
|
||||||
|
|
||||||
@@ -27,9 +28,9 @@ using namespace locale::vulkan;
|
|||||||
// std::vector<uint16_t> indices = {0, 1, 2, 2, 3, 0};
|
// std::vector<uint16_t> indices = {0, 1, 2, 2, 3, 0};
|
||||||
|
|
||||||
/* GPU visible buffer */
|
/* GPU visible buffer */
|
||||||
Buffer gVertexBuffer = {};
|
std::vector<Buffer> gVertexBuffers = {};
|
||||||
Buffer gIndexBuffer = {};
|
std::vector<Buffer> gIndexBuffers = {};
|
||||||
Buffer gInstancesBuffer = {};
|
std::vector<Buffer> gInstanceBuffers = {};
|
||||||
/* CPU visible buffer. TODO: Do we need this global? */
|
/* CPU visible buffer. TODO: Do we need this global? */
|
||||||
|
|
||||||
VkCommandPool gCommandPool = VK_NULL_HANDLE;
|
VkCommandPool gCommandPool = VK_NULL_HANDLE;
|
||||||
@@ -37,8 +38,7 @@ VkCommandPool gCommandPool = VK_NULL_HANDLE;
|
|||||||
|
|
||||||
static uint8_t createBuffer(VulkanState& vulkan_state, const VkDeviceSize size, VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage,
|
static uint8_t createBuffer(VulkanState& vulkan_state, const VkDeviceSize size, VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage,
|
||||||
const VmaAllocationCreateFlags allocationFlags, Buffer& buffer);
|
const VmaAllocationCreateFlags allocationFlags, Buffer& buffer);
|
||||||
static uint8_t copyBuffer(VulkanState& vulkan_state, VkBuffer src, VkBuffer dst, VkDeviceSize size);
|
static uint8_t copyBuffer(VulkanState& vulkan_state, VkBuffer src, VkBuffer dst, VkDeviceSize size, VkDeviceSize dest_offset = 0);
|
||||||
|
|
||||||
|
|
||||||
static uint8_t createCommandPools(VulkanState& vulkan_state);
|
static uint8_t createCommandPools(VulkanState& vulkan_state);
|
||||||
static uint8_t createVertexBuffer(VulkanState& vulkan_state);
|
static uint8_t createVertexBuffer(VulkanState& vulkan_state);
|
||||||
@@ -99,7 +99,7 @@ uint8_t createBuffer(VulkanState& vulkan_state, const VkDeviceSize size, VkBuffe
|
|||||||
* @param size Size of buffer to copy
|
* @param size Size of buffer to copy
|
||||||
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
|
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
|
||||||
*/
|
*/
|
||||||
uint8_t copyBuffer(VulkanState& vulkan_state, VkBuffer src, VkBuffer dst, VkDeviceSize size)
|
uint8_t copyBuffer(VulkanState& vulkan_state, VkBuffer src, VkBuffer dst, VkDeviceSize size, VkDeviceSize dest_offset)
|
||||||
{
|
{
|
||||||
/* Vulkan buffers can only be copied using command buffers */
|
/* Vulkan buffers can only be copied using command buffers */
|
||||||
VkBufferCopy copyRegion;
|
VkBufferCopy copyRegion;
|
||||||
@@ -120,7 +120,7 @@ uint8_t copyBuffer(VulkanState& vulkan_state, VkBuffer src, VkBuffer dst, VkDevi
|
|||||||
beginInfo.pInheritanceInfo = nullptr;
|
beginInfo.pInheritanceInfo = nullptr;
|
||||||
|
|
||||||
copyRegion.srcOffset = 0;
|
copyRegion.srcOffset = 0;
|
||||||
copyRegion.dstOffset = 0;
|
copyRegion.dstOffset = dest_offset;
|
||||||
copyRegion.size = size;
|
copyRegion.size = size;
|
||||||
|
|
||||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
@@ -134,15 +134,19 @@ uint8_t copyBuffer(VulkanState& vulkan_state, VkBuffer src, VkBuffer dst, VkDevi
|
|||||||
submitInfo.pSignalSemaphores = nullptr;
|
submitInfo.pSignalSemaphores = nullptr;
|
||||||
|
|
||||||
// FIXME: At result checks
|
// FIXME: At result checks
|
||||||
vkAllocateCommandBuffers(vulkan_state.device, &allocInfo, ©CommandBuffer);
|
VkResult status;
|
||||||
vkBeginCommandBuffer(copyCommandBuffer, &beginInfo);
|
status = vkAllocateCommandBuffers(vulkan_state.device, &allocInfo, ©CommandBuffer);
|
||||||
|
status = vkBeginCommandBuffer(copyCommandBuffer, &beginInfo);
|
||||||
vkCmdCopyBuffer(copyCommandBuffer, src, dst, 1, ©Region);
|
vkCmdCopyBuffer(copyCommandBuffer, src, dst, 1, ©Region);
|
||||||
vkEndCommandBuffer(copyCommandBuffer);
|
status = vkEndCommandBuffer(copyCommandBuffer);
|
||||||
vkQueueSubmit(vulkan_state.graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
|
status = vkQueueSubmit(vulkan_state.graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||||
/* TODO: Use fences to wait instead of idle */
|
/* TODO: Use fences to wait instead of idle */
|
||||||
vkQueueWaitIdle(vulkan_state.graphicsQueue);
|
status = vkQueueWaitIdle(vulkan_state.graphicsQueue);
|
||||||
vkFreeCommandBuffers(vulkan_state.device, gCommandPool, 1, ©CommandBuffer);
|
vkFreeCommandBuffers(vulkan_state.device, gCommandPool, 1, ©CommandBuffer);
|
||||||
|
|
||||||
|
if (status != VK_SUCCESS) {
|
||||||
|
return VULKAN_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
return VULKAN_ERROR_NO_ERROR;
|
return VULKAN_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,41 +185,21 @@ uint8_t createCommandPools(VulkanState& vulkan_state)
|
|||||||
*/
|
*/
|
||||||
uint8_t createVertexBuffer(VulkanState& vulkan_state)
|
uint8_t createVertexBuffer(VulkanState& vulkan_state)
|
||||||
{
|
{
|
||||||
void* mappedData;
|
|
||||||
VkDeviceSize bufferSize;
|
VkDeviceSize bufferSize;
|
||||||
Buffer staging_buffer;
|
Buffer vertex_buffer;
|
||||||
|
|
||||||
auto vertices = rse::graphics::mesh::get_mesh_vertices(0);
|
bufferSize = MAX_VERTEX_BUFFER_SIZE;
|
||||||
|
|
||||||
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, staging_buffer)) {
|
|
||||||
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
|
||||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create Vertex Buffer*/
|
/* Create Vertex Buffer*/
|
||||||
if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
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 */
|
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, /* Will not be mapped with vmaMapMemory */
|
||||||
gVertexBuffer)) {
|
vertex_buffer)) {
|
||||||
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill staging buffer */
|
vertex_buffer.allocated_size = 0;
|
||||||
if (VK_SUCCESS != vmaMapMemory(vulkan_state.allocator, staging_buffer.allocation, &mappedData)) {
|
gVertexBuffers.push_back(std::move(vertex_buffer));
|
||||||
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, staging_buffer.allocation);
|
|
||||||
|
|
||||||
copyBuffer(vulkan_state, staging_buffer.buffer, gVertexBuffer.buffer, bufferSize);
|
|
||||||
|
|
||||||
vmaDestroyBuffer(vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation);
|
|
||||||
|
|
||||||
return VULKAN_ERROR_NO_ERROR;
|
return VULKAN_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,79 +211,43 @@ uint8_t createVertexBuffer(VulkanState& vulkan_state)
|
|||||||
*/
|
*/
|
||||||
uint8_t createIndexBuffer(VulkanState& vulkan_state)
|
uint8_t createIndexBuffer(VulkanState& vulkan_state)
|
||||||
{
|
{
|
||||||
void* mappedData;
|
|
||||||
VkDeviceSize bufferSize;
|
VkDeviceSize bufferSize;
|
||||||
Buffer staging_buffer;
|
Buffer index_buffer;
|
||||||
|
|
||||||
auto indices = rse::graphics::mesh::get_mesh_indices(0);
|
bufferSize = MAX_VERTEX_BUFFER_SIZE;
|
||||||
|
|
||||||
bufferSize = sizeof(indices[0]) * indices.size();
|
/* Create Index Buffer*/
|
||||||
|
|
||||||
/* 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_INDEX_BUFFER_BIT,
|
if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||||
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, /* Will not be mapped with vmaMapMemory */
|
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, /* Will not be mapped with vmaMapMemory */
|
||||||
gIndexBuffer)) {
|
index_buffer)) {
|
||||||
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill staging buffer */
|
index_buffer.allocated_size = 0;
|
||||||
if (VK_SUCCESS != vmaMapMemory(vulkan_state.allocator, staging_buffer.allocation, &mappedData)) {
|
gIndexBuffers.push_back(std::move(index_buffer));
|
||||||
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, staging_buffer.allocation);
|
|
||||||
|
|
||||||
copyBuffer(vulkan_state, staging_buffer.buffer, gIndexBuffer.buffer, bufferSize);
|
|
||||||
vmaDestroyBuffer(vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation);
|
|
||||||
|
|
||||||
return VULKAN_ERROR_NO_ERROR;
|
return VULKAN_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t createInstancesBuffer(VulkanState& vulkan_state)
|
uint8_t createInstanceBuffer(VulkanState& vulkan_state)
|
||||||
{
|
{
|
||||||
void* mappedData;
|
|
||||||
VkDeviceSize bufferSize;
|
VkDeviceSize bufferSize;
|
||||||
Buffer staging_buffer;
|
Buffer instance_buffer;
|
||||||
|
|
||||||
auto instances = rse::graphics::mesh::get_instance_data_for_mesh(0);
|
|
||||||
|
|
||||||
bufferSize = sizeof(instances[0]) * instances.size();
|
bufferSize = MAX_VERTEX_BUFFER_SIZE;
|
||||||
|
|
||||||
/* Creating staging buffer*/
|
/* Create Instance 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,
|
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 */
|
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, /* Will not be mapped with vmaMapMemory */
|
||||||
gInstancesBuffer)) {
|
instance_buffer)) {
|
||||||
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill staging buffer */
|
instance_buffer.allocated_size = 0;
|
||||||
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);
|
|
||||||
|
|
||||||
|
gInstanceBuffers.push_back(std::move(instance_buffer));
|
||||||
return VULKAN_ERROR_NO_ERROR;
|
return VULKAN_ERROR_NO_ERROR;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -342,7 +290,9 @@ uint8_t allocateCommandBuffers(VulkanState& vulkan_state)
|
|||||||
allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; /* TODO: When needed, add secondary command buffer */
|
allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; /* TODO: When needed, add secondary command buffer */
|
||||||
allocateInfo.commandBufferCount = SWAP_BUFFER_COUNT;
|
allocateInfo.commandBufferCount = SWAP_BUFFER_COUNT;
|
||||||
|
|
||||||
if (VK_SUCCESS != vkAllocateCommandBuffers(vulkan_state.device, &allocateInfo, vulkan_state.pCommandBuffers.data())) {
|
if (VK_SUCCESS != vkAllocateCommandBuffers(vulkan_state.device,
|
||||||
|
&allocateInfo,
|
||||||
|
vulkan_state.pCommandBuffers.data())) {
|
||||||
LOGF << vulkanErrorMesssages[VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED];
|
LOGF << vulkanErrorMesssages[VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED];
|
||||||
return VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED;
|
return VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED;
|
||||||
}
|
}
|
||||||
@@ -360,12 +310,95 @@ void updateUniformBuffer(VulkanState& vulkan_state)
|
|||||||
// 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::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.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.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 =
|
ubo.proj = glm::perspective(glm::radians(45.0f),
|
||||||
glm::perspective(glm::radians(45.0f), vulkan_state.swapchainExtent.width / (float)vulkan_state.swapchainExtent.height, 0.1f, 20.0f);
|
vulkan_state.swapchainExtent.width / (float)vulkan_state.swapchainExtent.height,
|
||||||
|
0.1f,
|
||||||
|
20.0f);
|
||||||
ubo.proj[1][1] *= -1; /* GLM was developed for OpenGL, where Y coordinate of the clip is inverted */
|
ubo.proj[1][1] *= -1; /* GLM was developed for OpenGL, where Y coordinate of the clip is inverted */
|
||||||
memcpy(vulkan_state.uniformBuffers[vulkan_state.currentFrame].allocationInfo.pMappedData, &ubo, sizeof(ubo));
|
memcpy(vulkan_state.uniformBuffers[vulkan_state.currentFrame].allocationInfo.pMappedData, &ubo, sizeof(ubo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t update_mesh_buffers(VulkanState& vulkan_state,
|
||||||
|
const std::vector<rse::graphics::vulkanbase::Vertex>& vertices,
|
||||||
|
const std::vector<uint16_t>& indices)
|
||||||
|
{
|
||||||
|
// void* mapped_data;
|
||||||
|
Buffer staging_buffer;
|
||||||
|
auto vertices_size = sizeof(vertices[0]) * vertices.size();
|
||||||
|
auto indices_size = sizeof(indices[0]) * indices.size();
|
||||||
|
|
||||||
|
auto last_vertex_buffer = &gVertexBuffers[gVertexBuffers.size() - 1];
|
||||||
|
auto last_index_buffer = &gIndexBuffers[gIndexBuffers.size() - 1];
|
||||||
|
|
||||||
|
/* Creating staging buffer*/
|
||||||
|
if (VK_SUCCESS != createBuffer(vulkan_state,
|
||||||
|
MAX_VERTEX_BUFFER_SIZE,
|
||||||
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
|
VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||||
|
VMA_ALLOCATION_CREATE_MAPPED_BIT
|
||||||
|
| VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
|
||||||
|
staging_buffer)) {
|
||||||
|
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||||
|
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill staging buffer with vertex data */
|
||||||
|
memset(staging_buffer.allocationInfo.pMappedData, 0, MAX_VERTEX_BUFFER_SIZE);
|
||||||
|
memcpy(staging_buffer.allocationInfo.pMappedData, vertices.data(), vertices_size);
|
||||||
|
copyBuffer(vulkan_state,
|
||||||
|
staging_buffer.buffer,
|
||||||
|
last_vertex_buffer->buffer,
|
||||||
|
vertices_size,
|
||||||
|
last_vertex_buffer->allocated_size);
|
||||||
|
|
||||||
|
/* Fill staging buffer with index data */
|
||||||
|
memset(staging_buffer.allocationInfo.pMappedData, 0, MAX_VERTEX_BUFFER_SIZE);
|
||||||
|
memcpy(staging_buffer.allocationInfo.pMappedData, indices.data(), indices_size);
|
||||||
|
copyBuffer(vulkan_state,
|
||||||
|
staging_buffer.buffer,
|
||||||
|
last_index_buffer->buffer,
|
||||||
|
indices_size,
|
||||||
|
last_index_buffer->allocated_size);
|
||||||
|
|
||||||
|
vmaDestroyBuffer(vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation);
|
||||||
|
|
||||||
|
return VULKAN_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t update_mesh_instances(VulkanState& vulkan_state,
|
||||||
|
rse::graphics::mesh::InstanceData& instance_data)
|
||||||
|
{
|
||||||
|
Buffer staging_buffer;
|
||||||
|
|
||||||
|
auto last_instance_buffer = &gInstanceBuffers[gInstanceBuffers.size() - 1];
|
||||||
|
auto instance_size = sizeof(instance_data);
|
||||||
|
|
||||||
|
/* Creating staging buffer*/
|
||||||
|
if (VK_SUCCESS != createBuffer(vulkan_state,
|
||||||
|
MAX_VERTEX_BUFFER_SIZE,
|
||||||
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
|
VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||||
|
VMA_ALLOCATION_CREATE_MAPPED_BIT
|
||||||
|
| VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
|
||||||
|
staging_buffer)) {
|
||||||
|
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||||
|
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(staging_buffer.allocationInfo.pMappedData, &instance_data, instance_size);
|
||||||
|
copyBuffer(vulkan_state,
|
||||||
|
staging_buffer.buffer,
|
||||||
|
last_instance_buffer->buffer,
|
||||||
|
instance_size,
|
||||||
|
last_instance_buffer->allocated_size);
|
||||||
|
|
||||||
|
vmaDestroyBuffer(vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation);
|
||||||
|
|
||||||
|
last_instance_buffer->allocated_size += instance_size;
|
||||||
|
|
||||||
|
return VULKAN_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Records commands for provided command buffer
|
* @brief Records commands for provided command buffer
|
||||||
*
|
*
|
||||||
@@ -382,8 +415,6 @@ uint8_t recordCommandBuffer(VulkanState& vulkan_state, uint32_t imageIndex)
|
|||||||
VkRenderPassBeginInfo renderPassInfo{};
|
VkRenderPassBeginInfo renderPassInfo{};
|
||||||
VkViewport viewport{};
|
VkViewport viewport{};
|
||||||
VkRect2D scissor{};
|
VkRect2D scissor{};
|
||||||
VkBuffer vertexBuffers[] = {gVertexBuffer.buffer};
|
|
||||||
VkBuffer instanceBuffers[] = {gInstancesBuffer.buffer};
|
|
||||||
VkDeviceSize offsets[] = {0};
|
VkDeviceSize offsets[] = {0};
|
||||||
|
|
||||||
auto indices = rse::graphics::mesh::get_mesh_indices(0);
|
auto indices = rse::graphics::mesh::get_mesh_indices(0);
|
||||||
@@ -421,13 +452,20 @@ uint8_t recordCommandBuffer(VulkanState& vulkan_state, uint32_t imageIndex)
|
|||||||
scissor.extent = vulkan_state.swapchainExtent;
|
scissor.extent = vulkan_state.swapchainExtent;
|
||||||
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||||
|
|
||||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
|
for (size_t i = 0; i < gVertexBuffers.size(); ++i) {
|
||||||
vkCmdBindVertexBuffers(commandBuffer, 1, 1, instanceBuffers, offsets);
|
VkBuffer vertexBuffers[] = {gVertexBuffers[i].buffer};
|
||||||
vkCmdBindIndexBuffer(commandBuffer, gIndexBuffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
VkBuffer indexBuffer = {gIndexBuffers[i].buffer};
|
||||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_state.pipelineLayout, 0, 1,
|
VkBuffer instanceBuffers[] = {gInstanceBuffers[i].buffer};
|
||||||
&vulkan_state.descriptorSets[vulkan_state.currentFrame], 0, nullptr);
|
|
||||||
|
|
||||||
vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(indices.size()), instances.size(), 0, 0, 0);
|
/* TODO: Figure out the offset */
|
||||||
|
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
|
||||||
|
vkCmdBindVertexBuffers(commandBuffer, 1, 1, instanceBuffers, offsets);
|
||||||
|
vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 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()), instances.size(), 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
vkCmdEndRenderPass(commandBuffer);
|
vkCmdEndRenderPass(commandBuffer);
|
||||||
|
|
||||||
@@ -446,7 +484,7 @@ uint8_t create_buffers(VulkanState& vulkan_state)
|
|||||||
STATUS_CHECK(createCommandPools(vulkan_state));
|
STATUS_CHECK(createCommandPools(vulkan_state));
|
||||||
STATUS_CHECK(createVertexBuffer(vulkan_state));
|
STATUS_CHECK(createVertexBuffer(vulkan_state));
|
||||||
STATUS_CHECK(createIndexBuffer(vulkan_state));
|
STATUS_CHECK(createIndexBuffer(vulkan_state));
|
||||||
STATUS_CHECK(createInstancesBuffer(vulkan_state));
|
STATUS_CHECK(createInstanceBuffer(vulkan_state));
|
||||||
STATUS_CHECK(createUniformBuffers(vulkan_state));
|
STATUS_CHECK(createUniformBuffers(vulkan_state));
|
||||||
STATUS_CHECK(allocateCommandBuffers(vulkan_state));
|
STATUS_CHECK(allocateCommandBuffers(vulkan_state));
|
||||||
|
|
||||||
@@ -464,9 +502,11 @@ void destroy_buffers(VulkanState& vulkan_state)
|
|||||||
vmaDestroyBuffer(vulkan_state.allocator, vulkan_state.uniformBuffers[i].buffer, vulkan_state.uniformBuffers[i].allocation);
|
vmaDestroyBuffer(vulkan_state.allocator, vulkan_state.uniformBuffers[i].buffer, vulkan_state.uniformBuffers[i].allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
vmaDestroyBuffer(vulkan_state.allocator, gVertexBuffer.buffer, gVertexBuffer.allocation);
|
for (size_t i = 0; i < gVertexBuffers.size(); ++i) {
|
||||||
vmaDestroyBuffer(vulkan_state.allocator, gIndexBuffer.buffer, gIndexBuffer.allocation);
|
vmaDestroyBuffer(vulkan_state.allocator, gVertexBuffers[i].buffer, gVertexBuffers[i].allocation);
|
||||||
vmaDestroyBuffer(vulkan_state.allocator, gInstancesBuffer.buffer, gInstancesBuffer.allocation);
|
vmaDestroyBuffer(vulkan_state.allocator, gIndexBuffers[i].buffer, gIndexBuffers[i].allocation);
|
||||||
|
vmaDestroyBuffer(vulkan_state.allocator, gInstanceBuffers[i].buffer, gInstanceBuffers[i].allocation);
|
||||||
|
}
|
||||||
vkDestroyCommandPool(vulkan_state.device, gCommandPool, nullptr);
|
vkDestroyCommandPool(vulkan_state.device, gCommandPool, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ uint8_t create_buffers(VulkanState& vulkan_state);
|
|||||||
*/
|
*/
|
||||||
void updateUniformBuffer(VulkanState& vulkan_state);
|
void updateUniformBuffer(VulkanState& vulkan_state);
|
||||||
|
|
||||||
|
uint8_t update_mesh_buffers(VulkanState& vulkan_state,
|
||||||
|
const std::vector<rse::graphics::vulkanbase::Vertex>& vertices,
|
||||||
|
const std::vector<uint16_t>& indices);
|
||||||
|
|
||||||
|
uint8_t update_mesh_instances(VulkanState& vulkan_state,
|
||||||
|
rse::graphics::mesh::InstanceData& instance_data);
|
||||||
/**
|
/**
|
||||||
* @brief Record commands for given image index
|
* @brief Record commands for given image index
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ struct Vertex
|
|||||||
*/
|
*/
|
||||||
struct Buffer
|
struct Buffer
|
||||||
{
|
{
|
||||||
|
uint32_t allocated_size;
|
||||||
VkBuffer buffer;
|
VkBuffer buffer;
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
VmaAllocationInfo allocationInfo;
|
VmaAllocationInfo allocationInfo;
|
||||||
@@ -101,4 +102,14 @@ struct VulkanState
|
|||||||
|
|
||||||
} // namespace rse::graphics::vulkanbase
|
} // namespace rse::graphics::vulkanbase
|
||||||
|
|
||||||
|
namespace rse::graphics::mesh
|
||||||
|
{
|
||||||
|
struct InstanceData {
|
||||||
|
glm::vec3 pos;
|
||||||
|
glm::vec3 rot;
|
||||||
|
float scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace rse::graphics::mesh
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in new issue
Block a user