X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbackends%2Fvulkan%2Fpipelinecache.cpp;fp=source%2Fbackends%2Fvulkan%2Fpipelinecache.cpp;h=e24c72dbba4944dc6f3180b61af8557f6ac0a8ec;hb=99ca354f18119f82f1adeca100cd665a8f640317;hp=0000000000000000000000000000000000000000;hpb=4cd245dafe6a7ee5c93edca5aee2d146f1155309;p=libs%2Fgl.git diff --git a/source/backends/vulkan/pipelinecache.cpp b/source/backends/vulkan/pipelinecache.cpp new file mode 100644 index 00000000..e24c72db --- /dev/null +++ b/source/backends/vulkan/pipelinecache.cpp @@ -0,0 +1,171 @@ +#include +#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(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(get_vulkan_samples(format.get_samples())); + + unsigned i = 0; + unsigned color_count = 0; + for(FrameAttachment a: format) + { + attachments[i].format = static_cast(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 buffer; + ps.fill_creation_info(buffer); + const VkGraphicsPipelineCreateInfo *creation_info = reinterpret_cast(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 buffer; + unsigned n_writes = ps.fill_descriptor_writes(index, buffer); + VkWriteDescriptorSet *writes = reinterpret_cast(buffer.data()); + for(unsigned j=0; j(desc_set); + + vk.UpdateDescriptorSets(n_writes, writes, 0, 0); + + descriptor_sets.insert(make_pair(key, desc_set)); + + return desc_set; +} + +} // namespace GL +} // namespace Msp