]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/framebuffer_backend.cpp
9af8a2f7b1a7a9e52464d6d0027da801bee96700
[libs/gl.git] / source / backends / vulkan / framebuffer_backend.cpp
1 #include <msp/strings/format.h>
2 #include "device.h"
3 #include "framebuffer.h"
4 #include "framebuffer_backend.h"
5 #include "renderpass.h"
6 #include "vulkan.h"
7
8 using namespace std;
9
10 namespace Msp {
11 namespace GL {
12
13 VulkanFramebuffer::VulkanFramebuffer(bool):
14         device(Device::get_current())
15 { }
16
17 VulkanFramebuffer::VulkanFramebuffer(VulkanFramebuffer &&other):
18         device(other.device),
19         handle(other.handle),
20         debug_name(move(other.debug_name))
21 {
22         other.handle = 0;
23 }
24
25 VulkanFramebuffer::~VulkanFramebuffer()
26 {
27         DestroyQueue &dq = device.get_destroy_queue();
28         if(handle)
29                 dq.destroy(handle);
30         for(VkImageView h: view_handles)
31                 if(h)
32                         dq.destroy(h);
33 }
34
35 bool VulkanFramebuffer::is_format_supported(const FrameFormat &fmt)
36 {
37         const VulkanFunctions &vk = device.get_functions();
38         for(FrameAttachment a: fmt)
39         {
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)
45                 {
46                         if(!(props.optimalTilingFeatures&VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
47                                 return false;
48                 }
49                 else if(!(props.optimalTilingFeatures&VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT))
50                         return false;
51         }
52
53         return true;
54 }
55
56 void VulkanFramebuffer::update(unsigned mask) const
57 {
58         const Framebuffer &self = *static_cast<const Framebuffer *>(this);
59         const VulkanFunctions &vk = device.get_functions();
60
61         if(self.attachments.size()>view_handles.size())
62                 view_handles.resize(self.attachments.size());
63
64         if(handle)
65                 device.get_destroy_queue().destroy(handle);
66
67         VkImageView vk_attachments[FrameFormat::MAX_ATTACHMENTS*2] = { };
68         unsigned i = 0;
69         bool any_resolve = false;
70         for(const Framebuffer::Attachment &a: self.attachments)
71         {
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));
73
74                 if(mask&(1<<i))
75                 {
76                         if(use_tex_view)
77                                 a.tex->refresh_mip_views();
78                         else
79                         {
80                                 if(view_handles[i])
81                                         device.get_destroy_queue().destroy(view_handles[i]);
82
83                                 PixelFormat tex_format = a.tex->get_format();
84
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));
90
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;
95
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);
101
102                                 vk.CreateImageView(view_info, view_handles[i]);
103                         }
104                 }
105
106                 if(use_tex_view)
107                         vk_attachments[i] = a.tex->mip_view_handles[a.level];
108                 else if(view_handles[i])
109                         vk_attachments[i] = view_handles[i];
110                 else
111                         throw logic_error("unexpected framebuffer configuration");
112
113                 if(a.resolve)
114                 {
115                         a.resolve->refresh_mip_views();
116                         vk_attachments[self.format.size()+i] = a.resolve->mip_view_handles[0];
117                         any_resolve = true;
118                 }
119
120                 ++i;
121         }
122
123         RenderPass render_pass;
124         render_pass.framebuffer = &self;
125         render_pass.update(device);
126
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;
135
136         vk.CreateFramebuffer(framebuffer_info, handle);
137
138         if(!debug_name.empty())
139                 set_vulkan_object_name();
140 }
141
142 void VulkanFramebuffer::prepare_image_layouts(bool discard) const
143 {
144         for(const Framebuffer::Attachment &a: static_cast<const Framebuffer *>(this)->attachments)
145         {
146                 a.tex->change_layout(a.level, get_vulkan_attachment_layout(get_components(a.tex->get_format())), (discard && a.layer<0));
147                 if(a.resolve)
148                         a.resolve->change_layout(a.level, get_vulkan_attachment_layout(get_components(a.resolve->get_format())), discard);
149         }
150 }
151
152 void VulkanFramebuffer::set_debug_name(const string &name)
153 {
154 #ifdef DEBUG
155         debug_name = name;
156         if(handle)
157                 set_vulkan_object_name();
158 #else
159         (void)name;
160 #endif
161 }
162
163 void VulkanFramebuffer::set_vulkan_object_name() const
164 {
165 #ifdef DEBUG
166         const VulkanFunctions &vk = device.get_functions();
167
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);
174 #endif
175 }
176
177 } // namespace GL
178 } // namespace Msp