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>
30 static const mat4 CLIP_MATRIX(
31 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 );
33 struct Controller::Impl
37 ShaderRef vertexShader;
38 ShaderRef fragmentShader;
39 DescriptorPoolRef descriptorPool;
41 BufferRef vertexBuffer;
42 BufferRef uniformBuffer0;
43 BufferRef uniformBuffer1; // clip matrix
44 std::vector<DescriptorSetRef> descriptorSets;
45 CommandPoolRef commandPool;
46 CommandBufferRef drawCommand;
48 std::vector<CommandBufferRef> drawCommandPool; // max 1024 secondary buffers
49 uint32_t drawPoolIndex{0u};
52 Impl( Controller& owner, Dali::Graphics::Vulkan::Graphics& graphics )
53 : mGraphics( graphics ),
55 mDefaultAllocator( mGraphics.GetDeviceMemoryManager().GetDefaultAllocator() )
63 // TODO: @todo this function initialises basic buffers, shaders and pipeline
64 // for the prototype ONLY
65 #pragma GCC diagnostic push
66 #pragma GCC diagnostic ignored "-Wframe-larger-than="
69 mDebugPipelineState.vertexShader = Shader::New( mGraphics, VSH_CODE.data(), VSH_CODE.size() );
71 mDebugPipelineState.fragmentShader = Shader::New( mGraphics, FSH_CODE.data(), FSH_CODE.size() );
73 mDebugPipelineState.descriptorPool = CreateDescriptorPool();
75 const float halfWidth = 0.5f;
76 const float halfHeight = 0.5f;
78 const vec3 VERTICES[4] = {
79 {halfWidth, halfHeight, 0.0f},
80 {halfWidth, -halfHeight, 0.0f},
81 {-halfWidth, halfHeight, 0.0f},
82 {-halfWidth, -halfHeight, 0.0f},
86 const vec3 VERTICES[4] = {
87 {-halfWidth, -halfHeight, 0.0f},
88 {halfWidth, -halfHeight, 0.0f},
89 {halfWidth, halfHeight, 0.0f},
90 {-halfWidth, halfHeight, 0.0f}
93 mDebugPipelineState.vertexBuffer = Buffer::New( mGraphics, sizeof( VERTICES[0] ) * 4, Buffer::Type::VERTEX );
94 auto& defaultAllocator = mGraphics.GetDeviceMemoryManager().GetDefaultAllocator();
95 mDebugPipelineState.vertexBuffer->BindMemory(
96 defaultAllocator.Allocate( mDebugPipelineState.vertexBuffer, vk::MemoryPropertyFlagBits::eHostVisible ) );
98 auto ptr = mDebugPipelineState.vertexBuffer->GetMemoryHandle()->MapTyped<vec3>();
99 std::copy( VERTICES, VERTICES + 4, ptr );
100 mDebugPipelineState.vertexBuffer->GetMemoryHandle()->Unmap();
102 // create command pool
103 mDebugPipelineState.commandPool = CommandPool::New( mGraphics );
105 CreatePipeline( mDebugPipelineState );
107 // allocated descriptor pool ( 1024 sets, 1024 uniform buffers )
108 auto size = vk::DescriptorPoolSize{}.setDescriptorCount( 1024 ).setType( vk::DescriptorType::eUniformBuffer );
109 mDebugPipelineState.descriptorPool = DescriptorPool::New(
110 mGraphics, vk::DescriptorPoolCreateInfo{}.setPoolSizeCount( 1 ).setPPoolSizes( &size ).setMaxSets( 1024 ) );
112 mDebugPipelineState.uniformBuffer1 = Buffer::New( mGraphics, sizeof( CLIP_MATRIX ), Buffer::Type::UNIFORM );
113 mDebugPipelineState.uniformBuffer1->BindMemory(
114 mDefaultAllocator.Allocate( mDebugPipelineState.uniformBuffer1, vk::MemoryPropertyFlagBits::eHostVisible ) );
116 auto clipPtr = mDebugPipelineState.uniformBuffer1->GetMemoryHandle()->MapTyped<mat4>();
117 std::copy( &CLIP_MATRIX, &CLIP_MATRIX + 1, clipPtr );
118 mDebugPipelineState.uniformBuffer1->GetMemoryHandle()->Unmap();
123 PipelineRef CreatePipeline( State& state )
125 auto pipeline = Pipeline::New( mGraphics );
127 pipeline->SetShader( state.vertexShader, Shader::Type::VERTEX );
128 pipeline->SetShader( state.fragmentShader, Shader::Type::FRAGMENT );
130 auto size = mGraphics.GetSurface( 0u )->GetSize();
131 pipeline->SetViewport( 0, 0, static_cast<float>( size.width ), static_cast<float>( size.height ) );
133 pipeline->SetVertexInputState(
134 std::vector<vk::VertexInputAttributeDescription>{
135 vk::VertexInputAttributeDescription{}.setBinding( 0 ).setOffset( 0 ).setLocation( 0 ).setFormat(
136 vk::Format::eR32G32B32Sfloat )},
137 std::vector<vk::VertexInputBindingDescription>{vk::VertexInputBindingDescription{}
139 .setStride( sizeof( vec3 ) )
140 .setInputRate( vk::VertexInputRate::eVertex )} );
141 pipeline->SetInputAssemblyState( vk::PrimitiveTopology::eTriangleStrip, false );
143 if( !pipeline->Compile() )
148 state.pipeline = pipeline;
152 void SubmitCommand( API::RenderCommand&& command )
154 auto& state = mDebugPipelineState;
156 const auto& bufferList = command.GetBufferList();
157 auto drawcalls = command.GetPrimitiveCount();
159 // create pool of commands to be re-recorded
160 if( state.drawCommandPool.empty() )
162 for( auto i = 0u; i < 1024; ++i )
164 state.drawCommandPool.push_back( state.commandPool->NewCommandBuffer( false ) );
168 uint32_t stride = sizeof( mat4 ) + sizeof( vec4 ) + sizeof( vec3 );
169 std::vector<CommandBufferRef> executeCommands;
170 for( auto&& buf : bufferList.Get() )
172 // TODO: @todo implement minimum offset!
173 const uint32_t sizeOfUniformBuffer = U32( ( buf->GetSize() / drawcalls.Get() ) );
174 const uint32_t uniformBlockOffsetStride = ( ( sizeOfUniformBuffer / 256 ) + 1 ) * 256;
175 const uint32_t uniformBlockMemoryNeeded = U32( uniformBlockOffsetStride * drawcalls.Get() );
177 // create buffer if doesn't exist
178 if( !state.uniformBuffer0 )
180 state.uniformBuffer0 = Buffer::New( mGraphics, uniformBlockMemoryNeeded, Buffer::Type::UNIFORM );
182 if( state.uniformBuffer0->GetSize() < uniformBlockMemoryNeeded || !state.uniformBuffer0->GetMemoryHandle() )
184 // allocate and bind memory if needed ( buffer increased size or buffer hasn't been bound yet )
185 state.uniformBuffer0->BindMemory(
186 mDefaultAllocator.Allocate( state.uniformBuffer0, vk::MemoryPropertyFlagBits::eHostVisible ) );
196 } __attribute__( ( aligned( 16 ) ) );
198 auto memory = state.uniformBuffer0->GetMemoryHandle();
199 auto outPtr = memory->MapTyped<char>();
200 for( auto i = 0u; i < drawcalls.Get(); ++i )
202 // copy chunk of data
203 UB* inputData = ( reinterpret_cast<UB*>( buf->GetDataBase() ) ) + i;
204 UB* outputData = ( reinterpret_cast<UB*>( outPtr + ( i * uniformBlockOffsetStride ) ) );
205 *outputData = *inputData;
207 auto descriptorSets = state.descriptorPool->AllocateDescriptorSets(
208 vk::DescriptorSetAllocateInfo{}.setDescriptorSetCount( 1 ).setPSetLayouts(
209 state.pipeline->GetVkDescriptorSetLayouts().data() ) );
211 descriptorSets[0]->WriteUniformBuffer( 0, state.uniformBuffer0, i * uniformBlockOffsetStride, stride );
212 descriptorSets[0]->WriteUniformBuffer( 1, state.uniformBuffer1, 0, state.uniformBuffer1->GetSize() );
215 auto cmdbuf = state.commandPool->NewCommandBuffer( false );
216 cmdbuf->Begin( vk::CommandBufferUsageFlagBits::eRenderPassContinue );
217 cmdbuf->BindVertexBuffer( 0, state.vertexBuffer, 0 );
218 cmdbuf->BindGraphicsPipeline( state.pipeline );
219 cmdbuf->BindDescriptorSets( descriptorSets, 0 );
220 cmdbuf->Draw( 4, 1, 0, 0 );
223 executeCommands.push_back( cmdbuf );
229 mGraphics.GetSwapchainForFBID( 0u )->GetPrimaryCommandBuffer()->ExecuteCommands( executeCommands );
231 // break, one pass only
235 #pragma GCC diagnostic pop
238 auto surface = mGraphics.GetSurface( 0u );
240 auto swapchain = mGraphics.GetSwapchainForFBID( 0u );
241 swapchain->AcquireNextFramebuffer();
244 mDebugPipelineState.drawPoolIndex = 0u;
245 mDebugPipelineState.descriptorPool->Reset();
246 mDebugPipelineState.commandPool->Reset( true );
251 auto swapchain = mGraphics.GetSwapchainForFBID( 0u );
252 swapchain->Present();
255 DescriptorPoolRef CreateDescriptorPool()
257 vk::DescriptorPoolSize size;
258 size.setDescriptorCount( 1024 ).setType( vk::DescriptorType::eUniformBuffer );
260 // TODO: how to organize this???
261 auto pool = DescriptorPool::New(
262 mGraphics, vk::DescriptorPoolCreateInfo{}.setMaxSets( 1024 ).setPoolSizeCount( 1 ).setPPoolSizes( &size ) );
268 GpuMemoryAllocator& mDefaultAllocator;
270 State mDebugPipelineState;
273 // TODO: @todo temporarily ignore missing return type, will be fixed later
274 #pragma GCC diagnostic push
275 #pragma GCC diagnostic ignored "-Wreturn-type"
276 API::Accessor<API::Shader> Controller::CreateShader( const API::BaseFactory<API::Shader>& factory )
280 API::Accessor<API::Texture> Controller::CreateTexture( const API::BaseFactory<API::Texture>& factory )
284 API::Accessor<API::TextureSet> Controller::CreateTextureSet( const API::BaseFactory<API::TextureSet>& factory )
288 API::Accessor<API::DynamicBuffer> Controller::CreateDynamicBuffer( const API::BaseFactory<API::DynamicBuffer>& factory )
292 API::Accessor<API::StaticBuffer> Controller::CreateStaticBuffer( const API::BaseFactory<API::StaticBuffer>& factory )
296 API::Accessor<API::Sampler> Controller::CreateSampler( const API::BaseFactory<API::Sampler>& factory )
300 API::Accessor<API::Framebuffer> Controller::CreateFramebuffer( const API::BaseFactory<API::Framebuffer>& factory )
304 std::unique_ptr<char> Controller::CreateBuffer( size_t numberOfElements, size_t elementSize )
306 return std::unique_ptr<char>( new char[numberOfElements * elementSize] );
309 #pragma GCC diagnostic pop
311 std::unique_ptr<Controller> Controller::New( Graphics& vulkanGraphics )
313 return std::make_unique<Controller>( vulkanGraphics );
316 Controller::Controller( Graphics& vulkanGraphics ) : mImpl( std::make_unique<Impl>( *this, vulkanGraphics ) )
321 Controller::~Controller() = default;
322 Controller::Controller() = default;
323 Controller& Controller::operator=( Controller&& ) = default;
325 void Controller::GetRenderItemList()
329 void Controller::SubmitCommand( API::RenderCommand&& command )
331 mImpl->SubmitCommand( std::move( command ) );
334 void Controller::BeginFrame()
339 void Controller::EndFrame()
344 } // namespace Vulkan
345 } // namespace Graphics