78fa8866d18769f9566253e6c048418f1cbc4b0a
[platform/core/uifw/dali-core.git] / dali / graphics / vulkan / vulkan-graphics-controller.cpp
1 #include "generated/spv-shaders-gen.h"
2
3 #include <glm/glm.hpp>
4 #include <glm/gtc/matrix_transform.hpp>
5 #include <glm/matrix.hpp>
6 #include <glm/vector_relational.hpp>
7
8 #include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-allocator.h>
9 #include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-handle.h>
10 #include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-manager.h>
11 #include <dali/graphics/vulkan/vulkan-buffer.h>
12 #include <dali/graphics/vulkan/vulkan-command-buffer.h>
13 #include <dali/graphics/vulkan/vulkan-command-pool.h>
14 #include <dali/graphics/vulkan/vulkan-descriptor-set.h>
15 #include <dali/graphics/vulkan/vulkan-graphics-controller.h>
16 #include <dali/graphics/vulkan/vulkan-graphics.h>
17 #include <dali/graphics/vulkan/vulkan-pipeline.h>
18 #include <dali/graphics/vulkan/vulkan-shader.h>
19 #include <dali/graphics/vulkan/vulkan-framebuffer.h>
20 #include <dali/graphics/vulkan/vulkan-surface.h>
21 #include <dali/graphics/vulkan/vulkan-sampler.h>
22 #include <dali/graphics/vulkan/vulkan-image.h>
23 #include <dali/graphics/vulkan/vulkan-graphics-texture.h>
24 #include <dali/graphics-api/graphics-api-render-command.h>
25 #include <dali/graphics/graphics-object-owner.h>
26
27 // API
28 #include <dali/graphics/vulkan/api/vulkan-api-shader.h>
29 #include <dali/graphics/vulkan/api/vulkan-api-texture.h>
30 #include <dali/graphics/vulkan/api/vulkan-api-texture-factory.h>
31 #include <dali/graphics/vulkan/api/vulkan-api-shader-factory.h>
32
33 using namespace glm;
34
35 namespace Dali
36 {
37 namespace Graphics
38 {
39 namespace Vulkan
40 {
41 static const mat4 CLIP_MATRIX(
42   1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f );
43
44 /**
45  * Graphics pipeline state describes single batch-draw call state
46  */
47 struct GraphicsPipelineState
48 {
49   /**
50    * Internal Data structure collects only POD state
51    * details that are relevant to us
52    */
53   struct Info
54   {
55     // blending
56     vk::Bool32      blendEnabled;
57     vk::BlendFactor srcColor, srcAlpha;
58     vk::BlendFactor dstColor, dstAlpha;
59
60     // vertex input data
61     std::vector<vk::VertexInputAttributeDescription> vertexAttributeDescription;
62     std::vector<vk::VertexInputBindingDescription>   vertexInputBindingDescripton;
63
64     // viewport size
65     vk::Rect2D viewport;
66
67     // topology
68     vk::PrimitiveTopology topology;
69
70     // depth/stencil
71     vk::Bool32 depthTestEnabled;
72     vk::Bool32 stencilTestEnabled;
73
74     // shaders
75     ShaderRef vertexShader;
76     ShaderRef fragmentShader;
77
78     bool operator==( const Info& src ) const
79     {
80       return false; // TODO
81     }
82
83   } info;
84
85   GraphicsPipelineState( GraphicsPipelineState& src )
86   {
87     info = src.info;
88   }
89
90   bool operator==( const GraphicsPipelineState::Info& _info )
91   {
92     return (info == _info);
93   }
94
95   // Resets state
96   void Reset()
97   {
98     pipeline.Reset();
99   }
100
101   void Initialise()
102   {
103
104   }
105
106   // Compiles state
107   static std::unique_ptr<GraphicsPipelineState> Compile(const GraphicsPipelineState::Info& info)
108   {
109     return nullptr;
110   }
111
112   // state, created when compiled, immutable
113   // renders particular set of objects
114   PipelineRef pipeline;
115 };
116
117 struct GraphicsDrawCommand
118 {
119   GraphicsPipelineState& pipelineState;
120
121   // command buffer/pool
122   CommandPoolRef commandPool;
123   CommandBufferRef commandBuffer;
124   FenceRef fence;
125
126   // resources
127   std::vector<BufferRef>    buffers;
128   std::vector<ImageRef>     images;
129   std::vector<SamplerRef>   samplers;
130   std::vector<ImageViewRef> imageViews;
131
132   // descriptor sets and pool
133   std::vector<DescriptorSetRef> descriptorSets;
134   DescriptorPoolRef             descriptorPool;
135 };
136
137 struct Controller::Impl
138 {
139
140
141   struct State
142   {
143     ShaderRef                     vertexShader;
144     ShaderRef                     fragmentShader;
145     DescriptorPoolRef             descriptorPool;
146     PipelineRef                   pipeline;
147     BufferRef                     vertexBuffer;
148     BufferRef                     uniformBuffer0;
149     BufferRef                     uniformBuffer1; // clip matrix
150     std::vector<DescriptorSetRef> descriptorSets;
151     CommandPoolRef                commandPool;
152     CommandBufferRef              drawCommand;
153
154     std::vector<CommandBufferRef> drawCommandPool; // max 1024 secondary buffers
155     uint32_t                      drawPoolIndex{0u};
156   };
157
158   Impl( Controller& owner, Dali::Graphics::Vulkan::Graphics& graphics )
159   : mGraphics( graphics ),
160     mOwner( owner ),
161     mDefaultAllocator( mGraphics.GetDeviceMemoryManager().GetDefaultAllocator() )
162   {
163   }
164
165   ~Impl()
166   {
167   }
168
169   // TODO: @todo this function initialises basic buffers, shaders and pipeline
170   // for the prototype ONLY
171 #pragma GCC diagnostic push
172 #pragma GCC diagnostic ignored "-Wframe-larger-than="
173   bool Initialise()
174   {
175     // Create factories
176     mShaderFactory = std::make_unique<VulkanAPI::ShaderFactory>( mGraphics );
177     mTextureFactory = std::make_unique<VulkanAPI::TextureFactory>( mGraphics );
178
179     mDebugPipelineState.vertexShader = Shader::New( mGraphics, VSH_CODE.data(), VSH_CODE.size() );
180
181     mDebugPipelineState.fragmentShader = Shader::New( mGraphics, FSH_CODE.data(), FSH_CODE.size() );
182
183     mDebugPipelineState.descriptorPool = CreateDescriptorPool();
184
185     const float halfWidth  = 0.5f;
186     const float halfHeight = 0.5f;
187     //#if 0
188     const vec3 VERTICES[4] = {
189       {halfWidth, halfHeight, 0.0f},
190       {halfWidth, -halfHeight, 0.0f},
191       {-halfWidth, halfHeight, 0.0f},
192       {-halfWidth, -halfHeight, 0.0f},
193     };
194
195     mDebugPipelineState.vertexBuffer = Buffer::New( mGraphics, sizeof( VERTICES[0] ) * 4, Buffer::Type::VERTEX );
196     auto& defaultAllocator           = mGraphics.GetDeviceMemoryManager().GetDefaultAllocator();
197     mDebugPipelineState.vertexBuffer->BindMemory(
198       defaultAllocator.Allocate( mDebugPipelineState.vertexBuffer, vk::MemoryPropertyFlagBits::eHostVisible ) );
199
200     auto ptr = mDebugPipelineState.vertexBuffer->GetMemoryHandle()->MapTyped<vec3>();
201     std::copy( VERTICES, VERTICES + 4, ptr );
202     mDebugPipelineState.vertexBuffer->GetMemoryHandle()->Unmap();
203
204     // create command pool
205     mDebugPipelineState.commandPool = CommandPool::New( mGraphics );
206
207     CreatePipeline( mDebugPipelineState );
208
209     // allocated descriptor pool ( 1024 sets, 1024 uniform buffers )
210     auto size = vk::DescriptorPoolSize{}.setDescriptorCount( 1024 ).setType( vk::DescriptorType::eUniformBuffer );
211     mDebugPipelineState.descriptorPool = DescriptorPool::New(
212       mGraphics, vk::DescriptorPoolCreateInfo{}.setPoolSizeCount( 1 ).setPPoolSizes( &size ).setMaxSets( 1024 ) );
213
214     mDebugPipelineState.uniformBuffer1 = Buffer::New( mGraphics, sizeof( CLIP_MATRIX ), Buffer::Type::UNIFORM );
215     mDebugPipelineState.uniformBuffer1->BindMemory(
216       mDefaultAllocator.Allocate( mDebugPipelineState.uniformBuffer1, vk::MemoryPropertyFlagBits::eHostVisible ) );
217
218     auto clipPtr = mDebugPipelineState.uniformBuffer1->GetMemoryHandle()->MapTyped<mat4>();
219     std::copy( &CLIP_MATRIX, &CLIP_MATRIX + 1, clipPtr );
220     mDebugPipelineState.uniformBuffer1->GetMemoryHandle()->Unmap();
221
222     return true;
223   }
224
225   PipelineRef CreatePipeline( State& state )
226   {
227     auto pipeline = Pipeline::New( mGraphics );
228
229     pipeline->SetShader( state.vertexShader, Shader::Type::VERTEX );
230     pipeline->SetShader( state.fragmentShader, Shader::Type::FRAGMENT );
231
232     auto size = mGraphics.GetSurface( 0u )->GetSize();
233     pipeline->SetViewport( 0, 0, static_cast<float>( size.width ), static_cast<float>( size.height ) );
234
235     pipeline->SetVertexInputState(
236       std::vector<vk::VertexInputAttributeDescription>{
237         vk::VertexInputAttributeDescription{}.setBinding( 0 ).setOffset( 0 ).setLocation( 0 ).setFormat(
238           vk::Format::eR32G32B32Sfloat )},
239       std::vector<vk::VertexInputBindingDescription>{vk::VertexInputBindingDescription{}
240                                                        .setBinding( 0 )
241                                                        .setStride( sizeof( vec3 ) )
242                                                        .setInputRate( vk::VertexInputRate::eVertex )} );
243     pipeline->SetInputAssemblyState( vk::PrimitiveTopology::eTriangleStrip, false );
244
245
246
247     if( !pipeline->Compile() )
248     {
249       pipeline.Reset();
250     }
251
252     state.pipeline = pipeline;
253     return pipeline;
254   }
255
256   void SubmitCommand( Dali::Graphics::API::RenderCommand&& command )
257   {
258     auto& state = mDebugPipelineState;
259
260     const auto& bufferList = command.GetBufferList();
261     auto        drawcalls  = command.GetPrimitiveCount();
262
263     // create pool of commands to be re-recorded
264     if( state.drawCommandPool.empty() )
265     {
266       for( auto i = 0u; i < 1024; ++i )
267       {
268         state.drawCommandPool.push_back( state.commandPool->NewCommandBuffer( false ) );
269       }
270     }
271
272     uint32_t                      stride = sizeof( mat4 ) + sizeof( vec4 ) + sizeof( vec3 );
273     std::vector<CommandBufferRef> executeCommands;
274     for( auto&& buf : bufferList.Get() )
275     {
276       // TODO: @todo implement minimum offset!
277       const uint32_t sizeOfUniformBuffer      = U32( ( buf->GetSize() / drawcalls.Get() ) );
278       const uint32_t uniformBlockOffsetStride = ( ( sizeOfUniformBuffer / 256 ) + 1 ) * 256;
279       const uint32_t uniformBlockMemoryNeeded = U32( uniformBlockOffsetStride * drawcalls.Get() );
280
281       // create buffer if doesn't exist
282       if( !state.uniformBuffer0 )
283       {
284         state.uniformBuffer0 = Buffer::New( mGraphics, uniformBlockMemoryNeeded, Buffer::Type::UNIFORM );
285       }
286       if( state.uniformBuffer0->GetSize() < uniformBlockMemoryNeeded || !state.uniformBuffer0->GetMemoryHandle() )
287       {
288         // allocate and bind memory if needed ( buffer increased size or buffer hasn't been bound yet )
289         state.uniformBuffer0->BindMemory(
290           mDefaultAllocator.Allocate( state.uniformBuffer0, vk::MemoryPropertyFlagBits::eHostVisible ) );
291       }
292
293       // fill memory
294
295       struct UB
296       {
297         mat4 mvp;
298         vec4 color;
299         vec3 size;
300         uint samplerId;
301       } __attribute__( ( aligned( 16 ) ) );
302
303       auto memory = state.uniformBuffer0->GetMemoryHandle();
304       auto outPtr = memory->MapTyped<char>();
305       for( auto i = 0u; i < drawcalls.Get(); ++i )
306       {
307         // copy chunk of data
308         UB* inputData  = ( reinterpret_cast<UB*>( buf->GetDataBase() ) ) + i;
309         UB* outputData = ( reinterpret_cast<UB*>( outPtr + ( i * uniformBlockOffsetStride ) ) );
310         *outputData    = *inputData;
311
312         auto descriptorSets = state.descriptorPool->AllocateDescriptorSets(
313           vk::DescriptorSetAllocateInfo{}.setDescriptorSetCount( 1 ).setPSetLayouts(
314             state.pipeline->GetVkDescriptorSetLayouts().data() ) );
315
316         descriptorSets[0]->WriteUniformBuffer( 0, state.uniformBuffer0, i * uniformBlockOffsetStride, stride );
317         descriptorSets[0]->WriteUniformBuffer( 1, state.uniformBuffer1, 0, state.uniformBuffer1->GetSize() );
318         //if(inputData->samplerId >= 0)
319         {
320           descriptorSets[0]->WriteCombinedImageSampler(2, mTextures[inputData->samplerId]->GetSampler(),
321                                                        mTextures[inputData->samplerId]->GetImageView());
322         }
323
324         // record draw call
325         auto cmdbuf = state.commandPool->NewCommandBuffer( false );
326         cmdbuf->Begin( vk::CommandBufferUsageFlagBits::eRenderPassContinue );
327         cmdbuf->BindVertexBuffer( 0, state.vertexBuffer, 0 );
328         cmdbuf->BindGraphicsPipeline( state.pipeline );
329         cmdbuf->BindDescriptorSets( descriptorSets, 0 );
330         cmdbuf->Draw( 4, 1, 0, 0 );
331         cmdbuf->End();
332
333         executeCommands.push_back( cmdbuf );
334       }
335
336       memory->Unmap();
337
338       // execute buffer
339       mGraphics.GetSwapchainForFBID( 0u )->GetPrimaryCommandBuffer()->ExecuteCommands( executeCommands );
340
341       // break, one pass only
342       break;
343     }
344   }
345 #pragma GCC diagnostic pop
346   void BeginFrame()
347   {
348     auto surface = mGraphics.GetSurface( 0u );
349
350     auto swapchain = mGraphics.GetSwapchainForFBID( 0u );
351     swapchain->AcquireNextFramebuffer();
352
353     // rewind pools
354     mDebugPipelineState.drawPoolIndex = 0u;
355     mDebugPipelineState.descriptorPool->Reset();
356     mDebugPipelineState.commandPool->Reset( true );
357   }
358
359   void EndFrame()
360   {
361     auto swapchain = mGraphics.GetSwapchainForFBID( 0u );
362     swapchain->Present();
363   }
364
365   DescriptorPoolRef CreateDescriptorPool()
366   {
367     vk::DescriptorPoolSize size;
368     size.setDescriptorCount( 1024 ).setType( vk::DescriptorType::eUniformBuffer );
369
370     // TODO: how to organize this???
371     auto pool = DescriptorPool::New(
372       mGraphics, vk::DescriptorPoolCreateInfo{}.setMaxSets( 1024 ).setPoolSizeCount( 1 ).setPPoolSizes( &size ) );
373     return pool;
374   }
375
376   API::TextureFactory& GetTextureFactory() const
377   {
378     return *(mTextureFactory.get());
379   }
380
381   API::ShaderFactory& GetShaderFactory() const
382   {
383     return *(mShaderFactory.get());
384   }
385
386   // resources
387   std::vector<TextureRef> mTextures;
388   std::vector<ShaderRef>  mShaders;
389
390   // owner objects
391   ObjectOwner<API::Texture>   mTexturesOwner;
392   ObjectOwner<API::Shader>    mShadersOwner;
393
394
395   Graphics&           mGraphics;
396   Controller&         mOwner;
397   GpuMemoryAllocator& mDefaultAllocator;
398
399   State mDebugPipelineState;
400
401   std::unique_ptr<VulkanAPI::TextureFactory> mTextureFactory;
402   std::unique_ptr<VulkanAPI::ShaderFactory> mShaderFactory;
403
404   /**
405    * NEW IMPLEMENTACIONE
406    */
407
408   void SubmitDraw( const Dali::Graphics::API::BufferInfo& buffer )
409   {
410     // find pipeline state for this batch
411     auto info = GraphicsPipelineState::Info{};
412
413     //info.vertexShader =
414   }
415
416   void SubmitCommandV2( Dali::Graphics::API::RenderCommand&& command )
417   {
418
419     auto vertexShader = command.GetShader( Dali::Graphics::API::ShaderDetails::PipelineStage::VERTEX );
420     auto fragmentShader = command.GetShader( Dali::Graphics::API::ShaderDetails::PipelineStage::FRAGMENT );
421
422     // get shaders from backend
423     ShaderRef vsh, fsh;
424     if(vertexShader)
425     {
426       vsh = VulkanAPI::Shader::DownCast( vertexShader.Get() ).GetShader( vk::ShaderStageFlagBits::eVertex );
427     }
428
429     if(fragmentShader)
430     {
431       fsh = VulkanAPI::Shader::DownCast( vertexShader.Get() ).GetShader( vk::ShaderStageFlagBits::eFragment );
432     }
433
434 #if 0
435     const auto& bufferList = command.GetBufferList();
436     const auto& bufferVector = bufferList.Get();
437
438     for(const auto& bufferInfo : bufferVector )
439     {
440       /*
441       const auto ptr = bufferInfo->GetDataBase();
442       const auto size = bufferInfo->GetSize();
443
444       SubmitDraw( bufferInfo );
445       */
446       // new render state
447
448     }
449 #endif
450   }
451
452
453
454   std::vector<GraphicsPipelineState> mStatePerBatchCache;
455
456 };
457
458 // TODO: @todo temporarily ignore missing return type, will be fixed later
459 #pragma GCC diagnostic push
460 #pragma GCC diagnostic     ignored "-Wreturn-type"
461 API::Accessor<API::Shader> Controller::CreateShader( const API::BaseFactory<API::Shader>& factory )
462 {
463   auto handle = mImpl->mShadersOwner.CreateObject( factory );
464   auto& apiShader = static_cast<VulkanAPI::Shader&>(mImpl->mShadersOwner[handle]);
465   auto vertexShaderRef = apiShader.GetShaderRef( vk::ShaderStageFlagBits::eVertex );
466   auto fragmentShaderRef = apiShader.GetShaderRef( vk::ShaderStageFlagBits::eFragment );
467   mImpl->mShaders.push_back( vertexShaderRef );
468   mImpl->mShaders.push_back( fragmentShaderRef );
469   return API::Accessor<API::Shader>( mImpl->mShadersOwner, handle);
470 }
471
472 API::Accessor<API::Texture> Controller::CreateTexture( const API::BaseFactory<API::Texture>& factory )
473 {
474   auto handle = mImpl->mTexturesOwner.CreateObject( factory );
475   auto textureRef = static_cast<VulkanAPI::Texture&>(mImpl->mTexturesOwner[handle]).GetTextureRef();
476   mImpl->mTextures.push_back( textureRef );
477   return API::Accessor<API::Texture>( mImpl->mTexturesOwner, handle);
478 }
479
480 API::Accessor<API::TextureSet> Controller::CreateTextureSet( const API::BaseFactory<API::TextureSet>& factory )
481 {
482 }
483
484 API::Accessor<API::DynamicBuffer> Controller::CreateDynamicBuffer( const API::BaseFactory<API::DynamicBuffer>& factory )
485 {
486 }
487
488 API::Accessor<API::StaticBuffer> Controller::CreateStaticBuffer( const API::BaseFactory<API::StaticBuffer>& factory )
489 {
490 }
491
492 API::Accessor<API::Sampler> Controller::CreateSampler( const API::BaseFactory<API::Sampler>& factory )
493 {
494 }
495
496 API::Accessor<API::Framebuffer> Controller::CreateFramebuffer( const API::BaseFactory<API::Framebuffer>& factory )
497 {
498 }
499
500 std::unique_ptr<char> Controller::CreateBuffer( size_t numberOfElements, size_t elementSize )
501 {
502   return std::unique_ptr<char>( new char[numberOfElements * elementSize] );
503 }
504
505 #pragma GCC diagnostic pop
506
507 std::unique_ptr<Controller> Controller::New( Graphics& vulkanGraphics )
508 {
509   return std::make_unique<Controller>( vulkanGraphics );
510 }
511
512 Controller::Controller( Graphics& vulkanGraphics ) : mImpl( std::make_unique<Impl>( *this, vulkanGraphics ) )
513 {
514   mImpl->Initialise();
515 }
516
517 Controller::~Controller()       = default;
518 Controller::Controller()        = default;
519 Controller& Controller::operator=( Controller&& ) = default;
520
521 void Controller::GetRenderItemList()
522 {
523 }
524
525 void Controller::SubmitCommand( Dali::Graphics::API::RenderCommand&& command )
526 {
527   mImpl->SubmitCommand( std::move( command ) );
528   //SubmitCommandTest( std::move( command ) );
529 }
530
531 void Controller::BeginFrame()
532 {
533   mImpl->BeginFrame();
534 }
535
536 void Controller::EndFrame()
537 {
538   mImpl->EndFrame();
539 }
540
541 API::TextureFactory& Controller::GetTextureFactory() const
542 {
543   return mImpl->GetTextureFactory();
544 }
545
546 API::ShaderFactory& Controller::GetShaderFactory() const
547 {
548   return mImpl->GetShaderFactory();
549 }
550
551 } // namespace Vulkan
552 } // namespace Graphics
553 } // namespace Dali