2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/render/renderers/uniform-buffer.h>
21 namespace Dali::Internal::Render
23 UniformBuffer::UniformBuffer(Dali::Graphics::Controller* controller,
26 bool persistentMappedEnabled,
27 Graphics::BufferUsageFlags usageFlags)
28 : mController(controller),
30 mUsageFlags(usageFlags)
32 mAlignment = alignment;
35 Resize(sizeInBytes, true);
39 UniformBuffer::~UniformBuffer()
41 // Unmap and flush all allocated buffers
42 for( auto i = 0u; i < mBuffers.size(); ++i)
49 void UniformBuffer::Flush(uint32_t bufferIndex)
51 const auto& buffer = mBuffers[bufferIndex];
52 if(buffer.buffer && buffer.memory)
54 buffer.memory->Flush();
58 void UniformBuffer::Resize( uint32_t newSize, bool invalidate )
60 // The buffer is already optimal
61 if(newSize == mSize && !invalidate)
65 if(invalidate && newSize == mSize && mBuffers.size() == 1)
77 // Adjust alignment, the alignment is needed for
78 // real UBOs (it should be given by the buffer requirements)
81 newSize = ((newSize / mAlignment)+1)*mAlignment;
86 auto createInfo = Graphics::BufferCreateInfo()
87 .SetSize(newSize - mSize)
88 .SetBufferPropertiesFlags(0 | Graphics::BufferPropertiesFlagBit::CPU_ALLOCATED)
89 .SetUsage(mUsageFlags);
91 auto buffer = mController->CreateBuffer(createInfo, nullptr);
93 mBuffers.emplace_back(GfxBuffer(std::move(buffer), createInfo));
100 const UniformBuffer::GfxBuffer* UniformBuffer::GetBufferByOffset( uint32_t offset, uint32_t* newOffset, uint32_t* outBufferIndex ) const
102 uint32_t bufferOffset = offset;
103 uint32_t bufferIndex = 0u;
105 // Find buffer if UBO is fragmented
106 if(mBuffers.size() > 1)
108 for(const auto& buffer : mBuffers)
110 if( bufferOffset >= buffer.createInfo.size)
112 bufferOffset -= buffer.createInfo.size;
122 auto& bufferDesc = mBuffers[bufferIndex];
126 *outBufferIndex = bufferIndex;
131 *newOffset = bufferOffset;
137 void UniformBuffer::Write(const void* data, uint32_t size, uint32_t dstOffset)
139 // find which buffer we want to write into
140 uint32_t bufferOffset = dstOffset;
141 uint32_t bufferIndex = 0u;
143 // Find buffer if UBO is fragmented
144 if(mBuffers.size() > 1)
146 for(const auto& buffer : mBuffers)
148 if( bufferOffset >= buffer.createInfo.size)
150 bufferOffset -= buffer.createInfo.size;
160 auto& bufferDesc = mBuffers[bufferIndex];
162 if(bufferDesc.needsUpdate)
164 mController->WaitIdle();
165 bufferDesc.needsUpdate = false;
168 DALI_ASSERT_ALWAYS( mBuffers.size() > bufferIndex );
169 DALI_ASSERT_ALWAYS( mBuffers[bufferIndex].buffer );
170 DALI_ASSERT_ALWAYS( mBuffers[bufferIndex].createInfo.size > bufferOffset + size );
172 bool locallyMapped = (bufferDesc.mappedPtr != nullptr);
175 // Map once and keep it
179 if(bufferDesc.memory)
181 void* ptr = bufferDesc.memory->LockRegion(bufferOffset, size);
182 if(ptr && bufferOffset + size < mSize)
184 // size always divides by 4 (std140 alignment rules, so we can replace memcpy with unrolled assignments)
185 auto ptr32 = reinterpret_cast<uint32_t*>(ptr);
186 auto data32 = reinterpret_cast<const uint32_t*>(data);
187 for(auto i = 0u; i < size; i +=4 )
189 *ptr32++ = *data32++;;
192 bufferDesc.memory->Unlock(true);
196 void UniformBuffer::Map( uint32_t bufferIndex)
198 auto& buffer = mBuffers[bufferIndex];
200 if(buffer.needsUpdate)
202 mController->WaitIdle();
203 buffer.needsUpdate = false;
208 Graphics::MapBufferInfo info{};
209 info.buffer = buffer.buffer.get();
210 info.usage = 0 | Graphics::MemoryUsageFlagBits::WRITE;
212 info.size = buffer.createInfo.size;
213 buffer.memory = mController->MapBufferRange(info);
217 void UniformBuffer::Unmap( uint32_t bufferIndex)
219 auto& buffer = mBuffers[bufferIndex];
222 mController->UnmapMemory(std::move(buffer.memory));