UBO support on the Core side using CPU-based Buffer memory
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / uniform-buffer-manager.cpp
1 /*
2  * Copyright (c) 2021 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 "uniform-buffer-manager.h"
19 #include <dali/graphics-api/graphics-buffer-create-info.h>
20 #include <dali/graphics-api/graphics-buffer.h>
21
22 #include <cstring>
23 #include <memory>
24
25 namespace Dali
26 {
27 namespace Internal
28 {
29 namespace Render
30 {
31 UniformBuffer::UniformBuffer(Dali::Graphics::Controller* controller,
32                              uint32_t                    sizeInBytes,
33                              uint32_t                    alignment,
34                              bool                        persistentMappedEnabled,
35                              Graphics::BufferUsageFlags  usageFlags)
36 : mController(controller),
37   mSize(0u),
38   mPersistentMappedEnabled(persistentMappedEnabled),
39   mUsageFlags(usageFlags)
40 {
41   if(sizeInBytes)
42   {
43     Reserve(sizeInBytes);
44   }
45 }
46
47 UniformBuffer::~UniformBuffer()
48 {
49   if(mBuffer && mMemory)
50   {
51     mController->UnmapMemory(std::move(mMemory));
52   }
53 }
54
55 void UniformBuffer::Flush()
56 {
57   if(mBuffer && mMemory)
58   {
59     mMemory->Flush();
60   }
61 }
62
63 void UniformBuffer::Reserve(uint32_t size)
64 {
65   if(mBuffer && mMemory)
66   {
67     Unmap();
68     mMemory = nullptr;
69   }
70
71   mSize = size;
72
73   auto createInfo = Graphics::BufferCreateInfo()
74     .SetSize(mSize)
75     .SetBufferPropertiesFlags( 0 | Graphics::BufferPropertiesFlagBit::CPU_ALLOCATED )
76     .SetUsage(mUsageFlags);
77
78   mBuffer = mController->CreateBuffer(createInfo, std::move(mBuffer));
79
80   mMapBufferInfo.buffer = mBuffer.get();
81   mMapBufferInfo.usage  = 0 | Graphics::MemoryUsageFlagBits::WRITE;
82   mMapBufferInfo.offset = 0;
83   mMapBufferInfo.size   = size;
84
85   if(mPersistentMappedEnabled)
86   {
87     Map();
88   }
89 }
90
91 void UniformBuffer::Fill(char data, uint32_t offset, uint32_t size)
92 {
93   bool locallyMapped = (mMemory == nullptr);
94   if(locallyMapped)
95   {
96     Map();
97   }
98
99   if(mMemory)
100   {
101     void* ptr = mMemory->LockRegion(0, mSize);
102
103     auto begin = (reinterpret_cast<char*>(ptr) + offset);
104     if(size == 0)
105     {
106       size = mSize - offset - 1;
107     }
108     auto end = begin + size;
109     std::fill(begin, end, data);
110
111     mMemory->Unlock(true);
112   }
113
114   if(locallyMapped)
115   {
116     Unmap();
117   }
118 }
119
120 void UniformBuffer::Write(const void* data, uint32_t size, uint32_t dstOffset)
121 {
122   bool locallyMapped = (mMemory == nullptr);
123   if(locallyMapped)
124   {
125     Map();
126   }
127
128   if(mMemory)
129   {
130     void* ptr = mMemory->LockRegion(0, size);
131     if(dstOffset + size < mSize)
132     {
133       memcpy(reinterpret_cast<char*>(ptr) + dstOffset, data, size);
134     }
135     mMemory->Unlock(true);
136   }
137
138   if(locallyMapped)
139   {
140     Unmap();
141   }
142 }
143
144 void UniformBuffer::Map()
145 {
146   if(!mMemory)
147   {
148     mMemory = mController->MapBufferRange(mMapBufferInfo);
149   }
150 }
151
152 void UniformBuffer::Unmap()
153 {
154   if(mMemory)
155   {
156     mController->UnmapMemory(std::move(mMemory));
157   }
158 }
159
160 UniformBufferManager::UniformBufferManager(Dali::Graphics::Controller* controller)
161 : mController(controller)
162 {
163 }
164
165 UniformBufferManager::~UniformBufferManager() = default;
166
167 Graphics::UniquePtr<UniformBuffer> UniformBufferManager::AllocateUniformBuffer(uint32_t size)
168 {
169   return Graphics::UniquePtr<UniformBuffer>(
170     new UniformBuffer(mController, size, 256u, true, Dali::Graphics::BufferUsageFlags{0u} | Dali::Graphics::BufferUsage::TRANSFER_DST | Dali::Graphics::BufferUsage::UNIFORM_BUFFER));
171 }
172
173 } // namespace Render
174
175 } // namespace Internal
176
177 } // namespace Dali