2022-04-03 18:22:53 +02:00
/*
* Vulkan Example - Using VK_EXT_graphics_pipeline_library
*
* Important note : Work - in - progress , sample is not finished yet
*
* Copyright ( C ) 2022 by Sascha Willems - www . saschawillems . de
*
* This code is licensed under the MIT license ( MIT ) ( http : //opensource.org/licenses/MIT)
*/
# include "vulkanexamplebase.h"
# include "VulkanglTFModel.h"
# define ENABLE_VALIDATION false
class VulkanExample : public VulkanExampleBase
{
public :
vkglTF : : Model scene ;
vks : : Buffer uniformBuffer ;
// Same uniform buffer layout as shader
struct UBOVS {
glm : : mat4 projection ;
glm : : mat4 modelView ;
glm : : vec4 lightPos = glm : : vec4 ( 0.0f , 2.0f , 1.0f , 0.0f ) ;
} uboVS ;
VkPipelineLayout pipelineLayout ;
VkDescriptorSet descriptorSet ;
VkDescriptorSetLayout descriptorSetLayout ;
VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT graphicsPipelineLibraryFeatures { } ;
struct {
VkPipeline phong ;
VkPipeline wireframe ;
VkPipeline toon ;
} pipelines ;
2022-04-04 09:58:46 +02:00
struct ShaderInfo {
uint32_t * code ;
size_t size ;
} ;
2022-04-03 18:22:53 +02:00
VulkanExample ( ) : VulkanExampleBase ( ENABLE_VALIDATION )
{
title = " Graphics pipeline library " ;
camera . type = Camera : : CameraType : : lookat ;
camera . setPosition ( glm : : vec3 ( 0.0f , 0.0f , - 10.5f ) ) ;
camera . setRotation ( glm : : vec3 ( - 25.0f , 15.0f , 0.0f ) ) ;
camera . setRotationSpeed ( 0.5f ) ;
camera . setPerspective ( 60.0f , ( float ) ( width / 3.0f ) / ( float ) height , 0.1f , 256.0f ) ;
// Enable required extensions
enabledInstanceExtensions . push_back ( VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME ) ;
enabledDeviceExtensions . push_back ( VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME ) ;
enabledDeviceExtensions . push_back ( VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME ) ;
// Enable required extension features
graphicsPipelineLibraryFeatures . sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT ;
graphicsPipelineLibraryFeatures . graphicsPipelineLibrary = VK_TRUE ;
deviceCreatepNextChain = & graphicsPipelineLibraryFeatures ;
}
~ VulkanExample ( )
{
// Clean up used Vulkan resources
// Note : Inherited destructor cleans up resources stored in base class
vkDestroyPipeline ( device , pipelines . phong , nullptr ) ;
if ( deviceFeatures . fillModeNonSolid )
{
vkDestroyPipeline ( device , pipelines . wireframe , nullptr ) ;
}
vkDestroyPipeline ( device , pipelines . toon , nullptr ) ;
vkDestroyPipelineLayout ( device , pipelineLayout , nullptr ) ;
vkDestroyDescriptorSetLayout ( device , descriptorSetLayout , nullptr ) ;
uniformBuffer . destroy ( ) ;
}
// Enable physical device features required for this example
virtual void getEnabledFeatures ( )
{
// Fill mode non solid is required for wireframe display
if ( deviceFeatures . fillModeNonSolid ) {
enabledFeatures . fillModeNonSolid = VK_TRUE ;
// Wide lines must be present for line width > 1.0f
if ( deviceFeatures . wideLines ) {
enabledFeatures . wideLines = VK_TRUE ;
}
} ;
}
void buildCommandBuffers ( )
{
VkCommandBufferBeginInfo cmdBufInfo = vks : : initializers : : commandBufferBeginInfo ( ) ;
VkClearValue clearValues [ 2 ] ;
clearValues [ 0 ] . color = defaultClearColor ;
clearValues [ 1 ] . depthStencil = { 1.0f , 0 } ;
VkRenderPassBeginInfo renderPassBeginInfo = vks : : initializers : : renderPassBeginInfo ( ) ;
renderPassBeginInfo . renderPass = renderPass ;
renderPassBeginInfo . renderArea . offset . x = 0 ;
renderPassBeginInfo . renderArea . offset . y = 0 ;
renderPassBeginInfo . renderArea . extent . width = width ;
renderPassBeginInfo . renderArea . extent . height = height ;
renderPassBeginInfo . clearValueCount = 2 ;
renderPassBeginInfo . pClearValues = clearValues ;
for ( int32_t i = 0 ; i < drawCmdBuffers . size ( ) ; + + i )
{
// Set target frame buffer
renderPassBeginInfo . framebuffer = frameBuffers [ i ] ;
VK_CHECK_RESULT ( vkBeginCommandBuffer ( drawCmdBuffers [ i ] , & cmdBufInfo ) ) ;
vkCmdBeginRenderPass ( drawCmdBuffers [ i ] , & renderPassBeginInfo , VK_SUBPASS_CONTENTS_INLINE ) ;
VkViewport viewport = vks : : initializers : : viewport ( ( float ) width , ( float ) height , 0.0f , 1.0f ) ;
vkCmdSetViewport ( drawCmdBuffers [ i ] , 0 , 1 , & viewport ) ;
VkRect2D scissor = vks : : initializers : : rect2D ( width , height , 0 , 0 ) ;
vkCmdSetScissor ( drawCmdBuffers [ i ] , 0 , 1 , & scissor ) ;
vkCmdBindDescriptorSets ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelineLayout , 0 , 1 , & descriptorSet , 0 , NULL ) ;
scene . bindBuffers ( drawCmdBuffers [ i ] ) ;
// Left : Solid colored
viewport . width = ( float ) width / 3.0 ;
vkCmdSetViewport ( drawCmdBuffers [ i ] , 0 , 1 , & viewport ) ;
vkCmdBindPipeline ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelines . phong ) ;
scene . draw ( drawCmdBuffers [ i ] ) ;
// Center : Toon
viewport . x = ( float ) width / 3.0 ;
vkCmdSetViewport ( drawCmdBuffers [ i ] , 0 , 1 , & viewport ) ;
vkCmdBindPipeline ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelines . toon ) ;
// Line width > 1.0f only if wide lines feature is supported
if ( deviceFeatures . wideLines ) {
vkCmdSetLineWidth ( drawCmdBuffers [ i ] , 2.0f ) ;
}
scene . draw ( drawCmdBuffers [ i ] ) ;
if ( deviceFeatures . fillModeNonSolid )
{
// Right : Wireframe
viewport . x = ( float ) width / 3.0 + ( float ) width / 3.0 ;
vkCmdSetViewport ( drawCmdBuffers [ i ] , 0 , 1 , & viewport ) ;
vkCmdBindPipeline ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelines . wireframe ) ;
scene . draw ( drawCmdBuffers [ i ] ) ;
}
drawUI ( drawCmdBuffers [ i ] ) ;
vkCmdEndRenderPass ( drawCmdBuffers [ i ] ) ;
VK_CHECK_RESULT ( vkEndCommandBuffer ( drawCmdBuffers [ i ] ) ) ;
}
}
void loadAssets ( )
{
const uint32_t glTFLoadingFlags = vkglTF : : FileLoadingFlags : : PreTransformVertices | vkglTF : : FileLoadingFlags : : PreMultiplyVertexColors | vkglTF : : FileLoadingFlags : : FlipY ;
scene . loadFromFile ( getAssetPath ( ) + " models/treasure_smooth.gltf " , vulkanDevice , queue , glTFLoadingFlags ) ;
}
void setupDescriptorPool ( )
{
std : : vector < VkDescriptorPoolSize > poolSizes =
{
vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , 1 )
} ;
VkDescriptorPoolCreateInfo descriptorPoolInfo =
vks : : initializers : : descriptorPoolCreateInfo (
poolSizes . size ( ) ,
poolSizes . data ( ) ,
2 ) ;
VK_CHECK_RESULT ( vkCreateDescriptorPool ( device , & descriptorPoolInfo , nullptr , & descriptorPool ) ) ;
}
void setupDescriptorSetLayout ( )
{
std : : vector < VkDescriptorSetLayoutBinding > setLayoutBindings =
{
// Binding 0 : Vertex shader uniform buffer
vks : : initializers : : descriptorSetLayoutBinding (
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ,
VK_SHADER_STAGE_VERTEX_BIT ,
0 )
} ;
VkDescriptorSetLayoutCreateInfo descriptorLayout =
vks : : initializers : : descriptorSetLayoutCreateInfo (
setLayoutBindings . data ( ) ,
setLayoutBindings . size ( ) ) ;
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( device , & descriptorLayout , nullptr , & descriptorSetLayout ) ) ;
VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
vks : : initializers : : pipelineLayoutCreateInfo (
& descriptorSetLayout ,
1 ) ;
VK_CHECK_RESULT ( vkCreatePipelineLayout ( device , & pPipelineLayoutCreateInfo , nullptr , & pipelineLayout ) ) ;
}
void setupDescriptorSet ( )
{
VkDescriptorSetAllocateInfo allocInfo =
vks : : initializers : : descriptorSetAllocateInfo (
descriptorPool ,
& descriptorSetLayout ,
1 ) ;
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( device , & allocInfo , & descriptorSet ) ) ;
std : : vector < VkWriteDescriptorSet > writeDescriptorSets =
{
// Binding 0 : Vertex shader uniform buffer
vks : : initializers : : writeDescriptorSet (
descriptorSet ,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ,
0 ,
& uniformBuffer . descriptor )
} ;
vkUpdateDescriptorSets ( device , writeDescriptorSets . size ( ) , writeDescriptorSets . data ( ) , 0 , NULL ) ;
}
2022-04-04 09:58:46 +02:00
// With VK_EXT_graphics_pipeline_library we don't need to create the shader module when loading it, but instead have the driver create it at linking time
// So we use a custom function that only loads the required shader information without actually creating the shader module
# if defined(__ANDROID__)
// Android shaders are stored as assets in the apk so they need to be loaded via the asset manager
bool loadShader ( AAssetManager * assetManager , std : : string fileName , const uint32_t * * pShaderCode , size_t & shaderSize )
{
// Load shader from compressed asset
AAsset * asset = AAssetManager_open ( assetManager , fileName , AASSET_MODE_STREAMING ) ;
assert ( asset ) ;
size_t size = AAsset_getLength ( asset ) ;
assert ( size > 0 ) ;
char * shaderCode = new char [ size ] ;
AAsset_read ( asset , shaderCode , size ) ;
AAsset_close ( asset ) ;
VkShaderModule shaderModule ;
VkShaderModuleCreateInfo moduleCreateInfo ;
moduleCreateInfo . sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO ;
moduleCreateInfo . pNext = NULL ;
moduleCreateInfo . codeSize = size ;
moduleCreateInfo . pCode = ( uint32_t * ) shaderCode ;
moduleCreateInfo . flags = 0 ;
VK_CHECK_RESULT ( vkCreateShaderModule ( device , & moduleCreateInfo , NULL , & shaderModule ) ) ;
delete [ ] shaderCode ;
return shaderModule ;
}
# else
bool loadShaderFile ( std : : string fileName , ShaderInfo & shaderInfo )
{
std : : ifstream is ( fileName , std : : ios : : binary | std : : ios : : in | std : : ios : : ate ) ;
if ( is . is_open ( ) )
{
shaderInfo . size = is . tellg ( ) ;
is . seekg ( 0 , std : : ios : : beg ) ;
shaderInfo . code = new uint32_t [ shaderInfo . size ] ;
is . read ( reinterpret_cast < char * > ( shaderInfo . code ) , shaderInfo . size ) ;
is . close ( ) ;
return true ;
} else {
std : : cerr < < " Error: Could not open shader file \" " < < fileName < < " \" " < < " \n " ;
return false ;
}
}
# endif
2022-04-03 20:15:50 +02:00
VkPipeline createVertexInputState ( VkDevice device , VkPipelineCache vertexShaderCache , VkPipelineLayout layout )
{
VkGraphicsPipelineLibraryCreateInfoEXT libraryInfo { } ;
libraryInfo . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT ;
libraryInfo . flags = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT ;
VkPipelineVertexInputStateCreateInfo vertexInputState = * vkglTF : : Vertex : : getPipelineVertexInputState ( { vkglTF : : VertexComponent : : Position , vkglTF : : VertexComponent : : Normal , vkglTF : : VertexComponent : : Color } ) ;
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks : : initializers : : pipelineInputAssemblyStateCreateInfo ( VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , 0 , VK_FALSE ) ;
VkGraphicsPipelineCreateInfo vertexShaderCreateInfo { } ;
vertexShaderCreateInfo . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO ;
vertexShaderCreateInfo . pNext = & libraryInfo ;
vertexShaderCreateInfo . pInputAssemblyState = & inputAssemblyState ;
vertexShaderCreateInfo . pVertexInputState = & vertexInputState ;
VkPipeline vertexInputStateP ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , vertexShaderCache , 1 , & vertexShaderCreateInfo , nullptr , & vertexInputStateP ) ) ;
return vertexInputStateP ;
}
2022-04-04 09:58:46 +02:00
VkPipeline createVertexShader ( VkDevice device , const ShaderInfo shaderInfo , VkPipelineCache vertexShaderCache , VkPipelineLayout layout )
2022-04-03 18:22:53 +02:00
{
VkGraphicsPipelineLibraryCreateInfoEXT libraryInfo { } ;
libraryInfo . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT ;
libraryInfo . flags = VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT ;
VkDynamicState vertexDynamicStates [ 2 ] = {
VK_DYNAMIC_STATE_VIEWPORT ,
VK_DYNAMIC_STATE_SCISSOR } ;
VkPipelineDynamicStateCreateInfo dynamicInfo { } ;
dynamicInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO ;
dynamicInfo . dynamicStateCount = 2 ;
dynamicInfo . pDynamicStates = vertexDynamicStates ;
VkPipelineViewportStateCreateInfo viewportState = { } ;
viewportState . sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO ;
viewportState . viewportCount = 1 ;
viewportState . scissorCount = 1 ;
VkPipelineRasterizationStateCreateInfo rasterizationState = vks : : initializers : : pipelineRasterizationStateCreateInfo ( VK_POLYGON_MODE_FILL , VK_CULL_MODE_BACK_BIT , VK_FRONT_FACE_COUNTER_CLOCKWISE , 0 ) ;
2022-04-04 09:58:46 +02:00
VkShaderModuleCreateInfo shaderModuleCreateInfo { } ;
shaderModuleCreateInfo . sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO ;
shaderModuleCreateInfo . codeSize = shaderInfo . size ;
shaderModuleCreateInfo . pCode = shaderInfo . code ;
VkPipelineShaderStageCreateInfo shaderStageCreateInfo { } ;
shaderStageCreateInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO ;
shaderStageCreateInfo . pNext = & shaderModuleCreateInfo ;
shaderStageCreateInfo . stage = VK_SHADER_STAGE_VERTEX_BIT ;
shaderStageCreateInfo . pName = " main " ;
2022-04-03 18:22:53 +02:00
VkGraphicsPipelineCreateInfo vertexShaderCreateInfo { } ;
vertexShaderCreateInfo . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO ;
vertexShaderCreateInfo . pNext = & libraryInfo ;
vertexShaderCreateInfo . renderPass = renderPass ;
vertexShaderCreateInfo . flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT ;
vertexShaderCreateInfo . stageCount = 1 ;
vertexShaderCreateInfo . pStages = & shaderStageCreateInfo ;
vertexShaderCreateInfo . layout = layout ;
vertexShaderCreateInfo . pDynamicState = & dynamicInfo ;
vertexShaderCreateInfo . pViewportState = & viewportState ;
vertexShaderCreateInfo . pRasterizationState = & rasterizationState ;
VkPipeline vertexShader ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , vertexShaderCache , 1 , & vertexShaderCreateInfo , nullptr , & vertexShader ) ) ;
return vertexShader ;
}
2022-04-04 09:58:46 +02:00
VkPipeline createFragmentShader ( VkDevice device , const ShaderInfo shaderInfo , VkPipelineCache vertexShaderCache , VkPipelineLayout layout )
2022-04-03 18:22:53 +02:00
{
VkGraphicsPipelineLibraryCreateInfoEXT libraryInfo { } ;
libraryInfo . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT ;
libraryInfo . flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT ;
VkPipelineDepthStencilStateCreateInfo depthStencilState = vks : : initializers : : pipelineDepthStencilStateCreateInfo ( VK_TRUE , VK_TRUE , VK_COMPARE_OP_LESS_OR_EQUAL ) ;
2022-04-03 20:15:50 +02:00
VkPipelineMultisampleStateCreateInfo multisampleState = vks : : initializers : : pipelineMultisampleStateCreateInfo ( VK_SAMPLE_COUNT_1_BIT ) ;
2022-04-03 18:22:53 +02:00
2022-04-04 09:58:46 +02:00
VkShaderModuleCreateInfo shaderModuleCreateInfo { } ;
shaderModuleCreateInfo . sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO ;
shaderModuleCreateInfo . codeSize = shaderInfo . size ;
shaderModuleCreateInfo . pCode = shaderInfo . code ;
VkPipelineShaderStageCreateInfo shaderStageCreateInfo { } ;
shaderStageCreateInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO ;
shaderStageCreateInfo . pNext = & shaderModuleCreateInfo ;
shaderStageCreateInfo . stage = VK_SHADER_STAGE_FRAGMENT_BIT ;
shaderStageCreateInfo . pName = " main " ;
2022-04-03 18:22:53 +02:00
VkGraphicsPipelineCreateInfo fragmentShaderCreateInfo { } ;
fragmentShaderCreateInfo . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO ;
fragmentShaderCreateInfo . pNext = & libraryInfo ;
fragmentShaderCreateInfo . flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT ;
fragmentShaderCreateInfo . stageCount = 1 ;
fragmentShaderCreateInfo . pStages = & shaderStageCreateInfo ;
fragmentShaderCreateInfo . layout = layout ;
fragmentShaderCreateInfo . renderPass = renderPass ;
fragmentShaderCreateInfo . pDepthStencilState = & depthStencilState ;
2022-04-03 20:15:50 +02:00
fragmentShaderCreateInfo . pMultisampleState = & multisampleState ;
VkPipeline fragmentShader ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , vertexShaderCache , 1 , & fragmentShaderCreateInfo , nullptr , & fragmentShader ) ) ;
return fragmentShader ;
}
VkPipeline createFragmentOutputState ( VkDevice device , VkPipelineCache vertexShaderCache , VkPipelineLayout layout )
{
VkGraphicsPipelineLibraryCreateInfoEXT libraryInfo { } ;
libraryInfo . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT ;
libraryInfo . flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT ;
VkPipelineColorBlendAttachmentState blendAttachmentState = vks : : initializers : : pipelineColorBlendAttachmentState ( 0xf , VK_FALSE ) ;
VkPipelineColorBlendStateCreateInfo colorBlendState = vks : : initializers : : pipelineColorBlendStateCreateInfo ( 1 , & blendAttachmentState ) ;
VkPipelineMultisampleStateCreateInfo multisampleState = vks : : initializers : : pipelineMultisampleStateCreateInfo ( VK_SAMPLE_COUNT_1_BIT ) ;
VkGraphicsPipelineCreateInfo fragmentShaderCreateInfo { } ;
fragmentShaderCreateInfo . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO ;
fragmentShaderCreateInfo . pNext = & libraryInfo ;
fragmentShaderCreateInfo . flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT ;
fragmentShaderCreateInfo . layout = layout ;
fragmentShaderCreateInfo . renderPass = renderPass ;
fragmentShaderCreateInfo . pColorBlendState = & colorBlendState ;
fragmentShaderCreateInfo . pMultisampleState = & multisampleState ;
2022-04-03 18:22:53 +02:00
VkPipeline fragmentShader ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , vertexShaderCache , 1 , & fragmentShaderCreateInfo , nullptr , & fragmentShader ) ) ;
return fragmentShader ;
}
VkPipeline linkExecutable ( VkDevice device , const std : : vector < VkPipeline > libraries , VkPipelineCache executableCache , bool optimized )
{
VkPipelineLibraryCreateInfoKHR linkingInfo { } ;
linkingInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR ;
linkingInfo . libraryCount = static_cast < uint32_t > ( libraries . size ( ) ) ;
linkingInfo . pLibraries = libraries . data ( ) ;
VkGraphicsPipelineCreateInfo executablePipelineCreateInfo { } ;
executablePipelineCreateInfo . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO ;
executablePipelineCreateInfo . pNext = & linkingInfo ;
executablePipelineCreateInfo . flags | = optimized ? VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT : 0 ;
VkPipeline executable = VK_NULL_HANDLE ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , executableCache , 1 , & executablePipelineCreateInfo , nullptr , & executable ) ) ;
return executable ;
}
void preparePipelines ( )
{
2022-04-04 09:58:46 +02:00
struct Shaders {
ShaderInfo phongVS ;
ShaderInfo phongFS ;
} shaders ;
loadShaderFile ( getShadersPath ( ) + " pipelines/phong.vert.spv " , shaders . phongVS ) ;
loadShaderFile ( getShadersPath ( ) + " pipelines/phong.frag.spv " , shaders . phongFS ) ;
2022-04-03 18:22:53 +02:00
VkPipelineShaderStageCreateInfo vsShader = loadShader ( getShadersPath ( ) + " pipelines/phong.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ;
VkPipelineShaderStageCreateInfo fsShader = loadShader ( getShadersPath ( ) + " pipelines/phong.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
std : : vector < VkPipeline > libraries = {
2022-04-03 20:15:50 +02:00
createVertexInputState ( device , pipelineCache , pipelineLayout ) ,
2022-04-04 09:58:46 +02:00
createVertexShader ( device , shaders . phongVS , pipelineCache , pipelineLayout ) ,
createFragmentShader ( device , shaders . phongFS , pipelineCache , pipelineLayout ) ,
2022-04-03 20:15:50 +02:00
createFragmentOutputState ( device , pipelineCache , pipelineLayout ) ,
2022-04-03 18:22:53 +02:00
} ;
VkPipeline compiledPipeline = linkExecutable ( device , libraries , pipelineCache , true ) ;
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks : : initializers : : pipelineInputAssemblyStateCreateInfo ( VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , 0 , VK_FALSE ) ;
VkPipelineRasterizationStateCreateInfo rasterizationState = vks : : initializers : : pipelineRasterizationStateCreateInfo ( VK_POLYGON_MODE_FILL , VK_CULL_MODE_BACK_BIT , VK_FRONT_FACE_COUNTER_CLOCKWISE , 0 ) ;
VkPipelineColorBlendAttachmentState blendAttachmentState = vks : : initializers : : pipelineColorBlendAttachmentState ( 0xf , VK_FALSE ) ;
VkPipelineColorBlendStateCreateInfo colorBlendState = vks : : initializers : : pipelineColorBlendStateCreateInfo ( 1 , & blendAttachmentState ) ;
VkPipelineDepthStencilStateCreateInfo depthStencilState = vks : : initializers : : pipelineDepthStencilStateCreateInfo ( VK_TRUE , VK_TRUE , VK_COMPARE_OP_LESS_OR_EQUAL ) ;
VkPipelineViewportStateCreateInfo viewportState = vks : : initializers : : pipelineViewportStateCreateInfo ( 1 , 1 , 0 ) ;
VkPipelineMultisampleStateCreateInfo multisampleState = vks : : initializers : : pipelineMultisampleStateCreateInfo ( VK_SAMPLE_COUNT_1_BIT ) ;
std : : vector < VkDynamicState > dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT , VK_DYNAMIC_STATE_SCISSOR , VK_DYNAMIC_STATE_LINE_WIDTH , } ;
VkPipelineDynamicStateCreateInfo dynamicState = vks : : initializers : : pipelineDynamicStateCreateInfo ( dynamicStateEnables ) ;
std : : array < VkPipelineShaderStageCreateInfo , 2 > shaderStages ;
VkGraphicsPipelineCreateInfo pipelineCI = vks : : initializers : : pipelineCreateInfo ( pipelineLayout , renderPass ) ;
pipelineCI . pInputAssemblyState = & inputAssemblyState ;
pipelineCI . pRasterizationState = & rasterizationState ;
pipelineCI . pColorBlendState = & colorBlendState ;
pipelineCI . pMultisampleState = & multisampleState ;
pipelineCI . pViewportState = & viewportState ;
pipelineCI . pDepthStencilState = & depthStencilState ;
pipelineCI . pDynamicState = & dynamicState ;
pipelineCI . stageCount = shaderStages . size ( ) ;
pipelineCI . pStages = shaderStages . data ( ) ;
pipelineCI . pVertexInputState = vkglTF : : Vertex : : getPipelineVertexInputState ( { vkglTF : : VertexComponent : : Position , vkglTF : : VertexComponent : : Normal , vkglTF : : VertexComponent : : Color } ) ;
// Create the graphics pipeline state objects
// Textured pipeline
// Phong shading pipeline
2022-04-03 20:15:50 +02:00
//shaderStages[0] = loadShader(getShadersPath() + "pipelines/phong.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
//shaderStages[1] = loadShader(getShadersPath() + "pipelines/phong.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
//VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.phong));
pipelines . phong = compiledPipeline ;
2022-04-03 18:22:53 +02:00
// Toon shading pipeline
shaderStages [ 0 ] = loadShader ( getShadersPath ( ) + " pipelines/toon.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ;
shaderStages [ 1 ] = loadShader ( getShadersPath ( ) + " pipelines/toon.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCI , nullptr , & pipelines . toon ) ) ;
// Pipeline for wire frame rendering
// Non solid rendering is not a mandatory Vulkan feature
if ( deviceFeatures . fillModeNonSolid )
{
rasterizationState . polygonMode = VK_POLYGON_MODE_LINE ;
shaderStages [ 0 ] = loadShader ( getShadersPath ( ) + " pipelines/wireframe.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ;
shaderStages [ 1 ] = loadShader ( getShadersPath ( ) + " pipelines/wireframe.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCI , nullptr , & pipelines . wireframe ) ) ;
}
}
// Prepare and initialize uniform buffer containing shader uniforms
void prepareUniformBuffers ( )
{
// Create the vertex shader uniform buffer block
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ,
& uniformBuffer ,
sizeof ( uboVS ) ) ) ;
// Map persistent
VK_CHECK_RESULT ( uniformBuffer . map ( ) ) ;
updateUniformBuffers ( ) ;
}
void updateUniformBuffers ( )
{
uboVS . projection = camera . matrices . perspective ;
uboVS . modelView = camera . matrices . view ;
memcpy ( uniformBuffer . mapped , & uboVS , sizeof ( uboVS ) ) ;
}
void draw ( )
{
VulkanExampleBase : : prepareFrame ( ) ;
submitInfo . commandBufferCount = 1 ;
submitInfo . pCommandBuffers = & drawCmdBuffers [ currentBuffer ] ;
VK_CHECK_RESULT ( vkQueueSubmit ( queue , 1 , & submitInfo , VK_NULL_HANDLE ) ) ;
VulkanExampleBase : : submitFrame ( ) ;
}
void prepare ( )
{
VulkanExampleBase : : prepare ( ) ;
loadAssets ( ) ;
prepareUniformBuffers ( ) ;
setupDescriptorSetLayout ( ) ;
preparePipelines ( ) ;
setupDescriptorPool ( ) ;
setupDescriptorSet ( ) ;
buildCommandBuffers ( ) ;
prepared = true ;
}
virtual void render ( )
{
if ( ! prepared )
return ;
draw ( ) ;
if ( camera . updated ) {
updateUniformBuffers ( ) ;
}
}
virtual void OnUpdateUIOverlay ( vks : : UIOverlay * overlay )
{
if ( ! deviceFeatures . fillModeNonSolid ) {
if ( overlay - > header ( " Info " ) ) {
overlay - > text ( " Non solid fill modes not supported! " ) ;
}
}
}
} ;
VULKAN_EXAMPLE_MAIN ( )