]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/framebuffer_backend.cpp
Create image views in VulkanFramebuffer if necessary
[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 "vulkan.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace GL {
11
12 VulkanFramebuffer::VulkanFramebuffer(bool):
13         device(Device::get_current())
14 { }
15
16 VulkanFramebuffer::VulkanFramebuffer(VulkanFramebuffer &&other):
17         device(other.device),
18         handle(other.handle),
19         debug_name(move(other.debug_name))
20 {
21         other.handle = 0;
22 }
23
24 VulkanFramebuffer::~VulkanFramebuffer()
25 {
26         DestroyQueue &dq = device.get_destroy_queue();
27         if(handle)
28                 dq.destroy(handle);
29         for(VkImageView h: view_handles)
30                 if(h)
31                         dq.destroy(h);
32 }
33
34 bool VulkanFramebuffer::is_format_supported(const FrameFormat &fmt)
35 {
36         const VulkanFunctions &vk = device.get_functions();
37         for(FrameAttachment a: fmt)
38         {
39                 PixelFormat pf = get_attachment_pixelformat(a);
40                 PixelComponents comp = get_components(pf);
41                 VkFormatProperties props;
42                 vk.GetPhysicalDeviceFormatProperties(static_cast<VkFormat>(get_vulkan_pixelformat(pf)), props);
43                 if(comp==DEPTH_COMPONENT || comp==STENCIL_INDEX)
44                 {
45                         if(!(props.optimalTilingFeatures&VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
46                                 return false;
47                 }
48                 else if(!(props.optimalTilingFeatures&VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT))
49                         return false;
50         }
51
52         return true;
53 }
54
55 void VulkanFramebuffer::update(unsigned mask) const
56 {
57         const Framebuffer &self = *static_cast<const Framebuffer *>(this);
58         const VulkanFunctions &vk = device.get_functions();
59
60         if(self.attachments.size()>view_handles.size())
61                 view_handles.resize(self.attachments.size());
62
63         if(handle)
64                 device.get_destroy_queue().destroy(handle);
65
66         VkImageView vk_attachments[FrameFormat::MAX_ATTACHMENTS] = { };
67         unsigned i = 0;
68         for(const Framebuffer::Attachment &a: self.attachments)
69         {
70                 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));
71
72                 if(mask&(1<<i))
73                 {
74                         if(use_tex_view)
75                                 a.tex->refresh_mip_views();
76                         else
77                         {
78                                 if(view_handles[i])
79                                         device.get_destroy_queue().destroy(view_handles[i]);
80
81                                 PixelFormat tex_format = a.tex->get_format();
82
83                                 VkImageViewCreateInfo view_info = { };
84                                 view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
85                                 view_info.image = handle_cast<::VkImage>(a.tex->handle);
86                                 view_info.viewType = (a.layer<0 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D);
87                                 view_info.format = static_cast<VkFormat>(get_vulkan_pixelformat(tex_format));
88
89                                 view_info.components.r = VK_COMPONENT_SWIZZLE_R;
90                                 view_info.components.g = VK_COMPONENT_SWIZZLE_G;
91                                 view_info.components.b = VK_COMPONENT_SWIZZLE_B;
92                                 view_info.components.a = VK_COMPONENT_SWIZZLE_A;
93
94                                 view_info.subresourceRange.aspectMask = get_vulkan_aspect(get_components(tex_format));
95                                 view_info.subresourceRange.baseMipLevel = a.level;
96                                 view_info.subresourceRange.levelCount = 1;
97                                 view_info.subresourceRange.baseArrayLayer = max(a.layer, 0);
98                                 view_info.subresourceRange.layerCount = (a.layer<0 ? VK_REMAINING_ARRAY_LAYERS : 1);
99
100                                 vk.CreateImageView(view_info, view_handles[i]);
101                         }
102                 }
103
104                 if(use_tex_view)
105                         vk_attachments[i] = a.tex->mip_view_handles[a.level];
106                 else if(view_handles[i])
107                         vk_attachments[i] = view_handles[i];
108                 else
109                         throw logic_error("unexpected framebuffer configuration");
110
111                 ++i;
112         }
113
114         VkRenderPass render_pass = device.get_pipeline_cache().get_render_pass(self.format, false, false, false);
115
116         VkFramebufferCreateInfo framebuffer_info = { };
117         framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
118         framebuffer_info.renderPass = handle_cast<::VkRenderPass>(render_pass);
119         framebuffer_info.attachmentCount = self.format.size();
120         framebuffer_info.pAttachments = handle_cast<::VkImageView *>(vk_attachments);
121         framebuffer_info.width = self.width;
122         framebuffer_info.height = self.height;
123         framebuffer_info.layers = self.layers;
124
125         vk.CreateFramebuffer(framebuffer_info, handle);
126
127         if(!debug_name.empty())
128                 set_vulkan_object_name();
129 }
130
131 void VulkanFramebuffer::prepare_image_layouts(bool discard) const
132 {
133         for(const Framebuffer::Attachment &a: static_cast<const Framebuffer *>(this)->attachments)
134                 a.tex->change_layout(a.level, get_vulkan_attachment_layout(get_components(a.tex->get_format())), discard);
135 }
136
137 void VulkanFramebuffer::set_debug_name(const string &name)
138 {
139 #ifdef DEBUG
140         debug_name = name;
141         if(handle)
142                 set_vulkan_object_name();
143 #else
144         (void)name;
145 #endif
146 }
147
148 void VulkanFramebuffer::set_vulkan_object_name() const
149 {
150 #ifdef DEBUG
151         const VulkanFunctions &vk = device.get_functions();
152
153         VkDebugUtilsObjectNameInfoEXT name_info = { };
154         name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
155         name_info.objectType = VK_OBJECT_TYPE_FRAMEBUFFER;
156         name_info.objectHandle = reinterpret_cast<uint64_t>(handle);
157         name_info.pObjectName = debug_name.c_str();
158         vk.SetDebugUtilsObjectName(name_info);
159 #endif
160 }
161
162 } // namespace GL
163 } // namespace Msp