/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * 0 A.D. is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 0 A.D. If not, see . */ #include "precompiled.h" #include "Framebuffer.h" #include "renderer/backend/vulkan/Device.h" #include "renderer/backend/vulkan/Mapping.h" #include "renderer/backend/vulkan/RenderPassManager.h" #include "renderer/backend/vulkan/Texture.h" #include "renderer/backend/vulkan/Utilities.h" namespace Renderer { namespace Backend { namespace Vulkan { // static std::unique_ptr CFramebuffer::Create( CDevice* device, const char* name, SColorAttachment* colorAttachment, SDepthStencilAttachment* depthStencilAttachment) { ENSURE(colorAttachment || depthStencilAttachment); if (colorAttachment) ENSURE(colorAttachment->texture); if (depthStencilAttachment) ENSURE(depthStencilAttachment->texture); if (colorAttachment && depthStencilAttachment) { CTexture* colorAttachmentTexture = colorAttachment->texture->As(); CTexture* depthStencilAttachmentTexture = depthStencilAttachment->texture->As(); ENSURE( colorAttachmentTexture->GetWidth() == depthStencilAttachmentTexture->GetWidth() && colorAttachmentTexture->GetHeight() == depthStencilAttachmentTexture->GetHeight() && colorAttachmentTexture->GetSampleCount() == depthStencilAttachmentTexture->GetSampleCount()); } std::unique_ptr framebuffer(new CFramebuffer()); framebuffer->m_Device = device; framebuffer->m_UID = device->GenerateNextDeviceObjectUID(); if (colorAttachment) framebuffer->m_ClearColor = colorAttachment->clearColor; PS::StaticVector attachments; if (colorAttachment) { CTexture* colorAttachmentTexture = colorAttachment->texture->As(); ENSURE(colorAttachmentTexture->GetUsage() & ITexture::Usage::COLOR_ATTACHMENT); framebuffer->m_Width = colorAttachmentTexture->GetWidth(); framebuffer->m_Height = colorAttachmentTexture->GetHeight(); framebuffer->m_SampleCount = colorAttachmentTexture->GetSampleCount(); framebuffer->m_ColorAttachmentLoadOp = colorAttachment->loadOp; framebuffer->m_ColorAttachmentStoreOp = colorAttachment->storeOp; attachments.emplace_back(colorAttachmentTexture->GetAttachmentImageView()); framebuffer->m_ColorAttachments.emplace_back(colorAttachmentTexture); } if (depthStencilAttachment) { CTexture* depthStencilAttachmentTexture = depthStencilAttachment->texture->As(); ENSURE(depthStencilAttachmentTexture->GetUsage() & ITexture::Usage::DEPTH_STENCIL_ATTACHMENT); framebuffer->m_Width = depthStencilAttachmentTexture->GetWidth(); framebuffer->m_Height = depthStencilAttachmentTexture->GetHeight(); framebuffer->m_SampleCount = depthStencilAttachmentTexture->GetSampleCount(); framebuffer->m_DepthStencilAttachmentLoadOp = depthStencilAttachment->loadOp; framebuffer->m_DepthStencilAttachmentStoreOp = depthStencilAttachment->storeOp; attachments.emplace_back(depthStencilAttachmentTexture->GetAttachmentImageView()); framebuffer->m_DepthStencilAttachment = depthStencilAttachmentTexture; } ENSURE(framebuffer->m_Width > 0 && framebuffer->m_Height > 0); ENSURE(framebuffer->m_SampleCount > 0); framebuffer->m_RenderPass = device->GetRenderPassManager().GetOrCreateRenderPass( colorAttachment, depthStencilAttachment); VkFramebufferCreateInfo framebufferInfo{}; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebufferInfo.renderPass = framebuffer->m_RenderPass; framebufferInfo.attachmentCount = attachments.size(); framebufferInfo.pAttachments = attachments.data(); framebufferInfo.width = framebuffer->m_Width; framebufferInfo.height = framebuffer->m_Height; framebufferInfo.layers = 1; ENSURE_VK_SUCCESS(vkCreateFramebuffer( device->GetVkDevice(), &framebufferInfo, nullptr, &framebuffer->m_Framebuffer)); device->SetObjectName(VK_OBJECT_TYPE_FRAMEBUFFER, framebuffer->m_Framebuffer, name); return framebuffer; } CFramebuffer::~CFramebuffer() { if (m_Framebuffer != VK_NULL_HANDLE) m_Device->ScheduleObjectToDestroy( VK_OBJECT_TYPE_FRAMEBUFFER, m_Framebuffer, VK_NULL_HANDLE); } IDevice* CFramebuffer::GetDevice() { return m_Device; } } // namespace Vulkan } // namespace Backend } // namespace Renderer