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
@@ -0,0 +1,75 @@
|
||||
#include "mesh_controller.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <memory>
|
||||
|
||||
namespace rse::graphics::mesh
|
||||
{
|
||||
|
||||
std::map<uint16_t, struct Mesh> g_meshes;
|
||||
std::queue<uint16_t> 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)
|
||||
{
|
||||
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<struct MeshInstance>(
|
||||
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<InstanceData> get_instance_data_for_mesh(uint16_t mesh_id) {
|
||||
std::vector<InstanceData> data;
|
||||
|
||||
for(const auto& [id, instance] : g_meshes[mesh_id].instances) {
|
||||
data.push_back(instance.get()->instance_data);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
std::vector<rse::graphics::vulkanbase::Vertex> get_mesh_vertices(uint16_t mesh_id) {
|
||||
return g_meshes[mesh_id].vertices;
|
||||
}
|
||||
|
||||
std::vector<uint16_t> get_mesh_indices(uint16_t mesh_id) {
|
||||
return g_meshes[mesh_id].indices;
|
||||
}
|
||||
|
||||
} // namespace rse::graphics::mesh
|
||||
@@ -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 <cstdint>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#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<rse::graphics::vulkanbase::Vertex> vertices;
|
||||
std::vector<uint16_t> indices;
|
||||
std::map<uint16_t, std::unique_ptr<MeshInstance>> 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<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
|
||||
*
|
||||
* @param mesh_id Mesh id
|
||||
* @param instance_data Transformation info
|
||||
*/
|
||||
void create_mesh_instance(uint16_t mesh_id, InstanceData instance_data);
|
||||
|
||||
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<InstanceData> get_instance_data_for_mesh(uint16_t mesh_id);
|
||||
|
||||
|
||||
} // namespace rse::graphics::mesh
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -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<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, 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};
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "utilities/file_utils.hpp"
|
||||
#include "utilities/logger.hpp"
|
||||
#include "vulkan_errors.hpp"
|
||||
#include "mesh_controller.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
@@ -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<uint32_t>(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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user