Lugdunum  0.1.0
Pipeline.cpp
Go to the documentation of this file.
2 
3 #include <memory>
4 
12 #include <lug/System/Exception.hpp>
13 
14 namespace lug {
15 namespace Graphics {
16 namespace Vulkan {
17 namespace Render {
18 
19 Pipeline::Pipeline(Renderer& renderer, Id id) : Resource(Resource::Type::Pipeline, "Pipeline"), _renderer(renderer), _id(id) {}
20 
25 
26  API::Builder::GraphicsPipeline graphicsPipelineBuilder(_renderer.getDevice());
27 
28  // Set shaders state
29  {
30  // Vertex shader
31  {
32  std::vector<uint32_t> shaderCode{};
33 
34  try {
39  _id
40  );
41  } catch(const System::Exception& e) {
42  LUG_LOG.error("{}", e.what());
43  return false;
44  }
45 
46  if (!graphicsPipelineBuilder.setShaderFromData(VK_SHADER_STAGE_VERTEX_BIT, "main", shaderCode)) {
47  LUG_LOG.error("Vulkan::Render::Pipeline: Can't create vertex shader.");
48  return false;
49  }
50  }
51 
52  // Frament shader
53  {
54  std::vector<uint32_t> shaderCode{};
55 
56  try {
61  _id
62  );
63  } catch(const System::Exception& e) {
64  LUG_LOG.error("{}", e.what());
65  return false;
66  }
67 
68  if (!graphicsPipelineBuilder.setShaderFromData(VK_SHADER_STAGE_FRAGMENT_BIT, "main", shaderCode)) {
69  LUG_LOG.error("Vulkan::Render::Pipeline: Can't create fragment shader.");
70  return false;
71  }
72  }
73  }
74 
75  // Set vertex input state
76  {
77  // We always have position
78  auto positionBinding = graphicsPipelineBuilder.addInputBinding(sizeof(Math::Vec3f), VK_VERTEX_INPUT_RATE_VERTEX);
79  positionBinding.addAttributes(VK_FORMAT_R32G32B32_SFLOAT, 0);
80 
81  // We always have normal
82  auto normalBinding = graphicsPipelineBuilder.addInputBinding(sizeof(Math::Vec3f), VK_VERTEX_INPUT_RATE_VERTEX);
83  normalBinding.addAttributes(VK_FORMAT_R32G32B32_SFLOAT, 0);
84 
85  // Set vertex data attributes for dynamic attributes
86  if (primitivePart.tangentVertexData) {
87  auto tangentBinding = graphicsPipelineBuilder.addInputBinding(sizeof(Math::Vec4f), VK_VERTEX_INPUT_RATE_VERTEX);
88  tangentBinding.addAttributes(VK_FORMAT_R32G32B32A32_SFLOAT, 0);
89  }
90 
91  for (uint8_t i = 0; i < primitivePart.countTexCoord; ++i) {
92  auto uvBinding = graphicsPipelineBuilder.addInputBinding(sizeof(Math::Vec2f), VK_VERTEX_INPUT_RATE_VERTEX);
93  uvBinding.addAttributes(VK_FORMAT_R32G32_SFLOAT, 0);
94  }
95 
96  for (uint8_t i = 0; i < primitivePart.countColor; ++i) {
97  auto uvBinding = graphicsPipelineBuilder.addInputBinding(sizeof(Math::Vec4f), VK_VERTEX_INPUT_RATE_VERTEX);
98  uvBinding.addAttributes(VK_FORMAT_R32G32B32A32_SFLOAT, 0);
99  }
100  }
101 
102  // Set input assembly state
103  switch(static_cast<Render::Mesh::PrimitiveSet::Mode>(primitivePart.primitiveMode)) {
105  graphicsPipelineBuilder.setInputAssemblyInfo(VK_PRIMITIVE_TOPOLOGY_POINT_LIST, false);
106  break;
108  graphicsPipelineBuilder.setInputAssemblyInfo(VK_PRIMITIVE_TOPOLOGY_LINE_LIST, false);
109  break;
111  graphicsPipelineBuilder.setInputAssemblyInfo(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, false);
112  break;
114  graphicsPipelineBuilder.setInputAssemblyInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false);
115  break;
117  graphicsPipelineBuilder.setInputAssemblyInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, false);
118  break;
120  graphicsPipelineBuilder.setInputAssemblyInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, false);
121  break;
122  }
123 
124  // Set viewport state
125  const VkViewport viewport{
126  /* viewport.x */ 0.0f,
127  /* viewport.y */ 0.0f,
128  /* viewport.width */ 0.0f,
129  /* viewport.height */ 0.0f,
130  /* viewport.minDepth */ 0.0f,
131  /* viewport.maxDepth */ 1.0f,
132  };
133 
134  const VkRect2D scissor{
135  /* scissor.offset */ {0, 0},
136  /* scissor.extent */ {0, 0}
137  };
138 
139  auto viewportState = graphicsPipelineBuilder.getViewportState();
140  viewportState.addViewport(viewport);
141  viewportState.addScissor(scissor);
142 
143  // Set depth stencil state
144  auto depthStencilState = graphicsPipelineBuilder.getDepthStencilState();
145  depthStencilState.enableDepthTest(VK_COMPARE_OP_LESS_OR_EQUAL);
146  depthStencilState.enableDepthWrite();
147 
148  // Set color blend state
149  const VkPipelineColorBlendAttachmentState colorBlendAttachment{
150  /* colorBlendAttachment.blendEnable */ VK_TRUE,
151  /* colorBlendAttachment.srcColorBlendFactor */ VK_BLEND_FACTOR_ONE,
152  /* colorBlendAttachment.dstColorBlendFactor */ VK_BLEND_FACTOR_CONSTANT_COLOR,
153  /* colorBlendAttachment.colorBlendOp */ VK_BLEND_OP_ADD,
154  /* colorBlendAttachment.srcAlphaBlendFactor */ VK_BLEND_FACTOR_ONE,
155  /* colorBlendAttachment.dstAlphaBlendFactor */ VK_BLEND_FACTOR_CONSTANT_COLOR,
156  /* colorBlendAttachment.alphaBlendOp */ VK_BLEND_OP_ADD,
157  /* colorBlendAttachment.colorWriteMask */ VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
158  };
159 
160  auto colorBlendState = graphicsPipelineBuilder.getColorBlendState();
161  colorBlendState.addAttachment(colorBlendAttachment);
162 
163  // Set dynamic states
164  graphicsPipelineBuilder.setDynamicStates({
165  VK_DYNAMIC_STATE_VIEWPORT,
166  VK_DYNAMIC_STATE_SCISSOR,
167  VK_DYNAMIC_STATE_BLEND_CONSTANTS
168  });
169 
170  // Set pipeline layout
171  {
172  VkResult result{VK_SUCCESS};
173  std::vector<API::DescriptorSetLayout> descriptorSetLayouts(3);
174  API::Builder::DescriptorSetLayout descriptorSetLayoutBuilder(_renderer.getDevice());
175 
176  // Bindings set 0 : Camera uniform buffer (V/F)
177  {
178  // Camera uniform buffer
179  const VkDescriptorSetLayoutBinding binding{
180  /* binding.binding */ 0,
181  /* binding.descriptorType */ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
182  /* binding.descriptorCount */ 1,
183  /* binding.stageFlags */ VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
184  /* binding.pImmutableSamplers */ nullptr
185  };
186 
187  descriptorSetLayoutBuilder.setBindings({binding});
188  if (!descriptorSetLayoutBuilder.build(descriptorSetLayouts[0], &result)) {
189  LUG_LOG.error("Vulkan::Render::Pipeline: Can't create pipeline descriptor sets layout 0: {}", result);
190  return false;
191  }
192  }
193 
194  // Bindings set 1 : Light uniform buffer (F)
195  {
196  const std::vector<VkDescriptorSetLayoutBinding> bindings{
197  // Light array uniform buffer
198  {
199  /* binding.binding */ 0,
200  /* binding.descriptorType */ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
201  /* binding.descriptorCount */ 1,
202  /* binding.stageFlags */ VK_SHADER_STAGE_FRAGMENT_BIT,
203  /* binding.pImmutableSamplers */ nullptr
204  }
205  };
206 
207  descriptorSetLayoutBuilder.setBindings(bindings);
208  if (!descriptorSetLayoutBuilder.build(descriptorSetLayouts[1], &result)) {
209  LUG_LOG.error("Vulkan::Render::Pipeline: Can't create pipeline descriptor sets layout 1: {}", result);
210  return false;
211  }
212  }
213 
214  // Bindings set 2 : Material uniform buffer (F)
215  {
216  const VkDescriptorSetLayoutBinding materialBinding{
217  /* materialBinding.binding */ 0,
218  /* materialBinding.descriptorType */ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
219  /* materialBinding.descriptorCount */ 1,
220  /* materialBinding.stageFlags */ VK_SHADER_STAGE_FRAGMENT_BIT,
221  /* materialBinding.pImmutableSamplers */ nullptr
222  };
223 
224  descriptorSetLayoutBuilder.setBindings({materialBinding});
225  if (!descriptorSetLayoutBuilder.build(descriptorSetLayouts[2], &result)) {
226  LUG_LOG.error("Vulkan::Render::Pipeline: Can't create pipeline descriptor sets layout 2: {}", result);
227  return false;
228  }
229  }
230 
231  // Binding set 3 : Material Samplers (F)
232  {
233  std::vector<VkDescriptorSetLayoutBinding> bindings = {};
234 
235  // Set binding for samples of the material
236  uint8_t binding = 0;
237 
238  if (materialPart.baseColorInfo != 0b11) {
239  const VkDescriptorSetLayoutBinding textureBinding = {
240  /* textureBinding.binding */ binding++,
241  /* textureBinding.descriptorType */ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
242  /* textureBinding.descriptorCount */ 1,
243  /* textureBinding.stageFlags */ VK_SHADER_STAGE_FRAGMENT_BIT,
244  /* textureBinding.pImmutableSamplers */ nullptr
245  };
246 
247  bindings.push_back(std::move(textureBinding));
248  }
249 
250  if (materialPart.metallicRoughnessInfo != 0b11) {
251  const VkDescriptorSetLayoutBinding textureBinding = {
252  /* textureBinding.binding */ binding++,
253  /* textureBinding.descriptorType */ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
254  /* textureBinding.descriptorCount */ 1,
255  /* textureBinding.stageFlags */ VK_SHADER_STAGE_FRAGMENT_BIT,
256  /* textureBinding.pImmutableSamplers */ nullptr
257  };
258 
259  bindings.push_back(std::move(textureBinding));
260  }
261 
262  if (materialPart.normalInfo != 0b11) {
263  const VkDescriptorSetLayoutBinding textureBinding = {
264  /* textureBinding.binding */ binding++,
265  /* textureBinding.descriptorType */ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
266  /* textureBinding.descriptorCount */ 1,
267  /* textureBinding.stageFlags */ VK_SHADER_STAGE_FRAGMENT_BIT,
268  /* textureBinding.pImmutableSamplers */ nullptr
269  };
270 
271  bindings.push_back(std::move(textureBinding));
272  }
273 
274  if (materialPart.occlusionInfo != 0b11) {
275  const VkDescriptorSetLayoutBinding textureBinding = {
276  /* textureBinding.binding */ binding++,
277  /* textureBinding.descriptorType */ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
278  /* textureBinding.descriptorCount */ 1,
279  /* textureBinding.stageFlags */ VK_SHADER_STAGE_FRAGMENT_BIT,
280  /* textureBinding.pImmutableSamplers */ nullptr
281  };
282 
283  bindings.push_back(std::move(textureBinding));
284  }
285 
286  if (materialPart.emissiveInfo != 0b11) {
287  const VkDescriptorSetLayoutBinding textureBinding = {
288  /* textureBinding.binding */ binding++,
289  /* textureBinding.descriptorType */ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
290  /* textureBinding.descriptorCount */ 1,
291  /* textureBinding.stageFlags */ VK_SHADER_STAGE_FRAGMENT_BIT,
292  /* textureBinding.pImmutableSamplers */ nullptr
293  };
294 
295  bindings.push_back(std::move(textureBinding));
296  }
297 
298  if (extraPart.irradianceMapInfo) {
299  const VkDescriptorSetLayoutBinding textureBinding = {
300  /* textureBinding.binding */ binding++,
301  /* textureBinding.descriptorType */ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
302  /* textureBinding.descriptorCount */ 1,
303  /* textureBinding.stageFlags */ VK_SHADER_STAGE_FRAGMENT_BIT,
304  /* textureBinding.pImmutableSamplers */ nullptr
305  };
306 
307  bindings.push_back(std::move(textureBinding));
308  }
309 
310  if (extraPart.prefilteredMapInfo) {
311  // BRDF LUT
312  {
313  const VkDescriptorSetLayoutBinding textureBinding = {
314  /* textureBinding.binding */ binding++,
315  /* textureBinding.descriptorType */ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
316  /* textureBinding.descriptorCount */ 1,
317  /* textureBinding.stageFlags */ VK_SHADER_STAGE_FRAGMENT_BIT,
318  /* textureBinding.pImmutableSamplers */ nullptr
319  };
320 
321  bindings.push_back(std::move(textureBinding));
322  }
323 
324  // Prefiltered Map
325  {
326  const VkDescriptorSetLayoutBinding textureBinding = {
327  /* textureBinding.binding */ binding++,
328  /* textureBinding.descriptorType */ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
329  /* textureBinding.descriptorCount */ 1,
330  /* textureBinding.stageFlags */ VK_SHADER_STAGE_FRAGMENT_BIT,
331  /* textureBinding.pImmutableSamplers */ nullptr
332  };
333 
334  bindings.push_back(std::move(textureBinding));
335  }
336  }
337 
338  if (bindings.size() > 0) {
339  descriptorSetLayouts.resize(4);
340 
341  descriptorSetLayoutBuilder.setBindings(bindings);
342  if (!descriptorSetLayoutBuilder.build(descriptorSetLayouts[3], &result)) {
343  LUG_LOG.error("Vulkan::Render::Pipeline: Can't create pipeline descriptor sets layout 3: {}", result);
344  return false;
345  }
346  }
347  }
348 
349  // Model transformation
350  const VkPushConstantRange pushConstant{
351  /* pushConstant.stageFlags */ VK_SHADER_STAGE_VERTEX_BIT,
352  /* pushConstant.offset */ 0,
353  /* pushConstant.size */ sizeof(Math::Mat4x4f)
354  };
355 
356  API::Builder::PipelineLayout pipelineLayoutBuilder(_renderer.getDevice());
357 
358  pipelineLayoutBuilder.setPushConstants({pushConstant});
359  pipelineLayoutBuilder.setDescriptorSetLayouts(std::move(descriptorSetLayouts));
360 
361  API::PipelineLayout pipelineLayout;
362  if (!pipelineLayoutBuilder.build(pipelineLayout, &result)) {
363  LUG_LOG.error("Vulkan::Render::Pipeline: Can't create pipeline layout: {}", result);
364  return false;
365  }
366 
367  graphicsPipelineBuilder.setPipelineLayout(std::move(pipelineLayout));
368  }
369 
370  // Set render pass
371  {
372  API::Builder::RenderPass renderPassBuilder(_renderer.getDevice());
373 
374  const VkAttachmentDescription colorAttachment{
375  /* colorAttachment.flags */ 0,
376  /* colorAttachment.format */ _renderer.getRenderWindow()->getSwapchain().getFormat().format,
377  /* colorAttachment.samples */ VK_SAMPLE_COUNT_1_BIT,
378  /* colorAttachment.loadOp */ VK_ATTACHMENT_LOAD_OP_CLEAR,
379  /* colorAttachment.storeOp */ VK_ATTACHMENT_STORE_OP_STORE,
380  /* colorAttachment.stencilLoadOp */ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
381  /* colorAttachment.stencilStoreOp */ VK_ATTACHMENT_STORE_OP_DONT_CARE,
382  /* colorAttachment.initialLayout */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
383  /* colorAttachment.finalLayout */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
384  };
385 
386  auto colorAttachmentIndex = renderPassBuilder.addAttachment(colorAttachment);
387 
388  const VkFormat depthFormat = API::Image::findSupportedFormat(
390  {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT},
391  VK_IMAGE_TILING_OPTIMAL,
392  VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
393  );
394 
395  const VkAttachmentDescription depthAttachment{
396  /* depthAttachment.flags */ 0,
397  /* depthAttachment.format */ depthFormat,
398  /* depthAttachment.samples */ VK_SAMPLE_COUNT_1_BIT,
399  /* depthAttachment.loadOp */ VK_ATTACHMENT_LOAD_OP_CLEAR,
400  /* depthAttachment.storeOp */ VK_ATTACHMENT_STORE_OP_STORE,
401  /* depthAttachment.stencilLoadOp */ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
402  /* depthAttachment.stencilStoreOp */ VK_ATTACHMENT_STORE_OP_DONT_CARE,
403  /* depthAttachment.initialLayout */ VK_IMAGE_LAYOUT_UNDEFINED,
404  /* depthAttachment.finalLayout */ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
405  };
406 
407  auto depthAttachmentIndex = renderPassBuilder.addAttachment(depthAttachment);
408 
409  const API::Builder::RenderPass::SubpassDescription subpassDescription{
410  /* subpassDescription.pipelineBindPoint */ VK_PIPELINE_BIND_POINT_GRAPHICS,
411  /* subpassDescription.inputAttachments */ {},
412  /* subpassDescription.colorAttachments */ {{colorAttachmentIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}},
413  /* subpassDescription.resolveAttachments */ {},
414  /* subpassDescription.depthStencilAttachment */ {depthAttachmentIndex, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL},
415  /* subpassDescription.preserveAttachments */ {},
416  };
417 
418  renderPassBuilder.addSubpass(subpassDescription);
419 
420  VkResult result{VK_SUCCESS};
421  API::RenderPass renderPass;
422  if (!renderPassBuilder.build(renderPass, &result)) {
423  LUG_LOG.error("Vulkan::Render::Pipeline: Can't create render pass: {}", result);
424  return false;
425  }
426 
427  graphicsPipelineBuilder.setRenderPass(std::move(renderPass), 0);
428  }
429 
430  VkResult result{VK_SUCCESS};
431  if (!graphicsPipelineBuilder.build(_pipeline, &result)) {
432  LUG_LOG.error("Vulkan::Render::Pipeline: Can't create pipeline: {}", result);
433  return false;
434  }
435 
436  return true;
437 }
438 
440  if (renderer.containsPipeline(id)) {
441  return renderer.getPipeline(id);
442  }
443 
444  std::unique_ptr<Resource> resource{new Pipeline(renderer, id)};
445  Pipeline* pipeline = static_cast<Pipeline*>(resource.get());
446 
447  if (!pipeline->init()) {
448  return nullptr;
449  }
450 
451  Resource::SharedPtr<Pipeline> sharedPtrPipeline = renderer.getResourceManager()->add<Pipeline>(std::move(resource));
452  renderer.addPipeline(sharedPtrPipeline);
453 
454  return sharedPtrPipeline;
455 }
456 
457 } // Render
458 } // Vulkan
459 } // Graphics
460 } // lug
Id of the Pipeline. It&#39;s a concatenation of three parts: PrimitivePart, MaterialPart and PipelinePart...
Definition: Pipeline.hpp:33
Describes the material. How is the material composed, with textures, no textures, etc...
Definition: Pipeline.hpp:61
uint32_t occlusionInfo
0b00 texture with UV0, 0b01 texture with UV1, 0b10 texture with UV2, 0b11 no texture.
Definition: Pipeline.hpp:67
uint32_t countColor
The number of colors (maximum 3).
Definition: Pipeline.hpp:44
uint32_t baseColorInfo
0b00 texture with UV0, 0b01 texture with UV1, 0b10 texture with UV2, 0b11 no texture.
Definition: Pipeline.hpp:64
Pipeline(Renderer &renderer, Id id)
Definition: Pipeline.cpp:19
void setBindings(const std::vector< VkDescriptorSetLayoutBinding > &bindings)
Resource::SharedPtr< T > add(std::unique_ptr< Resource > resource)
Add a resource to the ResourceManager.
const char * what() const noexcept override
Return the full formated exception.
Definition: Exception.cpp:27
Resource::SharedPtr< Render::Pipeline > getPipeline(Render::Pipeline::Id id)
Definition: Renderer.inl:77
The first two vertices define the first segment, with subsequent pairs of vertices each defining one ...
Dummy class for a shared pointer.
Definition: Resource.hpp:66
bool containsPipeline(Render::Pipeline::Id id) const
Definition: Renderer.inl:73
const API::Swapchain & getSwapchain() const
Definition: Window.inl:1
const VkSurfaceFormatKHR & getFormat() const
Definition: Swapchain.inl:17
T e()
Definition: Constant.inl:82
Class for resource.
Definition: Resource.hpp:17
void addPipeline(Resource::SharedPtr< Render::Pipeline > pipeline)
Definition: Renderer.inl:69
Render::Technique::Type renderTechnique
Definition: Renderer.hpp:37
uint32_t irradianceMapInfo
1 texture, 0 no texture.
Definition: Pipeline.hpp:83
static std::vector< uint32_t > buildShader(std::string shaderRoot, ::lug::Graphics::Render::Technique::Type technique, Type type, Pipeline::Id id)
static VkFormat findSupportedFormat(const Device &device, const std::set< VkFormat > &formats, VkImageTiling tiling, VkFormatFeatureFlags features)
Definition: Image.cpp:82
uint32_t emissiveInfo
0b00 texture with UV0, 0b01 texture with UV1, 0b10 texture with UV2, 0b11 no texture.
Definition: Pipeline.hpp:68
Render::Window * getRenderWindow() const
Definition: Renderer.inl:85
const InitInfo & getInfo() const
Definition: Renderer.inl:1
void setPushConstants(const std::vector< VkPushConstantRange > &pushConstants)
uint32_t metallicRoughnessInfo
0b00 texture with UV0, 0b01 texture with UV1, 0b10 texture with UV2, 0b11 no texture.
Definition: Pipeline.hpp:65
#define LUG_LOG
Definition: Logger.hpp:73
uint32_t prefilteredMapInfo
1 texture, 0 no texture
Definition: Pipeline.hpp:84
The first vertex specifies the first segment’s start point while the second vertex specifies the fir...
static Resource::SharedPtr< Pipeline > create(Renderer &renderer, Id id)
Definition: Pipeline.cpp:439
Type
Type of the resource.
Definition: Resource.hpp:24
Each vertex defines a separate point.
uint32_t normalInfo
0b00 texture with UV0, 0b01 texture with UV1, 0b10 texture with UV2, 0b11 no texture.
Definition: Pipeline.hpp:66
uint32_t tangentVertexData
0 if no attribute tangeant.
Definition: Pipeline.hpp:42
ResourceManager * getResourceManager() const
Definition: Renderer.inl:9
Class for the Vulkan pipeline, Render side.
Definition: Pipeline.hpp:26
uint32_t countTexCoord
The number of texcoord (maximum 3).
Definition: Pipeline.hpp:43