1 #include <msp/strings/format.h>
3 #include "framebuffer.h"
4 #include "framebuffer_backend.h"
5 #include "renderpass.h"
13 VulkanFramebuffer::VulkanFramebuffer(bool):
14 device(Device::get_current())
17 VulkanFramebuffer::VulkanFramebuffer(VulkanFramebuffer &&other):
20 debug_name(move(other.debug_name))
25 VulkanFramebuffer::~VulkanFramebuffer()
27 DestroyQueue &dq = device.get_destroy_queue();
30 for(VkImageView h: view_handles)
35 bool VulkanFramebuffer::is_format_supported(const FrameFormat &fmt)
37 const VulkanFunctions &vk = device.get_functions();
38 for(FrameAttachment a: fmt)
40 PixelFormat pf = get_attachment_pixelformat(a);
41 PixelComponents comp = get_components(pf);
42 VkFormatProperties props;
43 vk.GetPhysicalDeviceFormatProperties(static_cast<VkFormat>(get_vulkan_pixelformat(pf)), props);
44 if(comp==DEPTH_COMPONENT || comp==STENCIL_INDEX)
46 if(!(props.optimalTilingFeatures&VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
49 else if(!(props.optimalTilingFeatures&VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT))
56 void VulkanFramebuffer::update(unsigned mask) const
58 const Framebuffer &self = *static_cast<const Framebuffer *>(this);
59 const VulkanFunctions &vk = device.get_functions();
61 if(self.attachments.size()>view_handles.size())
62 view_handles.resize(self.attachments.size());
65 device.get_destroy_queue().destroy(handle);
67 VkImageView vk_attachments[FrameFormat::MAX_ATTACHMENTS*2] = { };
69 bool any_resolve = false;
70 for(const Framebuffer::Attachment &a: self.attachments)
72 bool use_tex_view = (a.tex->view_type==VK_IMAGE_VIEW_TYPE_2D || (a.tex->view_type==VK_IMAGE_VIEW_TYPE_2D_ARRAY && a.layer<0));
77 a.tex->refresh_mip_views();
81 device.get_destroy_queue().destroy(view_handles[i]);
83 PixelFormat tex_format = a.tex->get_format();
85 VkImageViewCreateInfo view_info = { };
86 view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
87 view_info.image = handle_cast<::VkImage>(a.tex->handle);
88 view_info.viewType = (a.layer<0 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D);
89 view_info.format = static_cast<VkFormat>(get_vulkan_pixelformat(tex_format));
91 view_info.components.r = VK_COMPONENT_SWIZZLE_R;
92 view_info.components.g = VK_COMPONENT_SWIZZLE_G;
93 view_info.components.b = VK_COMPONENT_SWIZZLE_B;
94 view_info.components.a = VK_COMPONENT_SWIZZLE_A;
96 view_info.subresourceRange.aspectMask = get_vulkan_aspect(get_components(tex_format));
97 view_info.subresourceRange.baseMipLevel = a.level;
98 view_info.subresourceRange.levelCount = 1;
99 view_info.subresourceRange.baseArrayLayer = max(a.layer, 0);
100 view_info.subresourceRange.layerCount = (a.layer<0 ? VK_REMAINING_ARRAY_LAYERS : 1);
102 vk.CreateImageView(view_info, view_handles[i]);
107 vk_attachments[i] = a.tex->mip_view_handles[a.level];
108 else if(view_handles[i])
109 vk_attachments[i] = view_handles[i];
111 throw logic_error("unexpected framebuffer configuration");
115 a.resolve->refresh_mip_views();
116 vk_attachments[self.format.size()+i] = a.resolve->mip_view_handles[0];
123 RenderPass render_pass;
124 render_pass.framebuffer = &self;
125 render_pass.update(device);
127 VkFramebufferCreateInfo framebuffer_info = { };
128 framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
129 framebuffer_info.renderPass = handle_cast<::VkRenderPass>(render_pass.handle);
130 framebuffer_info.attachmentCount = self.format.size()*(1+any_resolve);
131 framebuffer_info.pAttachments = handle_cast<::VkImageView *>(vk_attachments);
132 framebuffer_info.width = self.width;
133 framebuffer_info.height = self.height;
134 framebuffer_info.layers = self.layers;
136 vk.CreateFramebuffer(framebuffer_info, handle);
138 if(!debug_name.empty())
139 set_vulkan_object_name();
142 void VulkanFramebuffer::prepare_image_layouts(bool discard) const
144 for(const Framebuffer::Attachment &a: static_cast<const Framebuffer *>(this)->attachments)
146 a.tex->change_layout(a.level, get_vulkan_attachment_layout(get_components(a.tex->get_format())), (discard && a.layer<0));
148 a.resolve->change_layout(a.level, get_vulkan_attachment_layout(get_components(a.resolve->get_format())), discard);
152 void VulkanFramebuffer::set_debug_name(const string &name)
157 set_vulkan_object_name();
163 void VulkanFramebuffer::set_vulkan_object_name() const
166 const VulkanFunctions &vk = device.get_functions();
168 VkDebugUtilsObjectNameInfoEXT name_info = { };
169 name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
170 name_info.objectType = VK_OBJECT_TYPE_FRAMEBUFFER;
171 name_info.objectHandle = reinterpret_cast<uint64_t>(handle);
172 name_info.pObjectName = debug_name.c_str();
173 vk.SetDebugUtilsObjectName(name_info);