diff --git a/src/steam/engine/buffer-provider.cpp b/src/steam/engine/buffer-provider.cpp index 0004c8a68..7f2766b6f 100644 --- a/src/steam/engine/buffer-provider.cpp +++ b/src/steam/engine/buffer-provider.cpp @@ -20,6 +20,7 @@ #include "lib/error.hpp" #include "steam/engine/buffer-provider.hpp" #include "steam/engine/buffer-metadata.hpp" /////////////////////////OOO must be removed from here +#include "steam/engine/simple-buffer-state-registry.hpp" /////////////OOO better use constexpr for hash-chaining? #include "lib/util.hpp" using util::isSameAdr; @@ -30,7 +31,7 @@ namespace engine { // storage for the default-marker constants const TypeHandler TypeHandler::RAW{}; const LocalTag LocalTag::UNKNOWN{}; - + const metadata::Key SimpleBufferStateRegistry::NULL_KEY{HashVal(0), size_t(0)}; //////OOO try to make this init into a constexpr and then do it in-class! namespace { // impl. details and definitions @@ -59,14 +60,16 @@ namespace engine { BuffDescr BufferProvider::getDescriptorFor (size_t storageSize) { - return BuffDescr (*this, bufferStage_->key (storageSize)); + auto& typeKey = bufferStage_->defineBufferType (storageSize, TypeHandler::RAW); + return BuffDescr (*this, typeKey); } BuffDescr BufferProvider::getDescriptorFor(size_t storageSize, TypeHandler specialTreatment) { - return BuffDescr (*this, bufferStage_->key (storageSize, specialTreatment)); + auto& typeKey = bufferStage_->defineBufferType (storageSize, move (specialTreatment)); + return BuffDescr (*this, typeKey); } diff --git a/src/steam/engine/buffer-provider.hpp b/src/steam/engine/buffer-provider.hpp index 02bdc2ba8..f8ddafb18 100644 --- a/src/steam/engine/buffer-provider.hpp +++ b/src/steam/engine/buffer-provider.hpp @@ -193,6 +193,7 @@ namespace engine { virtual ~BufferStage() { } ///< this is an interface using BufferMetadata::BufferMetadata; ///////////////////////////////////////////////////////////TICKET #1410 : actual implementation structures should move down into this classes implementation + virtual ID defineBufferType (size_t, TypeHandler) =0; virtual ID lookup (HashVal) =0; virtual ID mark_locked (ID typeKey, Buff*, LocalTag) =0; virtual ID mark_emitted (HashVal stateKey) =0; diff --git a/src/steam/engine/simple-buffer-state-registry.hpp b/src/steam/engine/simple-buffer-state-registry.hpp index 24259c1b6..039c3091c 100644 --- a/src/steam/engine/simple-buffer-state-registry.hpp +++ b/src/steam/engine/simple-buffer-state-registry.hpp @@ -50,15 +50,23 @@ namespace engine { : public BufferProviderSetup::Stage { ///////////////////////////////////////////////////////////////////////////////////////////////////////TICKET 1410 : rather hold BufferMetatdata object here + static const metadata::Key NULL_KEY; ////////////////////////////OOO better init directly here as constexpr (to keep it really an implementation detail) /* === BufferStage interface === */ - + ID lookup (HashVal key) override { - return this->get (key); + return this->isKnown(key)? this->get (key) + : NULL_KEY; } + ID + defineBufferType (size_t buffSiz, TypeHandler handlerFunctions) + { + return lookup (this->key (buffSiz, move (handlerFunctions))); + } // deliberately: create storage, and return reference to it + ID mark_locked (ID typeKey, Buff* storage, LocalTag implMark) override { diff --git a/src/steam/engine/type-handler.hpp b/src/steam/engine/type-handler.hpp index 27d44eeed..d20055dac 100644 --- a/src/steam/engine/type-handler.hpp +++ b/src/steam/engine/type-handler.hpp @@ -118,6 +118,7 @@ namespace engine { , destroyAttached() , identity{0} { } + // has value semantics; default copy OK /** build a TypeHandler * binding to arbitrary constructor and destructor functions. diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 794750f2e..908e307da 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -1252,16 +1252,23 @@ Mostly, the //client code,// i.e. code in need of using buffers, can access some :a //naive// implementation is used for unit-tests: each buffer request is simply allocated from the heap and this memory is not released or re-used, which allows to verify memory content after invoking the test subject. -
the generic BufferProvider implementation exposes a service to attach and maintain additional metadata with individual buffers. Using this service is not mandatory -- a concrete buffer provider implementation may chose to maintain more specific metadata right on the implementation level, especially if more elaborate management is necessary within the implementation anyway (e.g. the frame index). We can expect most buffer provider implementations to utilise at least the generic buffer type id service though. ++The generic BufferProvider implementation involves a service to attach and maintain additional metadata with individual buffers. The scheme used for forming this metadata became effectively part of the standard, to the degree that this generic high-level implementation of the //|Buffer Proivder Protocol«// is considered a façade, leaving room to configure the actual implementation backend. However, a concrete buffer provider implementation may chose to maintain more specific metadata right on the implementation level, especially if more elaborate management is necessary within the implementation anyway (e.g. the frame index). The metadata scheme offers a {{{LocalTag}}} to attach and mark such additional implementation-level qualification. + +We can expect every buffer provider implementation to utilise at least the generic buffer type-ID to keep track of the allocation size. + !buffer types and descriptors -Client code accesses buffer through [[smart buffer handles|BuffHandle]], including some kind of buffer type information, encoded into a type ID within the ''buffer descriptor''. These descriptors are used like prototypes, relating the type-~IDs hierarchically. Obviously, the most fundamental distinction is the BufferProvider in charge for that specific buffer. Below that, the next mandatory level of distinction is the ''buffer size''. In some cases, additional distinctions can be necessary. Each BufferProvider exposes a service to yield unique type ~IDs governed by such a hierarchical scheme. +Client code accesses buffer through [[opaque buffer handles|BuffHandle]], including some kind of buffer type information, encoded into a type ID within the ''buffer descriptor'' ({{{BuffDescr}}}). These descriptors are used like prototypes, relating the type-~IDs hierarchically. Obviously, the most fundamental distinction is the BufferProvider in charge for that specific buffer. Below that, the next mandatory level of distinction is the ''buffer size''. In some cases, additional distinctions can be necessary. Each BufferProvider exposes a service to yield unique type ~IDs governed by such a hierarchical scheme. + +Notably the //actual meaning of such a buffer type// remains implementation-defined. The scheme to generate and refine metadata, which is part of the //Buffer Provider Protocol,// only serves to keep different usage patterns disjoint. When following this protocol, some //type// of buffer is qualified first, and materialised as Descriptor. This may include some additional qualification steps, like the definition of a //type handler//, with functions to initialise and de-initialise the storage within the buffer; furthermore, an implementation-defined {{{LocalTag}}} can be attached. Together, this leads to a tree of hierarchically related hash-IDs. + +There is one crucial ''consistency criterion'' though: irrespective how a given usage arrives at some specific sub-type, there must be //only one single way// to transition into {{{LOCKED}}} state. The implementation //must ensure// that it is not possible to qualify different sub-types for //effectively the same storage location.// The high-level façade implementation „hooked behind“ the BufferProvider interface indeed fulfils this criterion: simply by requiring the client to present a Buffer Descriptor, that has been set-up and qualified in preceding steps. The implementation does not care //how// the client has obtained the type-ID embedded into the descriptor, but it provides //only one code path// to qualify any given type-ID with an actual //memory location//, so to obtain a //state-ID//, that can proceed through the stages of buffer lifecycle. !state and metadata for individual buffers Beyond that, it can be necessary to associate at least a state flag with //individual buffers.// Doing so requires the buffer to be in //locked state,// otherwise it wouldn't be distinguishable as an separate entity (a client is able to access the buffer memory address only after "locking" this buffer). Especially when using a buffer provider in conjunction with an OutputSlot, these states and transitions are crucial for performing an orderly handover of generated data from the producer (render engine) to the consumer (external output sink). -__Note__: while the API to access this service is uniform, conceptually there is a difference between just using the (shared) type information and associating individual metadata, like the buffer state. Type-~IDs, once allocated, will never be discarded (within the lifetime of an Lumiera application instance -- buffer associations aren't persistent). To the contrary, individual metadata //will be discarded,// when releasing the corresponding buffer. According to the ''prototype pattern'', individual metadata is treated as a one-way-off specialisation. +__Note__: while the API to access this service is uniform, conceptually there is a difference between just using the (shared) type information and associating individual metadata, like the buffer state. Type-~IDs, once allocated, will never be discarded (within the lifetime of an Lumiera application instance -- while buffer associations, and further individual metadata //will be discarded,// when releasing the corresponding buffer. According to the ''prototype pattern'', individual metadata is treated as a one-way-off specialisation.diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index d01483536..22a2f057d 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -84479,7 +84479,7 @@ Date: Thu Apr 20 18:53:17 2023 +0200
- + @@ -85218,6 +85218,11 @@ Date: Thu Apr 20 18:53:17 2023 +0200
+ + + + + @@ -85298,7 +85303,7 @@ Date: Thu Apr 20 18:53:17 2023 +0200