1 #include <msp/core/hash.h>
5 #include "framebuffer.h"
6 #include "pipelinecache.h"
7 #include "pipelinestate.h"
8 #include "stenciltest.h"
16 PipelineCache::PipelineCache(Device &d):
19 const VulkanFunctions &vk = device.get_functions();
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;
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;
33 vk.CreateDescriptorPool(pool_info, descriptor_pool);
36 PipelineCache::~PipelineCache()
38 const VulkanFunctions &vk = device.get_functions();
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);
47 VkRenderPass PipelineCache::get_render_pass(const FrameFormat &format, bool clear, bool discard, bool to_present)
49 const VulkanFunctions &vk = device.get_functions();
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);
55 auto j = render_passes.find(key);
56 if(j!=render_passes.end())
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;
64 VkSampleCountFlagBits vk_samples = static_cast<VkSampleCountFlagBits>(get_vulkan_samples(format.get_samples()));
67 unsigned color_count = 0;
68 for(FrameAttachment a: format)
70 attachments[i].format = static_cast<VkFormat>(get_vulkan_pixelformat(get_attachment_pixelformat(a)));
71 attachments[i].samples = vk_samples;
72 attachments[i].loadOp = (clear ? discard ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
73 attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
74 attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
75 attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
76 attachments[i].initialLayout = (clear ? VK_IMAGE_LAYOUT_UNDEFINED : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
77 attachments[i].finalLayout = (to_present ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
79 unsigned attach_pt = get_attach_point(a);
80 if(attach_pt==get_attach_point(COLOR_ATTACHMENT))
82 color_refs[color_count].attachment = i;
83 color_refs[color_count].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
86 else if(attach_pt==get_attach_point(DEPTH_ATTACHMENT))
88 depth_stencil_ref.attachment = i;
89 depth_stencil_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
95 VkSubpassDescription subpass = { };
96 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
97 subpass.colorAttachmentCount = color_count;
98 subpass.pColorAttachments = color_refs;
99 subpass.pDepthStencilAttachment = &depth_stencil_ref;
101 VkRenderPassCreateInfo render_pass_info = { };
102 render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
103 render_pass_info.attachmentCount = format.size();
104 render_pass_info.pAttachments = attachments;
105 render_pass_info.subpassCount = 1;
106 render_pass_info.pSubpasses = &subpass;
108 VkRenderPass render_pass;
109 vk.CreateRenderPass(render_pass_info, render_pass);
111 render_passes.insert(make_pair(key, render_pass));
116 VkPipeline PipelineCache::get_pipeline(const PipelineState &ps)
118 const VulkanFunctions &vk = device.get_functions();
120 uint64_t key = ps.compute_hash();
121 auto i = pipelines.find(key);
122 if(i!=pipelines.end())
126 ps.fill_creation_info(buffer);
127 const VkGraphicsPipelineCreateInfo *creation_info = reinterpret_cast<const VkGraphicsPipelineCreateInfo *>(buffer.data());
130 vk.CreateGraphicsPipelines(0, 1, creation_info, &pipeline);
132 pipelines.insert(make_pair(key, pipeline));
137 VkDescriptorSet PipelineCache::get_descriptor_set(const PipelineState &ps, unsigned index)
139 const VulkanFunctions &vk = device.get_functions();
141 uint64_t key = ps.compute_descriptor_set_hash(index);
142 auto i = descriptor_sets.find(key);
143 if(i!=descriptor_sets.end())
146 VkDescriptorSetLayout layout = ps.get_descriptor_set_layout(index);
148 VkDescriptorSetAllocateInfo alloc_info = { };
149 alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
150 alloc_info.descriptorPool = handle_cast<::VkDescriptorPool>(descriptor_pool);
151 alloc_info.descriptorSetCount = 1;
152 alloc_info.pSetLayouts = handle_cast<::VkDescriptorSetLayout *>(&layout);
154 VkDescriptorSet desc_set;
155 vk.AllocateDescriptorSets(alloc_info, &desc_set);
158 unsigned n_writes = ps.fill_descriptor_writes(index, buffer);
159 VkWriteDescriptorSet *writes = reinterpret_cast<VkWriteDescriptorSet *>(buffer.data());
160 for(unsigned j=0; j<n_writes; ++j)
161 writes[j].dstSet = handle_cast<::VkDescriptorSet>(desc_set);
163 vk.UpdateDescriptorSets(n_writes, writes, 0, 0);
165 descriptor_sets.insert(make_pair(key, desc_set));