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
@@ -51,6 +51,7 @@ target_sources(rse_graphics PRIVATE
|
|||||||
src/vulkan_buffers.cpp
|
src/vulkan_buffers.cpp
|
||||||
src/vulkan_descriptors.cpp
|
src/vulkan_descriptors.cpp
|
||||||
src/rse_graphics.cpp
|
src/rse_graphics.cpp
|
||||||
|
src/mesh_controller.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(rse_graphics PRIVATE
|
target_link_libraries(rse_graphics PRIVATE
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ class RseGraphics {
|
|||||||
RseGraphics(const RseGraphics&) = delete;
|
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.
|
* @return uint8_t 0 on success.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,12 +6,57 @@ layout(binding = 0) uniform UniformBufferObject {
|
|||||||
mat4 proj;
|
mat4 proj;
|
||||||
} ubo;
|
} ubo;
|
||||||
|
|
||||||
layout(location = 0) in vec2 inPosition;
|
layout(location = 0) in vec3 inPosition;
|
||||||
layout(location = 1) in vec3 inColor;
|
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;
|
layout(location = 0) out vec3 fragColor;
|
||||||
|
|
||||||
void main() {
|
void main()
|
||||||
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0);
|
{
|
||||||
|
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;
|
fragColor = inColor;
|
||||||
}
|
}
|
||||||
@@ -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 "window.hpp"
|
||||||
#include "vulkan_base.hpp"
|
#include "vulkan_base.hpp"
|
||||||
|
|
||||||
|
#include "mesh_controller.hpp"
|
||||||
|
#include "vulkan_commons.hpp"
|
||||||
namespace rse::graphics
|
namespace rse::graphics
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -26,11 +28,34 @@ RseGraphics::RseGraphics()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t RseGraphics::graphics_run(void)
|
uint8_t RseGraphics::graphics_run(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
window::windowInit();
|
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))
|
if (0 != vulkanbase::initVulkan(vulkan_state))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
#include "vulkan_buffers.hpp"
|
#include "vulkan_buffers.hpp"
|
||||||
|
|
||||||
#include "vulkan_errors.hpp"
|
|
||||||
|
|
||||||
#include "locale_vulkan.hpp"
|
|
||||||
#include "utilities/logger.hpp"
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#define GLM_FORCE_RADIANS
|
#define GLM_FORCE_RADIANS
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#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
|
namespace rse::graphics::vulkanbase
|
||||||
{
|
{
|
||||||
@@ -17,21 +17,20 @@ namespace rse::graphics::vulkanbase
|
|||||||
|
|
||||||
using namespace locale::vulkan;
|
using namespace locale::vulkan;
|
||||||
|
|
||||||
// FIXME: Temporary array of vertices, for testing purposes
|
// // 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}},
|
// 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, 1.0f, 1.0f}},
|
||||||
{{0.5f, 0.5f, 0.0f}, {0.0f, 0.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}}};
|
// {{-0.5f, 0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}}};
|
||||||
|
|
||||||
// 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};
|
||||||
|
|
||||||
/* GPU visible buffer */
|
/* GPU visible buffer */
|
||||||
Buffer gVertexBuffer = {};
|
Buffer gVertexBuffer = {};
|
||||||
/* CPU visible buffer. TODO: Do we need this global? */
|
|
||||||
Buffer gVertexStagingBuffer = {};
|
|
||||||
Buffer gIndexBuffer = {};
|
Buffer gIndexBuffer = {};
|
||||||
Buffer gIndexStagingBuffer = {};
|
Buffer gInstancesBuffer = {};
|
||||||
|
/* CPU visible buffer. TODO: Do we need this global? */
|
||||||
|
|
||||||
VkCommandPool gCommandPool = VK_NULL_HANDLE;
|
VkCommandPool gCommandPool = VK_NULL_HANDLE;
|
||||||
|
|
||||||
@@ -184,12 +183,15 @@ uint8_t createVertexBuffer(VulkanState& vulkan_state)
|
|||||||
{
|
{
|
||||||
void* mappedData;
|
void* mappedData;
|
||||||
VkDeviceSize bufferSize;
|
VkDeviceSize bufferSize;
|
||||||
|
Buffer staging_buffer;
|
||||||
|
|
||||||
|
auto vertices = rse::graphics::mesh::get_mesh_vertices(0);
|
||||||
|
|
||||||
bufferSize = sizeof(vertices[0]) * vertices.size();
|
bufferSize = sizeof(vertices[0]) * vertices.size();
|
||||||
|
|
||||||
/* Creating staging buffer*/
|
/* Creating staging buffer*/
|
||||||
if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
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];
|
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||||
}
|
}
|
||||||
@@ -203,14 +205,16 @@ uint8_t createVertexBuffer(VulkanState& vulkan_state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fill staging buffer */
|
/* 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];
|
LOGF << vulkanErrorMesssages[VULKAN_VERTEX_BUFFER_MAPPING_FAILED];
|
||||||
return VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED;
|
return VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED;
|
||||||
}
|
}
|
||||||
memcpy(mappedData, vertices.data(), sizeof(Vertex) * vertices.size());
|
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;
|
return VULKAN_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
@@ -225,12 +229,15 @@ uint8_t createIndexBuffer(VulkanState& vulkan_state)
|
|||||||
{
|
{
|
||||||
void* mappedData;
|
void* mappedData;
|
||||||
VkDeviceSize bufferSize;
|
VkDeviceSize bufferSize;
|
||||||
|
Buffer staging_buffer;
|
||||||
|
|
||||||
|
auto indices = rse::graphics::mesh::get_mesh_indices(0);
|
||||||
|
|
||||||
bufferSize = sizeof(indices[0]) * indices.size();
|
bufferSize = sizeof(indices[0]) * indices.size();
|
||||||
|
|
||||||
/* Creating staging buffer*/
|
/* Creating staging buffer*/
|
||||||
if (VK_SUCCESS != createBuffer(vulkan_state, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
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];
|
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||||
}
|
}
|
||||||
@@ -244,18 +251,59 @@ uint8_t createIndexBuffer(VulkanState& vulkan_state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fill staging buffer */
|
/* 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];
|
LOGF << vulkanErrorMesssages[VULKAN_VERTEX_BUFFER_MAPPING_FAILED];
|
||||||
return VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED;
|
return VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED;
|
||||||
}
|
}
|
||||||
memcpy(mappedData, indices.data(), static_cast<size_t>(bufferSize));
|
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;
|
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
|
* @brief Create a Uniform Buffers
|
||||||
*
|
*
|
||||||
@@ -309,6 +357,7 @@ uint8_t allocateCommandBuffers(VulkanState& vulkan_state)
|
|||||||
void updateUniformBuffer(VulkanState& vulkan_state)
|
void updateUniformBuffer(VulkanState& vulkan_state)
|
||||||
{
|
{
|
||||||
UniformBufferObject ubo{};
|
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.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 =
|
||||||
@@ -334,8 +383,12 @@ uint8_t recordCommandBuffer(VulkanState& vulkan_state, uint32_t imageIndex)
|
|||||||
VkViewport viewport{};
|
VkViewport viewport{};
|
||||||
VkRect2D scissor{};
|
VkRect2D scissor{};
|
||||||
VkBuffer vertexBuffers[] = {gVertexBuffer.buffer};
|
VkBuffer vertexBuffers[] = {gVertexBuffer.buffer};
|
||||||
|
VkBuffer instanceBuffers[] = {gInstancesBuffer.buffer};
|
||||||
VkDeviceSize offsets[] = {0};
|
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.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
beginInfo.flags = 0;
|
beginInfo.flags = 0;
|
||||||
beginInfo.pInheritanceInfo = nullptr;
|
beginInfo.pInheritanceInfo = nullptr;
|
||||||
@@ -369,11 +422,12 @@ uint8_t recordCommandBuffer(VulkanState& vulkan_state, uint32_t imageIndex)
|
|||||||
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||||
|
|
||||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
|
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
|
||||||
|
vkCmdBindVertexBuffers(commandBuffer, 1, 1, instanceBuffers, offsets);
|
||||||
vkCmdBindIndexBuffer(commandBuffer, gIndexBuffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
vkCmdBindIndexBuffer(commandBuffer, gIndexBuffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
||||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_state.pipelineLayout, 0, 1,
|
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_state.pipelineLayout, 0, 1,
|
||||||
&vulkan_state.descriptorSets[vulkan_state.currentFrame], 0, nullptr);
|
&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);
|
vkCmdEndRenderPass(commandBuffer);
|
||||||
|
|
||||||
@@ -392,6 +446,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(createUniformBuffers(vulkan_state));
|
STATUS_CHECK(createUniformBuffers(vulkan_state));
|
||||||
STATUS_CHECK(allocateCommandBuffers(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, gVertexBuffer.buffer, gVertexBuffer.allocation);
|
||||||
vmaDestroyBuffer(vulkan_state.allocator, gVertexStagingBuffer.buffer, gVertexStagingBuffer.allocation);
|
|
||||||
vmaDestroyBuffer(vulkan_state.allocator, gIndexBuffer.buffer, gIndexBuffer.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);
|
vkDestroyCommandPool(vulkan_state.device, gCommandPool, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "utilities/file_utils.hpp"
|
#include "utilities/file_utils.hpp"
|
||||||
#include "utilities/logger.hpp"
|
#include "utilities/logger.hpp"
|
||||||
#include "vulkan_errors.hpp"
|
#include "vulkan_errors.hpp"
|
||||||
|
#include "mesh_controller.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -496,19 +497,46 @@ void freeDynamicPipelineStateInfo(VkPipelineDynamicStateCreateInfo* dynamicState
|
|||||||
*/
|
*/
|
||||||
void fillVertexInputInfo(VkPipelineVertexInputStateCreateInfo* vertexInputInfo)
|
void fillVertexInputInfo(VkPipelineVertexInputStateCreateInfo* vertexInputInfo)
|
||||||
{
|
{
|
||||||
auto bindingDescription = Vertex::getBindingDescription();
|
auto vertexBindingDescription = Vertex::getBindingDescription();
|
||||||
auto attributeDescriptions = Vertex::getAttributeDescriptions();
|
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->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
vertexInputInfo->pNext = nullptr;
|
vertexInputInfo->pNext = nullptr;
|
||||||
vertexInputInfo->flags = 0U;
|
vertexInputInfo->flags = 0U;
|
||||||
vertexInputInfo->vertexBindingDescriptionCount = 1U;
|
vertexInputInfo->vertexBindingDescriptionCount = 2U;
|
||||||
vertexInputInfo->pVertexBindingDescriptions = new VkVertexInputBindingDescription(bindingDescription);
|
vertexInputInfo->pVertexBindingDescriptions = bindingDescriptions;
|
||||||
vertexInputInfo->vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
|
vertexInputInfo->vertexAttributeDescriptionCount = 5U;
|
||||||
|
vertexInputInfo->pVertexAttributeDescriptions = attributeDescriptions;
|
||||||
|
|
||||||
VkVertexInputAttributeDescription* tmp = new VkVertexInputAttributeDescription[attributeDescriptions.size()];
|
// VkVertexInputAttributeDescription* tmp = new VkVertexInputAttributeDescription[attributeDescriptions.size()];
|
||||||
std::copy(attributeDescriptions.begin(), attributeDescriptions.end(), tmp);
|
// std::copy(attributeDescriptions.begin(), attributeDescriptions.end(), tmp);
|
||||||
vertexInputInfo->pVertexAttributeDescriptions = tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in new issue
Block a user