22#include "aeongames/AeonEngine.hpp"
23#include "aeongames/Utilities.hpp"
25#include "aeongames/CRC.hpp"
26#include <vulkan/vulkan.h>
27#include "VulkanPipeline.hpp"
28#include "VulkanRenderer.hpp"
29#include "VulkanUtilities.hpp"
30#include "SPIR-V/CompilerLinker.hpp"
31#include <spirv_reflect.h>
35 static const std::unordered_map<SpvReflectFormat, VkFormat> SpvReflectToVulkanFormat
37 { SPV_REFLECT_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED },
38 { SPV_REFLECT_FORMAT_R16_UINT, VK_FORMAT_R16_UINT },
39 { SPV_REFLECT_FORMAT_R16_SINT, VK_FORMAT_R16_SINT },
40 { SPV_REFLECT_FORMAT_R16_SFLOAT, VK_FORMAT_R16_SFLOAT },
41 { SPV_REFLECT_FORMAT_R16G16_UINT, VK_FORMAT_R16G16_UINT },
42 { SPV_REFLECT_FORMAT_R16G16_SINT, VK_FORMAT_R16G16_SINT },
43 { SPV_REFLECT_FORMAT_R16G16_SFLOAT, VK_FORMAT_R16G16_SFLOAT },
44 { SPV_REFLECT_FORMAT_R16G16B16_UINT, VK_FORMAT_R16G16B16_UINT },
45 { SPV_REFLECT_FORMAT_R16G16B16_SINT, VK_FORMAT_R16G16B16_SINT },
46 { SPV_REFLECT_FORMAT_R16G16B16_SFLOAT, VK_FORMAT_R16G16B16_SFLOAT },
47 { SPV_REFLECT_FORMAT_R16G16B16A16_UINT, VK_FORMAT_R16G16B16A16_UINT },
48 { SPV_REFLECT_FORMAT_R16G16B16A16_SINT, VK_FORMAT_R16G16B16A16_SINT },
49 { SPV_REFLECT_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R16G16B16A16_SFLOAT },
50 { SPV_REFLECT_FORMAT_R32_UINT, VK_FORMAT_R32_UINT },
51 { SPV_REFLECT_FORMAT_R32_SINT, VK_FORMAT_R32_SINT },
52 { SPV_REFLECT_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT },
53 { SPV_REFLECT_FORMAT_R32G32_UINT, VK_FORMAT_R32G32_UINT },
54 { SPV_REFLECT_FORMAT_R32G32_SINT, VK_FORMAT_R32G32_SINT },
55 { SPV_REFLECT_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32_SFLOAT },
56 { SPV_REFLECT_FORMAT_R32G32B32_UINT, VK_FORMAT_R32G32B32_UINT },
57 { SPV_REFLECT_FORMAT_R32G32B32_SINT, VK_FORMAT_R32G32B32_SINT },
58 { SPV_REFLECT_FORMAT_R32G32B32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT },
59 { SPV_REFLECT_FORMAT_R32G32B32A32_UINT, VK_FORMAT_R32G32B32A32_UINT },
60 { SPV_REFLECT_FORMAT_R32G32B32A32_SINT, VK_FORMAT_R32G32B32A32_SINT },
61 { SPV_REFLECT_FORMAT_R32G32B32A32_SFLOAT, VK_FORMAT_R32G32B32A32_SFLOAT },
62 { SPV_REFLECT_FORMAT_R64_UINT, VK_FORMAT_R64_UINT },
63 { SPV_REFLECT_FORMAT_R64_SINT, VK_FORMAT_R64_SINT },
64 { SPV_REFLECT_FORMAT_R64_SFLOAT, VK_FORMAT_R64_SFLOAT },
65 { SPV_REFLECT_FORMAT_R64G64_UINT, VK_FORMAT_R64G64_UINT },
66 { SPV_REFLECT_FORMAT_R64G64_SINT, VK_FORMAT_R64G64_SINT },
67 { SPV_REFLECT_FORMAT_R64G64_SFLOAT, VK_FORMAT_R64G64_SFLOAT },
68 { SPV_REFLECT_FORMAT_R64G64B64_UINT, VK_FORMAT_R64G64B64_UINT },
69 { SPV_REFLECT_FORMAT_R64G64B64_SINT, VK_FORMAT_R64G64B64_SINT },
70 { SPV_REFLECT_FORMAT_R64G64B64_SFLOAT, VK_FORMAT_R64G64B64_SFLOAT },
71 { SPV_REFLECT_FORMAT_R64G64B64A64_UINT, VK_FORMAT_R64G64B64A64_UINT },
72 { SPV_REFLECT_FORMAT_R64G64B64A64_SINT, VK_FORMAT_R64G64B64A64_SINT },
73 { SPV_REFLECT_FORMAT_R64G64B64A64_SFLOAT, VK_FORMAT_R64G64B64A64_SFLOAT }
76 static const std::unordered_map<VkFormat, uint32_t> VkFormatToVulkanSize
78 { VK_FORMAT_UNDEFINED, 0 },
79 { VK_FORMAT_R8G8B8A8_UINT,
static_cast<uint32_t
> (
sizeof ( uint8_t ) * 4 ) },
80 { VK_FORMAT_R8G8B8A8_UNORM,
static_cast<uint32_t
> (
sizeof ( uint8_t ) * 4 ) },
81 { VK_FORMAT_R16_UINT,
static_cast<uint32_t
> (
sizeof ( uint16_t ) ) },
82 { VK_FORMAT_R16_SINT,
static_cast<uint32_t
> (
sizeof ( int16_t ) ) },
83 { VK_FORMAT_R16_SFLOAT,
static_cast<uint32_t
> (
sizeof ( float ) ) },
84 { VK_FORMAT_R16G16_UINT,
static_cast<uint32_t
> (
sizeof ( uint16_t ) * 2 ) },
85 { VK_FORMAT_R16G16_SINT,
static_cast<uint32_t
> (
sizeof ( int16_t ) * 2 ) },
86 { VK_FORMAT_R16G16_SFLOAT,
static_cast<uint32_t
> (
sizeof ( float ) * 2 ) },
87 { VK_FORMAT_R16G16B16_UINT,
static_cast<uint32_t
> (
sizeof ( uint16_t ) * 3 ) },
88 { VK_FORMAT_R16G16B16_SINT,
static_cast<uint32_t
> (
sizeof ( int16_t ) * 3 ) },
89 { VK_FORMAT_R16G16B16_SFLOAT,
static_cast<uint32_t
> (
sizeof ( float ) * 3 ) },
90 { VK_FORMAT_R16G16B16A16_UINT,
static_cast<uint32_t
> (
sizeof ( uint16_t ) * 4 ) },
91 { VK_FORMAT_R16G16B16A16_SINT,
static_cast<uint32_t
> (
sizeof ( int16_t ) * 4 ) },
92 { VK_FORMAT_R16G16B16A16_SFLOAT,
static_cast<uint32_t
> (
sizeof ( float ) * 4 ) },
93 { VK_FORMAT_R32_UINT,
static_cast<uint32_t
> (
sizeof ( uint32_t ) ) },
94 { VK_FORMAT_R32_SINT,
static_cast<uint32_t
> (
sizeof ( int32_t ) ) },
95 { VK_FORMAT_R32_SFLOAT,
static_cast<uint32_t
> (
sizeof ( float ) ) },
96 { VK_FORMAT_R32G32_UINT,
static_cast<uint32_t
> (
sizeof ( uint32_t ) * 2 ) },
97 { VK_FORMAT_R32G32_SINT,
static_cast<uint32_t
> (
sizeof ( int32_t ) * 2 ) },
98 { VK_FORMAT_R32G32_SFLOAT,
static_cast<uint32_t
> (
sizeof ( float ) * 2 ) },
99 { VK_FORMAT_R32G32B32_UINT,
static_cast<uint32_t
> (
sizeof ( uint32_t ) * 3 ) },
100 { VK_FORMAT_R32G32B32_SINT,
static_cast<uint32_t
> (
sizeof ( int32_t ) * 3 ) },
101 { VK_FORMAT_R32G32B32_SFLOAT,
static_cast<uint32_t
> (
sizeof ( float ) * 3 ) },
102 { VK_FORMAT_R32G32B32A32_UINT,
static_cast<uint32_t
> (
sizeof ( uint32_t ) * 4 ) },
103 { VK_FORMAT_R32G32B32A32_SINT,
static_cast<uint32_t
> (
sizeof ( int32_t ) * 4 ) },
104 { VK_FORMAT_R32G32B32A32_SFLOAT,
static_cast<uint32_t
> (
sizeof ( float ) * 4 ) },
105 { VK_FORMAT_R64_UINT,
static_cast<uint32_t
> (
sizeof ( uint64_t ) ) },
106 { VK_FORMAT_R64_SINT,
static_cast<uint32_t
> (
sizeof ( int64_t ) ) },
107 { VK_FORMAT_R64_SFLOAT,
static_cast<uint32_t
> (
sizeof ( float ) ) },
108 { VK_FORMAT_R64G64_UINT,
static_cast<uint32_t
> (
sizeof ( uint64_t ) * 2 ) },
109 { VK_FORMAT_R64G64_SINT,
static_cast<uint32_t
> (
sizeof ( int64_t ) * 2 ) },
110 { VK_FORMAT_R64G64_SFLOAT,
static_cast<uint32_t
> (
sizeof ( float ) * 2 ) },
111 { VK_FORMAT_R64G64B64_UINT,
static_cast<uint32_t
> (
sizeof ( uint64_t ) * 3 ) },
112 { VK_FORMAT_R64G64B64_SINT,
static_cast<uint32_t
> (
sizeof ( int64_t ) * 3 ) },
113 { VK_FORMAT_R64G64B64_SFLOAT,
static_cast<uint32_t
> (
sizeof ( float ) * 3 ) },
114 { VK_FORMAT_R64G64B64A64_UINT,
static_cast<uint32_t
> (
sizeof ( uint64_t ) * 4 ) },
115 { VK_FORMAT_R64G64B64A64_SINT,
static_cast<uint32_t
> (
sizeof ( int64_t ) * 4 ) },
116 { VK_FORMAT_R64G64B64A64_SFLOAT,
static_cast<uint32_t
> (
sizeof ( float ) * 4 ) }
119 static const std::unordered_map<SpvReflectDescriptorType, VkDescriptorType> SpvReflectToVulkanDescriptorType
121 { SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLER },
122 { SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER },
123 { SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
124 { SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },
125 { SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER },
126 { SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER },
127 { SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
128 { SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER },
129 { SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC },
130 { SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC },
131 { SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT },
132 { SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR }
135 static const std::unordered_map<uint32_t, VkPrimitiveTopology> TopologyClassToVulkanTopology
144 bool operator!= (
const VkDescriptorSetLayoutBinding& a,
const SpvReflectDescriptorBinding& b )
146 return ! ( a.binding == b.binding &&
147 a.descriptorType == SpvReflectToVulkanDescriptorType.at ( b.descriptor_type ) &&
148 a.descriptorCount == b.count &&
149 a.pImmutableSamplers ==
nullptr );
153 mVulkanRenderer{aVulkanPipeline.mVulkanRenderer}
155 std::swap ( mPipeline, aVulkanPipeline.mPipeline );
156 std::swap ( mVkPipelineLayout, aVulkanPipeline.mVkPipelineLayout );
157 std::swap ( mVkPipeline, aVulkanPipeline.mVkPipeline );
158 std::swap ( mVertexStride, aVulkanPipeline.mVertexStride );
159 std::swap ( mPushConstantModelMatrix, aVulkanPipeline.mPushConstantModelMatrix );
160 mVertexAttributes.swap ( aVulkanPipeline.mVertexAttributes );
161 mDescriptorSets.swap ( aVulkanPipeline.mDescriptorSets );
167 EShLanguage::EShLangVertex,
168 EShLanguage::EShLangFragment,
169 EShLanguage::EShLangCompute,
170 EShLanguage::EShLangTessControl,
171 EShLanguage::EShLangTessEvaluation,
172 EShLanguage::EShLangGeometry
178 VK_SHADER_STAGE_VERTEX_BIT,
179 VK_SHADER_STAGE_FRAGMENT_BIT,
180 VK_SHADER_STAGE_COMPUTE_BIT,
181 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
182 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
183 VK_SHADER_STAGE_GEOMETRY_BIT
187 mVulkanRenderer { aVulkanRenderer }, mPipeline{&aPipeline}
189 std::array < VkShaderModule, ShaderType::COUNT > shader_modules{ { VK_NULL_HANDLE } };
191 CompilerLinker::TOptions::EOptionSpv |
192 CompilerLinker::TOptions::EOptionVulkanRules |
193 CompilerLinker::TOptions::EOptionLinkProgram
197 std::array<std::string_view, ShaderType::COUNT> shader_codes =
209 if ( shader_codes.at ( i ).empty() )
218 std::ostringstream stream;
219 stream << ( ( result == CompilerLinker::EFailCompile ) ?
"Compilation" :
"Linking" ) <<
220 " Error:" << std::endl << compiler_linker.
GetLog();
222 throw std::runtime_error ( stream.str().c_str() );
225 uint32_t pipeline_shader_stage_create_info_count{0};
226 std::array<VkPipelineShaderStageCreateInfo, ShaderType::COUNT> pipeline_shader_stage_create_infos{ {} };
230 if ( spirv.size() == 0 )
234 VkShaderModuleCreateInfo shader_module_create_info{};
235 shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
236 shader_module_create_info.codeSize = spirv.size() *
sizeof ( uint32_t );
237 shader_module_create_info.pCode = spirv.data();
239 if ( VkResult result = vkCreateShaderModule ( mVulkanRenderer.GetDevice(), &shader_module_create_info,
nullptr, &shader_modules[ i ] ) )
241 std::ostringstream stream;
244 throw std::runtime_error ( stream.str().c_str() );
248 SpvReflectShaderModule module {};
249 SpvReflectResult result = spvReflectCreateShaderModule (
250 shader_module_create_info.codeSize,
251 shader_module_create_info.pCode,
253 if ( result != SPV_REFLECT_RESULT_SUCCESS )
255 std::ostringstream stream;
256 stream <<
"SPIR-V Reflect module creation failed: ( " <<
static_cast<int> ( result ) <<
" )";
258 throw std::runtime_error ( stream.str().c_str() );
264 ReflectAttributes ( module );
266 ReflectDescriptorSets ( module,
static_cast<ShaderType> ( i ) );
267 ReflectPushConstants ( module,
static_cast<ShaderType> ( i ) );
268 spvReflectDestroyShaderModule ( &module );
271 pipeline_shader_stage_create_infos[pipeline_shader_stage_create_info_count].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
272 pipeline_shader_stage_create_infos[pipeline_shader_stage_create_info_count].pNext =
nullptr;
273 pipeline_shader_stage_create_infos[pipeline_shader_stage_create_info_count].flags = 0;
274 pipeline_shader_stage_create_infos[pipeline_shader_stage_create_info_count].module = shader_modules[i];
275 pipeline_shader_stage_create_infos[pipeline_shader_stage_create_info_count].pName =
"main";
277 pipeline_shader_stage_create_infos[pipeline_shader_stage_create_info_count++].pSpecializationInfo =
nullptr;
281 std::array<VkVertexInputBindingDescription, 1> vertex_input_binding_descriptions { {} };
282 vertex_input_binding_descriptions[0].binding = 0;
283 vertex_input_binding_descriptions[0].stride = mVertexStride;
284 vertex_input_binding_descriptions[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
286 VkPipelineVertexInputStateCreateInfo pipeline_vertex_input_state_create_info {};
287 pipeline_vertex_input_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
288 pipeline_vertex_input_state_create_info.pNext =
nullptr;
289 pipeline_vertex_input_state_create_info.flags = 0;
290 pipeline_vertex_input_state_create_info.vertexBindingDescriptionCount =
static_cast<uint32_t
> ( vertex_input_binding_descriptions.size() );
291 pipeline_vertex_input_state_create_info.pVertexBindingDescriptions = vertex_input_binding_descriptions.data();
292 pipeline_vertex_input_state_create_info.vertexAttributeDescriptionCount =
static_cast<uint32_t
> ( mVertexAttributes.size() );
293 pipeline_vertex_input_state_create_info.pVertexAttributeDescriptions = mVertexAttributes.data();
296 VkPipelineInputAssemblyStateCreateInfo pipeline_input_assembly_state_create_info{};
297 pipeline_input_assembly_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
298 pipeline_input_assembly_state_create_info.pNext =
nullptr;
299 pipeline_input_assembly_state_create_info.flags = 0;
300 pipeline_input_assembly_state_create_info.topology = TopologyClassToVulkanTopology.at ( mPipeline->GetTopologyClass() );
301#ifdef VK_USE_PLATFORM_METAL_EXT
302 pipeline_input_assembly_state_create_info.primitiveRestartEnable = VK_TRUE;
304 pipeline_input_assembly_state_create_info.primitiveRestartEnable = VK_FALSE;
307 VkPipelineViewportStateCreateInfo pipeline_viewport_state_create_info {};
308 pipeline_viewport_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
309 pipeline_viewport_state_create_info.pNext =
nullptr;
310 pipeline_viewport_state_create_info.flags = 0;
311 pipeline_viewport_state_create_info.viewportCount = 1;
312 pipeline_viewport_state_create_info.pViewports =
nullptr;
313 pipeline_viewport_state_create_info.scissorCount = 1;
314 pipeline_viewport_state_create_info.pScissors =
nullptr;
317 VkPipelineRasterizationStateCreateInfo pipeline_rasterization_state_create_info{};
318 pipeline_rasterization_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
319 pipeline_rasterization_state_create_info.pNext =
nullptr;
320 pipeline_rasterization_state_create_info.flags = 0;
321 pipeline_rasterization_state_create_info.depthClampEnable = VK_FALSE;
322 pipeline_rasterization_state_create_info.rasterizerDiscardEnable = VK_FALSE;
323 pipeline_rasterization_state_create_info.polygonMode = VK_POLYGON_MODE_FILL;
324 pipeline_rasterization_state_create_info.cullMode = VK_CULL_MODE_BACK_BIT;
325 pipeline_rasterization_state_create_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
326 pipeline_rasterization_state_create_info.depthBiasEnable = VK_TRUE;
327 pipeline_rasterization_state_create_info.depthBiasConstantFactor = 0.0f;
328 pipeline_rasterization_state_create_info.depthBiasClamp = 0.0f;
329 pipeline_rasterization_state_create_info.depthBiasSlopeFactor = 0.0f;
330 pipeline_rasterization_state_create_info.lineWidth = 1.0f;
333 VkPipelineMultisampleStateCreateInfo pipeline_multisample_state_create_info{};
334 pipeline_multisample_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
335 pipeline_multisample_state_create_info.pNext =
nullptr;
336 pipeline_multisample_state_create_info.flags = 0;
337 pipeline_multisample_state_create_info.sampleShadingEnable = VK_FALSE;
338 pipeline_multisample_state_create_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
339 pipeline_multisample_state_create_info.minSampleShading = 0.0f;
340 pipeline_multisample_state_create_info.pSampleMask =
nullptr;
341 pipeline_multisample_state_create_info.alphaToCoverageEnable = VK_TRUE;
342 pipeline_multisample_state_create_info.alphaToOneEnable = VK_FALSE;
345 VkPipelineDepthStencilStateCreateInfo pipeline_depth_stencil_state_create_info{};
346 pipeline_depth_stencil_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
347 pipeline_depth_stencil_state_create_info.pNext =
nullptr;
348 pipeline_depth_stencil_state_create_info.flags = 0;
349 pipeline_depth_stencil_state_create_info.depthTestEnable = VK_TRUE;
350 pipeline_depth_stencil_state_create_info.depthWriteEnable = VK_TRUE;
351 pipeline_depth_stencil_state_create_info.depthCompareOp = VK_COMPARE_OP_LESS;
352 pipeline_depth_stencil_state_create_info.depthBoundsTestEnable = VK_FALSE;
353 pipeline_depth_stencil_state_create_info.stencilTestEnable = VK_FALSE;
354 pipeline_depth_stencil_state_create_info.front = {};
355 pipeline_depth_stencil_state_create_info.back = {};
356 pipeline_depth_stencil_state_create_info.minDepthBounds = 0.0f;
357 pipeline_depth_stencil_state_create_info.maxDepthBounds = 1.0f;
360 std::array<VkPipelineColorBlendAttachmentState, 1> pipeline_color_blend_attachment_states{ {} };
361 pipeline_color_blend_attachment_states[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
362 pipeline_color_blend_attachment_states[0].blendEnable = VK_TRUE;
363 pipeline_color_blend_attachment_states[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
364 pipeline_color_blend_attachment_states[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
365 pipeline_color_blend_attachment_states[0].colorBlendOp = VK_BLEND_OP_ADD;
366 pipeline_color_blend_attachment_states[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
367 pipeline_color_blend_attachment_states[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
368 pipeline_color_blend_attachment_states[0].alphaBlendOp = VK_BLEND_OP_ADD;
370 VkPipelineColorBlendStateCreateInfo pipeline_color_blend_state_create_info{};
371 pipeline_color_blend_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
372 pipeline_color_blend_state_create_info.pNext =
nullptr;
373 pipeline_color_blend_state_create_info.flags = 0;
374 pipeline_color_blend_state_create_info.logicOpEnable = VK_FALSE;
375 pipeline_color_blend_state_create_info.logicOp = VK_LOGIC_OP_COPY;
376 pipeline_color_blend_state_create_info.attachmentCount =
static_cast<uint32_t
> ( pipeline_color_blend_attachment_states.size() );
377 pipeline_color_blend_state_create_info.pAttachments = pipeline_color_blend_attachment_states.data();
378 memset ( pipeline_color_blend_state_create_info.blendConstants, 0, sizeof ( VkPipelineColorBlendStateCreateInfo::blendConstants ) );
381 std::array<VkDynamicState, 3> dynamic_states
384 VK_DYNAMIC_STATE_VIEWPORT,
385 VK_DYNAMIC_STATE_SCISSOR,
386 VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY
389 VkPipelineDynamicStateCreateInfo pipeline_dynamic_state_create_info{};
390 pipeline_dynamic_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
391 pipeline_dynamic_state_create_info.pNext =
nullptr;
392 pipeline_dynamic_state_create_info.flags = 0;
393 pipeline_dynamic_state_create_info.dynamicStateCount =
static_cast<uint32_t
> ( dynamic_states.size() );
394 pipeline_dynamic_state_create_info.pDynamicStates = dynamic_states.data();
396 std::array<VkDescriptorSetLayout, 8> descriptor_set_layouts{};
397 if ( mDescriptorSets.size() > descriptor_set_layouts.size() )
399 std::cout <<
LogLevel::Error <<
"More descriptor sets than available slots" << std::endl;
400 throw std::runtime_error (
"More descriptor sets than available slots" );
402 for (
const auto& i : mDescriptorSets )
404 if ( i.set >= mDescriptorSets.size() )
406 std::cout <<
LogLevel::Error <<
"Set index out of bounds" << std::endl;
407 throw std::runtime_error (
"Set index out of bounds" );
409 descriptor_set_layouts[i.set] = mVulkanRenderer.GetDescriptorSetLayout ( i.descriptor_set_layout_create_info );
412 VkPipelineLayoutCreateInfo pipeline_layout_create_info{};
413 pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
414 pipeline_layout_create_info.pNext =
nullptr;
415 pipeline_layout_create_info.setLayoutCount =
static_cast<uint32_t
> ( mDescriptorSets.size() );
416 pipeline_layout_create_info.pSetLayouts = mDescriptorSets.size() ? descriptor_set_layouts.data() :
nullptr;
417 pipeline_layout_create_info.pushConstantRangeCount = mPushConstantModelMatrix.offset == 0 && mPushConstantModelMatrix.size == 0 ? 0 : 1;
418 pipeline_layout_create_info.pPushConstantRanges = pipeline_layout_create_info.pushConstantRangeCount ? &mPushConstantModelMatrix :
nullptr;
419 if ( VkResult result = vkCreatePipelineLayout ( mVulkanRenderer.GetDevice(), &pipeline_layout_create_info,
nullptr, &mVkPipelineLayout ) )
421 std::ostringstream stream;
424 throw std::runtime_error ( stream.str().c_str() );
428 VkGraphicsPipelineCreateInfo graphics_pipeline_create_info {};
429 graphics_pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
430 graphics_pipeline_create_info.pNext =
nullptr;
431 graphics_pipeline_create_info.flags = 0;
432 graphics_pipeline_create_info.stageCount = pipeline_shader_stage_create_info_count;
433 graphics_pipeline_create_info.pStages = pipeline_shader_stage_create_infos.data();
434 graphics_pipeline_create_info.pVertexInputState = &pipeline_vertex_input_state_create_info;
435 graphics_pipeline_create_info.pInputAssemblyState = &pipeline_input_assembly_state_create_info;
436 graphics_pipeline_create_info.pTessellationState =
nullptr;
437 graphics_pipeline_create_info.pViewportState = &pipeline_viewport_state_create_info;
438 graphics_pipeline_create_info.pRasterizationState = &pipeline_rasterization_state_create_info;
439 graphics_pipeline_create_info.pMultisampleState = &pipeline_multisample_state_create_info;
440 graphics_pipeline_create_info.pDepthStencilState = &pipeline_depth_stencil_state_create_info;
441 graphics_pipeline_create_info.pColorBlendState = &pipeline_color_blend_state_create_info;
442 graphics_pipeline_create_info.pDynamicState = &pipeline_dynamic_state_create_info;
443 graphics_pipeline_create_info.layout = mVkPipelineLayout;
444 graphics_pipeline_create_info.renderPass = mVulkanRenderer.GetRenderPass();
445 graphics_pipeline_create_info.subpass = 0;
446 graphics_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
447 graphics_pipeline_create_info.basePipelineIndex = 0;
449 if ( VkResult result = vkCreateGraphicsPipelines ( mVulkanRenderer.GetDevice(), VK_NULL_HANDLE, 1, &graphics_pipeline_create_info,
nullptr, &mVkPipeline ) )
451 std::ostringstream stream;
454 throw std::runtime_error ( stream.str().c_str() );
456 for (
auto& i : shader_modules )
458 if ( i != VK_NULL_HANDLE )
460 vkDestroyShaderModule ( mVulkanRenderer.GetDevice(), i,
nullptr );
466 VulkanPipeline::~VulkanPipeline()
468 vkDestroyPipeline ( mVulkanRenderer.
GetDevice(), mVkPipeline,
nullptr );
469 vkDestroyPipelineLayout ( mVulkanRenderer.
GetDevice(), mVkPipelineLayout,
nullptr );
474 return mVkPipelineLayout;
489 auto it = std::lower_bound ( mDescriptorSets.begin(), mDescriptorSets.end(), name,
494 if ( it != mDescriptorSets.end() && it->hash == name )
496 return mVulkanRenderer.GetDescriptorSetLayout ( it->descriptor_set_layout_create_info );
498 return VK_NULL_HANDLE;
501 void VulkanPipeline::ReflectAttributes ( SpvReflectShaderModule& module )
503 uint32_t var_count{0};
504 SpvReflectResult result{spvReflectEnumerateInputVariables ( &module, &var_count,
nullptr ) };
505 if ( result != SPV_REFLECT_RESULT_SUCCESS )
507 std::ostringstream stream;
508 stream <<
"SPIR-V Reflect input variable enumeration failed: ( " <<
static_cast<int> ( result ) <<
" )";
510 throw std::runtime_error ( stream.str().c_str() );
512 std::vector<SpvReflectInterfaceVariable*> input_vars ( var_count );
513 result = spvReflectEnumerateInputVariables ( &module, &var_count, input_vars.data() );
514 if ( result != SPV_REFLECT_RESULT_SUCCESS )
516 std::ostringstream stream;
517 stream <<
"SPIR-V Reflect input variable enumeration failed: ( " <<
static_cast<int> ( result ) <<
" )";
519 throw std::runtime_error ( stream.str().c_str() );
521 mVertexAttributes.reserve ( mVertexAttributes.capacity() + input_vars.size() );
522 for (
const auto& i : input_vars )
524 if ( i->built_in < 0 )
526 const uint32_t name_crc{
crc32i ( i->name, strlen ( i->name ) ) };
531 format = VK_FORMAT_R8G8B8A8_UINT;
535 format = VK_FORMAT_R8G8B8A8_UNORM;
539 format = SpvReflectToVulkanFormat.at ( i->format );
542 auto it = std::lower_bound ( mVertexAttributes.begin(), mVertexAttributes.end(), i->location,
543 [] (
const VkVertexInputAttributeDescription & a,
const uint32_t b )
545 return a.location < b;
547 mVertexAttributes.insert ( it,
556 for (
auto& attr : mVertexAttributes )
559 attr.offset = mVertexStride;
560 mVertexStride += VkFormatToVulkanSize.at ( attr.format );
564 void VulkanPipeline::ReflectDescriptorSets ( SpvReflectShaderModule& aModule,
ShaderType aType )
567 uint32_t descriptor_set_count = 0;
568 SpvReflectResult result = spvReflectEnumerateDescriptorSets ( &aModule, &descriptor_set_count,
nullptr );
569 if ( result != SPV_REFLECT_RESULT_SUCCESS )
571 std::ostringstream stream;
572 stream <<
"SPIR-V Reflect descriptor set enumeration failed: ( " <<
static_cast<int> ( result ) <<
" )";
574 throw std::runtime_error ( stream.str().c_str() );
577 if ( descriptor_set_count > 0 )
579 std::vector<SpvReflectDescriptorSet*> descriptor_sets ( descriptor_set_count );
580 result = spvReflectEnumerateDescriptorSets ( &aModule, &descriptor_set_count, descriptor_sets.data() );
581 if ( result != SPV_REFLECT_RESULT_SUCCESS )
583 std::ostringstream stream;
584 stream <<
"SPIR-V Reflect descriptor set enumeration failed: ( " <<
static_cast<int> ( result ) <<
" )";
586 throw std::runtime_error ( stream.str().c_str() );
588 for (
const auto& descriptor_set : descriptor_sets )
591 const char* type_name{ ( descriptor_set->binding_count == 1 ) && descriptor_set->bindings[0]->descriptor_type == SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER ?
592 descriptor_set->bindings[0]->type_description->type_name :
"Samplers"};
593 uint32_t hash =
crc32i ( type_name,
594 strlen ( type_name ) );
596 auto it = std::lower_bound ( mDescriptorSets.begin(), mDescriptorSets.end(), hash,
597 [] (
const VulkanDescriptorSetInfo & a,
const uint32_t b )
603 if ( it != mDescriptorSets.end() && it->hash == hash && it->set == descriptor_set->set )
606 for (
auto& binding : it->descriptor_set_layout_bindings )
614 it = mDescriptorSets.insert ( it,
615 VulkanDescriptorSetInfo
619 VkDescriptorSetLayoutCreateInfo
621 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
627 it->descriptor_set_layout_bindings.reserve ( descriptor_set->binding_count );
628 std::cout <<
LogLevel::Debug <<
"Descriptor set " << descriptor_set->set << std::endl;
630 for ( uint32_t i = 0; i < descriptor_set->binding_count; ++i )
632 const SpvReflectDescriptorBinding& descriptor_set_binding = *descriptor_set->bindings[i];
633 auto layout_binding = std::lower_bound ( it->descriptor_set_layout_bindings.begin(), it->descriptor_set_layout_bindings.end(), descriptor_set_binding.binding,
634 [] (
const VkDescriptorSetLayoutBinding & a,
const uint32_t b )
636 return a.binding < b;
639 if ( layout_binding == it->descriptor_set_layout_bindings.end() || layout_binding->binding != descriptor_set_binding.binding )
641 layout_binding = it->descriptor_set_layout_bindings.insert ( layout_binding, VkDescriptorSetLayoutBinding{} );
642 layout_binding->binding = descriptor_set_binding.binding;
643 layout_binding->descriptorType = ( hash ==
Mesh::BindingLocations::SKELETON ) ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC : SpvReflectToVulkanDescriptorType.at ( descriptor_set_binding.descriptor_type );
644 layout_binding->descriptorCount = descriptor_set_binding.count;
646 layout_binding->stageFlags = VK_SHADER_STAGE_ALL;
647 layout_binding->pImmutableSamplers =
nullptr;
648 std::cout <<
LogLevel::Debug <<
"Set " << descriptor_set_binding.set <<
" New Binding " << descriptor_set_binding.binding <<
" Type Name " << type_name <<
" Shader Type " <<
ShaderTypeToString.at ( aType ) << std::endl;
651 it->descriptor_set_layout_create_info.bindingCount =
static_cast<uint32_t
> ( it->descriptor_set_layout_bindings.size() );
652 it->descriptor_set_layout_create_info.pBindings = it->descriptor_set_layout_bindings.data();
659 auto it = std::lower_bound ( mDescriptorSets.begin(), mDescriptorSets.end(), hash,
664 if ( it != mDescriptorSets.end() && it->hash == hash )
668 return std::numeric_limits<uint32_t>::max();
673 return mPushConstantModelMatrix;
676 void VulkanPipeline::ReflectPushConstants ( SpvReflectShaderModule& aModule,
ShaderType aType )
679 uint32_t push_constant_count{0};
680 SpvReflectResult result{spvReflectEnumeratePushConstantBlocks ( &aModule, &push_constant_count,
nullptr ) };
681 if ( result != SPV_REFLECT_RESULT_SUCCESS )
683 std::ostringstream stream;
684 stream <<
"SPIR-V Reflect push constant enumeration failed: ( " <<
static_cast<int> ( result ) <<
" )";
686 throw std::runtime_error ( stream.str().c_str() );
689 if ( push_constant_count > 0 )
691 std::vector<SpvReflectBlockVariable*> push_constant_blocks ( push_constant_count );
692 result = spvReflectEnumeratePushConstantBlocks ( &aModule, &push_constant_count, push_constant_blocks.data() );
693 if ( result != SPV_REFLECT_RESULT_SUCCESS )
695 std::ostringstream stream;
696 stream <<
"SPIR-V Reflect push constant enumeration failed: ( " <<
static_cast<int> ( result ) <<
" )";
698 throw std::runtime_error ( stream.str().c_str() );
700 for (
const auto& push_constant_block : push_constant_blocks )
703 if ( push_constant_block->member_count == 1 && push_constant_block->members[0].name !=
nullptr &&
704 strcmp ( push_constant_block->members[0].name,
"ModelMatrix" ) == 0 )
707 mPushConstantModelMatrix.offset = push_constant_block->offset;
708 mPushConstantModelMatrix.size = push_constant_block->size;
709 std::cout <<
LogLevel::Debug <<
"Model Matrix Push Constant Offset: " << mPushConstantModelMatrix.offset
710 <<
" Size: " << mPushConstantModelMatrix.size
Defines log severity levels and stream output for the AeonGames engine.
Compiles and links GLSL shaders into SPIR-V bytecode.
FailCode
Process exit/result codes.
FailCode CompileAndLink()
Compile all added shader sources and link into a program.
const std::vector< uint32_t > & GetSpirV(EShLanguage aStage) const
Get the compiled SPIR-V bytecode for a shader stage.
void AddShaderSource(EShLanguage aStage, const char *aSource)
Add GLSL source code for a shader stage.
const std::string & GetLog() const
Get the compilation/link log output.
TOptions
Compiler/linker option flags.
@ WEIGHT_INDEX
Bone weight indices.
@ WEIGHT_VALUE
Bone weight values.
@ SKELETON
Skeleton binding.
Rendering pipeline resource.
static const uint32_t TOPOLOGY_CLASS_POINT
Point topology class bitmask.
static const uint32_t TOPOLOGY_CLASS_LINE
Line topology class bitmask.
static const uint32_t TOPOLOGY_CLASS_TRIANGLE
Triangle topology class bitmask.
DLL const std::string_view GetShaderCode(ShaderType aType) const
Get the shader source code for the given shader stage.
static const uint32_t TOPOLOGY_CLASS_PATCH
Patch topology class bitmask.
VulkanPipeline(const VulkanRenderer &aVulkanRenderer, const Pipeline &aPipeline)
Construct from a renderer and pipeline resource.
const Pipeline * GetPipeline() const
Get the source Pipeline resource.
const VkDescriptorSetLayout GetDescriptorSetLayout(uint32_t name) const
Get a descriptor set layout by its name hash.
uint32_t GetDescriptorSetIndex(uint32_t hash) const
Get the descriptor set index for a given hash.
const VkPipeline GetVkPipeline() const
Get the Vulkan pipeline handle.
const VkPushConstantRange & GetPushConstantModelMatrix() const
Get the push constant range used for the model matrix.
const VkPipelineLayout GetPipelineLayout() const
Get the Vulkan pipeline layout handle.
Vulkan rendering backend implementing the Renderer interface.
const VkDevice & GetDevice() const
Get the logical device handle.
<- This is here just for the literals
DLL bool operator!=(const Vector3 &aLhs, const Vector3 &aRhs)
Inequality comparison operator.
uint32_t crc32i(const char *message, size_t size, uint32_t previous_crc)
Compute the CRC32 of a given message, continuing from a previous CRC value.
const char * GetVulkanResultString(VkResult aResult)
Convert a VkResult code to a human-readable string.
const std::unordered_map< ShaderType, const char * > ShaderTypeToString
Map from ShaderType enum values to human-readable string names.
std::array< VkShaderStageFlagBits, ShaderType::COUNT > ShaderTypeToShaderStageFlagBit
Mapping from ShaderType to VkShaderStageFlagBits.
ShaderType
Shader stage types.
@ COUNT
Number of shader types.
@ TESC
Tessellation control shader.
@ TESE
Tessellation evaluation shader.
@ Debug
Detailed diagnostic information.
std::array< EShLanguage, ShaderType::COUNT > ShaderTypeToEShLanguage
Mapping from ShaderType to glslang EShLanguage.
Holds Vulkan descriptor set layout metadata for pipeline reflection.