61 uint32_t currentImageIndex
77 LUG_LOG.error(
"Forward::render: Can't allocate camera buffer");
104 beginRenderPass.renderArea.offset = {
static_cast<int32_t
>(viewport.offset.x), static_cast<int32_t>(viewport.offset.y)};
105 beginRenderPass.renderArea.extent = {
static_cast<uint32_t
>(viewport.extent.width), static_cast<uint32_t>(viewport.extent.height)};
109 beginRenderPass.clearValues[0].color = {{clearColor.r(), clearColor.g(), clearColor.b(), 1.0f}};
114 const VkViewport vkViewport{
117 viewport.extent.width,
118 viewport.extent.height,
123 const VkRect2D scissor{
142 if (!cameraDescriptorSet) {
143 LUG_LOG.error(
"Forward::render: Can't allocate camera descriptor set");
153 const API::CommandBuffer::CmdBindDescriptors cameraBind{
155 VK_PIPELINE_BIND_POINT_GRAPHICS,
166 std::vector<const BufferPool::SubBuffer*> lightBuffers;
167 std::vector<const BufferPool::SubBuffer*> materialBuffers;
171 std::vector<const DescriptorSetPool::DescriptorSet*> lightDescriptorSets;
172 std::vector<const DescriptorSetPool::DescriptorSet*> materialDescriptorSets;
173 std::vector<const DescriptorSetPool::DescriptorSet*> materialTexturesDescriptorSets;
183 const float blendConstants[4] = {0.0f, 0.0f, 0.0f, 0.0f};
193 {lights.begin() + i, i + 50 > renderQueue.getLightsCount() ? lights.begin() + renderQueue.getLightsCount() : lights.begin() + i + 50}
195 lightBuffers.push_back(lightBuffer);
198 LUG_LOG.error(
"Forward::render: Can't allocate light buffer");
204 lightDescriptorSets.push_back(lightDescriptorSet);
206 if (!lightDescriptorSet) {
207 LUG_LOG.error(
"Forward::render: Can't allocate light descriptor set");
213 const API::CommandBuffer::CmdBindDescriptors lightBind{
215 VK_PIPELINE_BIND_POINT_GRAPHICS,
226 const float blendConstants[4] = {1.0f, 1.0f, 1.0f, 1.0f};
236 for (
const auto primitiveSetInstance : it.second) {
237 auto& node = *primitiveSetInstance.node;
238 const auto& primitiveSet = *primitiveSetInstance.primitiveSet;
239 auto& material = *primitiveSetInstance.material;
245 const API::CommandBuffer::CmdPushConstants cmdPushConstants{
246 static_cast<VkPipelineLayout
>(*pipeline->getPipelineAPI().getLayout()),
247 VK_SHADER_STAGE_VERTEX_BIT,
249 sizeof(pushConstants),
256 materialBuffers.push_back(materialBuffer);
258 if (!materialBuffer) {
259 LUG_LOG.error(
"Forward::render: Can't allocate material buffer");
265 materialDescriptorSets.push_back(materialDescriptorSet);
267 if (!materialDescriptorSet) {
268 LUG_LOG.error(
"Forward::render: Can't allocate material descriptor set");
272 std::vector<const API::DescriptorSet*> materialDescriptorSetsBind{&materialDescriptorSet->
getDescriptorSet()};
274 if (pipeline->getPipelineAPI().getLayout()->getDescriptorSetLayouts().size() > 3) {
277 pipeline->getPipelineAPI(),
279 std::vector<const ::lug::Graphics::Vulkan::Render::Texture*> textures;
281 if (material.getPipelineId().baseColorInfo != 0b11) {
282 textures.push_back(static_cast<const ::lug::Graphics::Vulkan::Render::Texture*>(material.getBaseColorTexture().texture.get()));
285 if (material.getPipelineId().metallicRoughnessInfo != 0b11) {
286 textures.push_back(static_cast<const ::lug::Graphics::Vulkan::Render::Texture*>(material.getMetallicRoughnessTexture().texture.get()));
289 if (material.getPipelineId().normalInfo != 0b11) {
290 textures.push_back(static_cast<const ::lug::Graphics::Vulkan::Render::Texture*>(material.getNormalTexture().texture.get()));
293 if (material.getPipelineId().occlusionInfo != 0b11) {
294 textures.push_back(static_cast<const ::lug::Graphics::Vulkan::Render::Texture*>(material.getOcclusionTexture().texture.get()));
297 if (material.getPipelineId().emissiveInfo != 0b11) {
298 textures.push_back(static_cast<const ::lug::Graphics::Vulkan::Render::Texture*>(material.getEmissiveTexture().texture.get()));
301 if (material.getIrradianceMap() && material.getIrradianceMap()->getEnvironnementTexture()) {
302 textures.push_back(static_cast<const ::lug::Graphics::Vulkan::Render::Texture*>(material.getIrradianceMap()->getEnvironnementTexture().get()));
305 if (material.getPrefilteredMap() && material.getPrefilteredMap()->getEnvironnementTexture()) {
307 textures.push_back(static_cast<const ::lug::Graphics::Vulkan::Render::Texture*>(material.getPrefilteredMap()->getEnvironnementTexture().get()));
314 if (!materialTexturesDescriptorSet) {
315 LUG_LOG.error(
"Forward::render: Can't allocate material textures descriptor set");
319 materialTexturesDescriptorSets.push_back(materialTexturesDescriptorSet);
320 materialDescriptorSetsBind.push_back(&materialTexturesDescriptorSet->
getDescriptorSet());
325 const API::CommandBuffer::CmdBindDescriptors materialBind{
326 *pipeline->getPipelineAPI().getLayout(),
327 VK_PIPELINE_BIND_POINT_GRAPHICS,
329 materialDescriptorSetsBind,
337 if (!primitiveSet.position || !primitiveSet.normal) {
338 LUG_LOG.warn(
"Forward::render: Mesh should have positions and normals data");
342 std::vector<const API::Buffer*> vertexBuffers{
343 static_cast<API::Buffer*
>(primitiveSet.position->_data),
344 static_cast<API::Buffer*>(primitiveSet.normal->_data)
347 if (primitiveSet.tangent) {
348 vertexBuffers.push_back(static_cast<API::Buffer*>(primitiveSet.tangent->_data));
351 for (
const auto& texCoord: primitiveSet.texCoords) {
352 vertexBuffers.push_back(static_cast<API::Buffer*>(texCoord->_data));
355 for (
const auto& color: primitiveSet.colors) {
356 vertexBuffers.push_back(static_cast<API::Buffer*>(color->_data));
359 const std::vector<VkDeviceSize> offsets(vertexBuffers.size());
362 if (primitiveSet.indices) {
365 if (primitiveSet.indices->buffer.size / primitiveSet.indices->buffer.elementsCount == 4) {
366 frameData.
renderCmdBuffer.bindIndexBuffer(*indicesBuffer, VK_INDEX_TYPE_UINT32);
368 frameData.
renderCmdBuffer.bindIndexBuffer(*indicesBuffer, VK_INDEX_TYPE_UINT16);
371 const API::CommandBuffer::CmdDrawIndexed cmdDrawIndexed {
372 primitiveSet.indices->buffer.elementsCount,
378 const API::CommandBuffer::CmdDraw cmdDraw {
379 primitiveSet.position->buffer.elementsCount,
393 if (skyBox && skyBox->getBackgroundTexture()) {
399 if (!skyBoxDescriptorSet) {
400 LUG_LOG.error(
"Forward::render: Can't allocate skyBox descriptor set");
410 const API::CommandBuffer::CmdBindDescriptors skyBoxBind{
412 VK_PIPELINE_BIND_POINT_GRAPHICS,
426 {
static_cast<API::Buffer*
>(primitiveSet.position->_data)},
431 frameData.
renderCmdBuffer.bindIndexBuffer(*indicesBuffer, VK_INDEX_TYPE_UINT16);
432 const API::CommandBuffer::CmdDrawIndexed cmdDrawIndexed {
433 primitiveSet.indices->buffer.elementsCount,
495 {static_cast<VkSemaphore>(frameData.transferSemaphore)},
501 {static_cast<VkSemaphore>(drawCompleteSemaphore)},
502 {static_cast<VkSemaphore>(frameData.transferSemaphore), static_cast<VkSemaphore>(imageReadySemaphore)},
503 {VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT},
509 VkResult result{VK_SUCCESS};
515 LUG_LOG.error(
"Forward::init: Can't find queue with name queue_graphics");
521 LUG_LOG.error(
"Forward::init: Can't create the graphics command pool: {}", result);
530 LUG_LOG.error(
"Forward::init: Can't find queue with name queue_transfer");
536 LUG_LOG.error(
"Forward::init: Can't create the transfer command pool: {}", result);
542 fenceBuilder.
setFlags(VK_FENCE_CREATE_SIGNALED_BIT);
545 graphicsCommandBufferBuilder.
setLevel(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
548 transferCommandBufferBuilder.
setLevel(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
553 for (uint32_t i = 0; i <
_framesData.size(); ++i) {
555 if (!fenceBuilder.build(
_framesData[i].renderFence, &result)) {
556 LUG_LOG.error(
"Forward::init: Can't create render fence: {}", result);
561 if (!fenceBuilder.build(
_framesData[i].transferFence, &result)) {
562 LUG_LOG.error(
"Forward::init: Can't create transfer fence: {}", result);
567 if (!graphicsCommandBufferBuilder.build(
_framesData[i].renderCmdBuffer, &result)) {
568 LUG_LOG.error(
"Forward::init: Can't create the render command buffer: {}", result);
573 if (!transferCommandBufferBuilder.build(
_framesData[i].transferCmdBuffer, &result)) {
574 LUG_LOG.error(
"Forward::init: Can't create the transfer command buffer: {}", result);
578 if (!semaphoreBuilder.build(
_framesData[i].transferSemaphore, &result)) {
579 LUG_LOG.error(
"Forward::init: Can't create the transfer semaphore: {}", result);
643 for (
const auto& subBuffer : frameData.lightBuffers) {
647 for (
const auto& subBuffer : frameData.materialBuffers) {
653 for (
const auto& descriptorSet : frameData.lightDescriptorSets) {
657 for (
const auto& descriptorSet : frameData.materialDescriptorSets) {
661 for (
const auto& descriptorSet : frameData.materialTexturesDescriptorSets) {
691 imageBuilder.
setUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
692 imageBuilder.setPreferedFormats({VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT});
693 imageBuilder.setFeatureFlags(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
698 deviceMemoryBuilder.
setMemoryFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
701 for (uint32_t i = 0; i < imageViews.size(); ++i) {
702 const VkExtent3D extent{
703 imageViews[i].getImage()->getExtent().width,
704 imageViews[i].getImage()->getExtent().height,
708 imageBuilder.setExtent(extent);
712 VkResult result{VK_SUCCESS};
713 if (!imageBuilder.build(
_framesData[i].depthBuffer.image, &result)) {
714 LUG_LOG.error(
"Forward::initDepthBuffers: Can't create depth buffer image: {}", result);
718 if (!deviceMemoryBuilder.addImage(
_framesData[i].depthBuffer.image)) {
719 LUG_LOG.error(
"Forward::initDepthBuffers: Can't add image to device memory");
727 VkResult result{VK_SUCCESS};
729 LUG_LOG.error(
"Forward::initDepthBuffers: Can't create device memory: {}", result);
735 for (uint32_t i = 0; i < imageViews.size(); ++i) {
741 imageViewBuilder.setAspectFlags(VK_IMAGE_ASPECT_DEPTH_BIT);
743 VkResult result{VK_SUCCESS};
744 if (!imageViewBuilder.build(
_framesData[i].depthBuffer.imageView, &result)) {
745 LUG_LOG.error(
"Forward::initDepthBuffers: Can't create depth buffer image view: {}", result);
761 const API::RenderPass* renderPass = basePipeline->getPipelineAPI().getRenderPass();
765 for (uint32_t i = 0; i < imageViews.size(); i++) {
770 framebufferBuilder.addAttachment(&imageViews[i]);
771 framebufferBuilder.addAttachment(&
_framesData[i].depthBuffer.imageView);
772 framebufferBuilder.setWidth(imageViews[i].getImage()->getExtent().width);
773 framebufferBuilder.setHeight(imageViews[i].getImage()->getExtent().height);
775 VkResult result{VK_SUCCESS};
776 if (!framebufferBuilder.build(
_framesData[i].framebuffer, &result)) {
777 LUG_LOG.error(
"Forward::initFramebuffers: Can't create framebuffer: {}", result);
bool render(const Render::Queue &renderQueue, const API::Semaphore &imageReadySemaphore, const API::Semaphore &drawCompleteSemaphore, uint32_t currentImageIndex) override final
bool reset(bool releaseRessources=false) const
std::vector< const DescriptorSetPool::DescriptorSet * > lightDescriptorSets
struct lug::Graphics::Render::View::Scissor::@2 offset
Resource::SharedPtr< Camera::Camera > getCamera() const
uint32_t getOffset() const
const std::vector< Scene::Node * > getLights() const
const BufferPool::SubBuffer * cameraBuffer
static std::unique_ptr< BufferPool::Material > _materialBufferPool
const API::DescriptorSet & getDescriptorSet() const
bool initDepthBuffers(const std::vector< API::ImageView > &imageViews) override final
static uint32_t _forwardCount
void setFlags(VkFenceCreateFlags flags)
std::vector< FrameData > _framesData
static const API::GraphicsPipeline & getPipeline()
const API::Queue * getQueue(const std::string &queueName) const
bool init(const std::vector< API::ImageView > &imageViews) override final
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
Resource::SharedPtr< Render::Pipeline > getPipeline(Render::Pipeline::Id id)
API::CommandPool _graphicsCommandPool
void setLevel(VkCommandBufferLevel level)
Dummy class for a shared pointer.
const std::map< Render::Pipeline::Id, std::vector< PrimitiveSetInstance > > getPrimitiveSets() const
std::vector< const DescriptorSetPool::DescriptorSet * > materialTexturesDescriptorSets
const DescriptorSetPool::DescriptorSet * skyBoxDescriptorSet
std::vector< const DescriptorSetPool::DescriptorSet * > materialDescriptorSets
const API::Queue * _transferQueue
void beginRenderPass(const API::RenderPass &renderPass, const CmdBeginRenderPass ¶meters, VkSubpassContents contents=VK_SUBPASS_CONTENTS_INLINE) const
const Scissor & getScissor() const
static std::unique_ptr< DescriptorSetPool::MaterialTextures > _materialTexturesDescriptorSetPool
const QueueFamily * getQueueFamily() const
std::vector< const BufferPool::SubBuffer * > lightBuffers
void setUsage(VkImageUsageFlags usage)
API::Framebuffer framebuffer
struct lug::Graphics::Render::View::Scissor::@3 extent
API::DeviceMemory _depthBufferMemory
bool initFramebuffers(const std::vector< API::ImageView > &imageViews) override final
void setFormat(VkFormat format)
API::CommandBuffer transferCmdBuffer
const Viewport & getViewport() const
const std::vector< Mesh::PrimitiveSet > & getPrimitiveSets() const
static SharedPtr< T > cast(const SharedPtr< RhsT > &rhs)
Dynamic casting of a SharedPtr to another one (RhsT to T)
static std::unique_ptr< DescriptorSetPool::Material > _materialDescriptorSetPool
static const lug::Graphics::Resource::SharedPtr< lug::Graphics::Render::Mesh > getMesh()
static std::unique_ptr< BufferPool::Light > _lightBufferPool
void setMemoryFlags(VkMemoryPropertyFlags flags)
API::Device & getDevice()
const DescriptorSetPool::DescriptorSet * cameraDescriptorSet
const API::Queue * _graphicsQueue
static std::unique_ptr< DescriptorSetPool::SkyBox > _skyBoxDescriptorSetPool
const Resource::SharedPtr< Render::SkyBox > getSkyBox() const
const PipelineLayout * getLayout() const
static const lug::Graphics::Resource::SharedPtr< lug::Graphics::Render::Texture > getBrdfLut()
API::CommandBuffer renderCmdBuffer
const Math::Vec3f & getClearColor() const
API::CommandPool _transferCommandPool
void setRenderPass(const API::RenderPass *renderPass)
static std::unique_ptr< BufferPool::Camera > _cameraBufferPool
void pushConstants(const CmdPushConstants ¶meters) const
std::vector< const BufferPool::SubBuffer * > materialBuffers
static std::unique_ptr< DescriptorSetPool::Camera > _cameraDescriptorSetPool
std::size_t getLightsCount() const
bool begin(VkCommandBufferUsageFlags flags=VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) const
void destroy() override final
Forward(Renderer &renderer, const View &renderView)
static std::unique_ptr< DescriptorSetPool::Light > _lightDescriptorSetPool