Doxygen Samurai Engine 0.0.1
Doxygen Samurai Engine Documentation
Loading...
Searching...
No Matches
containerManager.cpp
Go to the documentation of this file.
1#include "containerManager.h"
2
3#include <unordered_set>
4#include <chrono>
5#include <thread>
6#include <unordered_map>
7#include <filesystem>
8#include <imgui.h>
9
10#include "imgui_internal.h"
12
14 samurai::LoadedDll &loadedDll, samurai::LogManager &logManager,
15 samurai::samuraiImgui::ImGuiIdsManager &imguiIDsManager, std::string &cmd, size_t memoryPos)
16{
17
18 for(auto &i : loadedDll.containerInfo)
19 {
20
21 if (i.containerName == containerName)
22 {
23 return createContainer(i, loadedDll, logManager, imguiIDsManager, cmd, memoryPos);
24 }
25
26 }
27
28 logManager.log(("Couldn't create container, couldn't find the name: " + containerName).c_str(), samurai::logError);
29
30 return 0;
31}
32
33
34//todo mabe use regions further appart in production
36 samurai::ContainerInformation containerInformation, void *memPos)
37{
38 size_t memoryRequired = containerInformation.calculateMemoryRequirements();
39
40 void *baseMemory = allocateOSMemory(memoryRequired, memPos);
41
42 if (baseMemory == nullptr) { return 0; }
43
44 container.totalSize = memoryRequired;
45
46 allocateContainerMemoryAtBuffer(container, containerInformation, baseMemory);
47
48 return baseMemory;
49}
50
52 samurai::ContainerInformation containerInformation, void *buffer)
53{
54 const size_t staticMemory = containerInformation.containerStructBaseSize;
55 const size_t heapMemory = containerInformation.containerStaticInfo.defaultHeapMemorySize;
56
57 char *currentMemoryAdress = (char *)buffer;
58
59 container.arena.containerStructMemory.size = staticMemory;
60 container.arena.containerStructMemory.block = currentMemoryAdress;
61 currentMemoryAdress += staticMemory;
62 samurai::align64(currentMemoryAdress);
63
64 container.allocator.init(currentMemoryAdress, heapMemory);
65
66 currentMemoryAdress += heapMemory;
67
68 for (int i = 0; i < containerInformation.containerStaticInfo.bonusAllocators.size(); i++)
69 {
70 samurai::align64(currentMemoryAdress);
71
73 allocator.init(
74 currentMemoryAdress,
75 containerInformation.containerStaticInfo.bonusAllocators[i]
76 );
77 container.bonusAllocators.push_back(allocator);
78 currentMemoryAdress += containerInformation.containerStaticInfo.bonusAllocators[i];
79 }
80
81}
82
84{
85 deallocateOSMemory(container.arena.containerStructMemory.block);
86
87 //container.arena.dealocateStaticMemory(); //static memory
88 //deallocateOSMemory(container.allocator.originalBaseMemory); //heap memory
89 //
90 //for (auto &i : container.bonusAllocators)
91 //{
92 // deallocateOSMemory(i.originalBaseMemory);
93 //}
94}
95
97(samurai::ContainerInformation containerInformation,
98 samurai::LoadedDll &loadedDll, samurai::LogManager &logManager, samurai::samuraiImgui::ImGuiIdsManager &imguiIDsManager, std::string &cmd,
99 size_t memoryPos)
100{
101 containerId_t id = ++idCounter;
102
103 //not necessary if this is the only things that assigns ids.
104 //if (runningContainers.find(id) != runningContainers.end())
105 //{
106 // logManager.log((std::string("Container id already exists: #") + std::to_string(id)).c_str(), samurai::logError);
107 // return false;
108 //}
109
110 //todo a create and destruct wrapper
111
112 samurai::RuntimeContainer container = {};
113 samurai::strlcpy(container.baseContainerName, containerInformation.containerName,
114 sizeof(container.baseContainerName));
115
116 if (!allocateContainerMemory(container, containerInformation, (void*)memoryPos))
117 {
118 logManager.log((std::string("Couldn't allocate memory for constructing container: #")
119 + std::to_string(id)).c_str(), samurai::logError);
120 return 0;
121 }
122
123 // In SDL, this coulde be considered to create a texture as render target
124 if (containerInformation.containerStaticInfo.requestImguiFbo)
125 {
126#if !SAMURAI_SDL
127 container.requestedContainerInfo.requestedFBO.createFramebuffer(400, 400); //todo resize small or sthing
128#else
129 container.requestedContainerInfo.wind = imguiIDsManager.wind;
130 if (!container.requestedContainerInfo.wind) {
131 SDL_Log("Failed to retrieve window: %s", SDL_GetError());
132 // Handle error, possibly with return or exit.
133 }
134 container.requestedContainerInfo.renderer = SDL_GetRenderer(container.requestedContainerInfo.wind);
135 container.requestedContainerInfo.requestedFBO.texture = SDL_CreateTexture(container.requestedContainerInfo.renderer,
136 SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 400, 400);
137 container.requestedContainerInfo.requestedFBO.width = 400;
138 container.requestedContainerInfo.requestedFBO.height = 400;
139#endif
140 container.imguiWindowId = imguiIDsManager.getImguiIds();
141 }
142
143 loadedDll.bindAllocatorDllRealm(&container.allocator);
144
145 //this calls the constructors (from the dll realm)
146 if (!loadedDll.constructRuntimeContainer(container, containerInformation.containerName.c_str()))
147 {
148 loadedDll.resetAllocatorDllRealm();
149
150 logManager.log((std::string("Couldn't construct container: #") + std::to_string(id)).c_str(), samurai::logError);
151
152 freeContainerStuff(container);
153#if !SAMURAI_SDL
155#else
156
157#endif
158 return 0;
159 }
160
161
162 loadedDll.resetAllocatorDllRealm();
163
164
165#pragma region setup requested container info
166
167 container.requestedContainerInfo.mainAllocator = &container.allocator;
170 imguiIDsManager.getImguiIds(containerInformation.containerStaticInfo.requestImguiIds);
172
173#pragma endregion
174
175 samurai::StaticString<256> cmdArgs = {};
176
177 if (cmd.size() > cmdArgs.MAX_SIZE)
178 {
179 logManager.log(std::string(std::string("Couldn't pass cmd argument because it is too big ")
180 + container.baseContainerName + " #" + std::to_string(id)).c_str(), samurai::logError);
181 }
182 else
183 {
184 cmdArgs = cmd.c_str();
185 }
186
187 loadedDll.bindAllocatorDllRealm(&container.allocator);
188 bool rezult = container.pointer->create(container.requestedContainerInfo, cmdArgs); //this calls create() (from the dll realm)
189 loadedDll.resetAllocatorDllRealm();//sets the global allocator back to standard (used for runtime realm)
190
191 runningContainers[id] = container;
192
193 if (!rezult)
194 {
195 logManager.log((std::string("Couldn't create container because it returned 0")
196 + container.baseContainerName + " #" + std::to_string(id)).c_str(), samurai::logWarning);
197 destroyContainer(id, loadedDll, logManager);
198 return 0;
199 }
200 else
201 {
202 logManager.log(("Created container: " + std::string(container.baseContainerName)).c_str());
203 }
204
205
206 return id;
207}
208
212
213void samurai::ContainerManager::update(samurai::LoadedDll &loadedDll, samurai::Window &window,
215{
216 SAMURAI_DEVELOPMENT_ONLY_ASSERT(loadedDll.dllHand != 0, "dll not loaded when trying to update containers");
217
218#pragma region reload dll
219
220
221 //todo try to recover from a failed load
222
223 if (loadedDll.shouldReloadDll())
224 {
225 reloadDll(loadedDll, window, logs); //todo return 0 on fail
226
227 //todo mark shouldCallReaload or just call reload
228
229 }
230
231
232#pragma endregion
233
234
235
236#pragma region running containers
237 for (auto &c : runningContainers)
238 {
239
240 {
241#if !SAMURAI_SDL
242 SAMURAI_DEVELOPMENT_ONLY_ASSERT(
243 (c.second.requestedContainerInfo.requestedFBO.fbo == 0 &&
244 c.second.imguiWindowId == 0) ||
245 (
246 c.second.requestedContainerInfo.requestedFBO.fbo != 0 &&
247 c.second.imguiWindowId != 0), "we have a fbo but no imguiwindow id"
248 );
249#endif
250 auto windowInput = window.input;
251
252
253 auto callUpdate = [&](samurai::WindowState &windowState) -> bool
254 {
255
256 auto t1 = std::chrono::high_resolution_clock::now();
257
258 loadedDll.bindAllocatorDllRealm(&c.second.allocator);
259 bool rez = c.second.pointer->update(windowInput, windowState, c.second.requestedContainerInfo);
260 loadedDll.resetAllocatorDllRealm();
261
262 auto t2 = std::chrono::high_resolution_clock::now();
263
264 auto milliseconds = (std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1)).count()/1000.f;
265
266 c.second.frameTimer += milliseconds;
267 c.second.frameCounter++;
268 if (c.second.frameCounter >= 100)
269 {
270 c.second.currentMs = c.second.frameTimer/100.f;
271
272 c.second.frameTimer = 0;
273 c.second.frameCounter = 0;
274 }
275
276 return rez;
277
278 };
279
280 bool rez = 0;
281
282 if (c.second.imguiWindowId)
283 {
284
285 #pragma region imguiwindow
286 ImGui::PushID(c.second.imguiWindowId);
287 bool isOpen = 1;
288
289 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.f, 0.f, 0.f, 1.0f));
290 ImGui::SetNextWindowSize({200,200}, ImGuiCond_Once);
291 ImGui::Begin( (std::string("gameplay window id: ") + std::to_string(c.first)).c_str(),
292 &isOpen, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
293
294 //mouse pos and focus
295
296 {
297 auto windowPos = ImGui::GetWindowPos();
298
299 ImVec2 globalMousePos = {};
300 {
301 ImGuiContext *g = ImGui::GetCurrentContext();
302 globalMousePos = g->IO.MousePos;
303 }
304
305 windowInput.mouseX = globalMousePos.x;
306 windowInput.mouseY = globalMousePos.y;
307
308 ImVec2 vMin = ImGui::GetWindowContentRegionMin();
309 windowInput.mouseX -= windowPos.x + vMin.x;
310 windowInput.mouseY -= windowPos.y + vMin.y;
311
312
313 //https://github.com/ocornut/imgui/issues/5882
314 ImGuiViewport *viewPort = ImGui::GetWindowViewport();
315 auto io = ImGui::GetIO();
316
317 if (viewPort->PlatformUserData)
318 {
319 windowInput.hasFocus = ImGui::IsWindowFocused()
320 && ImGui::GetPlatformIO().Platform_GetWindowFocus(viewPort) && !io.AppFocusLost;
321 }
322
323 //windowInput.hasFocus = windowInput.hasFocus && !io.AppFocusLost;
324 }
325
326
327 auto s = ImGui::GetContentRegionMax();
328#if !SAMURAI_SDL
329 ImGui::Image((void *)c.second.requestedContainerInfo.requestedFBO.texture, s, {0, 1}, {1, 0},
330 {1,1,1,1}, {0,0,0,1});
331#else
332 ImGui::Image((void*)c.second.requestedContainerInfo.requestedFBO.texture, s, { 0, 1 }, { 1, 0 },
333 { 1,1,1,1 }, { 0,0,0,1 });
334#endif
335 ImGui::End();
336
337 ImGui::PopStyleColor();
338
339 ImGui::PopID();
340 #pragma endregion
341
342 auto windowState = window.windowState;
343 windowState.w = s.x;
344 windowState.h = s.y;
345
346
347#if !SAMURAI_SDL
348 c.second.requestedContainerInfo.requestedFBO.resizeFramebuffer(windowState.w, windowState.h);
349
350 glBindFramebuffer(GL_FRAMEBUFFER, c.second.requestedContainerInfo.requestedFBO.fbo);
351
352 rez = callUpdate(windowState);
353
354 glBindFramebuffer(GL_FRAMEBUFFER, 0);
355#else
356 if (c.second.requestedContainerInfo.requestedFBO.width != windowState.w ||
357 c.second.requestedContainerInfo.requestedFBO.height != windowState.h)
358 {
359 c.second.requestedContainerInfo.requestedFBO.width = windowState.w;
360 c.second.requestedContainerInfo.requestedFBO.height = windowState.h;
361 c.second.requestedContainerInfo.requestedFBO.texture = SDL_CreateTexture(c.second.requestedContainerInfo.renderer,
362 SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, windowState.w, windowState.h);
363 }
364 SDL_SetRenderTarget(c.second.requestedContainerInfo.renderer, c.second.requestedContainerInfo.requestedFBO.texture);
365 rez = callUpdate(windowState);
366
367 SDL_SetRenderTarget(c.second.requestedContainerInfo.renderer, nullptr);
368
369#endif
370 if (!isOpen)
371 {
372 rez = 1;
373 destroyContainer(c.first, loadedDll, logs);
374 }
375
376 }
377 else
378 {
379 rez = callUpdate(window.windowState);
380 }
381
382 if (!rez)
383 {
384 logs.log(("Terminated container because it returned 0: " + std::string(c.second.baseContainerName)
385 + " #" + std::to_string(c.first)).c_str());
386 destroyContainer(c.first, loadedDll, logs);
387 }
388
389 }
390
391 }
392#pragma endregion
393
394}
395
396void samurai::ContainerManager::reloadDll(samurai::LoadedDll &loadedDll, samurai::Window &window, samurai::LogManager &logs)
397{
398
399 std::this_thread::sleep_for(std::chrono::milliseconds(200));
400
401
402 auto oldContainerInfo = loadedDll.containerInfo;
403
404 if (!loadedDll.tryToloadDllUntillPossible(loadedDll.id, logs, std::chrono::seconds(5)))
405 {
406 logs.log("Couldn't reloaded dll", samurai::logWarning);
407 return;
408 }
409 //todo pospone dll reloading
410
411 std::unordered_map<std::string, samurai::ContainerInformation> containerNames;
412 for (auto &c : loadedDll.containerInfo)
413 {
414 containerNames[c.containerName] = c;
415 }
416
417 std::unordered_map<std::string, samurai::ContainerInformation> oldContainerNames;
418 for (auto &c : oldContainerInfo)
419 {
420 oldContainerNames[c.containerName] = c;
421 }
422
423 //clear containers that dissapeared
424 {
425
426
427 std::vector<samurai::containerId_t> containersToClean;
428 for (auto &i : runningContainers)
429 {
430 if (containerNames.find(i.second.baseContainerName) ==
431 containerNames.end())
432 {
433 std::string l = "Killed container because it does not exist anymore in dll: " +
434 std::string(i.second.baseContainerName)
435 + " #" + std::to_string(i.first);
436 logs.log(l.c_str(), samurai::logError);
437
438 containersToClean.push_back(i.first);
439 }
440 }
441
442 for (auto i : containersToClean)
443 {
444 forceTerminateContainer(i, loadedDll, logs);
445 }
446 }
447
448 //clear containers that changed static info
449 {
450
451 std::vector<samurai::containerId_t> containersToClean;
452 for (auto &i : runningContainers)
453 {
454
455 auto &newContainer = containerNames[i.second.baseContainerName];
456 auto &oldContainer = oldContainerNames[i.second.baseContainerName];
457
458 if (newContainer != oldContainer)
459 {
460 std::string l = "Killed container because its static container info\nhas changed: "
461 + std::string(i.second.baseContainerName)
462 + " #" + std::to_string(i.first);
463 logs.log(l.c_str(), samurai::logError);
464
465 containersToClean.push_back(i.first);
466 }
467
468 }
469
470 for (auto i : containersToClean)
471 {
472 forceTerminateContainer(i, loadedDll, logs);
473 }
474
475 }
476
477 //realocate pointers
478 {
479 std::unordered_map<std::string, size_t> vtable;
480
481 for (auto& i : runningContainers)
482 {
483 auto pos = vtable.find(i.second.baseContainerName);
484 if (pos == vtable.end())
485 {
486 samurai::RuntimeContainer container = {};
487 samurai::strlcpy(container.baseContainerName, i.second.baseContainerName,
488 sizeof(container.baseContainerName));
489
491 for (auto& l : loadedDll.containerInfo)
492 {
493 if (l.containerName == i.second.baseContainerName)
494 {
495 info = l;
496 }
497 }
498
499 if (!allocateContainerMemory(container, info, 0))
500 {
501 logs.log("Internal error 1 (couldn't allocate container memory)", samurai::logError);
502 }
503 else
504 {
505 loadedDll.bindAllocatorDllRealm(&container.allocator);
506
507 //this calls the constructors (from the dll realm)
508 if (!loadedDll.constructRuntimeContainer(container, i.second.baseContainerName))
509 {
510 loadedDll.resetAllocatorDllRealm();
511 logs.log("Internal error 2", samurai::logError);
512 freeContainerStuff(container);
513 loadedDll.resetAllocatorDllRealm();
514 }
515 else
516 {
517
518 size_t id = *(size_t*)container.pointer;
519
520 freeContainerStuff(container);
521 loadedDll.resetAllocatorDllRealm();
522
523 vtable[i.second.baseContainerName] = id;
524 }
525
526
527 }
528 }
529
530 pos = vtable.find(i.second.baseContainerName);
531 if (pos != vtable.end())
532 {
533 memcpy(i.second.pointer, (void*)&pos->second, sizeof(size_t));
534 }
535 }
536 }
537
538
539
540 loadedDll.gameplayReload_(window.context);
541
542
543
544 logs.log("Reloaded dll");
545
546}
547
548//not verbose flag
549bool samurai::ContainerManager::destroyContainer(containerId_t id, samurai::LoadedDll &loadedDll,
550 samurai::LogManager &logManager)
551{
552 SAMURAI_DEVELOPMENT_ONLY_ASSERT(loadedDll.dllHand != 0, "dll not loaded when trying to destroy container");
553
554 auto c = runningContainers.find(id);
555 if (c == runningContainers.end())
556 {
557 logManager.log((std::string("Couldn't find container for destruction: #") + std::to_string(id)).c_str(),
559 return false;
560 }
561
562 auto name = c->second.baseContainerName;
563
564 loadedDll.bindAllocatorDllRealm(&c->second.allocator);
565 loadedDll.destructContainer_(&(c->second.pointer), &c->second.arena);
566 loadedDll.resetAllocatorDllRealm();
567
568 freeContainerStuff(c->second);
569
570#if !SAMURAI_SDL
571 c->second.requestedContainerInfo.requestedFBO.deleteFramebuffer();
572#else
573 SDL_DestroyTexture(c->second.requestedContainerInfo.requestedFBO.texture);
574#endif
575 runningContainers.erase(c);
576
577 logManager.log(std::string("Destroyed continer").c_str());
578
579 return true;
580}
581
582//todo remove some of this functions in production
583
584
585
587{
588 SAMURAI_DEVELOPMENT_ONLY_ASSERT(loadedDll.dllHand != 0, "dll not loaded when trying to destroy container");
589
590 auto c = runningContainers.find(id);
591 if (c == runningContainers.end())
592 {
593 logManager.log((std::string("Couldn't find container for destruction: #") + std::to_string(id)).c_str(),
595 return false;
596 }
597
598 auto name = c->second.baseContainerName;
599
600 freeContainerStuff(c->second);
601
602 runningContainers.erase(c);
603
604 logManager.log((std::string("Force terminated continer: ") + name + " #" + std::to_string(id)).c_str());
605#if !SAMURAI_SDL
606 c->second.requestedContainerInfo.requestedFBO.deleteFramebuffer();
607#else
608 SDL_DestroyTexture(c->second.requestedContainerInfo.requestedFBO.texture);
609#endif
610 return true;
611}
612
613void samurai::ContainerManager::destroyAllContainers(samurai::LoadedDll &loadedDll,
614 samurai::LogManager &logManager)
615{
616 std::vector < samurai::containerId_t> containersId;
617 containersId.reserve(runningContainers.size());
618
619 for (auto &c : runningContainers)
620 {
621 containersId.push_back(c.first);
622 }
623
624 for (auto i : containersId)
625 {
626 destroyContainer(i, loadedDll, logManager);
627 }
628
629}
630
631#ifdef PIKA_PRODUCTION
632
633void *samurai::ContainerManager::allocateOSMemory(size_t size, void *baseAdress)
634{
635 SAMURAI_ASSERT(baseAdress == nullptr, "can't allocate fixed memory in production");
636 return malloc(size);
637}
638
640{
641 free(baseAdress);
642}
643
644#else
645
646#include <Windows.h>
647
648void *samurai::ContainerManager::allocateOSMemory(size_t size, void *baseAdress)
649{
650 return VirtualAlloc(baseAdress, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
651}
652
654{
655 VirtualFree(baseAdress, 0, MEM_RELEASE);
656}
657
658
659
660#endif
#define SAMURAI_ASSERT(expression, comment)
Definition assert.h:40
@ logWarning
Definition log.h:11
@ logError
Definition log.h:12
void align64(size_t &val)
Definition Sizes.h:14
unsigned int containerId_t
size_t strlcpy(char *dst, const char *src, size_t size)
virtual bool create(RequestedContainerInfo &requestedInfo, samurai::StaticString< 256 > commandLineArgument)=0
samurai::StaticVector< size_t, MaxAllocatorsCount > bonusAllocators
unsigned int requestImguiIds
samurai::StaticVector< samurai::memory::CustomAllocator, MaxAllocatorsCount > * bonusAllocators
samurai::memory::CustomAllocator * mainAllocator
samurai::GL::PikaFramebuffer requestedFBO
ContainerStaticInfo containerStaticInfo
void destroyAllContainers(samurai::LoadedDll &loadedDll, samurai::LogManager &logManager)
bool destroyContainer(containerId_t id, samurai::LoadedDll &loadedDll, samurai::LogManager &logManager)
bool forceTerminateContainer(containerId_t id, samurai::LoadedDll &loadedDll, samurai::LogManager &logManager)
void * allocateContainerMemory(samurai::RuntimeContainer &container, samurai::ContainerInformation containerInformation, void *memPos=0)
void freeContainerStuff(samurai::RuntimeContainer &container)
void deallocateOSMemory(void *baseAdress)
void allocateContainerMemoryAtBuffer(samurai::RuntimeContainer &container, samurai::ContainerInformation containerInformation, void *buffer)
void update(samurai::LoadedDll &loadedDll, samurai::Window &window, samurai::LogManager &logs, samurai::samuraiImgui::ImGuiIdsManager &imguiIdManager)
containerId_t createContainer(samurai::ContainerInformation containerInformation, samurai::LoadedDll &loadedDll, samurai::LogManager &logManager, samurai::samuraiImgui::ImGuiIdsManager &imguiIDsManager, std::string &cmd, size_t memoryPos=0)
void * allocateOSMemory(size_t size, void *baseAdress=0)
void reloadDll(samurai::LoadedDll &loadedDll, samurai::Window &window, samurai::LogManager &logs)
void createFramebuffer(unsigned int w, unsigned int h)
void log(const char *l, int type=samurai::logNormal)
Definition log.cpp:14
samurai::memory::CustomAllocator allocator
RequestedContainerInfo requestedContainerInfo
samurai::StaticVector< samurai::memory::CustomAllocator, MaxAllocatorsCount > bonusAllocators
samurai::memory::MemoryArena arena
void push_back(const T &el)
size_t size() const
static constexpr unsigned int MAX_SIZE
WindowState windowState
Definition window.h:34
Input input
Definition window.h:31
samurai::Context context
Definition window.h:26
void init(void *baseMemory, size_t memorySize)
int getImguiIds(unsigned int count=1)
Definition gui.h:60