mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Fix] (MG_Backend/DirectGLES): UBO ring review fixes - invalidate array-buffer bind cache on failed ring creation, bump generation on emergency drain, division-based alignment rounding
This commit is contained in:
@@ -939,6 +939,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
void* ptr = g_GLESFuncs.glMapBufferRange(TempBufferTarget, 0, static_cast<GLsizeiptr>(newSize),
|
void* ptr = g_GLESFuncs.glMapBufferRange(TempBufferTarget, 0, static_cast<GLsizeiptr>(newSize),
|
||||||
GL_MAP_WRITE_BIT | kMapPersistentBit | kMapCoherentBit);
|
GL_MAP_WRITE_BIT | kMapPersistentBit | kMapCoherentBit);
|
||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
|
// The dying id is what the array-buffer cache has recorded as
|
||||||
|
// bound; a later buffer recycling the name would false-skip.
|
||||||
|
InvalidateArrayBufferBindingCache();
|
||||||
g_GLESFuncs.glDeleteBuffers(1, &id);
|
g_GLESFuncs.glDeleteBuffers(1, &id);
|
||||||
id = 0;
|
id = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -954,20 +957,15 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const GLint capsAlignment = g_GLESCapabilities.UniformBufferOffsetAlignment;
|
const GLint capsAlignment = g_GLESCapabilities.UniformBufferOffsetAlignment;
|
||||||
SizeT alignment = capsAlignment > 0 ? static_cast<SizeT>(capsAlignment) : 256;
|
|
||||||
// The cursor math masks with (alignment - 1); spec doesn't promise a
|
|
||||||
// power of two, so round up to one.
|
|
||||||
SizeT pow2 = 1;
|
|
||||||
while (pow2 < alignment) pow2 <<= 1;
|
|
||||||
g_uboRing.id = id;
|
g_uboRing.id = id;
|
||||||
g_uboRing.size = newSize;
|
g_uboRing.size = newSize;
|
||||||
g_uboRing.head = 0;
|
g_uboRing.head = 0;
|
||||||
g_uboRing.tail = 0;
|
g_uboRing.tail = 0;
|
||||||
g_uboRing.generation = nextGeneration;
|
g_uboRing.generation = nextGeneration;
|
||||||
g_uboRing.alignment = pow2;
|
g_uboRing.alignment = capsAlignment > 0 ? static_cast<SizeT>(capsAlignment) : 256;
|
||||||
g_uboRingFrameMarks.clear();
|
g_uboRingFrameMarks.clear();
|
||||||
MGLOG_I("Global-UBO ring: %zu MiB persistent store ready (id %u, gen %u, align %zu).",
|
MGLOG_I("Global-UBO ring: %zu MiB persistent store ready (id %u, gen %u, align %zu).",
|
||||||
newSize / (1024u * 1024u), id, nextGeneration, pow2);
|
newSize / (1024u * 1024u), id, nextGeneration, g_uboRing.alignment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -989,7 +987,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
|
|
||||||
Bool UboRingAllocate(SizeT size, SizeT& outOffset) {
|
Bool UboRingAllocate(SizeT size, SizeT& outOffset) {
|
||||||
if (size == 0 || !UboRingAvailable()) return false;
|
if (size == 0 || !UboRingAvailable()) return false;
|
||||||
const SizeT alignedSize = (size + g_uboRing.alignment - 1) & ~(g_uboRing.alignment - 1);
|
// Division-based rounding: the spec doesn't promise a power-of-two
|
||||||
|
// alignment. Slot offsets stay multiples of the alignment because every
|
||||||
|
// slot size is, and wrap padding restarts at ring offset 0.
|
||||||
|
const SizeT alignedSize =
|
||||||
|
(size + g_uboRing.alignment - 1) / g_uboRing.alignment * g_uboRing.alignment;
|
||||||
if (g_uboRing.id == 0 && !CreateUboRingStorage(alignedSize)) {
|
if (g_uboRing.id == 0 && !CreateUboRingStorage(alignedSize)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1026,6 +1028,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
if (g_GLESFuncs.glFinish) g_GLESFuncs.glFinish();
|
if (g_GLESFuncs.glFinish) g_GLESFuncs.glFinish();
|
||||||
g_uboRing.tail = g_uboRing.head;
|
g_uboRing.tail = g_uboRing.head;
|
||||||
g_uboRingFrameMarks.clear();
|
g_uboRingFrameMarks.clear();
|
||||||
|
// Same-frame slots written before the drain may now be recycled by
|
||||||
|
// the very next allocations; a generation bump keeps later draws
|
||||||
|
// from rebinding those cached offsets.
|
||||||
|
++g_uboRing.generation;
|
||||||
offset = static_cast<SizeT>(g_uboRing.head % g_uboRing.size);
|
offset = static_cast<SizeT>(g_uboRing.head % g_uboRing.size);
|
||||||
if (offset + alignedSize > g_uboRing.size) {
|
if (offset + alignedSize > g_uboRing.size) {
|
||||||
g_uboRing.head += g_uboRing.size - offset;
|
g_uboRing.head += g_uboRing.size - offset;
|
||||||
|
|||||||
Reference in New Issue
Block a user