Lugdunum  0.1.0
SkyBox.cpp
Go to the documentation of this file.
2 
14 #include <lug/Math/Constant.hpp>
17 
18 namespace lug {
19 namespace Graphics {
20 namespace Vulkan {
21 namespace Render {
22 
23 API::GraphicsPipeline SkyBox::_pipeline;
24 API::GraphicsPipeline SkyBox::_irradianceMapPipeline;
25 API::GraphicsPipeline SkyBox::_prefilteredMapPipeline;
26 API::GraphicsPipeline SkyBox::_brdfLutPipeline;
29 uint32_t SkyBox::_skyBoxCount{0};
30 
31 SkyBox::SkyBox(const std::string& name) : ::lug::Graphics::Render::SkyBox(name) {}
32 
34  destroy();
35 }
36 
38  --_skyBoxCount;
39  if (_skyBoxCount == 0) {
40  SkyBox::_pipeline.destroy();
41  SkyBox::_irradianceMapPipeline.destroy();
42  SkyBox::_prefilteredMapPipeline.destroy();
43  SkyBox::_brdfLutPipeline.destroy();
44  }
45 }
46 
48  constexpr uint32_t irradianceMapSize = 64;
49 
50  // Constructor of SkyBox is private, we can't use std::make_unique
51  std::unique_ptr<Resource> resource{new Vulkan::Render::SkyBox(_name + "_irradiance_map")};
52  Vulkan::Render::SkyBox* irradianceMap = static_cast<Vulkan::Render::SkyBox*>(resource.get());
53 
54  Vulkan::Renderer& vkRenderer = static_cast<Vulkan::Renderer&>(renderer);
55 
57  if (!texture) {
58  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::createIrradianceMap: The skybox doesn't have an environnement");
59  return nullptr;
60  }
61 
62  lug::Graphics::Builder::Texture textureBuilder(vkRenderer);
63 
65  textureBuilder.setMagFilter(texture->getMagFilter());
66  textureBuilder.setMinFilter(texture->getMinFilter());
67  textureBuilder.setMipMapFilter(texture->getMipMapFilter());
68  textureBuilder.setWrapS(texture->getWrapS());
69  textureBuilder.setWrapT(texture->getWrapT());
70 
71  // TODO: Check which format to use
72  if (!textureBuilder.addLayer(irradianceMapSize, irradianceMapSize, lug::Graphics::Render::Texture::Format::R32G32B32A32_SFLOAT)
73  || !textureBuilder.addLayer(irradianceMapSize, irradianceMapSize, lug::Graphics::Render::Texture::Format::R32G32B32A32_SFLOAT)
74  || !textureBuilder.addLayer(irradianceMapSize, irradianceMapSize, lug::Graphics::Render::Texture::Format::R32G32B32A32_SFLOAT)
75  || !textureBuilder.addLayer(irradianceMapSize, irradianceMapSize, lug::Graphics::Render::Texture::Format::R32G32B32A32_SFLOAT)
76  || !textureBuilder.addLayer(irradianceMapSize, irradianceMapSize, lug::Graphics::Render::Texture::Format::R32G32B32A32_SFLOAT)
77  || !textureBuilder.addLayer(irradianceMapSize, irradianceMapSize, lug::Graphics::Render::Texture::Format::R32G32B32A32_SFLOAT)) {
78  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::build: Can't create irradiance map texture layers");
79  return nullptr;
80  }
81 
82  irradianceMap->_environnementTexture = textureBuilder.build();
83  if (!irradianceMap->_environnementTexture) {
84  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::build Can't create the irradiance map texture");
85  return nullptr;
86  }
87 
88  // Create Framebuffer for irradiance map generation
89  API::CommandPool commandPool;
90  API::CommandBuffer cmdBuffer;
91  API::Image offscreenImage;
92  API::ImageView offscreenImageView;
93  API::DeviceMemory imagesMemory;
94  API::Framebuffer framebuffer;
95  API::Fence fence;
97  API::DescriptorSet descriptorSet;
98  const API::Queue* graphicsQueue = nullptr;
99  VkResult result{VK_SUCCESS};
100  {
101  // Graphics queue
102  graphicsQueue = vkRenderer.getDevice().getQueue("queue_graphics");
103  if (!graphicsQueue) {
104  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::createIrradianceMap: Can't find queue with name queue_graphics");
105  return nullptr;
106  }
107 
108  // Command pool
109  API::Builder::CommandPool commandPoolBuilder(vkRenderer.getDevice(), *graphicsQueue->getQueueFamily());
110  if (!commandPoolBuilder.build(commandPool, &result)) {
111  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createIrradianceMap: Can't create the graphics command pool: {}", result);
112  return nullptr;
113  }
114 
115  // Command buffer
116  API::Builder::CommandBuffer commandBufferBuilder(vkRenderer.getDevice(), commandPool);
117  commandBufferBuilder.setLevel(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
118 
119  // Create the render command buffer
120  if (!commandBufferBuilder.build(cmdBuffer, &result)) {
121  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::createIrradianceMap: Can't create the command buffer: {}", result);
122  return nullptr;
123  }
124 
125  // Descriptor pool
126  {
127  API::Builder::DescriptorPool descriptorPoolBuilder(vkRenderer.getDevice());
128 
129  descriptorPoolBuilder.setFlags(0);
130 
131  descriptorPoolBuilder.setMaxSets(42);
132 
133  std::vector<VkDescriptorPoolSize> poolSizes{
134  {
135  /* poolSize.type */ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
136  /* poolSize.descriptorCount */ 42
137  }
138  };
139  descriptorPoolBuilder.setPoolSizes(poolSizes);
140 
141  if (!descriptorPoolBuilder.build(descriptorPool, &result)) {
142  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::createIrradianceMap: Can't create the descriptor pool: {}", result);
143  return nullptr;
144  }
145  }
146 
147  // Descriptor set
148  {
149  API::Builder::DescriptorSet descriptorSetBuilder(vkRenderer.getDevice(), descriptorPool);
150  descriptorSetBuilder.setDescriptorSetLayouts({static_cast<VkDescriptorSetLayout>(SkyBox::_irradianceMapPipeline.getLayout()->getDescriptorSetLayouts()[0])});
151 
152  if (!descriptorSetBuilder.build(descriptorSet, &result)) {
153  LUG_LOG.error("DescriptorSetPool: Can't create descriptor set: {}", result);
154  return nullptr;
155  }
156 
157  descriptorSet.updateImages(
158  0,
159  0,
160  VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
161  {
162  {
163  /* sampler */ static_cast<VkSampler>(texture->getSampler()),
164  /* imageView */ static_cast<VkImageView>(texture->getImageView()),
165  /* imageLayout */ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
166  }
167  }
168  );
169  }
170 
171  // Fence
172  {
173  API::Builder::Fence fenceBuilder(vkRenderer.getDevice());
174 
175  if (!fenceBuilder.build(fence, &result)) {
176  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::createIrradianceMap: Can't create render fence: {}", result);
177  return nullptr;
178  }
179  }
180 
181  // Depth and offscreen images
182  {
183  API::Builder::DeviceMemory deviceMemoryBuilder(vkRenderer.getDevice());
184  deviceMemoryBuilder.setMemoryFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
185 
186  // Create image and add it to API::Builder::DeviceMemory
187  const VkExtent3D extent{
188  /* extent.width */ irradianceMapSize,
189  /* extent.height */ irradianceMapSize,
190  /* extent.depth */ 1
191  };
192 
193  // Create offscreen image
194  {
195  API::Builder::Image imageBuilder(vkRenderer.getDevice());
196 
197  imageBuilder.setExtent(extent);
198  imageBuilder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
199  imageBuilder.setPreferedFormats({ Resource::SharedPtr<Render::Texture>::cast(irradianceMap->_environnementTexture)->getImage().getFormat() });
200  imageBuilder.setQueueFamilyIndices({ graphicsQueue->getQueueFamily()->getIdx() });
201  imageBuilder.setTiling(VK_IMAGE_TILING_OPTIMAL);
202 
203  if (!imageBuilder.build(offscreenImage, &result)) {
204  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createIrradianceMap: Can't create depth buffer image: {}", result);
205  return nullptr;
206  }
207 
208  if (!deviceMemoryBuilder.addImage(offscreenImage)) {
209  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createIrradianceMap: Can't add image to device memory");
210  return nullptr;
211  }
212  }
213 
214  // Initialize depth buffer memory
215  {
216  if (!deviceMemoryBuilder.build(imagesMemory, &result)) {
217  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createIrradianceMap: Can't create device memory: {}", result);
218  return nullptr;
219  }
220  }
221 
222  // Create offscreen image view
223  {
224  API::Builder::ImageView imageViewBuilder(vkRenderer.getDevice(), offscreenImage);
225 
226  imageViewBuilder.setFormat(offscreenImage.getFormat());
227  imageViewBuilder.setAspectFlags(VK_IMAGE_ASPECT_COLOR_BIT);
228 
229  if (!imageViewBuilder.build(offscreenImageView, &result)) {
230  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createIrradianceMap: Can't create depth buffer image view: {}", result);
231  return nullptr;
232  }
233  }
234  }
235 
236  // Create framebuffer
237  {
238  // Create depth buffer image view
239  API::Builder::Framebuffer framebufferBuilder(vkRenderer.getDevice());
240 
241  const API::RenderPass* renderPass = SkyBox::_irradianceMapPipeline.getRenderPass();
242 
243  framebufferBuilder.setRenderPass(renderPass);
244  framebufferBuilder.addAttachment(&offscreenImageView);
245  framebufferBuilder.setWidth(irradianceMapSize);
246  framebufferBuilder.setHeight(irradianceMapSize);
247 
248  if (!framebufferBuilder.build(framebuffer, &result)) {
249  LUG_LOG.error("Forward::initFramebuffers: Can't create framebuffer: {}", result);
250  return nullptr;
251  }
252  }
253  }
254 
255  // Generate the irradiance cube map
256  {
257  if (!cmdBuffer.begin()) {
258  return nullptr;
259  }
260 
261  cmdBuffer.bindPipeline(SkyBox::_irradianceMapPipeline);
262 
263  // Bind descriptor set of the skybox
264  {
265  const API::CommandBuffer::CmdBindDescriptors skyBoxBind{
266  /* skyBoxBind.pipelineLayout */ *SkyBox::_irradianceMapPipeline.getLayout(),
267  /* skyBoxBind.pipelineBindPoint */ VK_PIPELINE_BIND_POINT_GRAPHICS,
268  /* skyBoxBind.firstSet */ 0,
269  /* skyBoxBind.descriptorSets */ {&descriptorSet},
270  /* skyBoxBind.dynamicOffsets */ {},
271  };
272 
273  cmdBuffer.bindDescriptorSets(skyBoxBind);
274  }
275 
276  auto& primitiveSet = SkyBox::getMesh()->getPrimitiveSets()[0];
277 
278  cmdBuffer.bindVertexBuffers(
279  {static_cast<API::Buffer*>(primitiveSet.position->_data)},
280  {0}
281  );
282 
283  API::Buffer* indicesBuffer = static_cast<API::Buffer*>(primitiveSet.indices->_data);
284  cmdBuffer.bindIndexBuffer(*indicesBuffer, VK_INDEX_TYPE_UINT16);
285  const API::CommandBuffer::CmdDrawIndexed cmdDrawIndexed {
286  /* cmdDrawIndexed.indexCount */ primitiveSet.indices->buffer.elementsCount,
287  /* cmdDrawIndexed.instanceCount */ 1,
288  };
289 
290  Math::Mat4x4f projection = Math::Geometry::perspective(Math::halfPi<float>(), 1.0f, 0.1f, static_cast<float>(irradianceMapSize));
291  std::vector<Math::Mat4x4f> matrices = {
292  Math::Geometry::lookAt<float>({0.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}),
293  Math::Geometry::lookAt<float>({0.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}),
294  Math::Geometry::lookAt<float>({0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}),
295  Math::Geometry::lookAt<float>({0.0f, 0.0f, 0.0f}, {0.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}),
296  Math::Geometry::lookAt<float>({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f}),
297  Math::Geometry::lookAt<float>({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 1.0f, 0.0f})
298  };
299 
300  // Change offscreen image layout to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL for render
301  {
302  API::CommandBuffer::CmdPipelineBarrier pipelineBarrier;
303  pipelineBarrier.imageMemoryBarriers.resize(1);
304  pipelineBarrier.imageMemoryBarriers[0].srcAccessMask = 0;
305  pipelineBarrier.imageMemoryBarriers[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
306  pipelineBarrier.imageMemoryBarriers[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
307  pipelineBarrier.imageMemoryBarriers[0].newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
308  pipelineBarrier.imageMemoryBarriers[0].image = &offscreenImage;
309 
310  cmdBuffer.pipelineBarrier(pipelineBarrier);
311  }
312 
313  // Change irradiance layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL for copy
314  {
315  API::CommandBuffer::CmdPipelineBarrier pipelineBarrier;
316  pipelineBarrier.imageMemoryBarriers.resize(1);
317  pipelineBarrier.imageMemoryBarriers[0].srcAccessMask = 0;
318  pipelineBarrier.imageMemoryBarriers[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
319  pipelineBarrier.imageMemoryBarriers[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
320  pipelineBarrier.imageMemoryBarriers[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
321  pipelineBarrier.imageMemoryBarriers[0].image = &Resource::SharedPtr<Render::Texture>::cast(irradianceMap->_environnementTexture)->getImage();
322  pipelineBarrier.imageMemoryBarriers[0].subresourceRange.layerCount = 6;
323 
324  cmdBuffer.pipelineBarrier(pipelineBarrier);
325  }
326 
327  for (uint32_t i = 0; i < 6; ++i) {
328  // Begin of the render pass
329  {
330  // All the pipelines have the same renderPass
331  const API::RenderPass* renderPass = SkyBox::_irradianceMapPipeline.getRenderPass();
332 
333  API::CommandBuffer::CmdBeginRenderPass beginRenderPass{
334  /* beginRenderPass.framebuffer */ framebuffer,
335  /* beginRenderPass.renderArea */ {},
336  /* beginRenderPass.clearValues */ {}
337  };
338 
339  beginRenderPass.renderArea.offset = {0, 0};
340  beginRenderPass.renderArea.extent = {irradianceMapSize, irradianceMapSize};
341 
342  beginRenderPass.clearValues.resize(2);
343  beginRenderPass.clearValues[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}};
344  beginRenderPass.clearValues[1].depthStencil = {1.0f, 0};
345 
346  cmdBuffer.beginRenderPass(*renderPass, beginRenderPass);
347 
348  const VkViewport vkViewport{
349  /* vkViewport.x */ 0.0f,
350  /* vkViewport.y */ 0.0f,
351  /* vkViewport.width */ static_cast<float>(irradianceMapSize),
352  /* vkViewport.height */ static_cast<float>(irradianceMapSize),
353  /* vkViewport.minDepth */ 0.0f,
354  /* vkViewport.maxDepth */ 1.0f,
355  };
356 
357  const VkRect2D scissor{
358  /* scissor.offset */ {
359  0,
360  0
361  },
362  /* scissor.extent */ {
363  static_cast<uint32_t>(irradianceMapSize),
364  static_cast<uint32_t>(irradianceMapSize)
365  }
366  };
367 
368  cmdBuffer.setViewport({vkViewport});
369  cmdBuffer.setScissor({scissor});
370  }
371 
372  const Math::Mat4x4f pushConstants[] = {
373  projection * matrices[i]
374  };
375 
376  const API::CommandBuffer::CmdPushConstants cmdPushConstants{
377  /* cmdPushConstants.layout */ static_cast<VkPipelineLayout>(*SkyBox::_irradianceMapPipeline.getLayout()),
378  /* cmdPushConstants.stageFlags */ VK_SHADER_STAGE_VERTEX_BIT,
379  /* cmdPushConstants.offset */ 0,
380  /* cmdPushConstants.size */ sizeof(pushConstants),
381  /* cmdPushConstants.values */ pushConstants
382  };
383 
384  cmdBuffer.pushConstants(cmdPushConstants);
385 
386  cmdBuffer.drawIndexed(cmdDrawIndexed);
387 
388  // End of the render pass
389  cmdBuffer.endRenderPass();
390 
391  // Change offscreen image layout to VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL for render
392  {
393  API::CommandBuffer::CmdPipelineBarrier::ImageMemoryBarrier imageMemoryBarrier;
394  imageMemoryBarrier.image = &offscreenImage;
395  imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
396  imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
397  API::CommandBuffer::CmdPipelineBarrier cmdPipelineBarrier;
398  cmdPipelineBarrier.imageMemoryBarriers.push_back(std::move(imageMemoryBarrier));
399  cmdBuffer.pipelineBarrier(cmdPipelineBarrier);
400  }
401 
402  // Copy region for transfer from framebuffer to cube face
403  VkImageCopy copyRegion = {};
404 
405  copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
406  copyRegion.srcSubresource.baseArrayLayer = 0;
407  copyRegion.srcSubresource.mipLevel = 0;
408  copyRegion.srcSubresource.layerCount = 1;
409  copyRegion.srcOffset = { 0, 0, 0 };
410 
411  copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
412  copyRegion.dstSubresource.baseArrayLayer = i;
413  copyRegion.dstSubresource.mipLevel = 0;
414  copyRegion.dstSubresource.layerCount = 1;
415  copyRegion.dstOffset = { 0, 0, 0 };
416 
417  copyRegion.extent.width = irradianceMapSize;
418  copyRegion.extent.height = irradianceMapSize;
419  copyRegion.extent.depth = 1;
420 
421  const API::CommandBuffer::CmdCopyImage cmdCopyImage{
422  /* cmdCopyImage.srcImage */ offscreenImage,
423  /* cmdCopyImage.srcImageLayout */ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
424  /* cmdCopyImage.dstImage */ Resource::SharedPtr<Render::Texture>::cast(irradianceMap->_environnementTexture)->getImage(),
425  /* cmdCopyImage.dsrImageLayout */ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
426  /* cmdCopyImage.regions */ { copyRegion }
427  };
428 
429  cmdBuffer.copyImage(cmdCopyImage);
430 
431  // Change offscreen image layout to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL for render
432  {
433  API::CommandBuffer::CmdPipelineBarrier::ImageMemoryBarrier imageMemoryBarrier;
434  imageMemoryBarrier.image = &offscreenImage;
435  imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
436  imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
437  API::CommandBuffer::CmdPipelineBarrier cmdPipelineBarrier;
438  cmdPipelineBarrier.imageMemoryBarriers.push_back(std::move(imageMemoryBarrier));
439  cmdBuffer.pipelineBarrier(cmdPipelineBarrier);
440  }
441  }
442 
443  // Change irradiance layout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL for copy
444  {
445  API::CommandBuffer::CmdPipelineBarrier pipelineBarrier;
446  pipelineBarrier.imageMemoryBarriers.resize(1);
447  pipelineBarrier.imageMemoryBarriers[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
448  pipelineBarrier.imageMemoryBarriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
449  pipelineBarrier.imageMemoryBarriers[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
450  pipelineBarrier.imageMemoryBarriers[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
451  pipelineBarrier.imageMemoryBarriers[0].image = &Resource::SharedPtr<Render::Texture>::cast(irradianceMap->_environnementTexture)->getImage();
452  pipelineBarrier.imageMemoryBarriers[0].subresourceRange.layerCount = 6;
453 
454  cmdBuffer.pipelineBarrier(pipelineBarrier);
455  }
456 
457  if (!cmdBuffer.end()) {
458  return nullptr;
459  }
460  }
461 
462  if (!graphicsQueue->submit(
463  cmdBuffer,
464  {},
465  {},
466  {},
467  static_cast<VkFence>(fence)
468  )) {
469  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createIrradianceMap: Can't submit work to graphics queue: {}", result);
470  return nullptr;
471  }
472 
473  if (!fence.wait() || !graphicsQueue->waitIdle()) {
474  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createIrradianceMap:: Can't wait fence");
475  return nullptr;
476  }
477 
478  cmdBuffer.destroy();
479  commandPool.destroy();
480  offscreenImage.destroy();
481  offscreenImageView.destroy();
482  framebuffer.destroy();
483  descriptorPool.destroy();
484  fence.destroy();
485 
486  return vkRenderer.getResourceManager()->add<::lug::Graphics::Render::SkyBox>(std::move(resource));
487 }
488 
490  constexpr uint32_t prefilteredMapSize = 512;
491  const uint32_t mipMapCount = static_cast<uint32_t>(floor(log2(prefilteredMapSize))) + 1;
492 
493  // Constructor of SkyBox is private, we can't use std::make_unique
494  std::unique_ptr<Resource> resource{new Vulkan::Render::SkyBox(_name + "_prefiltered_map")};
495  Vulkan::Render::SkyBox* prefilteredMap = static_cast<Vulkan::Render::SkyBox*>(resource.get());
496 
497  Vulkan::Renderer& vkRenderer = static_cast<Vulkan::Renderer&>(renderer);
498 
499  lug::Graphics::Builder::Texture textureBuilder(vkRenderer);
500 
502  if (!texture) {
503  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::createPrefilteredMap: The skybox doesn't have an environnement");
504  return nullptr;
505  }
506 
508  textureBuilder.setMipLevels(mipMapCount);
509  textureBuilder.setMagFilter(texture->getMagFilter());
510  textureBuilder.setMinFilter(texture->getMinFilter());
511  textureBuilder.setMipMapFilter(texture->getMipMapFilter());
512  textureBuilder.setWrapS(texture->getWrapS());
513  textureBuilder.setWrapT(texture->getWrapT());
514 
515  // TODO: Check which format to use
516  if (!textureBuilder.addLayer(prefilteredMapSize, prefilteredMapSize, lug::Graphics::Render::Texture::Format::R32G32B32A32_SFLOAT)
517  || !textureBuilder.addLayer(prefilteredMapSize, prefilteredMapSize, lug::Graphics::Render::Texture::Format::R32G32B32A32_SFLOAT)
518  || !textureBuilder.addLayer(prefilteredMapSize, prefilteredMapSize, lug::Graphics::Render::Texture::Format::R32G32B32A32_SFLOAT)
519  || !textureBuilder.addLayer(prefilteredMapSize, prefilteredMapSize, lug::Graphics::Render::Texture::Format::R32G32B32A32_SFLOAT)
520  || !textureBuilder.addLayer(prefilteredMapSize, prefilteredMapSize, lug::Graphics::Render::Texture::Format::R32G32B32A32_SFLOAT)
521  || !textureBuilder.addLayer(prefilteredMapSize, prefilteredMapSize, lug::Graphics::Render::Texture::Format::R32G32B32A32_SFLOAT)) {
522  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::build: Can't create prefiltered map texture layers");
523  return nullptr;
524  }
525 
526  prefilteredMap->_environnementTexture = textureBuilder.build();
527  if (!prefilteredMap->_environnementTexture) {
528  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::build Can't create the prefiltered map texture");
529  return nullptr;
530  }
531 
532  // Create Framebuffer for prefiltered map generation
533  API::CommandPool commandPool;
534  API::CommandBuffer cmdBuffer;
535  API::Image offscreenImage;
536  API::ImageView offscreenImageView;
537  API::DeviceMemory imagesMemory;
538  API::Framebuffer framebuffer;
539  API::Fence fence;
541  API::DescriptorSet descriptorSet;
542  const API::Queue* graphicsQueue = nullptr;
543  VkResult result{VK_SUCCESS};
544  {
545  // Graphics queue
546  graphicsQueue = vkRenderer.getDevice().getQueue("queue_graphics");
547  if (!graphicsQueue) {
548  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::createPrefilteredMap: Can't find queue with name queue_graphics");
549  return nullptr;
550  }
551 
552  // Command pool
553  API::Builder::CommandPool commandPoolBuilder(vkRenderer.getDevice(), *graphicsQueue->getQueueFamily());
554  if (!commandPoolBuilder.build(commandPool, &result)) {
555  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createPrefilteredMap: Can't create the graphics command pool: {}", result);
556  return nullptr;
557  }
558 
559  // Command buffer
560  API::Builder::CommandBuffer commandBufferBuilder(vkRenderer.getDevice(), commandPool);
561  commandBufferBuilder.setLevel(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
562 
563  // Create the render command buffer
564  if (!commandBufferBuilder.build(cmdBuffer, &result)) {
565  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::createPrefilteredMap: Can't create the command buffer: {}", result);
566  return nullptr;
567  }
568 
569  // Descriptor pool
570  {
571  API::Builder::DescriptorPool descriptorPoolBuilder(vkRenderer.getDevice());
572 
573  descriptorPoolBuilder.setFlags(0);
574 
575  descriptorPoolBuilder.setMaxSets(42);
576 
577  std::vector<VkDescriptorPoolSize> poolSizes{
578  {
579  /* poolSize.type */ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
580  /* poolSize.descriptorCount */ 42
581  }
582  };
583  descriptorPoolBuilder.setPoolSizes(poolSizes);
584 
585  if (!descriptorPoolBuilder.build(descriptorPool, &result)) {
586  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::createPrefilteredMap: Can't create the descriptor pool: {}", result);
587  return nullptr;
588  }
589  }
590 
591  // Descriptor set
592  {
593  API::Builder::DescriptorSet descriptorSetBuilder(vkRenderer.getDevice(), descriptorPool);
594  descriptorSetBuilder.setDescriptorSetLayouts({static_cast<VkDescriptorSetLayout>(SkyBox::_prefilteredMapPipeline.getLayout()->getDescriptorSetLayouts()[0])});
595 
596  if (!descriptorSetBuilder.build(descriptorSet, &result)) {
597  LUG_LOG.error("DescriptorSetPool: Can't create descriptor set: {}", result);
598  return nullptr;
599  }
600 
601  descriptorSet.updateImages(
602  0,
603  0,
604  VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
605  {
606  {
607  /* sampler */ static_cast<VkSampler>(texture->getSampler()),
608  /* imageView */ static_cast<VkImageView>(texture->getImageView()),
609  /* imageLayout */ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
610  }
611  }
612  );
613  }
614 
615  // Fence
616  {
617  API::Builder::Fence fenceBuilder(vkRenderer.getDevice());
618 
619  if (!fenceBuilder.build(fence, &result)) {
620  LUG_LOG.error("Resource::SharedPtr<::lug::Graphics::Render::SkyBox>::createPrefilteredMap: Can't create render fence: {}", result);
621  return nullptr;
622  }
623  }
624 
625  // Depth and offscreen images
626  {
627  API::Builder::DeviceMemory deviceMemoryBuilder(vkRenderer.getDevice());
628  deviceMemoryBuilder.setMemoryFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
629 
630  // Create image and add it to API::Builder::DeviceMemory
631  const VkExtent3D extent{
632  /* extent.width */ prefilteredMapSize,
633  /* extent.height */ prefilteredMapSize,
634  /* extent.depth */ 1
635  };
636 
637  // Create offscreen image
638  {
639  API::Builder::Image imageBuilder(vkRenderer.getDevice());
640 
641  imageBuilder.setExtent(extent);
642  imageBuilder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
643  imageBuilder.setPreferedFormats({ Resource::SharedPtr<Render::Texture>::cast(prefilteredMap->_environnementTexture)->getImage().getFormat() });
644  imageBuilder.setQueueFamilyIndices({ graphicsQueue->getQueueFamily()->getIdx() });
645  imageBuilder.setTiling(VK_IMAGE_TILING_OPTIMAL);
646 
647  if (!imageBuilder.build(offscreenImage, &result)) {
648  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createPrefilteredMap: Can't create depth buffer image: {}", result);
649  return nullptr;
650  }
651 
652  if (!deviceMemoryBuilder.addImage(offscreenImage)) {
653  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createPrefilteredMap: Can't add image to device memory");
654  return nullptr;
655  }
656  }
657 
658  // Initialize depth buffer memory
659  {
660  if (!deviceMemoryBuilder.build(imagesMemory, &result)) {
661  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createPrefilteredMap: Can't create device memory: {}", result);
662  return nullptr;
663  }
664  }
665 
666  // Create offscreen image view
667  {
668  API::Builder::ImageView imageViewBuilder(vkRenderer.getDevice(), offscreenImage);
669 
670  imageViewBuilder.setFormat(offscreenImage.getFormat());
671  imageViewBuilder.setAspectFlags(VK_IMAGE_ASPECT_COLOR_BIT);
672 
673  if (!imageViewBuilder.build(offscreenImageView, &result)) {
674  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createPrefilteredMap: Can't create depth buffer image view: {}", result);
675  return nullptr;
676  }
677  }
678  }
679 
680  // Create framebuffer
681  {
682  // Create depth buffer image view
683  API::Builder::Framebuffer framebufferBuilder(vkRenderer.getDevice());
684 
685  const API::RenderPass* renderPass = SkyBox::_prefilteredMapPipeline.getRenderPass();
686 
687  framebufferBuilder.setRenderPass(renderPass);
688  framebufferBuilder.addAttachment(&offscreenImageView);
689  framebufferBuilder.setWidth(prefilteredMapSize);
690  framebufferBuilder.setHeight(prefilteredMapSize);
691 
692  if (!framebufferBuilder.build(framebuffer, &result)) {
693  LUG_LOG.error("Forward::initFramebuffers: Can't create framebuffer: {}", result);
694  return nullptr;
695  }
696  }
697  }
698 
699  // Generate the prefiltered cube map
700  {
701  if (!cmdBuffer.begin()) {
702  return nullptr;
703  }
704 
705  cmdBuffer.bindPipeline(SkyBox::_prefilteredMapPipeline);
706 
707  // Bind descriptor set of the skybox
708  {
709  const API::CommandBuffer::CmdBindDescriptors skyBoxBind{
710  /* skyBoxBind.pipelineLayout */ *SkyBox::_prefilteredMapPipeline.getLayout(),
711  /* skyBoxBind.pipelineBindPoint */ VK_PIPELINE_BIND_POINT_GRAPHICS,
712  /* skyBoxBind.firstSet */ 0,
713  /* skyBoxBind.descriptorSets */ {&descriptorSet},
714  /* skyBoxBind.dynamicOffsets */ {},
715  };
716 
717  cmdBuffer.bindDescriptorSets(skyBoxBind);
718  }
719 
720  auto& primitiveSet = SkyBox::getMesh()->getPrimitiveSets()[0];
721 
722  cmdBuffer.bindVertexBuffers(
723  {static_cast<API::Buffer*>(primitiveSet.position->_data)},
724  {0}
725  );
726 
727  API::Buffer* indicesBuffer = static_cast<API::Buffer*>(primitiveSet.indices->_data);
728  cmdBuffer.bindIndexBuffer(*indicesBuffer, VK_INDEX_TYPE_UINT16);
729  const API::CommandBuffer::CmdDrawIndexed cmdDrawIndexed {
730  /* cmdDrawIndexed.indexCount */ primitiveSet.indices->buffer.elementsCount,
731  /* cmdDrawIndexed.instanceCount */ 1,
732  };
733 
734  Math::Mat4x4f projection = Math::Geometry::perspective(Math::halfPi<float>(), 1.0f, 0.1f, static_cast<float>(prefilteredMapSize));
735  std::vector<Math::Mat4x4f> matrices = {
736  Math::Geometry::lookAt<float>({0.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}),
737  Math::Geometry::lookAt<float>({0.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}),
738  Math::Geometry::lookAt<float>({0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}),
739  Math::Geometry::lookAt<float>({0.0f, 0.0f, 0.0f}, {0.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}),
740  Math::Geometry::lookAt<float>({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f}),
741  Math::Geometry::lookAt<float>({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 1.0f, 0.0f})
742  };
743 
744  // Change offscreen image layout to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL for render
745  {
746  API::CommandBuffer::CmdPipelineBarrier pipelineBarrier;
747  pipelineBarrier.imageMemoryBarriers.resize(1);
748  pipelineBarrier.imageMemoryBarriers[0].srcAccessMask = 0;
749  pipelineBarrier.imageMemoryBarriers[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
750  pipelineBarrier.imageMemoryBarriers[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
751  pipelineBarrier.imageMemoryBarriers[0].newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
752  pipelineBarrier.imageMemoryBarriers[0].image = &offscreenImage;
753 
754  cmdBuffer.pipelineBarrier(pipelineBarrier);
755  }
756 
757  // Change prefiltered layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL for copy
758  {
759  API::CommandBuffer::CmdPipelineBarrier pipelineBarrier;
760  pipelineBarrier.imageMemoryBarriers.resize(1);
761  pipelineBarrier.imageMemoryBarriers[0].srcAccessMask = 0;
762  pipelineBarrier.imageMemoryBarriers[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
763  pipelineBarrier.imageMemoryBarriers[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
764  pipelineBarrier.imageMemoryBarriers[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
765  pipelineBarrier.imageMemoryBarriers[0].image = &Resource::SharedPtr<Render::Texture>::cast(prefilteredMap->_environnementTexture)->getImage();
766  pipelineBarrier.imageMemoryBarriers[0].subresourceRange.levelCount = mipMapCount;
767  pipelineBarrier.imageMemoryBarriers[0].subresourceRange.layerCount = 6;
768 
769  cmdBuffer.pipelineBarrier(pipelineBarrier);
770  }
771 
772 
773  for (uint32_t m = 0; m < mipMapCount; m++) {
774  const float roughness = (float)m / (float)(mipMapCount - 1);
775 
776  for (uint32_t i = 0; i < 6; ++i) {
777  // Begin of the render pass
778  {
779  // All the pipelines have the same renderPass
780  const API::RenderPass* renderPass = SkyBox::_prefilteredMapPipeline.getRenderPass();
781 
782  API::CommandBuffer::CmdBeginRenderPass beginRenderPass{
783  /* beginRenderPass.framebuffer */ framebuffer,
784  /* beginRenderPass.renderArea */ {},
785  /* beginRenderPass.clearValues */ {}
786  };
787 
788  beginRenderPass.renderArea.offset = {0, 0};
789  beginRenderPass.renderArea.extent = {prefilteredMapSize, prefilteredMapSize};
790 
791  beginRenderPass.clearValues.resize(2);
792  beginRenderPass.clearValues[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}};
793  beginRenderPass.clearValues[1].depthStencil = {1.0f, 0};
794 
795  cmdBuffer.beginRenderPass(*renderPass, beginRenderPass);
796 
797  const VkViewport vkViewport{
798  /* vkViewport.x */ 0.0f,
799  /* vkViewport.y */ 0.0f,
800  /* vkViewport.width */ static_cast<float>(prefilteredMapSize * std::pow(0.5f, m)),
801  /* vkViewport.height */ static_cast<float>(prefilteredMapSize * std::pow(0.5f, m)),
802  /* vkViewport.minDepth */ 0.0f,
803  /* vkViewport.maxDepth */ 1.0f,
804  };
805 
806  const VkRect2D scissor{
807  /* scissor.offset */ {
808  0,
809  0
810  },
811  /* scissor.extent */ {
812  static_cast<uint32_t>(prefilteredMapSize),
813  static_cast<uint32_t>(prefilteredMapSize)
814  }
815  };
816 
817  cmdBuffer.setViewport({vkViewport});
818  cmdBuffer.setScissor({scissor});
819  }
820 
821  {
822  const Math::Mat4x4f pushConstants[] = {
823  projection * matrices[i]
824  };
825 
826  const API::CommandBuffer::CmdPushConstants cmdPushConstants{
827  /* cmdPushConstants.layout */ static_cast<VkPipelineLayout>(*SkyBox::_prefilteredMapPipeline.getLayout()),
828  /* cmdPushConstants.stageFlags */ VK_SHADER_STAGE_VERTEX_BIT,
829  /* cmdPushConstants.offset */ 0,
830  /* cmdPushConstants.size */ sizeof(pushConstants),
831  /* cmdPushConstants.values */ pushConstants
832  };
833 
834  cmdBuffer.pushConstants(cmdPushConstants);
835  }
836 
837  {
838  const API::CommandBuffer::CmdPushConstants cmdPushConstants{
839  /* cmdPushConstants.layout */ static_cast<VkPipelineLayout>(*SkyBox::_prefilteredMapPipeline.getLayout()),
840  /* cmdPushConstants.stageFlags */ VK_SHADER_STAGE_FRAGMENT_BIT,
841  /* cmdPushConstants.offset */ sizeof(Math::Mat4x4f),
842  /* cmdPushConstants.size */ sizeof(roughness),
843  /* cmdPushConstants.values */ &roughness
844  };
845 
846  cmdBuffer.pushConstants(cmdPushConstants);
847  }
848 
849  cmdBuffer.drawIndexed(cmdDrawIndexed);
850 
851  // End of the render pass
852  cmdBuffer.endRenderPass();
853 
854  // Change offscreen image layout to VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL for render
855  {
856  API::CommandBuffer::CmdPipelineBarrier::ImageMemoryBarrier imageMemoryBarrier;
857  imageMemoryBarrier.image = &offscreenImage;
858  imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
859  imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
860  API::CommandBuffer::CmdPipelineBarrier cmdPipelineBarrier;
861  cmdPipelineBarrier.imageMemoryBarriers.push_back(std::move(imageMemoryBarrier));
862  cmdBuffer.pipelineBarrier(cmdPipelineBarrier);
863  }
864 
865  // Copy region for transfer from framebuffer to cube face
866  VkImageCopy copyRegion = {};
867 
868  copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
869  copyRegion.srcSubresource.baseArrayLayer = 0;
870  copyRegion.srcSubresource.mipLevel = 0;
871  copyRegion.srcSubresource.layerCount = 1;
872  copyRegion.srcOffset = { 0, 0, 0 };
873 
874  copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
875  copyRegion.dstSubresource.baseArrayLayer = i;
876  copyRegion.dstSubresource.mipLevel = m;
877  copyRegion.dstSubresource.layerCount = 1;
878  copyRegion.dstOffset = { 0, 0, 0 };
879 
880  copyRegion.extent.width = static_cast<uint32_t>(prefilteredMapSize * std::pow(0.5f, m));
881  copyRegion.extent.height = static_cast<uint32_t>(prefilteredMapSize * std::pow(0.5f, m));
882  copyRegion.extent.depth = 1;
883 
884  const API::CommandBuffer::CmdCopyImage cmdCopyImage{
885  /* cmdCopyImage.srcImage */ offscreenImage,
886  /* cmdCopyImage.srcImageLayout */ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
887  /* cmdCopyImage.dstImage */ Resource::SharedPtr<Render::Texture>::cast(prefilteredMap->_environnementTexture)->getImage(),
888  /* cmdCopyImage.dsrImageLayout */ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
889  /* cmdCopyImage.regions */ { copyRegion }
890  };
891 
892  cmdBuffer.copyImage(cmdCopyImage);
893 
894  // Change offscreen image layout to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL for render
895  {
896  API::CommandBuffer::CmdPipelineBarrier::ImageMemoryBarrier imageMemoryBarrier;
897  imageMemoryBarrier.image = &offscreenImage;
898  imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
899  imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
900  API::CommandBuffer::CmdPipelineBarrier cmdPipelineBarrier;
901  cmdPipelineBarrier.imageMemoryBarriers.push_back(std::move(imageMemoryBarrier));
902  cmdBuffer.pipelineBarrier(cmdPipelineBarrier);
903  }
904  }
905  }
906 
907  // Change prefiltered layout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL for copy
908  {
909  API::CommandBuffer::CmdPipelineBarrier pipelineBarrier;
910  pipelineBarrier.imageMemoryBarriers.resize(1);
911  pipelineBarrier.imageMemoryBarriers[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
912  pipelineBarrier.imageMemoryBarriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
913  pipelineBarrier.imageMemoryBarriers[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
914  pipelineBarrier.imageMemoryBarriers[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
915  pipelineBarrier.imageMemoryBarriers[0].image = &Resource::SharedPtr<Render::Texture>::cast(prefilteredMap->_environnementTexture)->getImage();
916  pipelineBarrier.imageMemoryBarriers[0].subresourceRange.levelCount = mipMapCount;
917  pipelineBarrier.imageMemoryBarriers[0].subresourceRange.layerCount = 6;
918 
919  cmdBuffer.pipelineBarrier(pipelineBarrier);
920  }
921 
922  if (!cmdBuffer.end()) {
923  return nullptr;
924  }
925  }
926 
927  if (!graphicsQueue->submit(
928  cmdBuffer,
929  {},
930  {},
931  {},
932  static_cast<VkFence>(fence)
933  )) {
934  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createPrefilteredMap: Can't submit work to graphics queue: {}", result);
935  return nullptr;
936  }
937 
938  if (!fence.wait() || !graphicsQueue->waitIdle()) {
939  LUG_LOG.error("Forward::iniResource::SharedPtr<::lug::Graphics::Render::SkyBox>::createPrefilteredMap:: Can't wait fence");
940  return nullptr;
941  }
942 
943  cmdBuffer.destroy();
944  commandPool.destroy();
945  offscreenImage.destroy();
946  offscreenImageView.destroy();
947  framebuffer.destroy();
948  descriptorPool.destroy();
949  fence.destroy();
950 
951  return vkRenderer.getResourceManager()->add<::lug::Graphics::Render::SkyBox>(std::move(resource));
952 }
953 
954 } // Render
955 } // Vulkan
956 } // Graphics
957 } // lug
lug::Graphics::Resource::SharedPtr< lug::Graphics::Render::Texture > _environnementTexture
Definition: SkyBox.hpp:41
const API::Sampler & getSampler() const
Definition: Texture.inl:13
Resource::SharedPtr< T > add(std::unique_ptr< Resource > resource)
Add a resource to the ResourceManager.
void setMinFilter(Render::Texture::Filter minFilter)
Definition: Texture.inl:17
static lug::Graphics::Resource::SharedPtr< lug::Graphics::Render::Mesh > _mesh
Definition: SkyBox.hpp:58
void pipelineBarrier(const CmdPipelineBarrier &parameters, VkDependencyFlags dependencyFlags=VK_DEPENDENCY_BY_REGION_BIT, VkPipelineStageFlags srcStageMask=VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VkPipelineStageFlags dstStageMask=VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) const
const API::Queue * getQueue(const std::string &queueName) const
Definition: Device.cpp:70
void setExtent(VkExtent3D extent)
Definition: Image.inl:17
bool submit(const CommandBuffer &commandBuffer, const std::vector< VkSemaphore > &signalSemaphores={}, const std::vector< VkSemaphore > &waitSemaphores={}, const std::vector< VkPipelineStageFlags > &waitDstStageMasks={}, VkFence fence=VK_NULL_HANDLE) const
Definition: Queue.cpp:32
void setWrapS(Render::Texture::WrappingMode wrapS)
Definition: Texture.inl:25
void setLevel(VkCommandBufferLevel level)
static uint32_t _skyBoxCount
Store the number of skybox created to know when to create/destroy the pipeline and mesh...
Definition: SkyBox.hpp:66
static API::GraphicsPipeline _pipeline
Definition: SkyBox.hpp:54
void setFlags(VkDescriptorPoolCreateFlags flags)
void setMagFilter(Render::Texture::Filter magFilter)
Definition: Texture.inl:13
Render::Texture::Filter getMinFilter() const
Definition: Texture.inl:17
Resource::SharedPtr< lug::Graphics::Render::SkyBox > createPrefilteredMap(lug::Graphics::Renderer &renderer) const override final
Definition: SkyBox.cpp:489
void setDescriptorSetLayouts(const std::vector< VkDescriptorSetLayout > &descriptorSetLayouts)
void beginRenderPass(const API::RenderPass &renderPass, const CmdBeginRenderPass &parameters, VkSubpassContents contents=VK_SUBPASS_CONTENTS_INLINE) const
bool addLayer(const std::string &filename, bool hdr=false)
Definition: Texture.cpp:98
const QueueFamily * getQueueFamily() const
Definition: Queue.cpp:86
void setWrapT(Render::Texture::WrappingMode wrapT)
Definition: Texture.inl:29
static API::GraphicsPipeline _prefilteredMapPipeline
Definition: SkyBox.hpp:56
const Resource::SharedPtr< lug::Graphics::Render::Texture > getEnvironnementTexture() const
Definition: SkyBox.inl:5
const std::vector< Mesh::PrimitiveSet > & getPrimitiveSets() const
Definition: Mesh.inl:1
static SharedPtr< T > cast(const SharedPtr< RhsT > &rhs)
Dynamic casting of a SharedPtr to another one (RhsT to T)
VkFormat getFormat() const
Definition: Image.inl:13
static const lug::Graphics::Resource::SharedPtr< lug::Graphics::Render::Mesh > getMesh()
Definition: SkyBox.inl:5
void setMipMapFilter(Render::Texture::Filter mipMapFilter)
Definition: Texture.inl:21
void setMemoryFlags(VkMemoryPropertyFlags flags)
Definition: DeviceMemory.inl:1
#define LUG_LOG
Definition: Logger.hpp:73
void updateImages(uint32_t dstBinding, uint32_t dstArrayElement, VkDescriptorType descriptorType, const std::vector< VkDescriptorImageInfo > &imageInfos) const
Update the descriptor set images.
Render::Texture::WrappingMode getWrapT() const
Definition: Texture.inl:29
const API::ImageView & getImageView() const
Definition: Texture.inl:9
void pushConstants(const CmdPushConstants &parameters) const
void setMipLevels(uint32_t mipLevels)
Definition: Texture.inl:9
Resource::SharedPtr< Render::Texture > build()
Definition: Texture.cpp:37
static lug::Graphics::Resource::SharedPtr< lug::Graphics::Render::Texture > _brdfLut
Definition: SkyBox.hpp:59
ResourceManager * getResourceManager() const
Definition: Renderer.inl:9
Class for graphics.
Definition: Graphics.hpp:25
Render::Texture::Filter getMipMapFilter() const
Definition: Texture.inl:21
bool begin(VkCommandBufferUsageFlags flags=VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) const
Render::Texture::WrappingMode getWrapS() const
Definition: Texture.inl:25
Render::Texture::Filter getMagFilter() const
Definition: Texture.inl:13
static API::GraphicsPipeline _irradianceMapPipeline
Definition: SkyBox.hpp:55
Matrix< 4, 4, T > perspective(T fovy, T aspect, T zNear, T zFar)
Definition: Transform.inl:95
static API::GraphicsPipeline _brdfLutPipeline
Definition: SkyBox.hpp:57
Resource::SharedPtr< lug::Graphics::Render::SkyBox > createIrradianceMap(lug::Graphics::Renderer &renderer) const override final
Definition: SkyBox.cpp:47