]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/renderpass.cpp
Check the flat qualifier from the correct member
[libs/gl.git] / source / backends / vulkan / renderpass.cpp
1 #include <msp/core/hash.h>
2 #include "device.h"
3 #include "framebuffer.h"
4 #include "renderpass.h"
5 #include "structurebuilder.h"
6 #include "vulkan.h"
7
8 using namespace std;
9
10 namespace Msp {
11 namespace GL {
12
13 void RenderPass::update(Device &device)
14 {
15         Rect fb_rect = framebuffer->get_rect();
16         render_area = fb_rect.intersect(render_area);
17         discard_fb_contents = (clear && render_area==fb_rect);
18         handle = device.get_pipeline_cache().get_render_pass(*this);
19 }
20
21 uint64_t RenderPass::compute_hash() const
22 {
23         const FrameFormat &format = framebuffer->get_format();
24         bool discard = (clear && !clear_values && discard_fb_contents);
25         bool resolve = framebuffer->has_resolve_attachments();
26         uint64_t result = hash<64>(static_cast<uint8_t>(clear | (discard<<1) | (resolve<<2) | (to_present<<3)));
27         result = hash_round<64>(result, format.get_samples());
28         for(FrameAttachment a: framebuffer->get_format())
29                 result = hash_update<64>(result, a);
30
31         return result;
32 }
33
34 void RenderPass::fill_creation_info(vector<char> &buffer) const
35 {
36         const FrameFormat &format = framebuffer->get_format();
37
38         bool has_depth = any_of(format.begin(), format.end(), [](FrameAttachment a){
39                 return get_components(get_attachment_pixelformat(a))==DEPTH_COMPONENT;
40         });
41         unsigned color_count = format.size()-has_depth;
42         bool resolve = framebuffer->has_resolve_attachments();
43
44         StructureBuilder sb(buffer, 7);
45         VkRenderPassCreateInfo2 *const &render_pass_info = sb.add<VkRenderPassCreateInfo2>();
46         VkSubpassDescription2 *const &subpass = sb.add<VkSubpassDescription2>();
47         VkAttachmentDescription2 *const &attachments = sb.add<VkAttachmentDescription2>(format.size()*(1+resolve));
48         VkAttachmentReference2 *const &color_refs = sb.add<VkAttachmentReference2>(color_count*(1+resolve));
49         VkAttachmentReference2 *const &depth_stencil_ref = sb.add<VkAttachmentReference2>(has_depth*(1+resolve));
50         VkSubpassDescriptionDepthStencilResolve *const &depth_stencil_resolve = sb.add<VkSubpassDescriptionDepthStencilResolve>(has_depth && resolve);
51         VkSubpassDependency2 *const &dependency = sb.add<VkSubpassDependency2>(to_present);
52
53         VkAttachmentReference2 *color_ptr = color_refs;
54         VkAttachmentReference2 *ds_ptr = depth_stencil_ref;
55         unsigned i = 0;
56         auto fill_attachment = [=, &color_ptr, &ds_ptr, &i](FrameAttachment a, VkSampleCountFlagBits samples, bool discard){
57                 VkImageLayout subpass_layout = static_cast<VkImageLayout>(get_vulkan_attachment_layout(get_components(get_attachment_pixelformat(a))));
58                 VkImageLayout external_layout = (to_present ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : subpass_layout);
59
60                 attachments[i].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2;
61                 attachments[i].format = static_cast<VkFormat>(get_vulkan_pixelformat(get_attachment_pixelformat(a)));
62                 attachments[i].samples = samples;
63                 attachments[i].loadOp = (discard ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
64                 attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
65                 attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
66                 attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
67                 attachments[i].initialLayout = (discard ? VK_IMAGE_LAYOUT_UNDEFINED : external_layout);
68                 attachments[i].finalLayout = external_layout;
69
70                 if(subpass_layout==VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
71                 {
72                         color_ptr->sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
73                         color_ptr->attachment = i;
74                         color_ptr->layout = subpass_layout;
75                         ++color_ptr;
76                 }
77                 else
78                 {
79                         ds_ptr->sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
80                         ds_ptr->attachment = i;
81                         ds_ptr->layout = subpass_layout;
82                 }
83
84                 ++i;
85         };
86
87         bool discard = (clear && !clear_values && discard_fb_contents);
88         VkSampleCountFlagBits vk_samples = static_cast<VkSampleCountFlagBits>(get_vulkan_samples(format.get_samples()));
89         for(FrameAttachment a: format)
90                 fill_attachment(a, vk_samples, discard);
91
92         if(resolve)
93         {
94                 ++ds_ptr;
95                 for(FrameAttachment a: format)
96                         fill_attachment(a, VK_SAMPLE_COUNT_1_BIT, true);
97         }
98
99         subpass->sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2;
100         subpass->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
101         subpass->colorAttachmentCount = color_count;
102         if(color_count)
103                 subpass->pColorAttachments = color_refs;
104         if(has_depth)
105                 subpass->pDepthStencilAttachment = depth_stencil_ref;
106         if(resolve)
107         {
108                 subpass->pResolveAttachments = color_refs+color_count;
109
110                 if(has_depth)
111                 {
112                         depth_stencil_resolve->sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE;
113                         depth_stencil_resolve->depthResolveMode = VK_RESOLVE_MODE_MIN_BIT;
114                         depth_stencil_resolve->pDepthStencilResolveAttachment = depth_stencil_ref+1;
115                         subpass->pNext = depth_stencil_resolve;
116                 }
117         }
118
119         render_pass_info->sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2;
120         render_pass_info->attachmentCount = format.size()*(1+resolve);
121         render_pass_info->pAttachments = attachments;
122         render_pass_info->subpassCount = 1;
123         render_pass_info->pSubpasses = subpass;
124
125         if(to_present)
126         {
127                 dependency->sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2;
128                 dependency->srcSubpass = 0;
129                 dependency->dstSubpass = VK_SUBPASS_EXTERNAL;
130                 dependency->srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
131                 dependency->srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
132                 dependency->dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
133                 dependency->dstAccessMask = 0;
134
135                 render_pass_info->dependencyCount = 1;
136                 render_pass_info->pDependencies = dependency;
137         }
138 }
139
140 void RenderPass::fill_begin_info(vector<char> &buffer) const
141 {
142         const FrameFormat &format = framebuffer->get_format();
143
144         StructureBuilder sb(buffer, 2);
145         VkRenderPassBeginInfo *const &begin_info = sb.add<VkRenderPassBeginInfo>(1);
146         VkClearValue *const &vk_clear_values = sb.add<VkClearValue>(format.size());
147
148         begin_info->sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
149         begin_info->renderPass = handle_cast<::VkRenderPass>(handle);
150         begin_info->framebuffer = handle_cast<::VkFramebuffer>(framebuffer->handle);
151
152         begin_info->renderArea.offset.x = render_area.left;
153         begin_info->renderArea.offset.y = render_area.bottom;
154         begin_info->renderArea.extent.width = render_area.width;
155         begin_info->renderArea.extent.height = render_area.height;
156
157         if(clear_values)
158         {
159                 unsigned i = 0;
160                 for(FrameAttachment a: format)
161                 {
162                         if(get_attach_point(a)==get_attach_point(DEPTH_ATTACHMENT))
163                                 vk_clear_values[i].depthStencil.depth = clear_values[i].depth_stencil.depth;
164                         else if(get_attach_point(a)==get_attach_point(STENCIL_ATTACHMENT))
165                                 vk_clear_values[i].depthStencil.stencil = clear_values[i].depth_stencil.stencil;
166                         else
167                         {
168                                 vk_clear_values[i].color.float32[0] = clear_values[i].color.r;
169                                 vk_clear_values[i].color.float32[1] = clear_values[i].color.g;
170                                 vk_clear_values[i].color.float32[2] = clear_values[i].color.b;
171                                 vk_clear_values[i].color.float32[3] = clear_values[i].color.a;
172                         }
173                         ++i;
174                 }
175
176                 begin_info->clearValueCount = format.size();
177                 begin_info->pClearValues = vk_clear_values;
178         }
179 }
180
181 } // namespace GL
182 } // namespace Msp