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); } /**