Lugdunum  0.1.0
Mesh.cpp
Go to the documentation of this file.
2 
11 
12 namespace lug {
13 namespace Graphics {
14 namespace Vulkan {
15 namespace Builder {
16 namespace Mesh {
17 
18 Resource::SharedPtr<::lug::Graphics::Render::Mesh> build(const ::lug::Graphics::Builder::Mesh& builder) {
19  // Constructor of Mesh is private, we can't use std::make_unique
20  std::unique_ptr<Resource> resource{new Vulkan::Render::Mesh(builder._name)};
21  Vulkan::Render::Mesh* mesh = static_cast<Vulkan::Render::Mesh*>(resource.get());
22 
23  Vulkan::Renderer& renderer = static_cast<Vulkan::Renderer&>(builder._renderer);
24 
25  const size_t primitiveSetsNb = builder._primitiveSets.size();
26  mesh->_primitiveSets.resize(primitiveSetsNb);
27 
28  uint32_t i = 0;
29  for (auto& builderPrimitiveSet : builder._primitiveSets) {
32 
33  targetPrimitiveSet.mode = builderPrimitiveSet.getMode();
34  targetPrimitiveSet.material = builderPrimitiveSet.getMaterial();
35 
36  auto& builderAttributes = builderPrimitiveSet.getAttributes();
37 
38  const uint32_t attributesNb = static_cast<uint32_t>(builderAttributes.size());
39  targetPrimitiveSet.attributes.resize(attributesNb);
40  primitiveSetData->buffers.resize(attributesNb);
41 
42  for (uint32_t j = 0; j < attributesNb; ++j) {
43  targetPrimitiveSet.attributes[j] = builderAttributes[j];
44 
45  // Pipeline::Handle::PrimitivePart support only 3 texture coordinates
47  targetPrimitiveSet.texCoords.size() == 3) {
48  LUG_LOG.warn("Vulkan::Mesh::build: More than 3 texture coordinates, others will be ignored");
49  continue;
50  }
51 
52  switch (targetPrimitiveSet.attributes[j].type) {
54  targetPrimitiveSet.indices = &targetPrimitiveSet.attributes[j];
55  break;
57  targetPrimitiveSet.position = &targetPrimitiveSet.attributes[j];
58  break;
60  targetPrimitiveSet.normal = &targetPrimitiveSet.attributes[j];
61  break;
63  targetPrimitiveSet.texCoords.push_back(&targetPrimitiveSet.attributes[j]);
64  break;
66  targetPrimitiveSet.colors.push_back(&targetPrimitiveSet.attributes[j]);
67  break;
69  targetPrimitiveSet.tangent = &targetPrimitiveSet.attributes[j];
70  break;
71  }
72 
73  {
74  API::Buffer buffer;
75  API::Builder::Buffer bufferBuilder(renderer.getDevice());
76 
77  const API::Queue* graphicsQueue = renderer.getDevice().getQueue("queue_graphics");
78  if (!graphicsQueue) {
79  LUG_LOG.error("Vulkan::Mesh::build: Can't find graphics queue");
80  return nullptr;
81  }
82 
83  bufferBuilder.setQueueFamilyIndices({graphicsQueue->getQueueFamily()->getIdx()});
84  bufferBuilder.setSize(targetPrimitiveSet.attributes[j].buffer.size);
85 
87  bufferBuilder.setUsage(VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
88  } else {
89  bufferBuilder.setUsage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
90  }
91 
92  VkResult result{VK_SUCCESS};
93  if (!bufferBuilder.build(primitiveSetData->buffers[j], &result)) {
94  LUG_LOG.error("Vulkan::Mesh::build: Can't create buffer: {}", result);
95  return nullptr;
96  }
97 
98  targetPrimitiveSet.attributes[j]._data = static_cast<void*>(&primitiveSetData->buffers[j]);
99  }
100  }
101 
102  primitiveSetData->pipelineIdPrimitivePart.positionVertexData = targetPrimitiveSet.position != nullptr;
103  primitiveSetData->pipelineIdPrimitivePart.normalVertexData = targetPrimitiveSet.normal != nullptr;
104  primitiveSetData->pipelineIdPrimitivePart.tangentVertexData = targetPrimitiveSet.tangent != nullptr;
105  primitiveSetData->pipelineIdPrimitivePart.countTexCoord = targetPrimitiveSet.texCoords.size();
106  primitiveSetData->pipelineIdPrimitivePart.countColor = targetPrimitiveSet.colors.size();
107  primitiveSetData->pipelineIdPrimitivePart.primitiveMode = static_cast<uint32_t>(targetPrimitiveSet.mode);
108 
109  targetPrimitiveSet._data = static_cast<void*>(primitiveSetData);
110  mesh->_primitiveSets[i] = std::move(targetPrimitiveSet);
111 
112  ++i;
113  }
114 
115  // Bind attributes buffers to mesh device memory
116  {
117  API::Builder::DeviceMemory deviceMemoryBuilder(renderer.getDevice());
118  // TODO(nokitoo): use memory flag VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
119  deviceMemoryBuilder.setMemoryFlags(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
120 
121  for (auto& primitiveSet : mesh->_primitiveSets) {
122  Render::Mesh::PrimitiveSetData* primitiveSetData = static_cast<Render::Mesh::PrimitiveSetData*>(primitiveSet._data);
123 
124  // Add buffers to memory
125  for (auto& buffer : primitiveSetData->buffers) {
126  if (!deviceMemoryBuilder.addBuffer(buffer)) {
127  LUG_LOG.error("Vulkan::Mesh::build: Can't add buffer to device memory");
128  return nullptr;
129  }
130  }
131  }
132 
133  VkResult result{VK_SUCCESS};
134  if (!deviceMemoryBuilder.build(mesh->_deviceMemory, &result)) {
135  LUG_LOG.error("Vulkan::Mesh::build: Can't create device memory: {}", result);
136  return nullptr;
137  }
138 
139  // Update buffers data
140  for (auto& primitiveSet : mesh->_primitiveSets) {
141  Render::Mesh::PrimitiveSetData* primitiveSetData = static_cast<Render::Mesh::PrimitiveSetData*>(primitiveSet._data);
142 
143  uint32_t attributesNb = static_cast<uint32_t>(primitiveSet.attributes.size());
144 
145  for (i = 0; i < attributesNb; ++i) {
146  primitiveSetData->buffers[i].updateData(
147  primitiveSet.attributes[i].buffer.data,
148  primitiveSet.attributes[i].buffer.size
149  );
150  }
151  }
152  }
153 
154  return builder._renderer.getResourceManager()->add<::lug::Graphics::Render::Mesh>(std::move(resource));
155 }
156 
157 } // Mesh
158 } // Builder
159 } // Vulkan
160 } // Graphics
161 } // lug
uint32_t countColor
The number of colors (maximum 3).
Definition: Pipeline.hpp:44
std::vector< Attribute * > texCoords
Definition: Mesh.hpp:73
uint32_t positionVertexData
0 if no attribute position.
Definition: Pipeline.hpp:40
Tangent (VEC4<FLOAT> w component is a sign value (-1 or +1) indicating handedness of the tangent basi...
Describes part of a Mesh.
Definition: Mesh.hpp:33
A Mesh, which itsef is a Resource. A mesh is composed of a vector of PrimitiveSet.
Definition: Mesh.hpp:26
const API::Queue * getQueue(const std::string &queueName) const
Definition: Device.cpp:70
Resource::SharedPtr< Material > material
Definition: Mesh.hpp:77
Dummy class for a shared pointer.
Definition: Resource.hpp:66
std::vector< PrimitiveSet > _primitiveSets
Definition: Mesh.hpp:97
Pipeline::Id::PrimitivePart pipelineIdPrimitivePart
Definition: Mesh.hpp:25
Resource::SharedPtr< lug::Graphics::Render::Mesh > build(const ::lug::Graphics::Builder::Mesh &builder)
Definition: Mesh.cpp:18
uint32_t normalVertexData
0 if no attribute normal.
Definition: Pipeline.hpp:41
std::vector< Attribute * > colors
Definition: Mesh.hpp:74
std::vector< Attribute > attributes
Definition: Mesh.hpp:68
void setMemoryFlags(VkMemoryPropertyFlags flags)
Definition: DeviceMemory.inl:1
#define LUG_LOG
Definition: Logger.hpp:73
API::DeviceMemory _deviceMemory
Definition: Mesh.hpp:44
uint32_t tangentVertexData
0 if no attribute tangeant.
Definition: Pipeline.hpp:42
uint32_t countTexCoord
The number of texcoord (maximum 3).
Definition: Pipeline.hpp:43