]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/framebuffer_backend.cpp
Some adjustments to includes
[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] = { };
68         unsigned i = 0;
69         for(const Framebuffer::Attachment &a: self.attachments)
70         {
71                 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));
72
73                 if(mask&(1<<i))
74                 {
75                         if(use_tex_view)
76                                 a.tex->refresh_mip_views();
77                         else
78                         {
79                                 if(view_handles[i])
80                                         device.get_destroy_queue().destroy(view_handles[i]);
81
82                                 PixelFormat tex_format = a.tex->get_format();
83
84                                 VkImageViewCreateInfo view_info = { };
85                                 view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
86                                 view_info.image = handle_cast<::VkImage>(a.tex->handle);
87                                 view_info.viewType = (a.layer<0 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D);
88                                 view_info.format = static_cast<VkFormat>(get_vulkan_pixelformat(tex_format));
89
90                                 view_info.components.r = VK_COMPONENT_SWIZZLE_R;
91                                 view_info.components.g = VK_COMPONENT_SWIZZLE_G;
92                                 view_info.components.b = VK_COMPONENT_SWIZZLE_B;
93                                 view_info.components.a = VK_COMPONENT_SWIZZLE_A;
94
95                                 view_info.subresourceRange.aspectMask = get_vulkan_aspect(get_components(tex_format));
96                                 view_info.subresourceRange.baseMipLevel = a.level;
97                                 view_info.subresourceRange.levelCount = 1;
98                                 view_info.subresourceRange.baseArrayLayer = max(a.layer, 0);
99                                 view_info.subresourceRange.layerCount = (a.layer<0 ? VK_REMAINING_ARRAY_LAYERS : 1);
100
101                                 vk.CreateImageView(view_info, view_handles[i]);
102                         }
103                 }
104
105                 if(use_tex_view)
106                         vk_attachments[i] = a.tex->mip_view_handles[a.level];
107                 else if(view_handles[i])
108                         vk_attachments[i] = view_handles[i];
109                 else
110                         throw logic_error("unexpected framebuffer configuration");
111
112                 ++i;
113         }
114
115         RenderPass render_pass;
116         render_pass.framebuffer = &self;
117         render_pass.update(device);
118
119         VkFramebufferCreateInfo framebuffer_info = { };
120         framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
121         framebuffer_info.renderPass = handle_cast<::VkRenderPass>(render_pass.handle);
122         framebuffer_info.attachmentCount = self.format.size();
123         framebuffer_info.pAttachments = handle_cast<::VkImageView *>(vk_attachments);
124         framebuffer_info.width = self.width;
125         framebuffer_info.height = self.height;
126         framebuffer_info.layers = self.layers;
127
128         vk.CreateFramebuffer(framebuffer_info, handle);
129
130         if(!debug_name.empty())
131                 set_vulkan_object_name();
132 }
133
134 void VulkanFramebuffer::prepare_image_layouts(bool discard) const
135 {
136         for(const Framebuffer::Attachment &a: static_cast<const Framebuffer *>(this)->attachments)
137                 a.tex->change_layout(a.level, get_vulkan_attachment_layout(get_components(a.tex->get_format())), (discard && a.layer<0));
138 }
139
140 void VulkanFramebuffer::set_debug_name(const string &name)
141 {
142 #ifdef DEBUG
143         debug_name = name;
144         if(handle)
145                 set_vulkan_object_name();
146 #else
147         (void)name;
148 #endif
149 }
150
151 void VulkanFramebuffer::set_vulkan_object_name() const
152 {
153 #ifdef DEBUG
154         const VulkanFunctions &vk = device.get_functions();
155
156         VkDebugUtilsObjectNameInfoEXT name_info = { };
157         name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
158         name_info.objectType = VK_OBJECT_TYPE_FRAMEBUFFER;
159         name_info.objectHandle = reinterpret_cast<uint64_t>(handle);
160         name_info.pObjectName = debug_name.c_str();
161         vk.SetDebugUtilsObjectName(name_info);
162 #endif
163 }
164
165 } // namespace GL
166 } // namespace Msp