]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/pipelinecache.cpp
Use PRESENT_SRC as the initial layout for swapchain images
[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         const VulkanFunctions &vk = device.get_functions();
20
21         VkDescriptorPoolSize pool_sizes[2] = { };
22         pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
23         pool_sizes[0].descriptorCount = 10000;
24         pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
25         pool_sizes[1].descriptorCount = 10000;
26
27         VkDescriptorPoolCreateInfo pool_info = { };
28         pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
29         pool_info.maxSets = 10000;
30         pool_info.poolSizeCount = 2;
31         pool_info.pPoolSizes = pool_sizes;
32
33         vk.CreateDescriptorPool(pool_info, descriptor_pool);
34 }
35
36 PipelineCache::~PipelineCache()
37 {
38         const VulkanFunctions &vk = device.get_functions();
39
40         for(const auto &kvp: render_passes)
41                 vk.DestroyRenderPass(kvp.second);
42         for(const auto &kvp: pipelines)
43                 vk.DestroyPipeline(kvp.second);
44         vk.DestroyDescriptorPool(descriptor_pool);
45 }
46
47 VkRenderPass PipelineCache::get_render_pass(const FrameFormat &format, bool clear, bool discard, bool to_present)
48 {
49         const VulkanFunctions &vk = device.get_functions();
50
51         uint64_t key = hash<64>(static_cast<uint8_t>(clear | (discard*2) | (to_present*4)));
52         for(FrameAttachment a: format)
53                 key = hash_update<64>(key, a);
54
55         auto j = render_passes.find(key);
56         if(j!=render_passes.end())
57                 return j->second;
58
59         VkAttachmentDescription attachments[FrameFormat::MAX_ATTACHMENTS] = { };
60         VkAttachmentReference color_refs[FrameFormat::MAX_ATTACHMENTS] = { };
61         VkAttachmentReference depth_stencil_ref = { };
62         depth_stencil_ref.attachment = VK_ATTACHMENT_UNUSED;
63
64         VkSampleCountFlagBits vk_samples = static_cast<VkSampleCountFlagBits>(get_vulkan_samples(format.get_samples()));
65         VkImageLayout default_layout = (to_present ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
66
67         unsigned i = 0;
68         unsigned color_count = 0;
69         for(FrameAttachment a: format)
70         {
71                 attachments[i].format = static_cast<VkFormat>(get_vulkan_pixelformat(get_attachment_pixelformat(a)));
72                 attachments[i].samples = vk_samples;
73                 attachments[i].loadOp = (clear ? discard ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
74                 attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
75                 attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
76                 attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
77                 attachments[i].initialLayout = (clear ? VK_IMAGE_LAYOUT_UNDEFINED : default_layout);
78                 attachments[i].finalLayout = default_layout;
79
80                 unsigned attach_pt = get_attach_point(a);
81                 if(attach_pt==get_attach_point(COLOR_ATTACHMENT))
82                 {
83                         color_refs[color_count].attachment = i;
84                         color_refs[color_count].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
85                         ++color_count;
86                 }
87                 else if(attach_pt==get_attach_point(DEPTH_ATTACHMENT))
88                 {
89                         depth_stencil_ref.attachment = i;
90                         depth_stencil_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
91                 }
92
93                 ++i;
94         }
95
96         VkSubpassDescription subpass = { };
97         subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
98         subpass.colorAttachmentCount = color_count;
99         subpass.pColorAttachments = color_refs;
100         subpass.pDepthStencilAttachment = &depth_stencil_ref;
101
102         VkRenderPassCreateInfo render_pass_info = { };
103         render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
104         render_pass_info.attachmentCount = format.size();
105         render_pass_info.pAttachments = attachments;
106         render_pass_info.subpassCount = 1;
107         render_pass_info.pSubpasses = &subpass;
108
109         VkRenderPass render_pass;
110         vk.CreateRenderPass(render_pass_info, render_pass);
111
112         render_passes.insert(make_pair(key, render_pass));
113
114         return render_pass;
115 }
116
117 VkPipeline PipelineCache::get_pipeline(const PipelineState &ps)
118 {
119         const VulkanFunctions &vk = device.get_functions();
120
121         uint64_t key = ps.compute_hash();
122         auto i = pipelines.find(key);
123         if(i!=pipelines.end())
124                 return i->second;
125
126         vector<char> buffer;
127         ps.fill_creation_info(buffer);
128         const VkGraphicsPipelineCreateInfo *creation_info = reinterpret_cast<const VkGraphicsPipelineCreateInfo *>(buffer.data());
129
130         VkPipeline pipeline;
131         vk.CreateGraphicsPipelines(0, 1, creation_info, &pipeline);
132
133         pipelines.insert(make_pair(key, pipeline));
134
135         return pipeline;
136 }
137
138 VkDescriptorSet PipelineCache::get_descriptor_set(const PipelineState &ps, unsigned index)
139 {
140         const VulkanFunctions &vk = device.get_functions();
141
142         uint64_t key = ps.compute_descriptor_set_hash(index);
143         auto i = descriptor_sets.find(key);
144         if(i!=descriptor_sets.end())
145                 return i->second;
146
147         VkDescriptorSetLayout layout = ps.get_descriptor_set_layout(index);
148
149         VkDescriptorSetAllocateInfo alloc_info = { };
150         alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
151         alloc_info.descriptorPool = handle_cast<::VkDescriptorPool>(descriptor_pool);
152         alloc_info.descriptorSetCount = 1;
153         alloc_info.pSetLayouts = handle_cast<::VkDescriptorSetLayout *>(&layout);
154
155         VkDescriptorSet desc_set;
156         vk.AllocateDescriptorSets(alloc_info, &desc_set);
157
158         vector<char> buffer;
159         unsigned n_writes = ps.fill_descriptor_writes(index, buffer);
160         VkWriteDescriptorSet *writes = reinterpret_cast<VkWriteDescriptorSet *>(buffer.data());
161         for(unsigned j=0; j<n_writes; ++j)
162                 writes[j].dstSet = handle_cast<::VkDescriptorSet>(desc_set);
163
164         vk.UpdateDescriptorSets(n_writes, writes, 0, 0);
165
166         descriptor_sets.insert(make_pair(key, desc_set));
167
168         return desc_set;
169 }
170
171 } // namespace GL
172 } // namespace Msp