]> git.tdb.fi Git - libs/gl.git/blobdiff - source/backends/vulkan/pipelinecache.cpp
Initial implementation of Vulkan backend
[libs/gl.git] / source / backends / vulkan / pipelinecache.cpp
diff --git a/source/backends/vulkan/pipelinecache.cpp b/source/backends/vulkan/pipelinecache.cpp
new file mode 100644 (file)
index 0000000..e24c72d
--- /dev/null
@@ -0,0 +1,171 @@
+#include <msp/core/hash.h>
+#include "blend.h"
+#include "depthtest.h"
+#include "device.h"
+#include "framebuffer.h"
+#include "pipelinecache.h"
+#include "pipelinestate.h"
+#include "stenciltest.h"
+#include "vulkan.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+PipelineCache::PipelineCache(Device &d):
+       device(d)
+{
+       const VulkanFunctions &vk = device.get_functions();
+
+       VkDescriptorPoolSize pool_sizes[2] = { };
+       pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+       pool_sizes[0].descriptorCount = 10000;
+       pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+       pool_sizes[1].descriptorCount = 10000;
+
+       VkDescriptorPoolCreateInfo pool_info = { };
+       pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+       pool_info.maxSets = 10000;
+       pool_info.poolSizeCount = 2;
+       pool_info.pPoolSizes = pool_sizes;
+
+       vk.CreateDescriptorPool(pool_info, descriptor_pool);
+}
+
+PipelineCache::~PipelineCache()
+{
+       const VulkanFunctions &vk = device.get_functions();
+
+       for(const auto &kvp: render_passes)
+               vk.DestroyRenderPass(kvp.second);
+       for(const auto &kvp: pipelines)
+               vk.DestroyPipeline(kvp.second);
+       vk.DestroyDescriptorPool(descriptor_pool);
+}
+
+VkRenderPass PipelineCache::get_render_pass(const FrameFormat &format, bool is_cleared, bool to_present)
+{
+       const VulkanFunctions &vk = device.get_functions();
+
+       uint64_t key = hash<64>(static_cast<uint8_t>(is_cleared | (to_present*2)));
+       for(FrameAttachment a: format)
+               key = hash_update<64>(key, a);
+
+       auto j = render_passes.find(key);
+       if(j!=render_passes.end())
+               return j->second;
+
+       VkAttachmentDescription attachments[FrameFormat::MAX_ATTACHMENTS] = { };
+       VkAttachmentReference color_refs[FrameFormat::MAX_ATTACHMENTS] = { };
+       VkAttachmentReference depth_stencil_ref = { };
+       depth_stencil_ref.attachment = VK_ATTACHMENT_UNUSED;
+
+       VkSampleCountFlagBits vk_samples = static_cast<VkSampleCountFlagBits>(get_vulkan_samples(format.get_samples()));
+
+       unsigned i = 0;
+       unsigned color_count = 0;
+       for(FrameAttachment a: format)
+       {
+               attachments[i].format = static_cast<VkFormat>(get_vulkan_pixelformat(get_attachment_pixelformat(a)));
+               attachments[i].samples = vk_samples;
+               attachments[i].loadOp = (is_cleared ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
+               attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+               attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+               attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
+               attachments[i].initialLayout = (is_cleared ? VK_IMAGE_LAYOUT_UNDEFINED : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+               attachments[i].finalLayout = (to_present ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+
+               unsigned attach_pt = get_attach_point(a);
+               if(attach_pt==get_attach_point(COLOR_ATTACHMENT))
+               {
+                       color_refs[color_count].attachment = i;
+                       color_refs[color_count].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+                       ++color_count;
+               }
+               else if(attach_pt==get_attach_point(DEPTH_ATTACHMENT))
+               {
+                       depth_stencil_ref.attachment = i;
+                       depth_stencil_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+               }
+
+               ++i;
+       }
+
+       VkSubpassDescription subpass = { };
+       subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+       subpass.colorAttachmentCount = color_count;
+       subpass.pColorAttachments = color_refs;
+       subpass.pDepthStencilAttachment = &depth_stencil_ref;
+
+       VkRenderPassCreateInfo render_pass_info = { };
+       render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+       render_pass_info.attachmentCount = format.size();
+       render_pass_info.pAttachments = attachments;
+       render_pass_info.subpassCount = 1;
+       render_pass_info.pSubpasses = &subpass;
+
+       VkRenderPass render_pass;
+       vk.CreateRenderPass(render_pass_info, render_pass);
+
+       render_passes.insert(make_pair(key, render_pass));
+
+       return render_pass;
+}
+
+VkPipeline PipelineCache::get_pipeline(const PipelineState &ps)
+{
+       const VulkanFunctions &vk = device.get_functions();
+
+       uint64_t key = ps.compute_hash();
+       auto i = pipelines.find(key);
+       if(i!=pipelines.end())
+               return i->second;
+
+       vector<char> buffer;
+       ps.fill_creation_info(buffer);
+       const VkGraphicsPipelineCreateInfo *creation_info = reinterpret_cast<const VkGraphicsPipelineCreateInfo *>(buffer.data());
+
+       VkPipeline pipeline;
+       vk.CreateGraphicsPipelines(0, 1, creation_info, &pipeline);
+
+       pipelines.insert(make_pair(key, pipeline));
+
+       return pipeline;
+}
+
+VkDescriptorSet PipelineCache::get_descriptor_set(const PipelineState &ps, unsigned index)
+{
+       const VulkanFunctions &vk = device.get_functions();
+
+       uint64_t key = ps.compute_descriptor_set_hash(index);
+       auto i = descriptor_sets.find(key);
+       if(i!=descriptor_sets.end())
+               return i->second;
+
+       VkDescriptorSetLayout layout = ps.get_descriptor_set_layout(index);
+
+       VkDescriptorSetAllocateInfo alloc_info = { };
+       alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+       alloc_info.descriptorPool = handle_cast<::VkDescriptorPool>(descriptor_pool);
+       alloc_info.descriptorSetCount = 1;
+       alloc_info.pSetLayouts = handle_cast<::VkDescriptorSetLayout *>(&layout);
+
+       VkDescriptorSet desc_set;
+       vk.AllocateDescriptorSets(alloc_info, &desc_set);
+
+       vector<char> buffer;
+       unsigned n_writes = ps.fill_descriptor_writes(index, buffer);
+       VkWriteDescriptorSet *writes = reinterpret_cast<VkWriteDescriptorSet *>(buffer.data());
+       for(unsigned j=0; j<n_writes; ++j)
+               writes[j].dstSet = handle_cast<::VkDescriptorSet>(desc_set);
+
+       vk.UpdateDescriptorSets(n_writes, writes, 0, 0);
+
+       descriptor_sets.insert(make_pair(key, desc_set));
+
+       return desc_set;
+}
+
+} // namespace GL
+} // namespace Msp