]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/pipelinecache.cpp
Annotate uniforms with descriptor set layout qualifiers
[libs/gl.git] / source / backends / vulkan / pipelinecache.cpp
1 #include <msp/core/hash.h>
2 #include "blend.h"
3 #include "depthtest.h"
4 #include "device.h"
5 #include "framebuffer.h"
6 #include "pipelinecache.h"
7 #include "pipelinestate.h"
8 #include "stenciltest.h"
9 #include "vulkan.h"
10
11 using namespace std;
12
13 namespace Msp {
14 namespace GL {
15
16 PipelineCache::PipelineCache(Device &d):
17         device(d)
18 { }
19
20 PipelineCache::~PipelineCache()
21 {
22         const VulkanFunctions &vk = device.get_functions();
23
24         for(const auto &kvp: render_passes)
25                 vk.DestroyRenderPass(kvp.second);
26         for(const auto &kvp: pipelines)
27                 vk.DestroyPipeline(kvp.second);
28 }
29
30 VkRenderPass PipelineCache::get_render_pass(const FrameFormat &format, bool clear, bool discard, bool to_present)
31 {
32         const VulkanFunctions &vk = device.get_functions();
33
34         uint64_t key = hash<64>(static_cast<uint8_t>(clear | (discard*2) | (to_present*4)));
35         for(FrameAttachment a: format)
36                 key = hash_update<64>(key, a);
37
38         auto j = render_passes.find(key);
39         if(j!=render_passes.end())
40                 return j->second;
41
42         VkAttachmentDescription attachments[FrameFormat::MAX_ATTACHMENTS] = { };
43         VkAttachmentReference color_refs[FrameFormat::MAX_ATTACHMENTS] = { };
44         VkAttachmentReference depth_stencil_ref = { };
45         depth_stencil_ref.attachment = VK_ATTACHMENT_UNUSED;
46
47         VkSampleCountFlagBits vk_samples = static_cast<VkSampleCountFlagBits>(get_vulkan_samples(format.get_samples()));
48
49         unsigned i = 0;
50         unsigned color_count = 0;
51         for(FrameAttachment a: format)
52         {
53                 VkImageLayout subpass_layout = static_cast<VkImageLayout>(get_vulkan_attachment_layout(get_components(get_attachment_pixelformat(a))));
54                 VkImageLayout external_layout = (to_present ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : subpass_layout);
55
56                 attachments[i].format = static_cast<VkFormat>(get_vulkan_pixelformat(get_attachment_pixelformat(a)));
57                 attachments[i].samples = vk_samples;
58                 attachments[i].loadOp = (clear ? discard ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
59                 attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
60                 attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
61                 attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
62                 attachments[i].initialLayout = ((clear && discard) ? VK_IMAGE_LAYOUT_UNDEFINED : external_layout);
63                 attachments[i].finalLayout = external_layout;
64
65                 if(subpass_layout==VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
66                 {
67                         color_refs[color_count].attachment = i;
68                         color_refs[color_count].layout = subpass_layout;
69                         ++color_count;
70                 }
71                 else
72                 {
73                         depth_stencil_ref.attachment = i;
74                         depth_stencil_ref.layout = subpass_layout;
75                 }
76
77                 ++i;
78         }
79
80         VkSubpassDescription subpass = { };
81         subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
82         subpass.colorAttachmentCount = color_count;
83         subpass.pColorAttachments = color_refs;
84         subpass.pDepthStencilAttachment = &depth_stencil_ref;
85
86         VkSubpassDependency dependency = { };
87         VkRenderPassCreateInfo render_pass_info = { };
88         render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
89         render_pass_info.attachmentCount = format.size();
90         render_pass_info.pAttachments = attachments;
91         render_pass_info.subpassCount = 1;
92         render_pass_info.pSubpasses = &subpass;
93
94         if(to_present)
95         {
96                 dependency.srcSubpass = 0;
97                 dependency.dstSubpass = VK_SUBPASS_EXTERNAL;
98                 dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
99                 dependency.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
100                 dependency.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
101                 dependency.dstAccessMask = 0;
102
103                 render_pass_info.dependencyCount = 1;
104                 render_pass_info.pDependencies = &dependency;
105         }
106
107         VkRenderPass render_pass;
108         vk.CreateRenderPass(render_pass_info, render_pass);
109
110         render_passes.insert(make_pair(key, render_pass));
111
112         return render_pass;
113 }
114
115 VkPipeline PipelineCache::get_pipeline(const PipelineState &ps)
116 {
117         const VulkanFunctions &vk = device.get_functions();
118
119         uint64_t key = ps.compute_hash();
120         auto i = pipelines.find(key);
121         if(i!=pipelines.end())
122                 return i->second;
123
124         vector<char> buffer;
125         ps.fill_creation_info(buffer);
126         const VkGraphicsPipelineCreateInfo *creation_info = reinterpret_cast<const VkGraphicsPipelineCreateInfo *>(buffer.data());
127
128         VkPipeline pipeline;
129         vk.CreateGraphicsPipelines(0, 1, creation_info, &pipeline);
130
131         pipelines.insert(make_pair(key, pipeline));
132
133         return pipeline;
134 }
135
136 } // namespace GL
137 } // namespace Msp