2 #include <msp/core/algorithm.h>
6 #include "program_backend.h"
7 #include "structurebuilder.h"
15 VulkanProgram::VulkanProgram():
16 device(Device::get_current())
19 VulkanProgram::VulkanProgram(VulkanProgram &&other):
21 n_stages(other.n_stages),
22 stage_flags(other.stage_flags),
23 creation_info(move(other.creation_info)),
24 desc_set_layout_handles(move(other.desc_set_layout_handles)),
25 layout_handle(other.layout_handle),
26 debug_name(move(other.debug_name))
28 other.desc_set_layout_handles.clear();
29 other.layout_handle = 0;
32 VulkanProgram::~VulkanProgram()
34 const VulkanFunctions &vk = device.get_functions();
37 vk.DestroyPipelineLayout(layout_handle);
38 for(VkDescriptorSetLayout d: desc_set_layout_handles)
39 vk.DestroyDescriptorSetLayout(d);
42 bool VulkanProgram::has_stages() const
47 void VulkanProgram::add_glsl_stages(const GlslModule &, const map<string, int> &)
49 throw invalid_operation("VulkanProgram::add_glsl_stages");
52 void VulkanProgram::add_spirv_stages(const SpirVModule &mod, const map<string, int> &spec_values)
54 const vector<SpirVModule::EntryPoint> &entry_points = mod.get_entry_points();
56 n_stages = entry_points.size();
57 size_t entry_names_size = 0;
58 for(const SpirVModule::EntryPoint &e: entry_points)
59 entry_names_size += e.name.size()+1;
61 StructureBuilder sb(creation_info, 5);
62 VkPipelineShaderStageCreateInfo *const &stage_infos = sb.add<VkPipelineShaderStageCreateInfo>(n_stages);
63 char *const &name_table = sb.add<char>(entry_names_size);
64 VkSpecializationInfo *const &spec_info = sb.add<VkSpecializationInfo>();
65 VkSpecializationMapEntry *const &spec_map = sb.add<VkSpecializationMapEntry>(spec_values.size());
66 int *const &spec_data = sb.add<int>(spec_values.size());
69 for(const SpirVModule::Constant &c: mod.get_spec_constants())
71 auto j = spec_values.find(c.name);
72 if(j!=spec_values.end())
74 spec_map[i].constantID = c.constant_id;
75 spec_map[i].offset = i*sizeof(int);
76 spec_map[i].size = sizeof(int);
77 spec_data[i] = j->second;
82 spec_info->mapEntryCount = i;
83 spec_info->pMapEntries = spec_map;
84 spec_info->dataSize = spec_values.size()*sizeof(int);
85 spec_info->pData = spec_data;
87 char *name_ptr = name_table;
89 for(const SpirVModule::EntryPoint &e: entry_points)
91 unsigned stage_bit = get_vulkan_stage(e.stage);
92 stage_flags |= stage_bit;
94 stage_infos[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
95 stage_infos[i].stage = static_cast<VkShaderStageFlagBits>(stage_bit);
96 stage_infos[i].module = handle_cast<::VkShaderModule>(mod.handle);
97 strcpy(name_ptr, e.name.c_str());
98 stage_infos[i].pName = name_ptr;
99 name_ptr += e.name.size()+1;
100 stage_infos[i].pSpecializationInfo = spec_info;
105 if(!debug_name.empty())
106 if(SpirVModule *spirv = static_cast<Program *>(this)->specialized_spirv)
107 spirv->set_debug_name(debug_name);
111 void VulkanProgram::finalize_uniforms()
113 const VulkanFunctions &vk = device.get_functions();
114 const ReflectData &rd = static_cast<const Program *>(this)->reflect_data;
116 auto i = find_member(rd.uniform_blocks, static_cast<int>(ReflectData::PUSH_CONSTANT), &ReflectData::UniformBlockInfo::bind_point);
117 const ReflectData::UniformBlockInfo *push_const_block = (i!=rd.uniform_blocks.end() ? &*i : 0);
119 desc_set_layout_handles.resize(rd.n_descriptor_sets);
120 for(unsigned j=0; j<rd.n_descriptor_sets; ++j)
122 std::vector<VkDescriptorSetLayoutBinding> bindings;
123 for(const ReflectData::UniformBlockInfo &b: rd.uniform_blocks)
124 if(b.bind_point>=0 && static_cast<unsigned>(b.bind_point>>20)==j)
126 bindings.emplace_back();
127 VkDescriptorSetLayoutBinding &binding = bindings.back();
128 binding.binding = b.bind_point&0xFFFFF;
129 binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
130 binding.descriptorCount = 1;
131 binding.stageFlags = stage_flags;
132 binding.pImmutableSamplers = 0;
135 for(const ReflectData::UniformInfo &u: rd.uniforms)
136 if(u.binding>=0 && static_cast<unsigned>(u.binding>>20)==j && is_image(u.type))
138 bindings.emplace_back();
139 VkDescriptorSetLayoutBinding &binding = bindings.back();
140 binding.binding = u.binding&0xFFFFF;
141 binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
142 binding.descriptorCount = 1;
143 binding.stageFlags = stage_flags;
144 binding.pImmutableSamplers = 0;
147 VkDescriptorSetLayoutCreateInfo set_layout_info = { };
148 set_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
149 set_layout_info.bindingCount = bindings.size();
150 set_layout_info.pBindings = bindings.data();
152 vk.CreateDescriptorSetLayout(set_layout_info, desc_set_layout_handles[j]);
155 VkPushConstantRange push_const_range = { };
156 push_const_range.stageFlags = stage_flags;
157 push_const_range.offset = 0;
158 push_const_range.size = (push_const_block ? push_const_block->data_size : 0);
160 VkPipelineLayoutCreateInfo layout_info = { };
161 layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
162 layout_info.setLayoutCount = rd.n_descriptor_sets;
163 layout_info.pSetLayouts = handle_cast<::VkDescriptorSetLayout *>(desc_set_layout_handles.data());
164 layout_info.pushConstantRangeCount = (push_const_block ? 1 : 0);
165 layout_info.pPushConstantRanges = &push_const_range;
167 vk.CreatePipelineLayout(layout_info, layout_handle);
170 if(!debug_name.empty())
171 set_vulkan_object_name();
175 void VulkanProgram::set_debug_name(const string &name)
179 set_vulkan_object_name();
180 if(SpirVModule *spirv = static_cast<Program *>(this)->specialized_spirv)
181 spirv->set_debug_name(debug_name);
187 void VulkanProgram::set_vulkan_object_name() const
190 const VulkanFunctions &vk = device.get_functions();
192 string layout_name = debug_name+" [layout]";
194 VkDebugUtilsObjectNameInfoEXT name_info = { };
195 name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
196 name_info.objectType = VK_OBJECT_TYPE_PIPELINE_LAYOUT;
197 name_info.objectHandle = reinterpret_cast<uint64_t>(layout_handle);
198 name_info.pObjectName = layout_name.c_str();
199 vk.SetDebugUtilsObjectName(name_info);
201 name_info.objectType = VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT;
202 for(unsigned i=0; i<desc_set_layout_handles.size(); ++i)
204 layout_name = format("%s [layout:%d]", debug_name, i);
205 name_info.objectHandle = reinterpret_cast<uint64_t>(desc_set_layout_handles[i]);
206 name_info.pObjectName = layout_name.c_str();
207 vk.SetDebugUtilsObjectName(name_info);