From c4734e99c28a19b12964be6f389ab02d02dea97f Mon Sep 17 00:00:00 2001 From: Piotr Krygier Date: Fri, 31 Mar 2023 15:44:03 +0200 Subject: [PATCH] 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). --- graphics/CMakeLists.txt | 1 + graphics/rse_graphics.hpp | 3 +- graphics/shaders/shader.vert | 51 ++++++++++++++- graphics/src/mesh_controller.cpp | 75 ++++++++++++++++++++++ graphics/src/mesh_controller.hpp | 77 +++++++++++++++++++++++ graphics/src/rse_graphics.cpp | 25 ++++++++ graphics/src/vulkan_buffers.cpp | 104 +++++++++++++++++++++++-------- graphics/src/vulkan_pipeline.cpp | 44 ++++++++++--- 8 files changed, 343 insertions(+), 37 deletions(-) create mode 100644 graphics/src/mesh_controller.cpp create mode 100644 graphics/src/mesh_controller.hpp diff --git a/graphics/CMakeLists.txt b/graphics/CMakeLists.txt index 08adcb8f..0757aaca 100644 --- a/graphics/CMakeLists.txt +++ b/graphics/CMakeLists.txt @@ -51,6 +51,7 @@ target_sources(rse_graphics PRIVATE src/vulkan_buffers.cpp src/vulkan_descriptors.cpp src/rse_graphics.cpp + src/mesh_controller.cpp ) target_link_libraries(rse_graphics PRIVATE diff --git a/graphics/rse_graphics.hpp b/graphics/rse_graphics.hpp index 621749bb..817aa140 100644 --- a/graphics/rse_graphics.hpp +++ b/graphics/rse_graphics.hpp @@ -13,7 +13,8 @@ class RseGraphics { RseGraphics(const RseGraphics&) = delete; /** - * @brief Initialize graphics module, runs main loop and deinits everything, when interrupted + * @brief Initialize graphics module, runs main loop and deinits everything, when interrupted. + * This has to been run AFTER all scene objects have been already created. * * @return uint8_t 0 on success. */ diff --git a/graphics/shaders/shader.vert b/graphics/shaders/shader.vert index af32e037..0bef39f9 100644 --- a/graphics/shaders/shader.vert +++ b/graphics/shaders/shader.vert @@ -6,12 +6,57 @@ layout(binding = 0) uniform UniformBufferObject { mat4 proj; } ubo; -layout(location = 0) in vec2 inPosition; +layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inColor; +layout(location = 2) in vec3 instancePosition; +layout(location = 3) in vec3 instanceRotation; +layout(location = 4) in float instanceScale; + layout(location = 0) out vec3 fragColor; -void main() { - gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); +void main() +{ + mat4 gRotMat; + mat3 mx, my, mz; + + // rotate around x + float s = sin(instanceRotation.x + 0); + float c = cos(instanceRotation.x + 0); + + mx[0] = vec3(1, 0.0, 0.0); + mx[1] = vec3(0, c, -s); + mx[2] = vec3(0.0, s, c); + + // rotate around y + s = sin(instanceRotation.y + 0); + c = cos(instanceRotation.y + 0); + + my[0] = vec3(c, 0.0, s); + my[1] = vec3(0.0, 1.0, 0.0); + my[2] = vec3(-s, 0.0, c); + + // rot around z + s = sin(instanceRotation.z + 0); + c = cos(instanceRotation.z + 0); + + mz[0] = vec3(c, -s, 0.0); + mz[1] = vec3(s, c, 0.0); + mz[2] = vec3(0.0, 0.0, 1); + + mat3 rotMat = mz * my * mx; + + s = sin(instanceRotation.y + 0); + c = cos(instanceRotation.y + 0); + gRotMat[0] = vec4(c, 0.0, s, 0.0); + gRotMat[1] = vec4(0.0, 1.0, 0.0, 0.0); + gRotMat[2] = vec4(-s, 0.0, c, 0.0); + gRotMat[3] = vec4(0.0, 0.0, 0.0, 1.0); + + vec4 locPos = vec4(inPosition.xyz * rotMat, 1.0); + vec4 pos = vec4((locPos.xyz * instanceScale) + instancePosition, 1.0); + + gl_Position = ubo.proj * ubo.view * ubo.model * pos; + fragColor = inColor; } \ No newline at end of file diff --git a/graphics/src/mesh_controller.cpp b/graphics/src/mesh_controller.cpp new file mode 100644 index 00000000..ecbc4141 --- /dev/null +++ b/graphics/src/mesh_controller.cpp @@ -0,0 +1,75 @@ +#include "mesh_controller.hpp" + +#include +#include +#include + +namespace rse::graphics::mesh +{ + +std::map g_meshes; +std::queue free_ids; + +std::map> instance_free_ids; + +uint16_t create_mesh(std::vector vertices, std::vector indices) +{ + static uint16_t last_id = 0U; + uint16_t assignable_id = 0U; + + if (free_ids.empty()) { + assignable_id = last_id++; + } else { + assignable_id = free_ids.front(); + free_ids.pop(); + } + + g_meshes.emplace(assignable_id, Mesh ( + assignable_id, + vertices, + indices + )); + + return assignable_id; +} + +void create_mesh_instance(uint16_t mesh_id, InstanceData instance_data) +{ + uint16_t instance_id = 0U; + auto& instances = g_meshes[mesh_id].instances; + auto& free_instance_ids = instance_free_ids[mesh_id]; + + if (free_instance_ids.empty()) { + instance_id = instances.size(); + } else { + instance_id = free_instance_ids.front(); + free_instance_ids.pop(); + } + + instances[instance_id] = std::make_unique( + instance_id, + 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 +std::vector get_instance_data_for_mesh(uint16_t mesh_id) { + std::vector data; + + for(const auto& [id, instance] : g_meshes[mesh_id].instances) { + data.push_back(instance.get()->instance_data); + } + + return data; +} + + +std::vector get_mesh_vertices(uint16_t mesh_id) { + return g_meshes[mesh_id].vertices; +} + +std::vector get_mesh_indices(uint16_t mesh_id) { + return g_meshes[mesh_id].indices; +} + +} // namespace rse::graphics::mesh diff --git a/graphics/src/mesh_controller.hpp b/graphics/src/mesh_controller.hpp new file mode 100644 index 00000000..e21bd0c4 --- /dev/null +++ b/graphics/src/mesh_controller.hpp @@ -0,0 +1,77 @@ +/** + * @file mesh_controller.hpp + * @author Piotr Krygier (piotr.krygier@meshsystems.com) + * @brief + * @version 0.1 + * @date 2023-03-29 + * + * @copyright Copyright (c) 2023 + * + */ + +#ifndef RSE_MESH_CONTROLLER_HPP +#define RSE_MESH_CONTROLLER_HPP + +#include +#include +#include +#include + +#include + +#include "vulkan_commons.hpp" + +namespace rse::graphics::mesh +{ + +/* Forward declarations */ +struct MeshInstance; + +struct InstanceData { + glm::vec3 pos; + glm::vec3 rot; + float scale; +}; + +struct MeshInstance +{ + uint32_t instance_id; + InstanceData instance_data; +}; + +struct Mesh +{ + uint32_t unique_id; + const std::vector vertices; + std::vector indices; + std::map> instances; +}; + + +/** + * @brief Create a new mesh for provided vertices and indices. + * + * @param vertices vector of vertices + * @param indices indices for mesh + * @return uint16_t Mesh identifier. Can be useful for getting vertices, indices and instances + */ +uint16_t create_mesh(std::vector vertices, std::vector indices); + +/** + * @brief Create a instance for the selected mesh. Instance can have its own location, rotation and scale + * + * @param mesh_id Mesh id + * @param instance_data Transformation info + */ +void create_mesh_instance(uint16_t mesh_id, InstanceData instance_data); + +std::vector get_mesh_vertices(uint16_t mesh_id); +std::vector get_mesh_indices(uint16_t mesh_id); +std::vector get_instance_data_for_mesh(uint16_t mesh_id); + + +} // namespace rse::graphics::mesh + + + +#endif \ No newline at end of file diff --git a/graphics/src/rse_graphics.cpp b/graphics/src/rse_graphics.cpp index 06a5fca9..1943bc5c 100644 --- a/graphics/src/rse_graphics.cpp +++ b/graphics/src/rse_graphics.cpp @@ -2,6 +2,8 @@ #include "window.hpp" #include "vulkan_base.hpp" +#include "mesh_controller.hpp" +#include "vulkan_commons.hpp" namespace rse::graphics { @@ -26,11 +28,34 @@ RseGraphics::RseGraphics() }; } + uint8_t RseGraphics::graphics_run(void) { window::windowInit(); + // FIXME: Temporary array of vertices, for testing purposes + const std::vector 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 indices = {0, 1, 2, 2, 3, 0}; + + uint16_t mesh_id = rse::graphics::mesh::create_mesh(vertices, indices); + rse::graphics::mesh::create_mesh_instance(mesh_id, rse::graphics::mesh::InstanceData( + glm::vec3(0.0f, 0.0f, 0.0f), + glm::vec3(0.0f, 0.0f, glm::radians(45.0f)), + 1.0f + )); + + rse::graphics::mesh::create_mesh_instance(mesh_id, rse::graphics::mesh::InstanceData( + glm::vec3(-1.0f, 0.0f, 0.0f), + glm::vec3(0.0f, 0.0f, 0.0f), + 1.0f + )); + if (0 != vulkanbase::initVulkan(vulkan_state)) return -1; diff --git a/graphics/src/vulkan_buffers.cpp b/graphics/src/vulkan_buffers.cpp index 309c19dc..a9988994 100644 --- a/graphics/src/vulkan_buffers.cpp +++ b/graphics/src/vulkan_buffers.cpp @@ -1,15 +1,15 @@ #include "vulkan_buffers.hpp" -#include "vulkan_errors.hpp" - -#include "locale_vulkan.hpp" -#include "utilities/logger.hpp" #include #define GLM_FORCE_RADIANS #include +#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 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 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 indices = {0, 1, 2, 2, 3, 0}; +// // FIXME: Temporary array of vertices, for testing purposes +// std::vector 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(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(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(indices.size()), 1, 0, 0, 0); + vkCmdDrawIndexed(commandBuffer, static_cast(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); } diff --git a/graphics/src/vulkan_pipeline.cpp b/graphics/src/vulkan_pipeline.cpp index 433f0c06..1b1b072f 100644 --- a/graphics/src/vulkan_pipeline.cpp +++ b/graphics/src/vulkan_pipeline.cpp @@ -4,6 +4,7 @@ #include "utilities/file_utils.hpp" #include "utilities/logger.hpp" #include "vulkan_errors.hpp" +#include "mesh_controller.hpp" #include #include @@ -496,19 +497,46 @@ void freeDynamicPipelineStateInfo(VkPipelineDynamicStateCreateInfo* dynamicState */ void fillVertexInputInfo(VkPipelineVertexInputStateCreateInfo* vertexInputInfo) { - auto bindingDescription = Vertex::getBindingDescription(); - auto attributeDescriptions = Vertex::getAttributeDescriptions(); + auto vertexBindingDescription = Vertex::getBindingDescription(); + auto vertexAttributeDescriptions = Vertex::getAttributeDescriptions(); + + //TODO: move somewhere else + auto bindingDescriptions = new VkVertexInputBindingDescription[2]; + bindingDescriptions[0] = vertexBindingDescription; + + bindingDescriptions[1].binding = 1; + bindingDescriptions[1].stride = sizeof(rse::graphics::mesh::InstanceData); //TODO: change + bindingDescriptions[1].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE; + + auto attributeDescriptions = new VkVertexInputAttributeDescription[5]; + std::copy(vertexAttributeDescriptions.begin(), vertexAttributeDescriptions.end(), attributeDescriptions); + + attributeDescriptions[2].binding = 1; + attributeDescriptions[2].location = 2; + attributeDescriptions[2].format = VK_FORMAT_R32G32B32_SFLOAT; + attributeDescriptions[2].offset = offsetof(rse::graphics::mesh::InstanceData, pos); + + attributeDescriptions[3].binding = 1; + attributeDescriptions[3].location = 3; + attributeDescriptions[3].format = VK_FORMAT_R32G32B32_SFLOAT; + attributeDescriptions[3].offset = offsetof(rse::graphics::mesh::InstanceData, rot); + + attributeDescriptions[4].binding = 1; + attributeDescriptions[4].location = 4; + attributeDescriptions[4].format = VK_FORMAT_R32_SFLOAT; + attributeDescriptions[4].offset = offsetof(rse::graphics::mesh::InstanceData, scale); + // ************************ vertexInputInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vertexInputInfo->pNext = nullptr; vertexInputInfo->flags = 0U; - vertexInputInfo->vertexBindingDescriptionCount = 1U; - vertexInputInfo->pVertexBindingDescriptions = new VkVertexInputBindingDescription(bindingDescription); - vertexInputInfo->vertexAttributeDescriptionCount = static_cast(attributeDescriptions.size()); + vertexInputInfo->vertexBindingDescriptionCount = 2U; + vertexInputInfo->pVertexBindingDescriptions = bindingDescriptions; + vertexInputInfo->vertexAttributeDescriptionCount = 5U; + vertexInputInfo->pVertexAttributeDescriptions = attributeDescriptions; - VkVertexInputAttributeDescription* tmp = new VkVertexInputAttributeDescription[attributeDescriptions.size()]; - std::copy(attributeDescriptions.begin(), attributeDescriptions.end(), tmp); - vertexInputInfo->pVertexAttributeDescriptions = tmp; + // VkVertexInputAttributeDescription* tmp = new VkVertexInputAttributeDescription[attributeDescriptions.size()]; + // std::copy(attributeDescriptions.begin(), attributeDescriptions.end(), tmp); } /**