1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "render_data_store_manager.h"
17
18 #include <cstddef>
19
20 #include <base/util/uid_util.h>
21 #include <render/datastore/intf_render_data_store.h>
22 #include <render/device/intf_device.h>
23 #include <render/intf_render_context.h>
24 #include <render/namespace.h>
25
26 #include "util/log.h"
27
28 using namespace BASE_NS;
29
RENDER_BEGIN_NAMESPACE()30 RENDER_BEGIN_NAMESPACE()
31 RenderDataStoreManager::RenderDataStoreManager(IRenderContext& renderContext) : renderContext_(renderContext) {}
32
CommitFrameData()33 void RenderDataStoreManager::CommitFrameData()
34 {
35 // only modify the write index when double buffered in use
36 if (renderDataStoreFlags_ & DOUBLE_BUFFERED_RENDER_DATA_STORES) {
37 frameWriteIndex_ = 1u - frameWriteIndex_;
38 }
39 #if (RENDER_VALIDATION_ENABLED == 1)
40 commitDeviceFrameIndex_ = renderContext_.GetDevice().GetFrameCount();
41 #endif
42
43 decltype(pendingRenderAccess_) pendingRenderAccess;
44 {
45 std::lock_guard<std::mutex> lock(mutex_);
46 pendingRenderAccess = std::move(pendingRenderAccess_);
47 }
48
49 // prepare access for render time access
50 for (auto& pendingRef : pendingRenderAccess) {
51 if (pendingRef.destroy) { // remove deferred destruction stores
52 renderAccessStores_.erase(pendingRef.hash);
53 } else {
54 PLUGIN_ASSERT(pendingRef.renderDataStore);
55 renderAccessStores_.insert_or_assign(pendingRef.hash, pendingRef.renderDataStore);
56 }
57 }
58
59 // all valid stores can be accessed from render access stores without locks
60 for (const auto& ref : renderAccessStores_) {
61 ref.second->CommitFrameData();
62 }
63 }
64
PreRender()65 void RenderDataStoreManager::PreRender()
66 {
67 // all valid stores can be accessed from render access stores without locks
68 for (const auto& ref : renderAccessStores_) {
69 ref.second->PreRender();
70 }
71 }
72
PostRender()73 void RenderDataStoreManager::PostRender()
74 {
75 // all valid stores can be accessed from render access stores without locks
76 for (const auto& ref : renderAccessStores_) {
77 ref.second->PostRender();
78 }
79 }
80
PreRenderBackend()81 void RenderDataStoreManager::PreRenderBackend()
82 {
83 // all valid stores can be accessed from render access stores without locks
84 for (const auto& ref : renderAccessStores_) {
85 ref.second->PreRenderBackend();
86 }
87 }
88
PostRenderBackend()89 void RenderDataStoreManager::PostRenderBackend()
90 {
91 // all valid stores can be accessed from render access stores without locks
92 for (const auto& ref : renderAccessStores_) {
93 ref.second->PostRenderBackend();
94 }
95
96 DeferredDestruction();
97 }
98
GetRenderDataStore(const string_view name) const99 IRenderDataStore* RenderDataStoreManager::GetRenderDataStore(const string_view name) const
100 {
101 if (name.empty()) {
102 return nullptr;
103 }
104
105 auto const nameHash = hash(name);
106
107 std::lock_guard<std::mutex> lock(mutex_);
108
109 if (const auto iter = stores_.find(nameHash); iter != stores_.cend()) {
110 return iter->second.get();
111 } else {
112 #if (RENDER_VALIDATION_ENABLED == 1)
113 PLUGIN_LOG_ONCE_W(
114 name + "_RDS_NOT_FOUND__", "RENDER_VALIDATION: render data store: (%s), not found", name.data());
115 #endif
116 return nullptr;
117 }
118 }
119
GetRenderTimeRenderDataStore(const string_view name) const120 IRenderDataStore* RenderDataStoreManager::GetRenderTimeRenderDataStore(const string_view name) const
121 {
122 if (name.empty()) {
123 return nullptr;
124 }
125
126 // not locked
127
128 auto const nameHash = hash(name);
129 if (const auto iter = renderAccessStores_.find(nameHash); iter != renderAccessStores_.cend()) {
130 return iter->second;
131 } else {
132 #if (RENDER_VALIDATION_ENABLED == 1)
133 PLUGIN_LOG_ONCE_W(
134 name + "_RDS_NOT_FOUND", "RENDER_VALIDATION: render data store: (%s), not found", name.data());
135 #endif
136 return nullptr;
137 }
138 }
139
Create(const Uid & dataStoreTypeUid,char const * dataStoreName)140 IRenderDataStore* RenderDataStoreManager::Create(const Uid& dataStoreTypeUid, char const* dataStoreName)
141 {
142 auto const dataStoreTypeHash = hash(dataStoreTypeUid);
143 if (auto const factoryIt = factories_.find(dataStoreTypeHash); factoryIt != factories_.end()) {
144 auto const dataStoreNameHash = hash(string_view(dataStoreName));
145 IRenderDataStore* dataStore = nullptr;
146
147 std::lock_guard<std::mutex> lock(mutex_);
148
149 if (auto const namedStoreIt = stores_.find(dataStoreNameHash); namedStoreIt != stores_.cend()) {
150 PLUGIN_LOG_D("Named data store already exists (type: %s) (name: %s)", to_string(dataStoreTypeUid).data(),
151 dataStoreName);
152 dataStore = namedStoreIt->second.get();
153 if (dataStore->GetUid() != dataStoreTypeUid) {
154 PLUGIN_LOG_E("Named data store (type: %s, name: %s) exists with different type (%s)",
155 to_string(dataStoreTypeUid).data(), dataStoreName, dataStore->GetTypeName().data());
156 dataStore = nullptr;
157 }
158 } else {
159 auto const dataStoreIt = stores_.insert_or_assign(dataStoreNameHash,
160 RenderDataStorePtr { factoryIt->second.createDataStore(renderContext_, dataStoreName),
161 factoryIt->second.destroyDataStore });
162 pointerToStoreHash_.insert_or_assign(dataStoreIt.first->second.get(), uint64_t { dataStoreNameHash });
163 dataStore = dataStoreIt.first->second.get();
164 }
165
166 pendingRenderAccess_.push_back({ dataStoreNameHash, dataStore, false });
167 return dataStore;
168 } else {
169 PLUGIN_LOG_E("render data store type not found (type: %s) (named: %s)", to_string(dataStoreTypeUid).data(),
170 dataStoreName);
171 PLUGIN_ASSERT(false);
172 }
173 return nullptr;
174 }
175
Destroy(const Uid & dataStoreTypeUid,IRenderDataStore * instance)176 void RenderDataStoreManager::Destroy(const Uid& dataStoreTypeUid, IRenderDataStore* instance)
177 {
178 if (instance) {
179 const uint64_t typeHash = hash(dataStoreTypeUid);
180
181 std::lock_guard<std::mutex> lock(mutex_);
182
183 deferredDestructionDataStores_.push_back({ typeHash, instance });
184
185 PLUGIN_ASSERT(pointerToStoreHash_.contains(instance));
186 if (auto const storeIt = pointerToStoreHash_.find(instance); storeIt != pointerToStoreHash_.cend()) {
187 pendingRenderAccess_.push_back({ storeIt->second, instance, true });
188 }
189 }
190 }
191
GetRenderDataStoreFlags() const192 IRenderDataStoreManager::RenderDataStoreFlags RenderDataStoreManager::GetRenderDataStoreFlags() const
193 {
194 return renderDataStoreFlags_;
195 }
196
197 #if (RENDER_VALIDATION_ENABLED == 1)
ValidateCommitFrameData() const198 void RenderDataStoreManager::ValidateCommitFrameData() const
199 {
200 if (renderDataStoreFlags_ & DOUBLE_BUFFERED_RENDER_DATA_STORES) {
201 if (commitDeviceFrameIndex_ != renderContext_.GetDevice().GetFrameCount()) {
202 PLUGIN_LOG_E("Render data store manager CommitFrameData() needs to be called before rendering when using "
203 "double buffered render data stores.");
204 }
205 }
206 }
207 #endif
208
GetFrameIndices() const209 IRenderDataStoreManager::FrameIndices RenderDataStoreManager::GetFrameIndices() const
210 {
211 if (renderDataStoreFlags_ & DOUBLE_BUFFERED_RENDER_DATA_STORES) {
212 return { frameWriteIndex_, 1u - frameWriteIndex_ };
213 } else {
214 return { frameWriteIndex_, frameWriteIndex_ };
215 }
216 }
217
DeferredDestruction()218 void RenderDataStoreManager::DeferredDestruction()
219 {
220 std::lock_guard<std::mutex> lock(mutex_);
221
222 for (const auto& destroyRef : deferredDestructionDataStores_) {
223 if (auto const pos = factories_.find(destroyRef.dataStoreHash); pos != factories_.end()) {
224 if (auto const storeIt = pointerToStoreHash_.find(destroyRef.instance);
225 storeIt != pointerToStoreHash_.cend()) {
226 stores_.erase(storeIt->second);
227 pointerToStoreHash_.erase(storeIt);
228 }
229 }
230 }
231 deferredDestructionDataStores_.clear();
232 }
233
AddRenderDataStoreFactory(const RenderDataStoreTypeInfo & typeInfo)234 void RenderDataStoreManager::AddRenderDataStoreFactory(const RenderDataStoreTypeInfo& typeInfo)
235 {
236 // plugin load and factory addition is sequential
237 // not locked access
238
239 if (typeInfo.createDataStore && typeInfo.destroyDataStore) {
240 auto const dataStoreTypeHash = hash(typeInfo.uid);
241 factories_.insert({ dataStoreTypeHash, typeInfo });
242 } else {
243 PLUGIN_LOG_E("RenderDataStoreTypeInfo must provide non-null function pointers");
244 PLUGIN_ASSERT(typeInfo.createDataStore && "createDataStore cannot be null");
245 PLUGIN_ASSERT(typeInfo.destroyDataStore && "destroyDataStore cannot be null");
246 }
247 }
248
RemoveRenderDataStoreFactory(const RenderDataStoreTypeInfo & typeInfo)249 void RenderDataStoreManager::RemoveRenderDataStoreFactory(const RenderDataStoreTypeInfo& typeInfo)
250 {
251 for (auto b = pointerToStoreHash_.begin(), e = pointerToStoreHash_.end(); b != e;) {
252 if (b->first->GetUid() == typeInfo.uid) {
253 stores_.erase(b->second);
254 b = pointerToStoreHash_.erase(b);
255 } else {
256 ++b;
257 }
258 }
259 auto const dataStoreTypeHash = hash(typeInfo.uid);
260 factories_.erase(dataStoreTypeHash);
261 }
262
RenderNodeRenderDataStoreManager(const RenderDataStoreManager & renderDataStoreMgr)263 RenderNodeRenderDataStoreManager::RenderNodeRenderDataStoreManager(const RenderDataStoreManager& renderDataStoreMgr)
264 : renderDataStoreMgr_(renderDataStoreMgr)
265 {}
266
GetRenderDataStore(const string_view name) const267 IRenderDataStore* RenderNodeRenderDataStoreManager::GetRenderDataStore(const string_view name) const
268 {
269 return renderDataStoreMgr_.GetRenderTimeRenderDataStore(name);
270 }
271 RENDER_END_NAMESPACE()
272