]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/renderpass.cpp
fb2389e5c8736d9078bba13a18748fb996e65a2d
[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         bool discard = (!clear_values && discard_fb_contents);
24         uint64_t result = hash<64>(static_cast<uint8_t>(clear | (discard*2) | (to_present*4)));
25         for(FrameAttachment a: framebuffer->get_format())
26                 result = hash_update<64>(result, a);
27
28         return result;
29 }
30
31 void RenderPass::fill_creation_info(vector<char> &buffer) const
32 {
33         const FrameFormat &format = framebuffer->get_format();
34
35         bool discard = (!clear_values && discard_fb_contents);
36         bool has_depth = any_of(format.begin(), format.end(), [](FrameAttachment a){
37                 return get_components(get_attachment_pixelformat(a))==DEPTH_COMPONENT;
38         });
39         unsigned color_count = format.size()-has_depth;
40
41         StructureBuilder sb(buffer, 6);
42         VkRenderPassCreateInfo *const &render_pass_info = sb.add<VkRenderPassCreateInfo>();
43         VkSubpassDescription *const &subpass = sb.add<VkSubpassDescription>();
44         VkAttachmentDescription *const &attachments = sb.add<VkAttachmentDescription>(format.size());
45         VkAttachmentReference *const &color_refs = sb.add<VkAttachmentReference>(color_count);
46         VkAttachmentReference *const &depth_stencil_ref = sb.add<VkAttachmentReference>(has_depth);
47         VkSubpassDependency *const &dependency = sb.add<VkSubpassDependency>(to_present);
48
49         VkSampleCountFlagBits vk_samples = static_cast<VkSampleCountFlagBits>(get_vulkan_samples(format.get_samples()));
50
51         VkAttachmentReference *color_ptr = color_refs;
52         unsigned i = 0;
53         for(FrameAttachment a: format)
54         {
55                 VkImageLayout subpass_layout = static_cast<VkImageLayout>(get_vulkan_attachment_layout(get_components(get_attachment_pixelformat(a))));
56                 VkImageLayout external_layout = (to_present ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : subpass_layout);
57
58                 attachments[i].format = static_cast<VkFormat>(get_vulkan_pixelformat(get_attachment_pixelformat(a)));
59                 attachments[i].samples = vk_samples;
60                 attachments[i].loadOp = (clear ? discard ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
61                 attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
62                 attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
63                 attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
64                 attachments[i].initialLayout = ((clear && discard) ? VK_IMAGE_LAYOUT_UNDEFINED : external_layout);
65                 attachments[i].finalLayout = external_layout;
66
67                 if(subpass_layout==VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
68                 {
69                         color_ptr->attachment = i;
70                         color_ptr->layout = subpass_layout;
71                         ++color_ptr;
72                 }
73                 else
74                 {
75                         depth_stencil_ref->attachment = i;
76                         depth_stencil_ref->layout = subpass_layout;
77                 }
78
79                 ++i;
80         }
81
82         subpass->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
83         subpass->colorAttachmentCount = color_count;
84         if(color_count)
85                 subpass->pColorAttachments = color_refs;
86         if(has_depth)
87                 subpass->pDepthStencilAttachment = depth_stencil_ref;
88
89         render_pass_info->sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
90         render_pass_info->attachmentCount = format.size();
91         render_pass_info->pAttachments = attachments;
92         render_pass_info->subpassCount = 1;
93         render_pass_info->pSubpasses = subpass;
94
95         if(to_present)
96         {
97                 dependency->srcSubpass = 0;
98                 dependency->dstSubpass = VK_SUBPASS_EXTERNAL;
99                 dependency->srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
100                 dependency->srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
101                 dependency->dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
102                 dependency->dstAccessMask = 0;
103
104                 render_pass_info->dependencyCount = 1;
105                 render_pass_info->pDependencies = dependency;
106         }
107 }
108
109 void RenderPass::fill_begin_info(vector<char> &buffer) const
110 {
111         const FrameFormat &format = framebuffer->get_format();
112
113         StructureBuilder sb(buffer, 2);
114         VkRenderPassBeginInfo *const &begin_info = sb.add<VkRenderPassBeginInfo>(1);
115         VkClearValue *const &vk_clear_values = sb.add<VkClearValue>(format.size());
116
117         begin_info->sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
118         begin_info->renderPass = handle_cast<::VkRenderPass>(handle);
119         begin_info->framebuffer = handle_cast<::VkFramebuffer>(framebuffer->handle);
120
121         begin_info->renderArea.offset.x = render_area.left;
122         begin_info->renderArea.offset.y = render_area.bottom;
123         begin_info->renderArea.extent.width = render_area.width;
124         begin_info->renderArea.extent.height = render_area.height;
125
126         if(clear_values)
127         {
128                 unsigned i = 0;
129                 for(FrameAttachment a: format)
130                 {
131                         if(get_attach_point(a)==get_attach_point(DEPTH_ATTACHMENT))
132                                 vk_clear_values[i].depthStencil.depth = clear_values[i].depth_stencil.depth;
133                         else if(get_attach_point(a)==get_attach_point(STENCIL_ATTACHMENT))
134                                 vk_clear_values[i].depthStencil.stencil = clear_values[i].depth_stencil.stencil;
135                         else
136                         {
137                                 vk_clear_values[i].color.float32[0] = clear_values[i].color.r;
138                                 vk_clear_values[i].color.float32[1] = clear_values[i].color.g;
139                                 vk_clear_values[i].color.float32[2] = clear_values[i].color.b;
140                                 vk_clear_values[i].color.float32[3] = clear_values[i].color.a;
141                         }
142                         ++i;
143                 }
144
145                 begin_info->clearValueCount = format.size();
146                 begin_info->pClearValues = vk_clear_values;
147         }
148 }
149
150 } // namespace GL
151 } // namespace Msp