Fix potential memory scribbling issue in Render::UniformBuffer
[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   Flush();
50   Unmap();
51 }
52
53 void UniformBuffer::Flush()
54 {
55   if(mBuffer && mMemory)
56   {
57     mMemory->Flush();
58   }
59 }
60
61 void UniformBuffer::Reserve(uint32_t size)
62 {
63   if(mBuffer && mMemory)
64   {
65     Unmap();
66     mMemory = nullptr;
67   }
68
69   mSize = size;
70
71   auto createInfo = Graphics::BufferCreateInfo()
72                       .SetSize(mSize)
73                       .SetBufferPropertiesFlags(0 | Graphics::BufferPropertiesFlagBit::CPU_ALLOCATED)
74                       .SetUsage(mUsageFlags);
75
76   mBuffer = mController->CreateBuffer(createInfo, std::move(mBuffer));
77
78   mMapBufferInfo.buffer = mBuffer.get();
79   mMapBufferInfo.usage  = 0 | Graphics::MemoryUsageFlagBits::WRITE;
80   mMapBufferInfo.offset = 0;
81   mMapBufferInfo.size   = size;
82
83   if(mPersistentMappedEnabled)
84   {
85     Map();
86   }
87 }
88
89 void UniformBuffer::Fill(char data, uint32_t offset, uint32_t size)
90 {
91   bool locallyMapped = (mMemory == nullptr);
92   if(locallyMapped)
93   {
94     Map();
95   }
96
97   if(mMemory)
98   {
99     void* ptr = mMemory->LockRegion(0, mSize);
100
101     auto begin = (reinterpret_cast<char*>(ptr) + offset);
102     if(size == 0)
103     {
104       size = mSize - offset - 1;
105     }
106     auto end = begin + size;
107     std::fill(begin, end, data);
108
109     mMemory->Unlock(true);
110   }
111
112   if(locallyMapped)
113   {
114     Unmap();
115   }
116 }
117
118 void UniformBuffer::Write(const void* data, uint32_t size, uint32_t dstOffset)
119 {
120   bool locallyMapped = (mMemory == nullptr);
121   if(locallyMapped)
122   {
123     Map();
124   }
125
126   if(mMemory)
127   {
128     void* ptr = mMemory->LockRegion(dstOffset, size);
129     if(ptr && dstOffset + size < mSize)
130     {
131       memcpy(ptr, data, size);
132     }
133     mMemory->Unlock(true);
134   }
135
136   if(locallyMapped)
137   {
138     Unmap();
139   }
140 }
141
142 void UniformBuffer::Map()
143 {
144   if(!mMemory)
145   {
146     mMemory = mController->MapBufferRange(mMapBufferInfo);
147   }
148 }
149
150 void UniformBuffer::Unmap()
151 {
152   if(mMemory)
153   {
154     mController->UnmapMemory(std::move(mMemory));
155   }
156 }
157
158 UniformBufferManager::UniformBufferManager(Dali::Graphics::Controller* controller)
159 : mController(controller)
160 {
161 }
162
163 UniformBufferManager::~UniformBufferManager() = default;
164
165 Graphics::UniquePtr<UniformBuffer> UniformBufferManager::AllocateUniformBuffer(uint32_t size)
166 {
167   return Graphics::UniquePtr<UniformBuffer>(
168     new UniformBuffer(mController, size, 256u, true, Dali::Graphics::BufferUsageFlags{0u} | Dali::Graphics::BufferUsage::TRANSFER_DST | Dali::Graphics::BufferUsage::UNIFORM_BUFFER));
169 }
170
171 } // namespace Render
172
173 } // namespace Internal
174
175 } // namespace Dali