1 #include "generated/spv-shaders-gen.h"
4 #include <glm/gtc/matrix_transform.hpp>
5 #include <glm/matrix.hpp>
6 #include <glm/vector_relational.hpp>
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>
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>
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 );
45 * Graphics pipeline state describes single batch-draw call state
47 struct GraphicsPipelineState
50 * Internal Data structure collects only POD state
51 * details that are relevant to us
56 vk::Bool32 blendEnabled;
57 vk::BlendFactor srcColor, srcAlpha;
58 vk::BlendFactor dstColor, dstAlpha;
61 std::vector<vk::VertexInputAttributeDescription> vertexAttributeDescription;
62 std::vector<vk::VertexInputBindingDescription> vertexInputBindingDescripton;
68 vk::PrimitiveTopology topology;
71 vk::Bool32 depthTestEnabled;
72 vk::Bool32 stencilTestEnabled;
75 ShaderRef vertexShader;
76 ShaderRef fragmentShader;
78 bool operator==( const Info& src ) const
85 GraphicsPipelineState( GraphicsPipelineState& src )
90 bool operator==( const GraphicsPipelineState::Info& _info )
92 return (info == _info);
107 static std::unique_ptr<GraphicsPipelineState> Compile(const GraphicsPipelineState::Info& info)
112 // state, created when compiled, immutable
113 // renders particular set of objects
114 PipelineRef pipeline;
117 struct GraphicsDrawCommand
119 GraphicsPipelineState& pipelineState;
121 // command buffer/pool
122 CommandPoolRef commandPool;
123 CommandBufferRef commandBuffer;
127 std::vector<BufferRef> buffers;
128 std::vector<ImageRef> images;
129 std::vector<SamplerRef> samplers;
130 std::vector<ImageViewRef> imageViews;
132 // descriptor sets and pool
133 std::vector<DescriptorSetRef> descriptorSets;
134 DescriptorPoolRef descriptorPool;
137 struct Controller::Impl
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;
154 std::vector<CommandBufferRef> drawCommandPool; // max 1024 secondary buffers
155 uint32_t drawPoolIndex{0u};
158 Impl( Controller& owner, Dali::Graphics::Vulkan::Graphics& graphics )
159 : mGraphics( graphics ),
161 mDefaultAllocator( mGraphics.GetDeviceMemoryManager().GetDefaultAllocator() )
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="
176 mShaderFactory = std::make_unique<VulkanAPI::ShaderFactory>( mGraphics );
177 mTextureFactory = std::make_unique<VulkanAPI::TextureFactory>( mGraphics );
179 mDebugPipelineState.vertexShader = Shader::New( mGraphics, VSH_CODE.data(), VSH_CODE.size() );
181 mDebugPipelineState.fragmentShader = Shader::New( mGraphics, FSH_CODE.data(), FSH_CODE.size() );
183 mDebugPipelineState.descriptorPool = CreateDescriptorPool();
185 const float halfWidth = 0.5f;
186 const float halfHeight = 0.5f;
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},
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 ) );
200 auto ptr = mDebugPipelineState.vertexBuffer->GetMemoryHandle()->MapTyped<vec3>();
201 std::copy( VERTICES, VERTICES + 4, ptr );
202 mDebugPipelineState.vertexBuffer->GetMemoryHandle()->Unmap();
204 // create command pool
205 mDebugPipelineState.commandPool = CommandPool::New( mGraphics );
207 CreatePipeline( mDebugPipelineState );
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 ) );
214 mDebugPipelineState.uniformBuffer1 = Buffer::New( mGraphics, sizeof( CLIP_MATRIX ), Buffer::Type::UNIFORM );
215 mDebugPipelineState.uniformBuffer1->BindMemory(
216 mDefaultAllocator.Allocate( mDebugPipelineState.uniformBuffer1, vk::MemoryPropertyFlagBits::eHostVisible ) );
218 auto clipPtr = mDebugPipelineState.uniformBuffer1->GetMemoryHandle()->MapTyped<mat4>();
219 std::copy( &CLIP_MATRIX, &CLIP_MATRIX + 1, clipPtr );
220 mDebugPipelineState.uniformBuffer1->GetMemoryHandle()->Unmap();
225 PipelineRef CreatePipeline( State& state )
227 auto pipeline = Pipeline::New( mGraphics );
229 pipeline->SetShader( state.vertexShader, Shader::Type::VERTEX );
230 pipeline->SetShader( state.fragmentShader, Shader::Type::FRAGMENT );
232 auto size = mGraphics.GetSurface( 0u )->GetSize();
233 pipeline->SetViewport( 0, 0, static_cast<float>( size.width ), static_cast<float>( size.height ) );
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{}
241 .setStride( sizeof( vec3 ) )
242 .setInputRate( vk::VertexInputRate::eVertex )} );
243 pipeline->SetInputAssemblyState( vk::PrimitiveTopology::eTriangleStrip, false );
247 if( !pipeline->Compile() )
252 state.pipeline = pipeline;
256 void SubmitCommand( Dali::Graphics::API::RenderCommand&& command )
258 auto& state = mDebugPipelineState;
260 const auto& bufferList = command.GetBufferList();
261 auto drawcalls = command.GetPrimitiveCount();
263 // create pool of commands to be re-recorded
264 if( state.drawCommandPool.empty() )
266 for( auto i = 0u; i < 1024; ++i )
268 state.drawCommandPool.push_back( state.commandPool->NewCommandBuffer( false ) );
272 uint32_t stride = sizeof( mat4 ) + sizeof( vec4 ) + sizeof( vec3 );
273 std::vector<CommandBufferRef> executeCommands;
274 for( auto&& buf : bufferList.Get() )
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() );
281 // create buffer if doesn't exist
282 if( !state.uniformBuffer0 )
284 state.uniformBuffer0 = Buffer::New( mGraphics, uniformBlockMemoryNeeded, Buffer::Type::UNIFORM );
286 if( state.uniformBuffer0->GetSize() < uniformBlockMemoryNeeded || !state.uniformBuffer0->GetMemoryHandle() )
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 ) );
301 } __attribute__( ( aligned( 16 ) ) );
303 auto memory = state.uniformBuffer0->GetMemoryHandle();
304 auto outPtr = memory->MapTyped<char>();
305 for( auto i = 0u; i < drawcalls.Get(); ++i )
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;
312 auto descriptorSets = state.descriptorPool->AllocateDescriptorSets(
313 vk::DescriptorSetAllocateInfo{}.setDescriptorSetCount( 1 ).setPSetLayouts(
314 state.pipeline->GetVkDescriptorSetLayouts().data() ) );
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)
320 descriptorSets[0]->WriteCombinedImageSampler(2, mTextures[inputData->samplerId]->GetSampler(),
321 mTextures[inputData->samplerId]->GetImageView());
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 );
333 executeCommands.push_back( cmdbuf );
339 mGraphics.GetSwapchainForFBID( 0u )->GetPrimaryCommandBuffer()->ExecuteCommands( executeCommands );
341 // break, one pass only
345 #pragma GCC diagnostic pop
348 auto surface = mGraphics.GetSurface( 0u );
350 auto swapchain = mGraphics.GetSwapchainForFBID( 0u );
351 swapchain->AcquireNextFramebuffer();
354 mDebugPipelineState.drawPoolIndex = 0u;
355 mDebugPipelineState.descriptorPool->Reset();
356 mDebugPipelineState.commandPool->Reset( true );
361 auto swapchain = mGraphics.GetSwapchainForFBID( 0u );
362 swapchain->Present();
365 DescriptorPoolRef CreateDescriptorPool()
367 vk::DescriptorPoolSize size;
368 size.setDescriptorCount( 1024 ).setType( vk::DescriptorType::eUniformBuffer );
370 // TODO: how to organize this???
371 auto pool = DescriptorPool::New(
372 mGraphics, vk::DescriptorPoolCreateInfo{}.setMaxSets( 1024 ).setPoolSizeCount( 1 ).setPPoolSizes( &size ) );
376 API::TextureFactory& GetTextureFactory() const
378 return *(mTextureFactory.get());
381 API::ShaderFactory& GetShaderFactory() const
383 return *(mShaderFactory.get());
387 std::vector<TextureRef> mTextures;
388 std::vector<ShaderRef> mShaders;
391 ObjectOwner<API::Texture> mTexturesOwner;
392 ObjectOwner<API::Shader> mShadersOwner;
397 GpuMemoryAllocator& mDefaultAllocator;
399 State mDebugPipelineState;
401 std::unique_ptr<VulkanAPI::TextureFactory> mTextureFactory;
402 std::unique_ptr<VulkanAPI::ShaderFactory> mShaderFactory;
405 * NEW IMPLEMENTACIONE
408 void SubmitDraw( const Dali::Graphics::API::BufferInfo& buffer )
410 // find pipeline state for this batch
411 auto info = GraphicsPipelineState::Info{};
413 //info.vertexShader =
416 void SubmitCommandV2( Dali::Graphics::API::RenderCommand&& command )
419 auto vertexShader = command.GetShader( Dali::Graphics::API::ShaderDetails::PipelineStage::VERTEX );
420 auto fragmentShader = command.GetShader( Dali::Graphics::API::ShaderDetails::PipelineStage::FRAGMENT );
422 // get shaders from backend
426 vsh = VulkanAPI::Shader::DownCast( vertexShader.Get() ).GetShader( vk::ShaderStageFlagBits::eVertex );
431 fsh = VulkanAPI::Shader::DownCast( vertexShader.Get() ).GetShader( vk::ShaderStageFlagBits::eFragment );
435 const auto& bufferList = command.GetBufferList();
436 const auto& bufferVector = bufferList.Get();
438 for(const auto& bufferInfo : bufferVector )
441 const auto ptr = bufferInfo->GetDataBase();
442 const auto size = bufferInfo->GetSize();
444 SubmitDraw( bufferInfo );
454 std::vector<GraphicsPipelineState> mStatePerBatchCache;
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 )
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);
472 API::Accessor<API::Texture> Controller::CreateTexture( const API::BaseFactory<API::Texture>& factory )
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);
480 API::Accessor<API::TextureSet> Controller::CreateTextureSet( const API::BaseFactory<API::TextureSet>& factory )
484 API::Accessor<API::DynamicBuffer> Controller::CreateDynamicBuffer( const API::BaseFactory<API::DynamicBuffer>& factory )
488 API::Accessor<API::StaticBuffer> Controller::CreateStaticBuffer( const API::BaseFactory<API::StaticBuffer>& factory )
492 API::Accessor<API::Sampler> Controller::CreateSampler( const API::BaseFactory<API::Sampler>& factory )
496 API::Accessor<API::Framebuffer> Controller::CreateFramebuffer( const API::BaseFactory<API::Framebuffer>& factory )
500 std::unique_ptr<char> Controller::CreateBuffer( size_t numberOfElements, size_t elementSize )
502 return std::unique_ptr<char>( new char[numberOfElements * elementSize] );
505 #pragma GCC diagnostic pop
507 std::unique_ptr<Controller> Controller::New( Graphics& vulkanGraphics )
509 return std::make_unique<Controller>( vulkanGraphics );
512 Controller::Controller( Graphics& vulkanGraphics ) : mImpl( std::make_unique<Impl>( *this, vulkanGraphics ) )
517 Controller::~Controller() = default;
518 Controller::Controller() = default;
519 Controller& Controller::operator=( Controller&& ) = default;
521 void Controller::GetRenderItemList()
525 void Controller::SubmitCommand( Dali::Graphics::API::RenderCommand&& command )
527 mImpl->SubmitCommand( std::move( command ) );
528 //SubmitCommandTest( std::move( command ) );
531 void Controller::BeginFrame()
536 void Controller::EndFrame()
541 API::TextureFactory& Controller::GetTextureFactory() const
543 return mImpl->GetTextureFactory();
546 API::ShaderFactory& Controller::GetShaderFactory() const
548 return mImpl->GetShaderFactory();
551 } // namespace Vulkan
552 } // namespace Graphics