lumiera_documentation/tests/vault/mem/engine-buffer-manager-test.cpp
Ichthyostega 5a47b099be BufferProvider: find a solution for processing allocations
Implementing the `EngineBufferManager` the desired way,
with the ability to post allocation requests asynchronously,
raises the difficult question of who will ultimately perform
the allocation / deallocation and further management work.

The point is that this management effort takes up capacity
originally assigned for the render workers themselves, either
by implicitly pushing aside those threads, or as a dedicated
processing assigned to some worker.

In the current stage of development it seems impossible to decide
upon the proper mechanism to schedule this excess work explicitly.

The solution proposed hereby however circumvents this dilemma,
insofar it allows to implement the synchronous, fallback processing
in terms of the asynchronous processing, just performed exclusively
within the current thread. Unless some processing will be scheduled
explicitly (which can be added as performance optimisation later on),
the handling of a direct allocation request will ''fold down'' into
the current worker eventually, thereby using it's processing capability
without the need of any explicit scheduling.
2026-05-12 23:46:55 +02:00

161 lines
4.2 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
EngineBufferManager(Test) - cover the interface to a central buffer manager
Copyright (C)
2026, Hermann Vosseler <Ichthyostega@web.de>
  **Lumiera** is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the
  Free Software Foundation; either version 2 of the License, or (at your
  option) any later version. See the file COPYING for further details.
* *****************************************************************/
/** @file engine-buffer-manager-test.cpp
** unit test \ref EngineBufferManager_test
*/
#include "test/run.hpp"
#include "test/test-helper.hpp"
//#include "vault/mem/engine-buffer-metadata.hpp"
#include "vault/mem/engine-buffer-manager.hpp"
#include "vault/mem/engine-buffer-allocator.hpp"
//#include "lib/depend-inject.hpp"
//#include "lib/thread.hpp"
//#include "lib/error.hpp"
#include "lib/symbol.hpp"
#include "test/diagnostic-output.hpp"////////////TODO
#include <algorithm>
//using std::this_thread::yield;
//using lib::Thread;
using lib::Literal;
namespace vault {
namespace mem {
namespace test {
// using LERR_(LOGIC);
// using LERR_(LIFECYCLE);
namespace { // Test helper
// template<typename X>
// Buff*
// mark_as_Buffer(X& something)
// {
// return reinterpret_cast<Buff*> (std::addressof(something));
// }
//
}
/*****************************************************************************//**
* @test Show how the central buffer manager of the Render Engine can be accessed.
*/
class EngineBufferManager_test : public Test
{
virtual void
run (Arg)
{
// seedRand();
demonstrate_AllocatorInterface();
verify_syncRequest();
verify_asyncRequest();
verify_lulz();
}
/** @test show how to allocate buffer memory
* with the underlying base allocator.
* @remark 4/2026 for the first integration of the Render Engine,
* a simplified implementation is used that just delegates
* to the regular heap allocator (which actually performs
* quite well on modern C++ STDLib). The plan is to
* use some kind of tiling pool allocator eventually,
* contingent on the actual performance observations.
*/
void
demonstrate_AllocatorInterface()
{
using Allo = HeapBufferAllocator;
CHECK (lib::allo::is_Stateless_v<Allo>);
Allo allo;
auto a1 = allo.allocate (55);
auto a2 = allo.allocate (555);
CHECK (a1.mem);
CHECK (a2.mem);
CHECK (a1.siz == Allo::TILE_SIZ);
CHECK (a2.siz % Allo::TILE_SIZ == 0);
CHECK (a2.siz > 555);
// can use that memory without blowing up....
auto doooh = new(a1.mem) f128{std::numeric_limits<f128>::max()};
*doooh /= 2;
CHECK (2 == std::numeric_limits<f128>::max() / *doooh);
allo.deallocate (a1);
allo.deallocate (a2);
}
/** @test show that a direct request for allocation is honored */
void
verify_syncRequest()
{
EngineBufferManager manager;
SHOW_EXPR(watch(manager).isEmpty())
Alloc alloc = manager.requestAllocation (555);
CHECK (not alloc.empty());
CHECK (alloc.siz >= 555);
SHOW_EXPR(watch(manager).bytesAllocd())
SHOW_EXPR(watch(manager).bytesLeased())
// can use that memory
char* buf = reinterpret_cast<char*> (alloc.mem);
string ranS{lib::randStr(555-1)};
auto* p = std::copy (ranS.begin(), ranS.end(), buf);
SHOW_EXPR(p - buf)
*p = '\0';
CHECK (ranS == buf);
}
/** @test show that an working allocation request across thread boundaries */
void
verify_asyncRequest()
{
}
/** @test
*/
void
verify_lulz()
{
}
};
/** Register this test class... */
LAUNCHER (EngineBufferManager_test, "unit engine");
}}} // namespace vault::mem::test