mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 04:38:30 +09:00
[Feat] (State): give RenderbufferObject the never-reused lifetime id every other cache-keyable state object already has
- RenderbufferObject was the last state object a backend twin registry keys on that could only be identified by its heap address or its GL name - both of which recycle. BufferObject, VertexArrayObject and ProgramObject all carry a process-wide, never-reused id for exactly this; the renderbuffer's absence is named in plan B §10.4-5 as one of the two latent problems P0 closes. - Mirrors BufferObject.h:202-208 / BufferObject.cpp:19-24 verbatim in shape: a private static AllocateLifetimeId() over a namespace-scope std::atomic<Uint64> starting at 1 (so a zero-initialised memo slot can never carry a live object's id), a const member initialised from it at construction, and an inline const getter. The doc comment is the buffer one restated for the renderbuffer's own recycling sources. - Deliberately NO GetVersion(): plan B §11 P0 says the id only. A mutation counter would be a second, independent invalidation surface to keep correct, and nothing needs one yet - the renderbuffer's mutable content already reaches the backends through AllocateStorage / SetInternalFormat / SetSamples. - No caller yet, by design: the id exists so §4.7.3's D1 rekey (and the DirectGLES renderbuffer twin registry at Managers.h:1858) has something to key on. It is a pure addition - no existing field, signature or answer changes. - ObjectLifetimeIdTest gains the two cases the other two object types already have, so the renderbuffer is covered by the same allocator-reuse probe: an object rebuilt at a freed address must not answer to the dead one's id, and two live ones must differ. - Tested: cmake --build build-linux -j 24 (clean); ctest -R ObjectLifetimeId -> 6/6 passed (4 pre-existing + 2 new).
This commit is contained in:
@@ -9,9 +9,21 @@
|
||||
#include "RenderbufferObject.h"
|
||||
#include <MG_Util/Metrics/TextureMetrics.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
namespace {
|
||||
// Starts at 1 so a zero-initialized cache slot can never carry a live
|
||||
// renderbuffer's id.
|
||||
std::atomic<Uint64> g_nextRenderbufferLifetimeId{1};
|
||||
}
|
||||
|
||||
Uint64 RenderbufferObject::AllocateLifetimeId() {
|
||||
return g_nextRenderbufferLifetimeId.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
RenderbufferObject::RenderbufferObject(Uint externalIndex) : m_externalIndex(externalIndex) {}
|
||||
|
||||
Uint RenderbufferObject::GetExternalIndex() const {
|
||||
|
||||
@@ -42,9 +42,20 @@ namespace MobileGL {
|
||||
Int GetDepthSize() const;
|
||||
Int GetStencilSize() const;
|
||||
Int GetSamples() const;
|
||||
// Globally-unique, never-reused id for THIS object's lifetime - same contract
|
||||
// and same motivation as BufferObject::GetLifetimeId(),
|
||||
// ProgramObject::GetLifetimeId() and VertexArrayObject::GetLifetimeId(). A
|
||||
// backend that folds a renderbuffer's IDENTITY into a cache key must use this,
|
||||
// never the GL name (LIFO-recycled by glGenRenderbuffers) and never the heap
|
||||
// address (recycled by the allocator): both let a deleted-and-recreated
|
||||
// renderbuffer answer to a dead one's cache entry.
|
||||
Uint64 GetLifetimeId() const { return m_lifetimeId; }
|
||||
|
||||
private:
|
||||
static Uint64 AllocateLifetimeId();
|
||||
|
||||
Uint m_externalIndex = 0;
|
||||
const Uint64 m_lifetimeId = AllocateLifetimeId();
|
||||
TextureInternalFormat m_internalFormat = TextureInternalFormat::RGBA;
|
||||
Int m_width = 0;
|
||||
Int m_height = 0;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "Includes.h"
|
||||
|
||||
#include <MG_State/GLState/BufferState/BufferObject.h>
|
||||
#include <MG_State/GLState/RenderbufferState/RenderbufferObject.h>
|
||||
#include <MG_State/GLState/VertexArrayState/VertexArrayObject.h>
|
||||
|
||||
using namespace MobileGL;
|
||||
@@ -138,3 +139,20 @@ TEST(ObjectLifetimeIdTest, LiveVertexArrayObjectsHaveDistinctLifetimeIds) {
|
||||
TEST(ObjectLifetimeIdTest, LiveBufferObjectsHaveDistinctLifetimeIds) {
|
||||
ExpectDistinctIdsWhileBothAlive<MG_State::GLState::BufferObject>("BufferObject");
|
||||
}
|
||||
|
||||
// The renderbuffer had no lifetime id at all until plan B §11 P0 gave it one: it is
|
||||
// the one FBO attachment source whose identity a backend twin registry can only have
|
||||
// keyed on the heap address or the GL name, both of which recycle.
|
||||
TEST(ObjectLifetimeIdTest, RenderbufferObjectAtARecycledAddressCarriesAFreshLifetimeId) {
|
||||
using MG_State::GLState::RenderbufferObject;
|
||||
const int reuseCount = ProbeLifetimeIdAcrossAddressReuse<RenderbufferObject>("RenderbufferObject");
|
||||
if (reuseCount == 0) {
|
||||
GTEST_SKIP() << "inconclusive, not proven: this allocator never handed the same address back across 64 "
|
||||
"construct/destroy rounds, so the recycled-address case was never exercised";
|
||||
}
|
||||
RecordProperty("address_reuses_observed", reuseCount);
|
||||
}
|
||||
|
||||
TEST(ObjectLifetimeIdTest, LiveRenderbufferObjectsHaveDistinctLifetimeIds) {
|
||||
ExpectDistinctIdsWhileBothAlive<MG_State::GLState::RenderbufferObject>("RenderbufferObject");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user