2019-01-11 00:48:33 -08:00
//
2019-12-01 15:49:49 -08:00
// KRPipeline.cpp
2021-08-16 16:35:36 -07:00
// Kraken Engine
2019-01-11 00:48:33 -08:00
//
2022-04-03 21:56:23 -07:00
// Copyright 2022 Kearwood Gilbert. All rights reserved.
2019-01-11 00:48:33 -08:00
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
2019-12-01 15:49:49 -08:00
# include "KRPipeline.h"
2019-01-11 00:48:33 -08:00
# include "assert.h"
# include "KRLight.h"
# include "KRDirectionalLight.h"
# include "KRSpotLight.h"
# include "KRPointLight.h"
2021-08-11 01:11:52 -07:00
# include "KRContext.h"
2022-03-27 21:56:45 -07:00
# include "KRRenderPass.h"
2019-01-11 00:48:33 -08:00
2022-09-07 23:48:46 -07:00
const char * KRPipeline : : KRENGINE_PUSH_CONSTANT_NAMES [ ] = {
" material_ambient " , // PushConstant::material_ambient
" material_diffuse " , // PushConstant::material_diffuse
" material_specular " , // PushConstant::material_specular
" material_reflection " , // PushConstant::material_reflection
" material_alpha " , // PushConstant::material_alpha
" material_shininess " , // PushConstant::material_shininess
" light_position " , // PushConstant::light_position
" light_direction_model_space " , // PushConstant::light_direction_model_space
" light_direction_view_space " , // PushConstant::light_direction_view_space
" light_color " , // PushConstant::light_color
" light_decay_start " , // PushConstant::light_decay_start
" light_cutoff " , // PushConstant::light_cutoff
" light_intensity " , // PushConstant::light_intensity
" flare_size " , // PushConstant::flare_size
" view_space_model_origin " , // PushConstant::view_space_model_origin
" mvp_matrix " , // PushConstant::mvp
" inv_projection_matrix " , // PushConstant::invp
" inv_mvp_matrix " , // PushConstant::invmvp
" inv_mvp_matrix_no_translate " , // PushConstant::invmvp_no_translate
" model_view_inverse_transpose_matrix " , // PushConstant::model_view_inverse_transpose
" model_inverse_transpose_matrix " , // PushConstant::model_inverse_transpose
" model_view_matrix " , // PushConstant::model_view
" model_matrix " , // PushConstant::model_matrix
" projection_matrix " , // PushConstant::projection_matrix
" camera_position_model_space " , // PushConstant::camerapos_model_space
" viewport " , // PushConstant::viewport
" diffuseTexture " , // PushConstant::diffusetexture
" specularTexture " , // PushConstant::speculartexture
" reflectionCubeTexture " , // PushConstant::reflectioncubetexture
" reflectionTexture " , // PushConstant::reflectiontexture
" normalTexture " , // PushConstant::normaltexture
" diffuseTexture_Scale " , // PushConstant::diffusetexture_scale
" specularTexture_Scale " , // PushConstant::speculartexture_scale
" reflectionTexture_Scale " , // PushConstant::reflectiontexture_scale
" normalTexture_Scale " , // PushConstant::normaltexture_scale
" normalTexture_Scale " , // PushConstant::ambienttexture_scale
" diffuseTexture_Offset " , // PushConstant::diffusetexture_offset
" specularTexture_Offset " , // PushConstant::speculartexture_offset
" reflectionTexture_Offset " , // PushConstant::reflectiontexture_offset
" normalTexture_Offset " , // PushConstant::normaltexture_offset
" ambientTexture_Offset " , // PushConstant::ambienttexture_offset
" shadow_mvp1 " , // PushConstant::shadow_mvp1
" shadow_mvp2 " , // PushConstant::shadow_mvp2
" shadow_mvp3 " , // PushConstant::shadow_mvp3
" shadowTexture1 " , // PushConstant::shadowtexture1
" shadowTexture2 " , // PushConstant::shadowtexture2
" shadowTexture3 " , // PushConstant::shadowtexture3
" lightmapTexture " , // PushConstant::lightmaptexture
" gbuffer_frame " , // PushConstant::gbuffer_frame
" gbuffer_depth " , // PushConstant::gbuffer_depth
" depthFrame " , // PushConstant::depth_frame
" volumetricEnvironmentFrame " , // PushConstant::volumetric_environment_frame
" renderFrame " , // PushConstant::render_frame
" time_absolute " , // PushConstant::absolute_time
" fog_near " , // PushConstant::fog_near
" fog_far " , // PushConstant::fog_far
" fog_density " , // PushConstant::fog_density
" fog_color " , // PushConstant::fog_color
" fog_scale " , // PushConstant::fog_scale
" fog_density_premultiplied_exponential " , // PushConstant::density_premultiplied_exponential
" fog_density_premultiplied_squared " , // PushConstant::density_premultiplied_squared
" slice_depth_scale " , // PushConstant::slice_depth_scale
" particle_origin " , // PushConstant::particle_origin
" bone_transforms " , // PushConstant::bone_transforms
" rim_color " , // PushConstant::rim_color
" rim_power " , // PushConstant::rim_power
" fade_color " , // PushConstant::fade_color
2019-01-11 00:48:33 -08:00
} ;
2022-07-07 22:51:16 -07:00
KRPipeline : : KRPipeline ( KRContext & context , KRSurface & surface , const PipelineInfo & info , const char * szKey , const std : : vector < KRShader * > & shaders , uint32_t vertexAttributes , ModelFormat modelFormat )
2022-09-27 18:58:00 -07:00
: KRPipeline ( context , surface . m_deviceHandle , surface . getForwardOpaquePass ( ) , surface . getDimensions ( ) , surface . getDimensions ( ) , info , szKey , shaders , vertexAttributes , modelFormat )
{
// TODO - renderPass needs to be selected dynamically from info.render_pass
}
KRPipeline : : KRPipeline ( KRContext & context , KrDeviceHandle deviceHandle , KRRenderPass & renderPass , Vector2i viewport_size , Vector2i scissor_size , const PipelineInfo & info , const char * szKey , const std : : vector < KRShader * > & shaders , uint32_t vertexAttributes , ModelFormat modelFormat )
2021-08-10 20:13:32 -07:00
: KRContextObject ( context )
2022-09-27 18:58:00 -07:00
, m_deviceHandle ( deviceHandle )
2021-08-10 20:13:32 -07:00
{
2022-09-27 18:58:00 -07:00
std : : unique_ptr < KRDevice > & device = getContext ( ) . getDeviceManager ( ) - > getDevice ( m_deviceHandle ) ;
2022-09-15 20:33:41 -07:00
for ( StageInfo & stageInfo : m_stages ) {
PushConstantInfo & pushConstants = stageInfo . pushConstants ;
2022-08-06 00:14:21 -07:00
pushConstants . buffer = nullptr ;
pushConstants . bufferSize = 0 ;
2022-09-07 23:48:46 -07:00
memset ( pushConstants . size , 0 , kPushConstantCount ) ;
memset ( pushConstants . offset , 0 , kPushConstantCount * sizeof ( int ) ) ;
2022-08-06 00:14:21 -07:00
pushConstants . layout = nullptr ;
2022-08-02 00:43:36 -07:00
}
2022-07-07 19:29:50 -07:00
2022-09-07 22:33:07 -07:00
m_descriptorSetLayout = nullptr ;
2021-08-11 17:46:26 -07:00
m_pipelineLayout = nullptr ;
2021-08-11 01:11:52 -07:00
m_graphicsPipeline = nullptr ;
2022-09-20 18:54:01 -07:00
m_descriptorSets . reserve ( KRENGINE_MAX_FRAMES_IN_FLIGHT ) ;
2022-02-27 23:51:29 -08:00
2022-01-22 01:32:32 -08:00
// TODO - Handle device removal
2021-08-11 00:25:38 -07:00
2021-08-10 20:13:32 -07:00
strcpy ( m_szKey , szKey ) ;
const int kMaxStages = 4 ;
VkPipelineShaderStageCreateInfo stages [ kMaxStages ] ;
memset ( static_cast < void * > ( stages ) , 0 , sizeof ( VkPipelineShaderStageCreateInfo ) * kMaxStages ) ;
size_t stage_count = 0 ;
2022-09-07 22:33:07 -07:00
std : : vector < VkDescriptorSetLayoutBinding > uboLayoutBindings ;
2022-02-27 23:51:29 -08:00
// TODO - Refactor this... These lookup tables should be in KRMesh...
static const KRMesh : : vertex_attrib_t attribute_mapping [ KRMesh : : KRENGINE_NUM_ATTRIBUTES ] = {
KRMesh : : KRENGINE_ATTRIB_VERTEX ,
KRMesh : : KRENGINE_ATTRIB_NORMAL ,
KRMesh : : KRENGINE_ATTRIB_TANGENT ,
KRMesh : : KRENGINE_ATTRIB_TEXUVA ,
KRMesh : : KRENGINE_ATTRIB_TEXUVB ,
KRMesh : : KRENGINE_ATTRIB_BONEINDEXES ,
KRMesh : : KRENGINE_ATTRIB_BONEWEIGHTS ,
KRMesh : : KRENGINE_ATTRIB_VERTEX ,
KRMesh : : KRENGINE_ATTRIB_NORMAL ,
KRMesh : : KRENGINE_ATTRIB_TANGENT ,
KRMesh : : KRENGINE_ATTRIB_TEXUVA ,
KRMesh : : KRENGINE_ATTRIB_TEXUVB ,
} ;
uint32_t attribute_locations [ KRMesh : : KRENGINE_NUM_ATTRIBUTES ] = { } ;
2022-09-07 22:33:07 -07:00
uint32_t layout_binding_count = 0 ;
for ( KRShader * shader : shaders ) {
const SpvReflectShaderModule * reflection = shader - > getReflection ( ) ;
layout_binding_count + = reflection - > descriptor_binding_count ;
}
uboLayoutBindings . reserve ( layout_binding_count ) ;
2021-08-10 20:13:32 -07:00
for ( KRShader * shader : shaders ) {
VkShaderModule shaderModule ;
2022-02-27 23:51:29 -08:00
if ( ! shader - > createShaderModule ( device - > m_logicalDevice , shaderModule ) ) {
2021-08-10 20:13:32 -07:00
// failed! TODO - Error handling
}
2022-02-27 23:51:29 -08:00
const SpvReflectShaderModule * reflection = shader - > getReflection ( ) ;
2022-09-07 22:33:07 -07:00
for ( uint32_t b = 0 ; b < reflection - > descriptor_binding_count ; b + + ) {
SpvReflectDescriptorBinding & binding_reflect = reflection - > descriptor_bindings [ b ] ;
VkDescriptorSetLayoutBinding & binding = uboLayoutBindings . emplace_back ( ) ;
memset ( & binding , 0 , sizeof ( VkDescriptorSetLayoutBinding ) ) ;
binding . binding = binding_reflect . binding ;
// Note: VkDescriptorType and SpvReflectDescriptorType values match
binding . descriptorType = static_cast < VkDescriptorType > ( binding_reflect . descriptor_type ) ;
binding . descriptorCount = binding_reflect . count ;
binding . pImmutableSamplers = nullptr ;
2022-09-09 00:36:22 -07:00
binding . stageFlags = shader - > getShaderStageFlagBits ( ) ;
2022-09-07 22:33:07 -07:00
}
2021-08-10 20:13:32 -07:00
VkPipelineShaderStageCreateInfo & stageInfo = stages [ stage_count + + ] ;
stageInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO ;
2022-09-09 00:36:22 -07:00
stageInfo . stage = shader - > getShaderStageFlagBits ( ) ;
2022-09-08 23:58:24 -07:00
if ( stageInfo . stage = = VK_SHADER_STAGE_VERTEX_BIT ) {
2022-02-27 23:51:29 -08:00
for ( uint32_t i = 0 ; i < reflection - > input_variable_count ; i + + ) {
// TODO - We should have an interface to allow classes such as KRMesh to expose bindings
SpvReflectInterfaceVariable & input_var = * reflection - > input_variables [ i ] ;
if ( strcmp ( input_var . name , " vertex_position " ) = = 0 ) {
attribute_locations [ KRMesh : : KRENGINE_ATTRIB_VERTEX ] = input_var . location + 1 ;
2022-08-08 01:07:26 -07:00
} else if ( strcmp ( input_var . name , " vertex_normal " ) = = 0 ) {
2022-02-27 23:51:29 -08:00
attribute_locations [ KRMesh : : KRENGINE_ATTRIB_NORMAL ] = input_var . location + 1 ;
2022-08-08 01:07:26 -07:00
} else if ( strcmp ( input_var . name , " vertex_tangent " ) = = 0 ) {
2022-02-27 23:51:29 -08:00
attribute_locations [ KRMesh : : KRENGINE_ATTRIB_TANGENT ] = input_var . location + 1 ;
2022-08-08 01:07:26 -07:00
} else if ( strcmp ( input_var . name , " vertex_uv " ) = = 0 ) {
2022-02-27 23:51:29 -08:00
attribute_locations [ KRMesh : : KRENGINE_ATTRIB_TEXUVA ] = input_var . location + 1 ;
2022-08-08 01:07:26 -07:00
} else if ( strcmp ( input_var . name , " vertex_lightmap_uv " ) = = 0 ) {
2022-02-27 23:51:29 -08:00
attribute_locations [ KRMesh : : KRENGINE_ATTRIB_TEXUVB ] = input_var . location + 1 ;
2022-08-08 01:07:26 -07:00
} else if ( strcmp ( input_var . name , " bone_indexes " ) = = 0 ) {
2022-02-27 23:51:29 -08:00
attribute_locations [ KRMesh : : KRENGINE_ATTRIB_BONEINDEXES ] = input_var . location + 1 ;
2022-08-08 01:07:26 -07:00
} else if ( strcmp ( input_var . name , " bone_weights " ) = = 0 ) {
2022-02-27 23:51:29 -08:00
attribute_locations [ KRMesh : : KRENGINE_ATTRIB_BONEWEIGHTS ] = input_var . location + 1 ;
}
}
2021-08-10 20:13:32 -07:00
}
2022-09-15 20:33:41 -07:00
2022-09-09 00:38:46 -07:00
initPushConstantStage ( shader - > getShaderStage ( ) , reflection ) ;
2022-09-15 20:33:41 -07:00
initDescriptorSetStage ( shader - > getShaderStage ( ) , reflection ) ;
2021-08-10 20:13:32 -07:00
stageInfo . module = shaderModule ;
2021-08-11 01:11:52 -07:00
stageInfo . pName = " main " ;
}
2022-02-13 22:22:51 -08:00
VkVertexInputBindingDescription bindingDescription { } ;
bindingDescription . binding = 0 ;
2022-02-27 23:51:29 -08:00
bindingDescription . stride = KRMesh : : VertexSizeForAttributes ( vertexAttributes ) ;
2022-02-13 22:22:51 -08:00
bindingDescription . inputRate = VK_VERTEX_INPUT_RATE_VERTEX ;
2022-02-27 23:51:29 -08:00
uint32_t vertexAttributeCount = 0 ;
VkVertexInputAttributeDescription vertexAttributeDescriptions [ KRMesh : : KRENGINE_NUM_ATTRIBUTES ] { } ;
for ( int i = KRMesh : : KRENGINE_ATTRIB_VERTEX ; i < KRMesh : : KRENGINE_NUM_ATTRIBUTES ; i + + ) {
KRMesh : : vertex_attrib_t mesh_attrib = static_cast < KRMesh : : vertex_attrib_t > ( i ) ;
int location_attrib = attribute_mapping [ i ] ;
if ( KRMesh : : has_vertex_attribute ( vertexAttributes , ( KRMesh : : vertex_attrib_t ) i ) & & attribute_locations [ location_attrib ] ) {
VkVertexInputAttributeDescription & desc = vertexAttributeDescriptions [ vertexAttributeCount + + ] ;
desc . binding = 0 ;
desc . location = attribute_locations [ location_attrib ] - 1 ;
desc . format = KRMesh : : AttributeVulkanFormat ( mesh_attrib ) ;
desc . offset = KRMesh : : AttributeOffset ( mesh_attrib , vertexAttributes ) ;
}
}
2022-02-13 22:22:51 -08:00
2021-08-11 00:25:38 -07:00
VkPipelineVertexInputStateCreateInfo vertexInputInfo { } ;
vertexInputInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO ;
2022-02-13 22:22:51 -08:00
vertexInputInfo . vertexBindingDescriptionCount = 1 ;
vertexInputInfo . pVertexBindingDescriptions = & bindingDescription ;
2022-02-27 23:51:29 -08:00
vertexInputInfo . vertexAttributeDescriptionCount = vertexAttributeCount ;
2022-02-13 22:22:51 -08:00
vertexInputInfo . pVertexAttributeDescriptions = vertexAttributeDescriptions ;
2021-08-11 00:25:38 -07:00
VkPipelineInputAssemblyStateCreateInfo inputAssembly { } ;
inputAssembly . sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO ;
2022-02-28 22:04:24 -08:00
switch ( modelFormat ) {
2022-07-07 22:51:16 -07:00
case ModelFormat : : KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES :
case ModelFormat : : KRENGINE_MODEL_FORMAT_TRIANGLES :
2022-02-28 22:04:24 -08:00
inputAssembly . topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST ;
break ;
2022-07-07 22:51:16 -07:00
case ModelFormat : : KRENGINE_MODEL_FORMAT_INDEXED_STRIP :
case ModelFormat : : KRENGINE_MODEL_FORMAT_STRIP :
2022-02-28 22:04:24 -08:00
inputAssembly . topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP ;
break ;
}
2021-08-11 00:25:38 -07:00
inputAssembly . primitiveRestartEnable = VK_FALSE ;
VkViewport viewport { } ;
viewport . x = 0.0f ;
viewport . y = 0.0f ;
2022-09-27 18:58:00 -07:00
viewport . width = static_cast < float > ( viewport_size . x ) ;
viewport . height = static_cast < float > ( viewport_size . y ) ;
2021-08-11 00:25:38 -07:00
viewport . minDepth = 0.0f ;
viewport . maxDepth = 1.0f ;
VkRect2D scissor { } ;
scissor . offset = { 0 , 0 } ;
2022-09-27 18:58:00 -07:00
scissor . extent . width = scissor_size . x ;
scissor . extent . height = scissor_size . y ;
2021-08-11 00:25:38 -07:00
VkPipelineViewportStateCreateInfo viewportState { } ;
viewportState . sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO ;
viewportState . viewportCount = 1 ;
viewportState . pViewports = & viewport ;
viewportState . scissorCount = 1 ;
viewportState . pScissors = & scissor ;
VkPipelineRasterizationStateCreateInfo rasterizer { } ;
rasterizer . sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO ;
rasterizer . depthClampEnable = VK_FALSE ;
rasterizer . rasterizerDiscardEnable = VK_FALSE ;
rasterizer . polygonMode = VK_POLYGON_MODE_FILL ;
rasterizer . lineWidth = 1.0f ;
2022-07-04 20:49:46 -07:00
switch ( info . cullMode ) {
2022-07-07 22:51:16 -07:00
case CullMode : : kCullBack :
2022-07-04 20:49:46 -07:00
rasterizer . cullMode = VK_CULL_MODE_BACK_BIT ;
break ;
2022-07-07 22:51:16 -07:00
case CullMode : : kCullFront :
2022-07-04 20:49:46 -07:00
rasterizer . cullMode = VK_CULL_MODE_FRONT_BIT ;
break ;
2022-07-07 22:51:16 -07:00
case CullMode : : kCullNone :
2022-07-04 20:49:46 -07:00
rasterizer . cullMode = VK_CULL_MODE_NONE ;
break ;
}
2021-08-11 00:25:38 -07:00
rasterizer . frontFace = VK_FRONT_FACE_CLOCKWISE ;
rasterizer . depthBiasEnable = VK_FALSE ;
rasterizer . depthBiasConstantFactor = 0.0f ;
rasterizer . depthBiasClamp = 0.0f ;
rasterizer . depthBiasSlopeFactor = 0.0f ;
VkPipelineMultisampleStateCreateInfo multisampling { } ;
multisampling . sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO ;
multisampling . sampleShadingEnable = VK_FALSE ;
multisampling . rasterizationSamples = VK_SAMPLE_COUNT_1_BIT ;
multisampling . minSampleShading = 1.0f ;
multisampling . pSampleMask = nullptr ;
multisampling . alphaToCoverageEnable = VK_FALSE ;
multisampling . alphaToOneEnable = VK_FALSE ;
VkPipelineColorBlendAttachmentState colorBlendAttachment { } ;
colorBlendAttachment . colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT ;
2022-07-03 21:33:52 -07:00
switch ( info . rasterMode ) {
2022-07-07 22:51:16 -07:00
case RasterMode : : kOpaque :
case RasterMode : : kOpaqueLessTest :
case RasterMode : : kOpaqueNoTest :
case RasterMode : : kOpaqueNoDepthWrite :
2022-07-03 21:33:52 -07:00
colorBlendAttachment . blendEnable = VK_FALSE ;
colorBlendAttachment . srcColorBlendFactor = VK_BLEND_FACTOR_ONE ;
colorBlendAttachment . dstColorBlendFactor = VK_BLEND_FACTOR_ZERO ;
colorBlendAttachment . colorBlendOp = VK_BLEND_OP_ADD ;
break ;
2022-07-07 22:51:16 -07:00
case RasterMode : : kAlphaBlend :
case RasterMode : : kAlphaBlendNoTest :
2022-07-03 21:33:52 -07:00
colorBlendAttachment . blendEnable = VK_TRUE ;
colorBlendAttachment . srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA ;
colorBlendAttachment . dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA ;
colorBlendAttachment . colorBlendOp = VK_BLEND_OP_ADD ;
break ;
2022-07-07 22:51:16 -07:00
case RasterMode : : kAdditive :
case RasterMode : : kAdditiveNoTest :
2022-07-03 21:33:52 -07:00
colorBlendAttachment . blendEnable = VK_TRUE ;
colorBlendAttachment . srcColorBlendFactor = VK_BLEND_FACTOR_ONE ;
colorBlendAttachment . dstColorBlendFactor = VK_BLEND_FACTOR_ONE ;
colorBlendAttachment . colorBlendOp = VK_BLEND_OP_ADD ;
break ;
}
2021-08-11 00:25:38 -07:00
colorBlendAttachment . srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE ;
colorBlendAttachment . dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO ;
colorBlendAttachment . alphaBlendOp = VK_BLEND_OP_ADD ;
VkPipelineColorBlendStateCreateInfo colorBlending { } ;
colorBlending . sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO ;
colorBlending . logicOpEnable = VK_FALSE ;
colorBlending . logicOp = VK_LOGIC_OP_COPY ;
colorBlending . attachmentCount = 1 ;
colorBlending . pAttachments = & colorBlendAttachment ;
colorBlending . blendConstants [ 0 ] = 0.0f ;
colorBlending . blendConstants [ 1 ] = 0.0f ;
colorBlending . blendConstants [ 2 ] = 0.0f ;
colorBlending . blendConstants [ 3 ] = 0.0f ;
2022-09-07 22:33:07 -07:00
if ( uboLayoutBindings . size ( ) ) {
VkDescriptorSetLayoutCreateInfo layoutInfo { } ;
layoutInfo . sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO ;
layoutInfo . bindingCount = uboLayoutBindings . size ( ) ;
layoutInfo . pBindings = uboLayoutBindings . data ( ) ;
if ( vkCreateDescriptorSetLayout ( device - > m_logicalDevice , & layoutInfo , nullptr , & m_descriptorSetLayout ) ! = VK_SUCCESS ) {
// failed! TODO - Error handling
}
}
2021-08-11 00:25:38 -07:00
VkPipelineLayoutCreateInfo pipelineLayoutInfo { } ;
pipelineLayoutInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO ;
2022-09-07 22:33:07 -07:00
if ( uboLayoutBindings . size ( ) ) {
pipelineLayoutInfo . setLayoutCount = 1 ;
pipelineLayoutInfo . pSetLayouts = & m_descriptorSetLayout ;
} else {
pipelineLayoutInfo . setLayoutCount = 0 ;
pipelineLayoutInfo . pSetLayouts = nullptr ;
}
2021-08-11 00:25:38 -07:00
pipelineLayoutInfo . pushConstantRangeCount = 0 ;
pipelineLayoutInfo . pPushConstantRanges = nullptr ;
2022-02-27 23:51:29 -08:00
if ( vkCreatePipelineLayout ( device - > m_logicalDevice , & pipelineLayoutInfo , nullptr , & m_pipelineLayout ) ! = VK_SUCCESS ) {
2021-08-11 00:25:38 -07:00
// failed! TODO - Error handling
}
2022-08-06 00:14:21 -07:00
int iStage = 0 ;
2022-09-15 20:33:41 -07:00
for ( StageInfo & stageInfo : m_stages ) {
PushConstantInfo & pushConstants = stageInfo . pushConstants ;
2022-08-06 00:14:21 -07:00
if ( pushConstants . buffer ) {
VkPipelineLayoutCreateInfo pushConstantsLayoutInfo { } ;
pushConstantsLayoutInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO ;
pushConstantsLayoutInfo . setLayoutCount = 0 ;
pushConstantsLayoutInfo . pSetLayouts = nullptr ;
pushConstantsLayoutInfo . pushConstantRangeCount = 0 ;
pushConstantsLayoutInfo . pPushConstantRanges = nullptr ;
// TODO - We need to support push constants for other shader stages
VkPushConstantRange push_constant { } ;
push_constant . offset = 0 ;
push_constant . size = pushConstants . bufferSize ;
2022-09-09 00:36:22 -07:00
push_constant . stageFlags = getShaderStageFlagBitsFromShaderStage ( static_cast < ShaderStage > ( iStage ) ) ;
2022-08-06 00:14:21 -07:00
pushConstantsLayoutInfo . pPushConstantRanges = & push_constant ;
pushConstantsLayoutInfo . pushConstantRangeCount = 1 ;
if ( vkCreatePipelineLayout ( device - > m_logicalDevice , & pushConstantsLayoutInfo , nullptr , & pushConstants . layout ) ! = VK_SUCCESS ) {
// failed! TODO - Error handling
}
2022-07-07 19:29:50 -07:00
}
2022-08-06 00:14:21 -07:00
iStage + + ;
2022-07-07 19:29:50 -07:00
}
2022-03-01 23:53:42 -08:00
VkPipelineDepthStencilStateCreateInfo depthStencil { } ;
depthStencil . sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO ;
2022-07-03 21:33:52 -07:00
switch ( info . rasterMode ) {
2022-07-07 22:51:16 -07:00
case RasterMode : : kOpaque :
case RasterMode : : kOpaqueLessTest :
2022-07-03 21:33:52 -07:00
depthStencil . depthTestEnable = VK_TRUE ;
depthStencil . depthWriteEnable = VK_TRUE ;
break ;
2022-07-07 22:51:16 -07:00
case RasterMode : : kOpaqueNoTest :
2022-07-04 20:18:00 -07:00
depthStencil . depthTestEnable = VK_FALSE ;
depthStencil . depthWriteEnable = VK_TRUE ;
break ;
2022-07-07 22:51:16 -07:00
case RasterMode : : kOpaqueNoDepthWrite :
case RasterMode : : kAlphaBlend :
case RasterMode : : kAdditive :
2022-07-03 21:33:52 -07:00
depthStencil . depthTestEnable = VK_TRUE ;
depthStencil . depthWriteEnable = VK_FALSE ;
break ;
2022-07-07 22:51:16 -07:00
case RasterMode : : kAlphaBlendNoTest :
case RasterMode : : kAdditiveNoTest :
2022-07-03 21:33:52 -07:00
depthStencil . depthTestEnable = VK_FALSE ;
depthStencil . depthWriteEnable = VK_FALSE ;
break ;
}
2022-07-07 22:51:16 -07:00
if ( info . rasterMode = = RasterMode : : kOpaqueLessTest ) {
2022-07-03 21:33:52 -07:00
depthStencil . depthCompareOp = VK_COMPARE_OP_LESS ;
} else {
depthStencil . depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL ;
}
2022-08-08 01:07:26 -07:00
2022-03-01 23:53:42 -08:00
depthStencil . depthBoundsTestEnable = VK_FALSE ;
depthStencil . minDepthBounds = 0.0f ;
depthStencil . maxDepthBounds = 1.0f ;
depthStencil . stencilTestEnable = VK_FALSE ;
depthStencil . front = { } ;
depthStencil . back = { } ;
2021-08-11 01:11:52 -07:00
VkGraphicsPipelineCreateInfo pipelineInfo { } ;
pipelineInfo . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO ;
pipelineInfo . stageCount = stage_count ;
pipelineInfo . pStages = stages ;
pipelineInfo . pVertexInputState = & vertexInputInfo ;
pipelineInfo . pInputAssemblyState = & inputAssembly ;
pipelineInfo . pViewportState = & viewportState ;
pipelineInfo . pRasterizationState = & rasterizer ;
pipelineInfo . pMultisampleState = & multisampling ;
2022-03-01 23:53:42 -08:00
pipelineInfo . pDepthStencilState = & depthStencil ;
2021-08-11 01:11:52 -07:00
pipelineInfo . pColorBlendState = & colorBlending ;
pipelineInfo . pDynamicState = nullptr ;
2021-08-11 17:46:26 -07:00
pipelineInfo . layout = m_pipelineLayout ;
2022-03-27 21:56:45 -07:00
pipelineInfo . renderPass = renderPass . m_renderPass ;
2021-08-11 01:11:52 -07:00
pipelineInfo . subpass = 0 ;
pipelineInfo . basePipelineHandle = VK_NULL_HANDLE ;
pipelineInfo . basePipelineIndex = - 1 ;
2022-02-27 23:51:29 -08:00
if ( vkCreateGraphicsPipelines ( device - > m_logicalDevice , VK_NULL_HANDLE , 1 , & pipelineInfo , nullptr , & m_graphicsPipeline ) ! = VK_SUCCESS ) {
2021-08-11 01:11:52 -07:00
// Failed! TODO - Error handling
}
2021-08-10 20:13:32 -07:00
}
2022-08-08 01:07:26 -07:00
KRPipeline : : ~ KRPipeline ( )
{
2021-08-11 01:11:52 -07:00
if ( m_graphicsPipeline ) {
// TODO: vkDestroyPipeline(device, m_graphicsPipeline, nullptr);
}
2021-08-11 17:46:26 -07:00
if ( m_pipelineLayout ) {
// TODO: vkDestroyPipelineLayout(device, m_pipelineLayout, nullptr);
}
2022-09-07 22:33:07 -07:00
if ( m_descriptorSetLayout ) {
// TODO: vkDestroyDescriptorSetLayout(device, m_descriptorSetLayout, nullptr);
}
2022-08-06 00:14:21 -07:00
2022-08-08 01:07:26 -07:00
if ( getContext ( ) . getPipelineManager ( ) - > m_active_pipeline = = this ) {
getContext ( ) . getPipelineManager ( ) - > m_active_pipeline = NULL ;
2022-07-07 19:29:50 -07:00
}
2022-09-15 20:33:41 -07:00
for ( StageInfo & stageInfo : m_stages ) {
PushConstantInfo & pushConstants = stageInfo . pushConstants ;
if ( pushConstants . layout ) {
// TODO: vkDestroyPipelineLayout(device, pushConstants.layout, nullptr);
}
if ( pushConstants . buffer ) {
delete pushConstants . buffer ;
pushConstants . buffer = nullptr ;
}
2022-08-06 00:14:21 -07:00
}
}
2022-09-09 00:36:22 -07:00
void KRPipeline : : initPushConstantStage ( ShaderStage stage , const SpvReflectShaderModule * reflection )
2022-08-06 00:14:21 -07:00
{
2022-09-15 20:33:41 -07:00
PushConstantInfo & pushConstants = m_stages [ static_cast < int > ( stage ) ] . pushConstants ;
2022-08-06 00:14:21 -07:00
for ( int i = 0 ; i < reflection - > push_constant_block_count ; i + + ) {
const SpvReflectBlockVariable & block = reflection - > push_constant_blocks [ i ] ;
if ( stricmp ( block . name , " constants " ) = = 0 ) {
if ( block . size > 0 ) {
pushConstants . buffer = ( __uint8_t * ) malloc ( block . size ) ;
memset ( pushConstants . buffer , 0 , block . size ) ;
pushConstants . bufferSize = block . size ;
// Get push constant offsets
2022-09-07 23:48:46 -07:00
for ( int iUniform = 0 ; iUniform < kPushConstantCount ; iUniform + + ) {
2022-08-06 00:14:21 -07:00
for ( int iMember = 0 ; iMember < block . member_count ; iMember + + ) {
const SpvReflectBlockVariable & member = block . members [ iMember ] ;
2022-09-07 23:48:46 -07:00
if ( stricmp ( KRENGINE_PUSH_CONSTANT_NAMES [ iUniform ] , member . name ) = = 0 ) {
2022-08-06 00:14:21 -07:00
pushConstants . offset [ iUniform ] = member . offset ;
pushConstants . size [ iUniform ] = member . size ;
}
}
}
}
}
2022-07-07 19:29:50 -07:00
}
2019-01-11 00:48:33 -08:00
}
2022-09-15 20:33:41 -07:00
void KRPipeline : : initDescriptorSetStage ( ShaderStage stage , const SpvReflectShaderModule * reflection )
{
std : : vector < DescriptorSetInfo > & descriptorSets = m_stages [ static_cast < int > ( stage ) ] . descriptorSets ;
descriptorSets . reserve ( reflection - > descriptor_set_count ) ;
for ( int i = 0 ; i < reflection - > descriptor_set_count ; i + + ) {
SpvReflectDescriptorSet descriptorSet = reflection - > descriptor_sets [ i ] ;
DescriptorSetInfo & descriptorSetInfo = descriptorSets . emplace_back ( ) ;
2022-09-21 00:27:15 -07:00
descriptorSetInfo . bindings . reserve ( descriptorSet . binding_count ) ;
2022-09-15 20:33:41 -07:00
for ( int j = 0 ; j < descriptorSet . binding_count ; j + + ) {
SpvReflectDescriptorBinding & binding = * descriptorSet . bindings [ j ] ;
2022-09-21 00:27:15 -07:00
DescriptorBinding & descriptorQuery = descriptorSetInfo . bindings . emplace_back ( ) ;
2022-09-15 20:33:41 -07:00
switch ( binding . descriptor_type ) {
2022-09-21 00:27:15 -07:00
case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER :
{
ImageDescriptorInfo & imageInfo = descriptorQuery . emplace < ImageDescriptorInfo > ( ) ;
imageInfo . name = binding . name ;
imageInfo . texture = nullptr ;
imageInfo . sampler = nullptr ;
}
break ;
case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER :
{
UniformBufferDescriptorInfo & bufferInfo = descriptorQuery . emplace < UniformBufferDescriptorInfo > ( ) ;
bufferInfo . name = binding . name ;
bufferInfo . buffer = nullptr ;
}
break ;
default :
// Not supported
// TODO - Error handling
break ;
2022-09-15 20:33:41 -07:00
}
}
}
}
2022-09-07 23:48:46 -07:00
bool KRPipeline : : hasPushConstant ( PushConstant location ) const
2019-01-11 00:48:33 -08:00
{
2022-09-15 20:33:41 -07:00
for ( const StageInfo & stageInfo : m_stages ) {
const PushConstantInfo & pushConstants = stageInfo . pushConstants ;
if ( pushConstants . size [ static_cast < size_t > ( location ) ] ) {
2022-08-05 23:44:46 -07:00
return true ;
}
2022-07-07 19:29:50 -07:00
}
2022-08-05 23:44:46 -07:00
return false ;
2019-01-11 00:48:33 -08:00
}
2022-07-07 19:29:50 -07:00
2022-09-07 23:48:46 -07:00
void KRPipeline : : setPushConstant ( PushConstant location , float value )
2022-08-02 00:43:36 -07:00
{
2022-09-15 20:33:41 -07:00
for ( StageInfo & stageInfo : m_stages ) {
PushConstantInfo & pushConstants = stageInfo . pushConstants ;
if ( pushConstants . size [ static_cast < size_t > ( location ) ] = = sizeof ( value ) ) {
float * constant = ( float * ) ( pushConstants . buffer + pushConstants . offset [ static_cast < size_t > ( location ) ] ) ;
2022-08-05 23:44:46 -07:00
* constant = value ;
2022-08-02 00:43:36 -07:00
}
}
}
2022-08-05 23:44:46 -07:00
2022-09-07 23:48:46 -07:00
void KRPipeline : : setPushConstant ( PushConstant location , int value )
2019-01-11 00:48:33 -08:00
{
2022-09-15 20:33:41 -07:00
for ( StageInfo & stageInfo : m_stages ) {
PushConstantInfo & pushConstants = stageInfo . pushConstants ;
if ( pushConstants . size [ static_cast < size_t > ( location ) ] = = sizeof ( value ) ) {
int * constant = ( int * ) ( pushConstants . buffer + pushConstants . offset [ static_cast < size_t > ( location ) ] ) ;
2022-08-05 23:44:46 -07:00
* constant = value ;
}
2022-07-07 19:29:50 -07:00
}
2019-01-11 00:48:33 -08:00
}
2022-09-07 23:48:46 -07:00
void KRPipeline : : setPushConstant ( PushConstant location , const Vector2 & value )
2019-01-11 00:48:33 -08:00
{
2022-09-15 20:33:41 -07:00
for ( StageInfo & stageInfo : m_stages ) {
PushConstantInfo & pushConstants = stageInfo . pushConstants ;
if ( pushConstants . size [ static_cast < size_t > ( location ) ] = = sizeof ( value ) ) {
Vector2 * constant = ( Vector2 * ) ( pushConstants . buffer + pushConstants . offset [ static_cast < size_t > ( location ) ] ) ;
2022-08-05 23:44:46 -07:00
* constant = value ;
}
2022-07-07 19:29:50 -07:00
}
2019-01-11 00:48:33 -08:00
}
2022-09-07 23:48:46 -07:00
void KRPipeline : : setPushConstant ( PushConstant location , const Vector3 & value )
2019-01-11 00:48:33 -08:00
{
2022-09-15 20:33:41 -07:00
for ( StageInfo & stageInfo : m_stages ) {
PushConstantInfo & pushConstants = stageInfo . pushConstants ;
if ( pushConstants . size [ static_cast < size_t > ( location ) ] = = sizeof ( value ) ) {
Vector3 * constant = ( Vector3 * ) ( pushConstants . buffer + pushConstants . offset [ static_cast < size_t > ( location ) ] ) ;
2022-08-05 23:44:46 -07:00
* constant = value ;
}
2022-07-07 19:29:50 -07:00
}
2019-01-11 00:48:33 -08:00
}
2022-07-07 19:29:50 -07:00
2022-09-07 23:48:46 -07:00
void KRPipeline : : setPushConstant ( PushConstant location , const Vector4 & value )
2019-01-11 00:48:33 -08:00
{
2022-09-15 20:33:41 -07:00
for ( StageInfo & stageInfo : m_stages ) {
PushConstantInfo & pushConstants = stageInfo . pushConstants ;
if ( pushConstants . size [ static_cast < size_t > ( location ) ] = = sizeof ( value ) ) {
Vector4 * constant = ( Vector4 * ) ( pushConstants . buffer + pushConstants . offset [ static_cast < size_t > ( location ) ] ) ;
2022-08-05 23:44:46 -07:00
* constant = value ;
}
2022-07-07 19:29:50 -07:00
}
2019-01-11 00:48:33 -08:00
}
2022-09-07 23:48:46 -07:00
void KRPipeline : : setPushConstant ( PushConstant location , const Matrix4 & value )
2019-01-11 00:48:33 -08:00
{
2022-09-15 20:33:41 -07:00
for ( StageInfo & stageInfo : m_stages ) {
PushConstantInfo & pushConstants = stageInfo . pushConstants ;
if ( pushConstants . size [ static_cast < size_t > ( location ) ] = = sizeof ( value ) ) {
Matrix4 * constant = ( Matrix4 * ) ( pushConstants . buffer + pushConstants . offset [ static_cast < size_t > ( location ) ] ) ;
2022-08-05 23:44:46 -07:00
* constant = value ;
}
2022-07-07 19:29:50 -07:00
}
2019-01-11 00:48:33 -08:00
}
2022-09-07 23:48:46 -07:00
void KRPipeline : : setPushConstant ( PushConstant location , const Matrix4 * value , const size_t count )
2022-08-02 00:43:36 -07:00
{
2022-09-15 20:33:41 -07:00
for ( StageInfo & stageInfo : m_stages ) {
PushConstantInfo & pushConstants = stageInfo . pushConstants ;
2022-08-05 23:44:46 -07:00
// TODO - Vulkan refactoring
2022-09-21 18:18:13 -07:00
// GLDEBUG(glUniformMatrix4fv(pushConstants.offset[KRPipeline::PushConstant::bone_transforms], (int)bones.size(), GL_FALSE, bone_mats));
2022-08-05 23:44:46 -07:00
}
2022-08-02 00:43:36 -07:00
}
2022-09-21 00:27:15 -07:00
void KRPipeline : : updateDescriptorBinding ( )
{
// TODO - Implement
// Vulkan Refactoring
}
2022-08-08 01:07:26 -07:00
bool KRPipeline : : bind ( VkCommandBuffer & commandBuffer , KRCamera & camera , const KRViewport & viewport , const Matrix4 & matModel , const std : : vector < KRPointLight * > * point_lights , const std : : vector < KRDirectionalLight * > * directional_lights , const std : : vector < KRSpotLight * > * spot_lights , const KRNode : : RenderPass & renderPass )
2022-02-28 01:07:32 -08:00
{
2022-09-21 00:27:15 -07:00
updateDescriptorBinding ( ) ;
2022-09-20 18:54:01 -07:00
updateDescriptorSets ( ) ;
2022-09-20 19:02:54 -07:00
bindDescriptorSets ( commandBuffer ) ;
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : absolute_time , getContext ( ) . getAbsoluteTime ( ) ) ;
2022-08-08 01:07:26 -07:00
int light_directional_count = 0 ;
//int light_point_count = 0;
//int light_spot_count = 0;
// TODO - Need to support multiple lights and more light types in forward rendering
if ( renderPass ! = KRNode : : RENDER_PASS_DEFERRED_LIGHTS & & renderPass ! = KRNode : : RENDER_PASS_DEFERRED_GBUFFER & & renderPass ! = KRNode : : RENDER_PASS_DEFERRED_OPAQUE & & renderPass ! = KRNode : : RENDER_PASS_GENERATE_SHADOWMAPS ) {
if ( directional_lights ) {
for ( std : : vector < KRDirectionalLight * > : : const_iterator light_itr = directional_lights - > begin ( ) ; light_itr ! = directional_lights - > end ( ) ; light_itr + + ) {
KRDirectionalLight * directional_light = ( * light_itr ) ;
if ( light_directional_count = = 0 ) {
int cShadowBuffers = directional_light - > getShadowBufferCount ( ) ;
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( PushConstant : : shadowtexture1 ) & & cShadowBuffers > 0 ) {
2022-09-19 00:14:42 -07:00
// TODO - Vulkan Refactoring. Note: Sampler needs clamp-to-edge and linear filtering
2022-09-21 18:18:13 -07:00
if ( m_pContext - > getTextureManager ( ) - > selectTexture ( 0 /*GL_TEXTURE_2D*/ , 3 , directional_light - > getShadowTextures ( ) [ 0 ] ) ) {
2022-08-08 01:07:26 -07:00
GLDEBUG ( glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ) ;
GLDEBUG ( glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ) ;
2019-01-11 00:48:33 -08:00
}
2022-08-08 01:07:26 -07:00
}
2022-04-05 22:25:19 -07:00
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( PushConstant : : shadowtexture2 ) & & cShadowBuffers > 1 & & camera . settings . m_cShadowBuffers > 1 ) {
2022-09-19 00:14:42 -07:00
// TODO - Vulkan Refactoring. Note: Sampler needs clamp-to-edge and linear filtering
2022-09-21 18:18:13 -07:00
if ( m_pContext - > getTextureManager ( ) - > selectTexture ( 0 /*GL_TEXTURE_2D*/ , 4 , directional_light - > getShadowTextures ( ) [ 1 ] ) ) {
2022-08-08 01:07:26 -07:00
GLDEBUG ( glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ) ;
GLDEBUG ( glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ) ;
2022-04-05 22:25:19 -07:00
}
2022-08-08 01:07:26 -07:00
}
2022-04-05 22:25:19 -07:00
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( PushConstant : : shadowtexture3 ) & & cShadowBuffers > 2 & & camera . settings . m_cShadowBuffers > 2 ) {
2022-09-19 00:14:42 -07:00
// TODO - Vulkan Refactoring. Note: Sampler needs clamp-to-edge and linear filtering
2022-09-21 18:18:13 -07:00
if ( m_pContext - > getTextureManager ( ) - > selectTexture ( 0 /*GL_TEXTURE_2D*/ , 5 , directional_light - > getShadowTextures ( ) [ 2 ] ) ) {
2022-08-08 01:07:26 -07:00
GLDEBUG ( glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ) ;
GLDEBUG ( glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ) ;
2022-04-05 22:25:19 -07:00
}
2022-08-08 01:07:26 -07:00
}
2022-04-05 22:25:19 -07:00
2022-08-08 01:07:26 -07:00
Matrix4 matBias ;
matBias . translate ( 1.0 , 1.0 , 1.0 ) ;
matBias . scale ( 0.5 ) ;
for ( int iShadow = 0 ; iShadow < cShadowBuffers ; iShadow + + ) {
2022-09-07 23:48:46 -07:00
setPushConstant ( static_cast < PushConstant > ( static_cast < int > ( PushConstant : : shadow_mvp1 ) + iShadow ) , matModel * directional_light - > getShadowViewports ( ) [ iShadow ] . getViewProjectionMatrix ( ) * matBias ) ;
2022-04-05 22:25:19 -07:00
}
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( PushConstant : : light_direction_model_space ) ) {
2022-08-08 01:07:26 -07:00
Matrix4 inverseModelMatrix = matModel ;
inverseModelMatrix . invert ( ) ;
// Bind the light direction vector
Vector3 lightDirObject = Matrix4 : : Dot ( inverseModelMatrix , directional_light - > getWorldLightDirection ( ) ) ;
lightDirObject . normalize ( ) ;
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : light_direction_model_space , lightDirObject ) ;
2022-08-08 01:07:26 -07:00
}
2019-01-11 00:48:33 -08:00
}
2022-08-08 01:07:26 -07:00
light_directional_count + + ;
}
2019-01-11 00:48:33 -08:00
}
2022-08-08 01:07:26 -07:00
//light_point_count = point_lights.size();
//light_spot_count = spot_lights.size();
}
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( PushConstant : : camerapos_model_space ) ) {
2022-08-08 01:07:26 -07:00
Matrix4 inverseModelMatrix = matModel ;
inverseModelMatrix . invert ( ) ;
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( PushConstant : : camerapos_model_space ) ) {
2022-08-08 01:07:26 -07:00
// Transform location of camera to object space for calculation of specular halfVec
Vector3 cameraPosObject = Matrix4 : : Dot ( inverseModelMatrix , viewport . getCameraPosition ( ) ) ;
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : camerapos_model_space , cameraPosObject ) ;
2019-01-11 00:48:33 -08:00
}
2022-08-08 01:07:26 -07:00
}
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( PushConstant : : mvp ) | | hasPushConstant ( KRPipeline : : PushConstant : : invmvp ) ) {
2022-08-08 01:07:26 -07:00
// Bind our modelmatrix variable to be a uniform called mvpmatrix in our shaderprogram
Matrix4 mvpMatrix = matModel * viewport . getViewProjectionMatrix ( ) ;
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : mvp , mvpMatrix ) ;
2022-08-08 01:07:26 -07:00
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( KRPipeline : : PushConstant : : invmvp ) ) {
setPushConstant ( KRPipeline : : PushConstant : : invmvp , Matrix4 : : Invert ( mvpMatrix ) ) ;
2019-01-11 00:48:33 -08:00
}
2022-08-08 01:07:26 -07:00
}
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( KRPipeline : : PushConstant : : view_space_model_origin ) | | hasPushConstant ( PushConstant : : model_view_inverse_transpose ) | | hasPushConstant ( KRPipeline : : PushConstant : : model_view ) ) {
2022-08-08 01:07:26 -07:00
Matrix4 matModelView = matModel * viewport . getViewMatrix ( ) ;
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : model_view , matModelView ) ;
2022-08-08 01:07:26 -07:00
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( KRPipeline : : PushConstant : : view_space_model_origin ) ) {
2022-08-08 01:07:26 -07:00
Vector3 view_space_model_origin = Matrix4 : : Dot ( matModelView , Vector3 : : Zero ( ) ) ; // Origin point of model space is the light source position. No perspective, so no w divide required
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : view_space_model_origin , view_space_model_origin ) ;
2019-01-11 00:48:33 -08:00
}
2022-08-08 01:07:26 -07:00
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( PushConstant : : model_view_inverse_transpose ) ) {
2022-08-08 01:07:26 -07:00
Matrix4 matModelViewInverseTranspose = matModelView ;
matModelViewInverseTranspose . transpose ( ) ;
matModelViewInverseTranspose . invert ( ) ;
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : model_view_inverse_transpose , matModelViewInverseTranspose ) ;
2019-01-11 00:48:33 -08:00
}
2022-08-08 01:07:26 -07:00
}
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( PushConstant : : model_inverse_transpose ) ) {
2022-08-08 01:07:26 -07:00
Matrix4 matModelInverseTranspose = matModel ;
matModelInverseTranspose . transpose ( ) ;
matModelInverseTranspose . invert ( ) ;
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : model_inverse_transpose , matModelInverseTranspose ) ;
2022-08-08 01:07:26 -07:00
}
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( KRPipeline : : PushConstant : : invp ) ) {
setPushConstant ( PushConstant : : invp , viewport . getInverseProjectionMatrix ( ) ) ;
2022-08-08 01:07:26 -07:00
}
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( KRPipeline : : PushConstant : : invmvp_no_translate ) ) {
2022-08-08 01:07:26 -07:00
Matrix4 matInvMVPNoTranslate = matModel * viewport . getViewMatrix ( ) ; ;
// Remove the translation
matInvMVPNoTranslate . getPointer ( ) [ 3 ] = 0 ;
matInvMVPNoTranslate . getPointer ( ) [ 7 ] = 0 ;
matInvMVPNoTranslate . getPointer ( ) [ 11 ] = 0 ;
matInvMVPNoTranslate . getPointer ( ) [ 12 ] = 0 ;
matInvMVPNoTranslate . getPointer ( ) [ 13 ] = 0 ;
matInvMVPNoTranslate . getPointer ( ) [ 14 ] = 0 ;
matInvMVPNoTranslate . getPointer ( ) [ 15 ] = 1.0 ;
matInvMVPNoTranslate = matInvMVPNoTranslate * viewport . getProjectionMatrix ( ) ;
matInvMVPNoTranslate . invert ( ) ;
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : invmvp_no_translate , matInvMVPNoTranslate ) ;
2022-08-08 01:07:26 -07:00
}
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : model_matrix , matModel ) ;
if ( hasPushConstant ( PushConstant : : projection_matrix ) ) {
setPushConstant ( PushConstant : : projection_matrix , viewport . getProjectionMatrix ( ) ) ;
2022-08-08 01:07:26 -07:00
}
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( PushConstant : : viewport ) ) {
setPushConstant ( PushConstant : : viewport , Vector4 : : Create (
2022-08-08 01:07:26 -07:00
( float ) 0.0 ,
( float ) 0.0 ,
( float ) viewport . getSize ( ) . x ,
( float ) viewport . getSize ( ) . y
)
) ;
}
// Fog parameters
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : fog_near , camera . settings . fog_near ) ;
setPushConstant ( PushConstant : : fog_far , camera . settings . fog_far ) ;
setPushConstant ( PushConstant : : fog_density , camera . settings . fog_density ) ;
setPushConstant ( PushConstant : : fog_color , camera . settings . fog_color ) ;
2022-08-08 01:07:26 -07:00
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( PushConstant : : fog_scale ) ) {
setPushConstant ( PushConstant : : fog_scale , 1.0f / ( camera . settings . fog_far - camera . settings . fog_near ) ) ;
2022-08-08 01:07:26 -07:00
}
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( PushConstant : : density_premultiplied_exponential ) ) {
setPushConstant ( PushConstant : : density_premultiplied_exponential , - camera . settings . fog_density * 1.442695f ) ; // -fog_density / log(2)
2022-08-08 01:07:26 -07:00
}
2022-09-07 23:48:46 -07:00
if ( hasPushConstant ( PushConstant : : density_premultiplied_squared ) ) {
setPushConstant ( PushConstant : : density_premultiplied_squared , ( float ) ( - camera . settings . fog_density * camera . settings . fog_density * 1.442695 ) ) ; // -fog_density * fog_density / log(2)
2022-08-08 01:07:26 -07:00
}
// Sets the diffuseTexture variable to the first texture unit
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : diffusetexture , 0 ) ;
2022-08-08 01:07:26 -07:00
// Sets the specularTexture variable to the second texture unit
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : speculartexture , 1 ) ;
2022-08-08 01:07:26 -07:00
// Sets the normalTexture variable to the third texture unit
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : normaltexture , 2 ) ;
2022-08-08 01:07:26 -07:00
// Sets the shadowTexture variable to the fourth texture unit
2022-09-07 23:48:46 -07:00
setPushConstant ( PushConstant : : shadowtexture1 , 3 ) ;
setPushConstant ( PushConstant : : shadowtexture2 , 4 ) ;
setPushConstant ( PushConstant : : shadowtexture3 , 5 ) ;
setPushConstant ( PushConstant : : reflectioncubetexture , 4 ) ;
setPushConstant ( PushConstant : : lightmaptexture , 5 ) ;
setPushConstant ( PushConstant : : gbuffer_frame , 6 ) ;
setPushConstant ( PushConstant : : gbuffer_depth , 7 ) ; // Texture unit 7 is used for reading the depth buffer in gBuffer pass #2 and in post-processing pass
setPushConstant ( PushConstant : : reflectiontexture , 7 ) ; // Texture unit 7 is used for the reflection map textures in gBuffer pass #3 and when using forward rendering
setPushConstant ( PushConstant : : depth_frame , 0 ) ;
setPushConstant ( PushConstant : : render_frame , 1 ) ;
setPushConstant ( PushConstant : : volumetric_environment_frame , 2 ) ;
2022-08-08 01:07:26 -07:00
2022-09-15 20:33:41 -07:00
for ( StageInfo & stageInfo : m_stages ) {
PushConstantInfo & pushConstants = stageInfo . pushConstants ;
2022-08-08 01:07:26 -07:00
if ( pushConstants . buffer ) {
vkCmdPushConstants ( commandBuffer , pushConstants . layout , VK_SHADER_STAGE_VERTEX_BIT , 0 , pushConstants . bufferSize , pushConstants . buffer ) ;
2019-01-11 00:48:33 -08:00
}
2022-08-08 01:07:26 -07:00
}
2022-07-07 19:29:50 -07:00
2022-08-08 01:07:26 -07:00
vkCmdBindPipeline ( commandBuffer , VK_PIPELINE_BIND_POINT_GRAPHICS , m_graphicsPipeline ) ;
2019-01-11 00:48:33 -08:00
2022-08-08 01:07:26 -07:00
return true ;
2019-01-11 00:48:33 -08:00
}
2022-09-20 18:54:01 -07:00
void KRPipeline : : updateDescriptorSets ( )
{
if ( m_descriptorSetLayout = = VK_NULL_HANDLE ) {
// There are no descriptors
return ;
}
std : : unique_ptr < KRDevice > & device = getContext ( ) . getDeviceManager ( ) - > getDevice ( m_deviceHandle ) ;
2022-09-21 00:11:48 -07:00
// If the descriptor sets are not yet allocted, create them
if ( m_descriptorSets . size ( ) = = 0 ) {
int descriptorSetCount = 0 ;
for ( int stage = 0 ; stage < static_cast < size_t > ( ShaderStage : : ShaderStageCount ) ; stage + + ) {
const StageInfo & stageInfo = m_stages [ stage ] ;
descriptorSetCount + = stageInfo . descriptorSets . size ( ) ;
}
m_descriptorSets . resize ( KRENGINE_MAX_FRAMES_IN_FLIGHT * descriptorSetCount , VK_NULL_HANDLE ) ;
std : : vector < VkDescriptorSetLayout > layouts ( KRENGINE_MAX_FRAMES_IN_FLIGHT , m_descriptorSetLayout ) ;
device - > createDescriptorSets ( layouts , m_descriptorSets ) ;
}
// Update the descriptor sets
// TODO - We should only do this when the descriptors have changed
int descriptorSetCount = m_descriptorSets . size ( ) / KRENGINE_MAX_FRAMES_IN_FLIGHT ;
int descriptorSetStart = ( getContext ( ) . getCurrentFrame ( ) % KRENGINE_MAX_FRAMES_IN_FLIGHT ) * descriptorSetCount ;
int descriptorSetIndex = descriptorSetStart ;
std : : vector < VkWriteDescriptorSet > descriptorWrites ;
std : : vector < VkDescriptorBufferInfo > buffers ;
std : : vector < VkDescriptorImageInfo > images ;
for ( int stage = 0 ; stage < static_cast < size_t > ( ShaderStage : : ShaderStageCount ) ; stage + + ) {
StageInfo & stageInfo = m_stages [ stage ] ;
for ( DescriptorSetInfo & descriptorSetInfo : stageInfo . descriptorSets ) {
VkDescriptorSet descriptorSet = m_descriptorSets [ descriptorSetIndex + + ] ;
int bindingIndex = 0 ;
for ( DescriptorBinding & binding : descriptorSetInfo . bindings ) {
UniformBufferDescriptorInfo * buffer = std : : get_if < UniformBufferDescriptorInfo > ( & binding ) ;
ImageDescriptorInfo * image = std : : get_if < ImageDescriptorInfo > ( & binding ) ;
if ( buffer ) {
VkDescriptorBufferInfo & bufferInfo = buffers . emplace_back ( VkDescriptorBufferInfo { } ) ;
bufferInfo . buffer = buffer - > buffer - > getBuffer ( ) ;
bufferInfo . offset = 0 ;
bufferInfo . range = VK_WHOLE_SIZE ;
VkWriteDescriptorSet & descriptorWrite = descriptorWrites . emplace_back ( VkWriteDescriptorSet { } ) ;
descriptorWrite . sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET ;
descriptorWrite . dstSet = descriptorSet ;
descriptorWrite . dstBinding = bindingIndex ;
descriptorWrite . dstArrayElement = 0 ;
descriptorWrite . descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ;
descriptorWrite . descriptorCount = 1 ;
descriptorWrite . pBufferInfo = & bufferInfo ;
} else if ( image ) {
VkDescriptorImageInfo & imageInfo = images . emplace_back ( VkDescriptorImageInfo { } ) ;
imageInfo . imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ;
imageInfo . imageView = image - > texture - > getFullImageView ( m_deviceHandle ) ;
imageInfo . sampler = image - > sampler - > getSampler ( m_deviceHandle ) ;
VkWriteDescriptorSet & descriptorWrite = descriptorWrites . emplace_back ( VkWriteDescriptorSet { } ) ;
descriptorWrite . sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET ;
descriptorWrite . dstSet = descriptorSet ;
descriptorWrite . dstBinding = bindingIndex + + ;
descriptorWrite . dstArrayElement = 0 ;
descriptorWrite . descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ;
descriptorWrite . descriptorCount = 1 ;
descriptorWrite . pImageInfo = & imageInfo ;
} else {
// TODO - Error Handling
assert ( false ) ;
}
bindingIndex + + ;
}
}
}
if ( ! descriptorWrites . empty ( ) ) {
vkUpdateDescriptorSets ( device - > m_logicalDevice , static_cast < uint32_t > ( descriptorWrites . size ( ) ) , descriptorWrites . data ( ) , 0 , nullptr ) ;
}
2022-09-20 18:54:01 -07:00
}
2022-09-20 19:02:54 -07:00
void KRPipeline : : bindDescriptorSets ( VkCommandBuffer & commandBuffer )
{
if ( m_descriptorSets . empty ( ) ) {
return ;
}
2022-09-21 00:11:48 -07:00
int descriptorSetCount = m_descriptorSets . size ( ) / KRENGINE_MAX_FRAMES_IN_FLIGHT ;
int startDescriptorSet = ( getContext ( ) . getCurrentFrame ( ) % KRENGINE_MAX_FRAMES_IN_FLIGHT ) * descriptorSetCount ;
VkDescriptorSet descriptorSet = m_descriptorSets [ startDescriptorSet ] ;
2022-09-20 19:02:54 -07:00
if ( descriptorSet = = VK_NULL_HANDLE ) {
return ;
}
// TODO - Vulkan Refactoring - Support multiple descriptor set binding
2022-09-21 00:11:48 -07:00
vkCmdBindDescriptorSets ( commandBuffer , VK_PIPELINE_BIND_POINT_GRAPHICS , m_pipelineLayout , 0 , descriptorSetCount , & descriptorSet , 0 , nullptr ) ;
2022-09-20 19:02:54 -07:00
}
2022-08-08 01:07:26 -07:00
const char * KRPipeline : : getKey ( ) const
{
return m_szKey ;
2019-01-11 00:48:33 -08:00
}
2021-08-12 19:51:47 -07:00
2021-08-12 22:40:40 -07:00
VkPipeline & KRPipeline : : getPipeline ( )
{
return m_graphicsPipeline ;
2022-02-28 01:07:32 -08:00
}
2022-09-15 20:33:41 -07:00
void KRPipeline : : setImageBinding ( const std : : string & name , KRTexture * texture , KRSampler * sampler )
{
2022-09-21 00:27:15 -07:00
for ( int stage = 0 ; stage < static_cast < size_t > ( ShaderStage : : ShaderStageCount ) ; stage + + ) {
StageInfo & stageInfo = m_stages [ stage ] ;
for ( DescriptorSetInfo & descriptorSetInfo : stageInfo . descriptorSets ) {
for ( DescriptorBinding & binding : descriptorSetInfo . bindings ) {
ImageDescriptorInfo * image = std : : get_if < ImageDescriptorInfo > ( & binding ) ;
if ( image ) {
if ( image - > name = = name ) {
image - > texture = texture ;
image - > sampler = sampler ;
}
}
}
}
}
2022-09-15 20:33:41 -07:00
}