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-surface.h>
29 static const mat4 CLIP_MATRIX(
30 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 );
32 struct Controller::Impl
36 ShaderRef vertexShader;
37 ShaderRef fragmentShader;
38 DescriptorPoolRef descriptorPool;
40 BufferRef vertexBuffer;
41 BufferRef uniformBuffer0;
42 BufferRef uniformBuffer1; // clip matrix
43 std::vector<DescriptorSetRef> descriptorSets;
44 CommandPoolRef commandPool;
45 CommandBufferRef drawCommand;
47 std::vector<CommandBufferRef> drawCommandPool; // max 1024 secondary buffers
48 uint32_t drawPoolIndex{0u};
51 Impl( Controller& owner, Dali::Graphics::Vulkan::Graphics& graphics )
52 : mGraphics( graphics ),
54 mDefaultAllocator( mGraphics.GetDeviceMemoryManager().GetDefaultAllocator() )
62 // TODO: @todo this function initialises basic buffers, shaders and pipeline
63 // for the prototype ONLY
64 #pragma GCC diagnostic push
65 #pragma GCC diagnostic ignored "-Wframe-larger-than="
68 mDebugPipelineState.vertexShader = Shader::New( mGraphics, VSH_CODE.data(), VSH_CODE.size() );
70 mDebugPipelineState.fragmentShader = Shader::New( mGraphics, FSH_CODE.data(), FSH_CODE.size() );
72 mDebugPipelineState.descriptorPool = CreateDescriptorPool();
74 const float halfWidth = 0.5f;
75 const float halfHeight = 0.5f;
77 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.GetSurface( 0u ).GetCurrentCommandBuffer()->ExecuteCommands( executeCommands );
231 // break, one pass only
235 #pragma GCC diagnostic pop
238 auto& surface = mGraphics.GetSurface( 0u );
239 surface.AcquireNextImage();
242 mDebugPipelineState.drawPoolIndex = 0u;
243 mDebugPipelineState.descriptorPool->Reset();
244 mDebugPipelineState.commandPool->Reset( true );
249 auto& surface = mGraphics.GetSurface( 0u );
253 DescriptorPoolRef CreateDescriptorPool()
255 vk::DescriptorPoolSize size;
256 size.setDescriptorCount( 1024 ).setType( vk::DescriptorType::eUniformBuffer );
258 // TODO: how to organize this???
259 auto pool = DescriptorPool::New(
260 mGraphics, vk::DescriptorPoolCreateInfo{}.setMaxSets( 1024 ).setPoolSizeCount( 1 ).setPPoolSizes( &size ) );
266 GpuMemoryAllocator& mDefaultAllocator;
268 State mDebugPipelineState;
271 // TODO: @todo temporarily ignore missing return type, will be fixed later
272 #pragma GCC diagnostic push
273 #pragma GCC diagnostic ignored "-Wreturn-type"
274 API::Accessor<API::Shader> Controller::CreateShader( const API::BaseFactory<API::Shader>& factory )
278 API::Accessor<API::Texture> Controller::CreateTexture( const API::BaseFactory<API::Texture>& factory )
282 API::Accessor<API::TextureSet> Controller::CreateTextureSet( const API::BaseFactory<API::TextureSet>& factory )
286 API::Accessor<API::DynamicBuffer> Controller::CreateDynamicBuffer( const API::BaseFactory<API::DynamicBuffer>& factory )
290 API::Accessor<API::StaticBuffer> Controller::CreateStaticBuffer( const API::BaseFactory<API::StaticBuffer>& factory )
294 API::Accessor<API::Sampler> Controller::CreateSampler( const API::BaseFactory<API::Sampler>& factory )
298 API::Accessor<API::Framebuffer> Controller::CreateFramebuffer( const API::BaseFactory<API::Framebuffer>& factory )
302 std::unique_ptr<char> Controller::CreateBuffer( size_t numberOfElements, size_t elementSize )
304 return std::unique_ptr<char>( new char[numberOfElements * elementSize] );
307 #pragma GCC diagnostic pop
309 std::unique_ptr<Controller> Controller::New( Graphics& vulkanGraphics )
311 return std::make_unique<Controller>( vulkanGraphics );
314 Controller::Controller( Graphics& vulkanGraphics ) : mImpl( std::make_unique<Impl>( *this, vulkanGraphics ) )
319 Controller::~Controller() = default;
320 Controller::Controller() = default;
321 Controller& Controller::operator=( Controller&& ) = default;
323 void Controller::GetRenderItemList()
327 void Controller::SubmitCommand( API::RenderCommand&& command )
329 mImpl->SubmitCommand( std::move( command ) );
332 void Controller::BeginFrame()
337 void Controller::EndFrame()
342 } // namespace Vulkan
343 } // namespace Graphics