1 #include <msp/core/hash.h>
3 #include "framebuffer.h"
4 #include "pipelinecache.h"
5 #include "pipelinestate.h"
13 PipelineCache::PipelineCache(Device &d):
17 PipelineCache::~PipelineCache()
19 const VulkanFunctions &vk = device.get_functions();
21 for(const auto &kvp: render_passes)
22 vk.DestroyRenderPass(kvp.second);
23 for(const auto &kvp: pipelines)
24 vk.DestroyPipeline(kvp.second);
27 VkRenderPass PipelineCache::get_render_pass(const FrameFormat &format, bool clear, bool discard, bool to_present)
29 const VulkanFunctions &vk = device.get_functions();
31 uint64_t key = hash<64>(static_cast<uint8_t>(clear | (discard*2) | (to_present*4)));
32 for(FrameAttachment a: format)
33 key = hash_update<64>(key, a);
35 auto j = render_passes.find(key);
36 if(j!=render_passes.end())
39 VkAttachmentDescription attachments[FrameFormat::MAX_ATTACHMENTS] = { };
40 VkAttachmentReference color_refs[FrameFormat::MAX_ATTACHMENTS] = { };
41 VkAttachmentReference depth_stencil_ref = { };
42 depth_stencil_ref.attachment = VK_ATTACHMENT_UNUSED;
44 VkSampleCountFlagBits vk_samples = static_cast<VkSampleCountFlagBits>(get_vulkan_samples(format.get_samples()));
47 unsigned color_count = 0;
48 for(FrameAttachment a: format)
50 VkImageLayout subpass_layout = static_cast<VkImageLayout>(get_vulkan_attachment_layout(get_components(get_attachment_pixelformat(a))));
51 VkImageLayout external_layout = (to_present ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : subpass_layout);
53 attachments[i].format = static_cast<VkFormat>(get_vulkan_pixelformat(get_attachment_pixelformat(a)));
54 attachments[i].samples = vk_samples;
55 attachments[i].loadOp = (clear ? discard ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
56 attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
57 attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
58 attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
59 attachments[i].initialLayout = ((clear && discard) ? VK_IMAGE_LAYOUT_UNDEFINED : external_layout);
60 attachments[i].finalLayout = external_layout;
62 if(subpass_layout==VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
64 color_refs[color_count].attachment = i;
65 color_refs[color_count].layout = subpass_layout;
70 depth_stencil_ref.attachment = i;
71 depth_stencil_ref.layout = subpass_layout;
77 VkSubpassDescription subpass = { };
78 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
79 subpass.colorAttachmentCount = color_count;
80 subpass.pColorAttachments = color_refs;
81 subpass.pDepthStencilAttachment = &depth_stencil_ref;
83 VkSubpassDependency dependency = { };
84 VkRenderPassCreateInfo render_pass_info = { };
85 render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
86 render_pass_info.attachmentCount = format.size();
87 render_pass_info.pAttachments = attachments;
88 render_pass_info.subpassCount = 1;
89 render_pass_info.pSubpasses = &subpass;
93 dependency.srcSubpass = 0;
94 dependency.dstSubpass = VK_SUBPASS_EXTERNAL;
95 dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
96 dependency.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
97 dependency.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
98 dependency.dstAccessMask = 0;
100 render_pass_info.dependencyCount = 1;
101 render_pass_info.pDependencies = &dependency;
104 VkRenderPass render_pass;
105 vk.CreateRenderPass(render_pass_info, render_pass);
107 render_passes.insert(make_pair(key, render_pass));
112 VkPipeline PipelineCache::get_pipeline(const PipelineState &ps)
114 const VulkanFunctions &vk = device.get_functions();
116 uint64_t key = ps.compute_hash();
117 auto i = pipelines.find(key);
118 if(i!=pipelines.end())
122 ps.fill_creation_info(buffer);
123 const VkGraphicsPipelineCreateInfo *creation_info = reinterpret_cast<const VkGraphicsPipelineCreateInfo *>(buffer.data());
126 vk.CreateGraphicsPipelines(0, 1, creation_info, &pipeline);
128 pipelines.insert(make_pair(key, pipeline));