[Vulkan] Basic Vulkan backend
[platform/core/uifw/dali-core.git] / dali / graphics / vulkan / vulkan-pipeline.cpp
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <dali/graphics/vulkan/vulkan-pipeline.h>
19 #include <dali/graphics/vulkan/vulkan-graphics.h>
20 #include <dali/graphics/vulkan/vulkan-surface.h>
21
22 namespace Dali
23 {
24 namespace Graphics
25 {
26 namespace Vulkan
27 {
28
29 /**
30  * Class Pipeline::Impl
31  * Internal implementation of the pipeline
32  */
33 struct Pipeline::Impl
34 {
35   Impl( Vulkan::Graphics& graphics, const vk::GraphicsPipelineCreateInfo& info ) :
36     mInfo( info ),
37     mGraphics( graphics )
38   {
39   };
40
41   Impl() = default;
42   ~Impl()
43   {
44     if(mPipelineLayout)
45     {
46       mGraphics.GetDevice().destroyPipelineLayout( mPipelineLayout, mGraphics.GetAllocator() );
47     }
48     if(mPipeline)
49     {
50       mGraphics.GetDevice().destroyPipeline( mPipeline, mGraphics.GetAllocator() );
51     }
52   }
53
54   /**
55    *
56    * @return
57    */
58   vk::Pipeline GetVkPipeline() const
59   {
60     return mPipeline;
61   }
62
63   vk::Result Initialise()
64   {
65     if( !ValidateShaderModules() )
66     {
67       return vk::Result::eErrorInitializationFailed;
68     }
69
70     CreatePipelineLayout();
71
72     // use default render pass for default framebuffer
73     // TODO: swapchain/surface should use vulkan-framebuffer object
74     // in place of swapchain structures!
75     if( !mInfo.renderPass )
76     {
77       SetRenderPass( mGraphics.GetSurface( 0 ).GetRenderPass() );
78     }
79
80     SetRasterizationState();
81
82     SetDepthStencilState();
83
84     SetMultisampleState();
85
86     SetColorBlendState();
87
88     mInfo.setFlags( vk::PipelineCreateFlagBits::eAllowDerivatives );
89     // create pipeline
90     mPipeline = VkAssert( mGraphics.GetDevice().createGraphicsPipeline( nullptr, mInfo, mGraphics.GetAllocator() ) );
91     if(mPipeline)
92     {
93       return vk::Result::eSuccess;
94     }
95     return vk::Result::eErrorInitializationFailed;
96   }
97
98   void SetRenderPass( vk::RenderPass renderpass )
99   {
100     mInfo.setRenderPass( renderpass );
101   }
102
103   void SetDepthStencilState()
104   {
105     mDepthStencilState = vk::PipelineDepthStencilStateCreateInfo{};
106     mDepthStencilState.setDepthBoundsTestEnable( false );
107     mDepthStencilState.setStencilTestEnable( false );
108     mInfo.setPDepthStencilState( & mDepthStencilState );
109   }
110
111   void SetMultisampleState()
112   {
113     mMultisampleState = vk::PipelineMultisampleStateCreateInfo{};
114     mMultisampleState.setSampleShadingEnable( false );
115     mMultisampleState.setRasterizationSamples( vk::SampleCountFlagBits::e1);
116     mMultisampleState.setAlphaToCoverageEnable( false );
117     mMultisampleState.setMinSampleShading( 1.0f );
118     mMultisampleState.setPSampleMask( nullptr );
119     mInfo.setPMultisampleState( &mMultisampleState );
120   }
121
122   void SetVertexInputState(
123     std::vector<vk::VertexInputAttributeDescription> attrDesc,
124     std::vector<vk::VertexInputBindingDescription> bindingDesc)
125   {
126     mBindingDesc.clear();
127     mAttrDesc.clear();
128     mVertexInputState = vk::PipelineVertexInputStateCreateInfo{};
129     mVertexInputState.setPVertexAttributeDescriptions( (mAttrDesc = attrDesc).data() );
130     mVertexInputState.setPVertexBindingDescriptions( (mBindingDesc = bindingDesc).data() );
131     mVertexInputState.setVertexAttributeDescriptionCount( U32(mAttrDesc.size()) );
132     mVertexInputState.setVertexBindingDescriptionCount( U32(mBindingDesc.size()) );
133     mInfo.setPVertexInputState( &mVertexInputState );
134   }
135
136   /**
137    * Sets the viewport on uncompiled pipeline
138    * @return
139    */
140   void SetViewport( float x, float y, float width, float height )
141   {
142     assert( !mPipeline && "Pipeline cannot be changed anymore!");
143
144     // AB: add scissor, read data from graphics for fullscreen viewport
145     // simplified mode for the demo purposes
146     mViewports.emplace_back( x, y, width, height );
147     mViewports[0].setMinDepth( 0.0f );
148     mViewports[0].setMaxDepth( 1.0f );
149     mScissors = vk::Rect2D( { static_cast<int32_t>(x), static_cast<int32_t>(y) },
150                             { U32(width), U32(height) });
151     mViewportState = vk::PipelineViewportStateCreateInfo{}.
152            setViewportCount( U32(mViewports.size()) ).
153            setPViewports( mViewports.data() ).
154            setPScissors( &mScissors ).
155            setScissorCount( 1 );
156
157     // replace viewport state
158     mInfo.setPViewportState( &mViewportState );
159   }
160
161   /**
162    *
163    * @param topology
164    * @param restartEnable
165    */
166   void SetInputAssemblyState( vk::PrimitiveTopology topology, bool restartEnable )
167   {
168     mInputAssemblyState = vk::PipelineInputAssemblyStateCreateInfo{};
169     mInputAssemblyState.setPrimitiveRestartEnable( restartEnable );
170     mInputAssemblyState.setTopology( topology );
171     mInfo.setPInputAssemblyState( &mInputAssemblyState );
172   }
173
174   void SetRasterizationState()
175   {
176     mRasterizationState = vk::PipelineRasterizationStateCreateInfo{};
177     mRasterizationState.setCullMode( vk::CullModeFlagBits::eNone );
178     mRasterizationState.setDepthBiasClamp( 0.0f );
179     mRasterizationState.setDepthBiasEnable( false );
180     mRasterizationState.setDepthClampEnable( false );
181     mRasterizationState.setFrontFace( vk::FrontFace::eClockwise );
182     mRasterizationState.setPolygonMode( vk::PolygonMode::eFill );
183     mRasterizationState.setRasterizerDiscardEnable( false );
184     mRasterizationState.setLineWidth( 1.0f );
185     mInfo.setPRasterizationState( & mRasterizationState );
186   }
187
188   void SetColorBlendState()
189   {
190     mAttachementNoBlendState = vk::PipelineColorBlendAttachmentState{};
191     //mAttachementNoBlendState.setBlendEnable( true );
192     mAttachementNoBlendState.setColorWriteMask( vk::ColorComponentFlagBits::eR |
193                                                   vk::ColorComponentFlagBits::eG |
194                                                   vk::ColorComponentFlagBits::eB |
195                                                   vk::ColorComponentFlagBits::eA );
196
197     mColorBlendState.setBlendConstants( { 1.0f, 1.0f, 1.0f, 1.0f });
198     mColorBlendState = vk::PipelineColorBlendStateCreateInfo{};
199     mColorBlendState.setAttachmentCount( 1 );
200     mColorBlendState.setPAttachments( &mAttachementNoBlendState );
201     mInfo.setPColorBlendState(&mColorBlendState);
202   }
203
204   /**
205    * Sets the shader. Must be set before compiling the pipeline, compiled pipeline
206    * becomes immutable.
207    * @param shader
208    * @param stage
209    * @return
210    */
211   bool SetShader( ShaderRef shader, Shader::Type stage )
212   {
213     assert( !mPipeline && "Pipeline cannot be changed anymore!");
214
215     // check if shader isn't orphaned for some reason
216     if( !mGraphics.FindShader( *shader ) )
217     {
218       return false;
219     }
220
221     auto info = vk::PipelineShaderStageCreateInfo{}.
222                                                      setModule( *shader ).
223                                                      setStage( static_cast<vk::ShaderStageFlagBits>( stage ) ).
224                                                      setPName( "main" );
225
226     mShaderStageCreateInfo.push_back( info );
227     mShaderResources.push_back( shader );
228
229     mInfo.setPStages( mShaderStageCreateInfo.data() );
230     mInfo.setStageCount( static_cast<uint32_t>(mShaderStageCreateInfo.size()) );
231
232     return false;
233   }
234
235   /**
236    *
237    */
238   void CreatePipelineLayout()
239   {
240     // pull desciptor set layouts from shaders
241     auto layoutInfo = vk::PipelineLayoutCreateInfo{};
242
243     //info.setPSetLayouts( vk::DescriptorSetLayout )
244
245     std::vector<vk::DescriptorSetLayout> allLayouts{};
246     for( auto&& shader : mShaderResources )
247     {
248       auto& layouts = shader->GetDescriptorSetLayouts();
249       if( layouts.size() )
250       {
251         allLayouts.resize(layouts.size());
252         for (auto i = 0u; i < layouts.size(); ++i)
253         {
254           if (layouts[i])
255           {
256             allLayouts[i] = layouts[i];
257           }
258         }
259       }
260     }
261
262     layoutInfo.setPSetLayouts( allLayouts.data() );
263     layoutInfo.setSetLayoutCount( static_cast<uint32_t>(allLayouts.size()) );
264
265     mPipelineLayout = VkAssert( mGraphics.GetDevice().createPipelineLayout( layoutInfo, mGraphics.GetAllocator() ) );
266
267     mInfo.setLayout( mPipelineLayout );
268   }
269
270
271   bool Compile()
272   {
273     return Initialise() == vk::Result::eSuccess;
274   }
275
276   bool ValidateShaderModules()
277   {
278     for( auto i = 0u; i < mInfo.stageCount; ++i )
279     {
280       const auto& stage = mInfo.pStages[i];
281       auto shaderHandle = mGraphics.FindShader( stage.module );
282       if( shaderHandle )
283       {
284         mShaderResources.push_back( shaderHandle );
285       }
286       else
287       {
288         return false; // invalid shader! Can't track it
289       }
290     }
291     return true;
292   }
293
294
295   vk::GraphicsPipelineCreateInfo  mInfo           {    };
296   vk::Pipeline                    mPipeline       { nullptr };
297   uint32_t                        mModified       { 0u };
298   Graphics&                       mGraphics;
299
300   // resources
301   std::vector<Handle<Shader>>     mShaderResources;
302
303   vk::PipelineViewportStateCreateInfo mViewportState {};
304   std::vector<vk::Viewport> mViewports {};
305   vk::Rect2D mScissors {};
306
307   std::vector<vk::PipelineShaderStageCreateInfo> mShaderStageCreateInfo;
308   vk::PipelineLayout mPipelineLayout{};
309
310   // vertex input state
311   vk::PipelineVertexInputStateCreateInfo            mVertexInputState {};
312   std::vector<vk::VertexInputAttributeDescription>  mAttrDesc;
313   std::vector<vk::VertexInputBindingDescription>    mBindingDesc;
314
315   // vertex input assembly state
316   vk::PipelineInputAssemblyStateCreateInfo          mInputAssemblyState {};
317
318   // rasterization state
319   vk::PipelineRasterizationStateCreateInfo          mRasterizationState {};
320
321   // Dpeth/stencil state
322   vk::PipelineDepthStencilStateCreateInfo           mDepthStencilState {};
323
324   // Multisample state
325   vk::PipelineMultisampleStateCreateInfo            mMultisampleState {};
326
327   // Color blend
328   vk::PipelineColorBlendStateCreateInfo             mColorBlendState {};
329   vk::PipelineColorBlendAttachmentState             mAttachementNoBlendState {};
330 };
331
332 /*********************************************************************
333  * Class Pipeline
334  *
335  */
336
337 PipelineRef Pipeline::New( Graphics& graphics, const vk::GraphicsPipelineCreateInfo& info )
338 {
339   auto pipeline = Handle<Pipeline>( new Pipeline(graphics, info) );
340   graphics.AddPipeline(pipeline);
341   return pipeline;
342 }
343
344 Pipeline::~Pipeline() = default;
345
346 Pipeline::Pipeline( Graphics& graphics, const vk::GraphicsPipelineCreateInfo& info )
347 {
348   mImpl = MakeUnique<Pipeline::Impl>( graphics, info );
349 }
350
351 vk::Pipeline Pipeline::GetVkPipeline() const
352 {
353   return mImpl->GetVkPipeline();
354 }
355
356 bool Pipeline::OnDestroy()
357 {
358   return false;
359 }
360
361 void Pipeline::SetViewport( float x, float y, float width, float height )
362 {
363   mImpl->SetViewport( x, y, width, height );
364 }
365
366 bool Pipeline::SetShader( ShaderRef shader, Shader::Type stage )
367 {
368   return mImpl->SetShader( shader, stage );
369 }
370
371 void Pipeline::SetVertexInputState(std::vector<vk::VertexInputAttributeDescription> attrDesc,
372                          std::vector<vk::VertexInputBindingDescription> bindingDesc)
373 {
374   mImpl->SetVertexInputState( attrDesc, bindingDesc );
375 }
376
377 void Pipeline::SetInputAssemblyState( vk::PrimitiveTopology topology, bool restartEnable )
378 {
379   mImpl->SetInputAssemblyState( topology, restartEnable );
380 }
381
382 bool Pipeline::Compile()
383 {
384   return mImpl->Compile();
385 }
386
387 vk::PipelineLayout Pipeline::GetVkPipelineLayout() const
388 {
389   return mImpl->mPipelineLayout;
390 }
391
392 } // namespace Vulkan
393
394 } // namespace Graphics
395
396 } // namespace Dali