[Chore, Docs] (...): drop the archived notes and move the skill under tools

- the archive freeze rule goes with the directory
- code comments lose citations to the removed notes
This commit is contained in:
BZLZHH
2026-10-31 19:29:06 +08:00
parent b5d64175a1
commit 6e36bf2c1b
1064 changed files with 1022 additions and 200727 deletions
@@ -1,34 +0,0 @@
// dmahash <pid> : for each dma-buf fd of <pid> at least 1 MB, print inode, size and a sampled checksum.
#include <dirent.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char** argv) {
char dir[64];
snprintf(dir, sizeof dir, "/proc/%s/fd", argv[1]);
DIR* d = opendir(dir);
if (!d) { perror("opendir"); return 1; }
struct dirent* e;
while ((e = readdir(d))) {
char p[128], l[128] = {0};
snprintf(p, sizeof p, "%s/%s", dir, e->d_name);
if (readlink(p, l, sizeof l - 1) <= 0 || strncmp(l, "/dmabuf", 7) != 0) continue;
int fd = open(p, O_RDONLY);
if (fd < 0) continue;
struct stat st; fstat(fd, &st);
if (st.st_size < (1 << 20)) { close(fd); continue; }
const uint8_t* m = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (m == MAP_FAILED) { printf("fd %s ino %lu mmap failed\n", e->d_name, (unsigned long)st.st_ino); close(fd); continue; }
uint64_t h = 1469598103934665603ull; unsigned nz = 0;
for (off_t i = 0; i < st.st_size; i += 64) { h = (h ^ m[i]) * 1099511628211ull; nz += m[i] != 0; }
printf("fd %s ino %lu size %ld hash %016llx nz %u\n", e->d_name, (unsigned long)st.st_ino, (long)st.st_size,
(unsigned long long)h, nz);
munmap((void*)m, st.st_size); close(fd);
}
return 0;
}
@@ -1,95 +0,0 @@
/* texfmt: does a texture keep its alpha? One opaque red texel and one transparent texel per
* format, sampled across a 64x64 ES3 pbuffer cleared white with SRC_ALPHA blending. Expect the
* left half red and the right half WHITE; a black right half means the alpha was lost. */
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <GLES2/gl2ext.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define P(T, n) T n = (T)eglGetProcAddress(#n)
static const char* vs = "#version 300 es\nlayout(location=0) in vec2 p; out vec2 uv; void main(){uv=p*0.5+0.5; gl_Position=vec4(p,0,1);}";
static const char* fs = "#version 300 es\nprecision mediump float; uniform sampler2D t; uniform int mode; in vec2 uv; out vec4 o;"
"void main(){vec4 c=texture(t,uv); o = mode==1 ? vec4(1.0,0.0,0.0,c.a) : (mode==2 ? vec4(c.r,0.0,0.0,c.r) : c);}";
int main(void) {
EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(d, 0, 0); eglBindAPI(EGL_OPENGL_ES_API);
EGLint ca[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE};
EGLConfig c; EGLint n; eglChooseConfig(d, ca, &c, 1, &n);
EGLint xa[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
EGLContext x = eglCreateContext(d, c, EGL_NO_CONTEXT, xa);
EGLint pa[] = {EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE};
EGLSurface s = eglCreatePbufferSurface(d, c, pa); eglMakeCurrent(d, s, s, x);
P(PFNGLCREATESHADERPROC, glCreateShader); P(PFNGLSHADERSOURCEPROC, glShaderSource); P(PFNGLCOMPILESHADERPROC, glCompileShader);
P(PFNGLCREATEPROGRAMPROC, glCreateProgram); P(PFNGLATTACHSHADERPROC, glAttachShader); P(PFNGLLINKPROGRAMPROC, glLinkProgram);
P(PFNGLUSEPROGRAMPROC, glUseProgram); P(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation); P(PFNGLUNIFORM1IPROC, glUniform1i);
P(PFNGLGENBUFFERSPROC, glGenBuffers); P(PFNGLBINDBUFFERPROC, glBindBuffer); P(PFNGLBUFFERDATAPROC, glBufferData);
P(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer); P(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray);
P(PFNGLDRAWARRAYSPROC, glDrawArrays); P(PFNGLCLEARCOLORPROC, glClearColor); P(PFNGLCLEARPROC, glClear);
P(PFNGLREADPIXELSPROC, glReadPixels); P(PFNGLVIEWPORTPROC, glViewport); P(PFNGLGENTEXTURESPROC, glGenTextures);
P(PFNGLBINDTEXTUREPROC, glBindTexture); P(PFNGLTEXIMAGE2DPROC, glTexImage2D); P(PFNGLTEXPARAMETERIPROC, glTexParameteri);
P(PFNGLENABLEPROC, glEnable); P(PFNGLBLENDFUNCPROC, glBlendFunc); P(PFNGLGETERRORPROC, glGetError);
P(PFNGLTEXSTORAGE2DPROC, glTexStorage2D); P(PFNGLTEXSUBIMAGE2DPROC, glTexSubImage2D); P(PFNGLGETSTRINGPROC, glGetString);
printf("GL_VERSION %s\n", glGetString(GL_VERSION));
printf("BGRA ext: %s\n", strstr((const char*)glGetString(GL_EXTENSIONS), "GL_EXT_texture_format_BGRA8888") ? "yes" : "no");
GLuint v = glCreateShader(GL_VERTEX_SHADER), f = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(v, 1, &vs, 0); glCompileShader(v); glShaderSource(f, 1, &fs, 0); glCompileShader(f);
GLuint pr = glCreateProgram(); glAttachShader(pr, v); glAttachShader(pr, f); glLinkProgram(pr); glUseProgram(pr);
float q[] = {-1,-1, 1,-1, -1,1, 1,1};
GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof q, q, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(0);
GLint lm = glGetUniformLocation(pr, "mode");
glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
struct { const char* name; GLint ifmt; GLenum fmt; int bpp; int mode; int storage; GLenum sized; unsigned char px[8]; } cases[] = {
{"RGBA/TexImage", GL_RGBA, GL_RGBA, 4, 0, 0, 0, {255,0,0,255, 0,0,0,0}},
{"BGRA_EXT/TexImage", GL_BGRA_EXT, GL_BGRA_EXT, 4, 0, 0, 0, {0,0,255,255, 0,0,0,0}},
{"BGRA8_EXT/TexStorage+Sub", 0, GL_BGRA_EXT, 4, 0, 1, GL_BGRA8_EXT, {0,0,255,255, 0,0,0,0}},
{"RGBA8/TexStorage+Sub", 0, GL_RGBA, 4, 0, 1, GL_RGBA8, {255,0,0,255, 0,0,0,0}},
{"ALPHA", GL_ALPHA, GL_ALPHA, 1, 1, 0, 0, {255, 0}},
{"LUMINANCE_ALPHA", GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, 2, 1, 0, 0, {255,255, 0,0}},
{"R8/TexStorage+Sub", 0, GL_RED, 1, 2, 1, GL_R8, {255, 0}},
};
for (unsigned i = 0; i < sizeof cases / sizeof cases[0]; ++i) {
GLuint t; glGenTextures(1, &t); glBindTexture(GL_TEXTURE_2D, t);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
while (glGetError()) {}
if (cases[i].storage) {
glTexStorage2D(GL_TEXTURE_2D, 1, cases[i].sized, 2, 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, cases[i].fmt, GL_UNSIGNED_BYTE, cases[i].px);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, cases[i].ifmt, 2, 1, 0, cases[i].fmt, GL_UNSIGNED_BYTE, cases[i].px);
}
GLenum err = glGetError();
glUniform1i(lm, cases[i].mode);
glViewport(0, 0, 64, 64); glClearColor(1, 1, 1, 1); glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
unsigned char l[4], r[4];
glReadPixels(16, 32, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, l); glReadPixels(48, 32, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, r);
const int ok = l[0] > 200 && l[1] < 60 && l[2] < 60 && r[0] > 200 && r[1] > 200 && r[2] > 200;
printf("%-26s err=0x%04x left=%3d,%3d,%3d right=%3d,%3d,%3d %s\n", cases[i].name, err, l[0], l[1], l[2], r[0], r[1], r[2], ok ? "ok" : "BAD");
}
/* ANGLE's emulation of ALPHA8 / LUMINANCE_ALPHA8 on a desktop-GL driver: R8 / RG8 + swizzle. */
P(PFNGLTEXPARAMETERIPROC, glTexParameteri2);
struct { const char* name; GLenum sized, fmt; int bpp; GLint sw[4]; unsigned char px[4]; unsigned char wantL[3], wantR[3]; } sz[] = {
{"R8 swizzled as ALPHA8", GL_R8, GL_RED, 1, {GL_ZERO, GL_ZERO, GL_ZERO, GL_RED}, {255, 0}, {0,0,0}, {255,255,255}},
{"RG8 swizzled as LUM_ALPHA", GL_RG8, GL_RG, 2, {GL_RED, GL_RED, GL_RED, GL_GREEN}, {255,255, 0,0}, {255,255,255}, {255,255,255}},
{"RG8 as LUM_ALPHA (lum 0)", GL_RG8, GL_RG, 2, {GL_RED, GL_RED, GL_RED, GL_GREEN}, {0,255, 0,0}, {0,0,0}, {255,255,255}},
};
glUniform1i(lm, 0);
for (unsigned i = 0; i < sizeof sz / sizeof sz[0]; ++i) {
GLuint t; glGenTextures(1, &t); glBindTexture(GL_TEXTURE_2D, t);
glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexStorage2D(GL_TEXTURE_2D, 1, sz[i].sized, 2, 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, sz[i].fmt, GL_UNSIGNED_BYTE, sz[i].px);
glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, sz[i].sw[0]); glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, sz[i].sw[1]);
glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, sz[i].sw[2]); glTexParameteri2(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, sz[i].sw[3]);
GLenum err = glGetError();
glClearColor(1, 1, 1, 1); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
unsigned char l[4], r[4];
glReadPixels(16, 32, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, l); glReadPixels(48, 32, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, r);
int ok = 1;
for (int k = 0; k < 3; ++k) ok = ok && abs(l[k] - sz[i].wantL[k]) < 40 && abs(r[k] - sz[i].wantR[k]) < 40;
printf("%-26s err=0x%04x left=%3d,%3d,%3d right=%3d,%3d,%3d %s\n", sz[i].name, err, l[0], l[1], l[2], r[0], r[1], r[2], ok ? "ok" : "BAD");
}
return 0;
}
-2
View File
@@ -78,7 +78,6 @@ Example:
- Generated code, only together with a CI step that regenerates it and fails on any difference. - Generated code, only together with a CI step that regenerates it and fails on any difference.
- Binary test fixtures. - Binary test fixtures.
- Not raw logs, and not working papers such as agent briefs, review rounds and drafts. Keep those outside the repository and commit the conclusion: a design-document change, a `DEBTS.md` entry, a measurement under `docs/Performance`. - Not raw logs, and not working papers such as agent briefs, review rounds and drafts. Keep those outside the repository and commit the conclusion: a design-document change, a `DEBTS.md` entry, a measurement under `docs/Performance`.
- `docs/archive/` keeps the planning notes and agent contracts of the disaggregation work as they were. It is frozen: no file there is added, edited or removed.
## Checks ## Checks
@@ -88,7 +87,6 @@ These fail on any violation:
- commit messages, as described above; - commit messages, as described above;
- a new file under `docs/Disaggregated/notes/` or a new `.log` file (moving a file is not adding it); - a new file under `docs/Disaggregated/notes/` or a new `.log` file (moving a file is not adding it);
- any change under `docs/archive/`;
- a missing or wrong license header; - a missing or wrong license header;
- a text file that is not UTF-8; - a text file that is not UTF-8;
- an external project name in a comment; - an external project name in a comment;
+3 -3
View File
@@ -643,7 +643,7 @@ namespace MobileGL::MG_Config {
// (WireTables.cpp), half of the stream link's 24-entry answer store. // (WireTables.cpp), half of the stream link's 24-entry answer store.
// Measurements: docs/Performance/ipc-create-window.md. // Measurements: docs/Performance/ipc-create-window.md.
Uint32 CreateWindow = 10; Uint32 CreateWindow = 10;
// MOBILEGL_IPC_PBO_READBACK_SYNC (P9 W1, docs/archive/contracts/CONTRACT-P9.md §1): 1 = a glReadPixels // MOBILEGL_IPC_PBO_READBACK_SYNC (P9 W1 §1): 1 = a glReadPixels
// or glGetTexImage into a bound GL_PIXEL_PACK_BUFFER takes the reply-slot form again - // or glGetTexImage into a bound GL_PIXEL_PACK_BUFFER takes the reply-slot form again -
// the client waits for the pixels and uploads them into the buffer itself, as before P9. // the client waits for the pixels and uploads them into the buffer itself, as before P9.
// 0 (default) sends read_pixels_to_buffer / get_texture_image_to_buffer, waits for // 0 (default) sends read_pixels_to_buffer / get_texture_image_to_buffer, waits for
@@ -651,7 +651,7 @@ namespace MobileGL::MG_Config {
// red-once of the wait-count gate (PackBufferReadbackScenario): it must show a reply // red-once of the wait-count gate (PackBufferReadbackScenario): it must show a reply
// wait per read. // wait per read.
Uint32 PboReadbackSync = 0; Uint32 PboReadbackSync = 0;
// MOBILEGL_IPC_POLL_ESCALATE (P10, docs/archive/contracts/CONTRACT-P10.md §1): a glClientWaitSync with a // MOBILEGL_IPC_POLL_ESCALATE (P10 §1): a glClientWaitSync with a
// zero timeout or a glGetSynciv(GL_SYNC_STATUS) is answered by the client from what the // zero timeout or a glGetSynciv(GL_SYNC_STATUS) is answered by the client from what the
// server reported (kEventFenceSignaled) - "signaled" when it has been, "not yet" otherwise // server reported (kEventFenceSignaled) - "signaled" when it has been, "not yet" otherwise
// - and only the Nth "not yet" in a row on one fence crosses as a real round trip, so a // - and only the Nth "not yet" in a row on one fence crosses as a real round trip, so a
@@ -677,7 +677,7 @@ namespace MobileGL::MG_Config {
// platform and the backend's POST self-test allow it; 0 = never grant it (the session // platform and the backend's POST self-test allow it; 0 = never grant it (the session
// runs T2 and says so). Read by the server role only; kept through ServerSpawn. // runs T2 and says so). Read by the server role only; kept through ServerSpawn.
Uint32 AllowAdoptT0 = 1; Uint32 AllowAdoptT0 = 1;
// MOBILEGL_IPC_RUN_AHEAD (P5e, docs/archive/contracts/CONTRACT-P5E.md §1): 1 = after publishing an // MOBILEGL_IPC_RUN_AHEAD (P5e §1): 1 = after publishing an
// UNBARRIERED record the client returns immediately instead of waiting for its apply. // UNBARRIERED record the client returns immediately instead of waiting for its apply.
// It is one half of a conjunction and never a switch on its own - the client arms // It is one half of a conjunction and never a switch on its own - the client arms
// run-ahead only when the server also publishes kCapRunAheadApply, so on Magma, and on // run-ahead only when the server also publishes kCapRunAheadApply, so on Magma, and on
+1 -1
View File
@@ -609,7 +609,7 @@ namespace MobileGL::MG_ConfigLoader {
ipc.AdoptTier = QueryEnvUint32("MOBILEGL_IPC_ADOPT_TIER", MG_Config::kAdoptTierUnset, 0, 2); ipc.AdoptTier = QueryEnvUint32("MOBILEGL_IPC_ADOPT_TIER", MG_Config::kAdoptTierUnset, 0, 2);
// P11 B2: the server's own T0 allow switch (Config.h). // P11 B2: the server's own T0 allow switch (Config.h).
ipc.AllowAdoptT0 = QueryEnvUint32("MOBILEGL_IPC_ALLOW_ADOPT_T0", 1, 0, 1); ipc.AllowAdoptT0 = QueryEnvUint32("MOBILEGL_IPC_ALLOW_ADOPT_T0", 1, 0, 1);
// P5e (docs/archive/contracts/CONTRACT-P5E.md §1). The wait rule's A/B, parsed here like every // P5e (§1). The wait rule's A/B, parsed here like every
// other IPC knob and armed only where the server publishes kCapRunAheadApply. // other IPC knob and armed only where the server publishes kCapRunAheadApply.
ipc.RunAhead = QueryEnvUint32("MOBILEGL_IPC_RUN_AHEAD", 1, 0, 1); ipc.RunAhead = QueryEnvUint32("MOBILEGL_IPC_RUN_AHEAD", 1, 0, 1);
// ... and forced OFF by the verify harness for BatchWaits' reason, one step further: // ... and forced OFF by the verify harness for BatchWaits' reason, one step further:
+1 -1
View File
@@ -61,7 +61,7 @@ namespace MobileGL::MG_Backend {
(void)region; (void)region;
return true; return true;
} }
// IMPLICIT SYNC BY FLUSH (docs/archive/notes/anland/plan-x11-gpu.md): the session // IMPLICIT SYNC BY FLUSH: the session
// on this (the apply) thread ends a frame at a glFlush. Every shared image it used since // on this (the apply) thread ends a frame at a glFlush. Every shared image it used since
// its last boundary is published as written and read by one fence of everything it // its last boundary is published as written and read by one fence of everything it
// submitted (SharedImages::ReadTracker::PublishFrameAsWrite), and from now on its first // submitted (SharedImages::ReadTracker::PublishFrameAsWrite), and from now on its first
+1 -1
View File
@@ -516,7 +516,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} // namespace RenderStateImpl } // namespace RenderStateImpl
#if MOBILEGL_BUILD_DISAGGREGATED #if MOBILEGL_BUILD_DISAGGREGATED
// ---- SHARED IMAGES (docs/archive/notes/anland/plan-ahb-dmabuf.md) ---- // ---- SHARED IMAGES ----
// //
// A shared image reaches the driver only through the Android import path: its AHardwareBuffer // A shared image reaches the driver only through the Android import path: its AHardwareBuffer
// becomes an EGLImage (EGL_ANDROID_get_native_client_buffer + EGL_ANDROID_image_native_buffer) // becomes an EGLImage (EGL_ANDROID_get_native_client_buffer + EGL_ANDROID_image_native_buffer)
@@ -358,7 +358,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// server process has no frontend at all, so pDefaultFramebufferInfo is null there. Gating on // server process has no frontend at all, so pDefaultFramebufferInfo is null there. Gating on
// it returned before the post, the client kept Init.cpp's GL_DEPTH32F_STENCIL8 guess for a // it returned before the post, the client kept Init.cpp's GL_DEPTH32F_STENCIL8 guess for a
// D24S8 pbuffer, and a blit into a buffer allocated from that guess lost depth and stencil // D24S8 pbuffer, and a blit into a buffer allocated from that guess lost depth and stencil
// (docs/archive/notes/p8/SE.md). Inproc only passed because client and server share the process. // Inproc only passed because client and server share the process.
if (!g_GLESFuncs.glGetFramebufferAttachmentParameteriv) return; if (!g_GLESFuncs.glGetFramebufferAttachmentParameteriv) return;
if (!defaultFBOInfo && MG_Pipe::gMGPipeCallbacks.OnSurfaceChanged == nullptr) return; if (!defaultFBOInfo && MG_Pipe::gMGPipeCallbacks.OnSurfaceChanged == nullptr) return;
@@ -1458,7 +1458,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// format, not only the redundant-encoding ones this mirror serves, and marks the store // format, not only the redundant-encoding ones this mirror serves, and marks the store
// driver-written where it cannot. The store is what answers a split glGetTexImage the // driver-written where it cannot. The store is what answers a split glGetTexImage the
// driver refuses to read back (DirectGLESReadback.cpp's store route); every other split // driver refuses to read back (DirectGLESReadback.cpp's store route); every other split
// read of the destination reads the GPU level itself (docs/archive/notes/p8/E.md). // read of the destination reads the GPU level itself.
// //
// BEHIND #if MOBILEGL_BUILD_DISAGGREGATED so the pull build's code does not move (G1), // BEHIND #if MOBILEGL_BUILD_DISAGGREGATED so the pull build's code does not move (G1),
// and the arm is the TRANSPORT and not the build - build-split runs its unit and // and the arm is the TRANSPORT and not the build - build-split runs its unit and
@@ -1491,7 +1491,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_E_ONCE("%s: source or destination image failed to sync; declining the copy", __func__); MGLOG_E_ONCE("%s: source or destination image failed to sync; declining the copy", __func__);
return; return;
} }
// P8-E (docs/archive/notes/p8/E.md): THE SERVER'S STAGED STORE FOLLOWS THE COPY. Both endpoints are synced, // P8-E: THE SERVER'S STAGED STORE FOLLOWS THE COPY. Both endpoints are synced,
// so every byte the store holds for them is on the driver, and the copy below is a raw // so every byte the store holds for them is on the driver, and the copy below is a raw
// texel-block move - the store makes the same move, which keeps the destination level // texel-block move - the store makes the same move, which keeps the destination level
// answerable from here when the driver will not read it back (ReadTextureImageWire's store // answerable from here when the driver will not read it back (ReadTextureImageWire's store
@@ -1795,7 +1795,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
return width == extent.x() && height == extent.y() && (!layered || depth == extent.z()); return width == extent.x() && height == extent.y() && (!layered || depth == extent.z());
} }
// P8-E (docs/archive/notes/p8/E.md). MGITEST_ESPRYT_REFUSE_TEXTURE_READBACK_EXTENT=<w>x<h>, READ BY THE SERVER: // P8-E. MGITEST_ESPRYT_REFUSE_TEXTURE_READBACK_EXTENT=<w>x<h>, READ BY THE SERVER:
// a colour level of exactly that extent is treated as one the driver refused to attach - what an // a colour level of exactly that extent is treated as one the driver refused to attach - what an
// Adreno does for RGB16 and the 16-bit SNORM formats, and what no host driver can be made to do. // Adreno does for RGB16 and the 16-bit SNORM formats, and what no host driver can be made to do.
// Scoped by the extent so the tcp lane's shared supervisor can carry it for the whole lane: only // Scoped by the extent so the tcp lane's shared supervisor can carry it for the whole lane: only
@@ -10,7 +10,7 @@
namespace MobileGL::MG_Backend::DirectGLES { namespace MobileGL::MG_Backend::DirectGLES {
#if MOBILEGL_BUILD_DISAGGREGATED #if MOBILEGL_BUILD_DISAGGREGATED
// ---- SHARED IMAGES (DirectGLES.h; docs/archive/notes/anland/plan-ahb-dmabuf.md) ------ // ---- SHARED IMAGES (DirectGLES.h) ------
namespace SharedImageImpl { namespace SharedImageImpl {
#if defined(__ANDROID__) #if defined(__ANDROID__)
+6 -6
View File
@@ -1553,7 +1553,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// applier stored, so the answer is the same whichever side resolved it first. // applier stored, so the answer is the same whichever side resolved it first.
Bool BackendUsesNativeBaseInstance(); Bool BackendUsesNativeBaseInstance();
// ---- P5e SEAM (docs/archive/contracts/CONTRACT-P5E.md §4.2; declared by c0e, bodied by id/vi) ---- // ---- P5e SEAM (§4.2; declared by c0e, bodied by id/vi) ----
// //
// THE VAO TWIN, RESOLVED FROM THE HANDLE THE RECORD CARRIED - MGPipeApplierState:: // THE VAO TWIN, RESOLVED FROM THE HANDLE THE RECORD CARRIED - MGPipeApplierState::
// BoundVertexElements - instead of from the frontend VertexArrayObject the draw's // BoundVertexElements - instead of from the frontend VertexArrayObject the draw's
@@ -1728,7 +1728,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// flag, allocator or pixel-store object participates. P9 W2: a level // flag, allocator or pixel-store object participates. P9 W2: a level
// the driver does not hold (defined after the last sync) is never read // the driver does not hold (defined after the last sync) is never read
// back, and a readback the driver refuses falls back to the staged // back, and a readback the driver refuses falls back to the staged
// level when the store covers it (docs/archive/notes/p9/W2-REMINT.md). // level when the store covers it.
void RequireImageBindableStorageByHandle(MG_Pipe::MGPipeHandle res, void RequireImageBindableStorageByHandle(MG_Pipe::MGPipeHandle res,
const MG_Pipe::MGPipeResourceRecord& record); const MG_Pipe::MGPipeResourceRecord& record);
#if MOBILEGL_BUILD_DISAGGREGATED #if MOBILEGL_BUILD_DISAGGREGATED
@@ -2051,7 +2051,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// table's answer is an array element and only a GetOrCreate that GROWS the table moves // table's answer is an array element and only a GetOrCreate that GROWS the table moves
// it, which this function has already done by the time it returns. // it, which this function has already done by the time it returns.
BackendTextureObject* ResolveTextureTwin(MG_Pipe::MGPipeHandle res); BackendTextureObject* ResolveTextureTwin(MG_Pipe::MGPipeHandle res);
// ---- P5e SEAM (docs/archive/contracts/CONTRACT-P5E.md §4.2, §5.2; declared by c0e, bodied by // ---- P5e SEAM (the contract §4.2, §5.2; declared by c0e, bodied by
// id/tx2) -------------------------------------------------------------------------- // id/tx2) --------------------------------------------------------------------------
// //
// EVERY DRAW-PATH TEXTURE ENTRY, BY HANDLE. The caller holds a Texture handle - a // EVERY DRAW-PATH TEXTURE ENTRY, BY HANDLE. The caller holds a Texture handle - a
@@ -2078,7 +2078,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// glCopyImageSubData passes: it tries FollowCopyImageInStagedStore first and marks the store // glCopyImageSubData passes: it tries FollowCopyImageInStagedStore first and marks the store
// itself when that fails. // itself when that fails.
void NoteDriverSideTextureWriteByHandle(MG_Pipe::MGPipeHandle texture, Bool storeFollowsTheWrite = false); void NoteDriverSideTextureWriteByHandle(MG_Pipe::MGPipeHandle texture, Bool storeFollowsTheWrite = false);
// P8-E (docs/archive/notes/p8/E.md): make glCopyImageSubData's texel-block move in the server's staged // P8-E: make glCopyImageSubData's texel-block move in the server's staged
// store too (StagedTextureStore::FollowCopy), so the destination level's bytes stay its // store too (StagedTextureStore::FollowCopy), so the destination level's bytes stay its
// content. Box in each image's own texel grid. False when the store cannot follow: a cube // content. Box in each image's own texel grid. False when the store cannot follow: a cube
// map or 1D array endpoint (copy-image puts faces / layers on z, the store does not), a view, // map or 1D array endpoint (copy-image puts faces / layers on z, the store does not), a view,
@@ -2137,7 +2137,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
~BackendFramebufferObject(); ~BackendFramebufferObject();
BackendFramebufferObject(const BackendFramebufferObject&) = delete; BackendFramebufferObject(const BackendFramebufferObject&) = delete;
BackendFramebufferObject& operator=(const BackendFramebufferObject&) = delete; BackendFramebufferObject& operator=(const BackendFramebufferObject&) = delete;
// P5e SEAM (docs/archive/contracts/CONTRACT-P5E.md §5.4; declared by c0e, bodied by fb): the same // P5e SEAM (§5.4; declared by c0e, bodied by fb): the same
// sync keyed on the framebuffer HANDLE. The record's eleven surfaces ARE the point // sync keyed on the framebuffer HANDLE. The record's eleven surfaces ARE the point
// set - the emitter refuses a point at or above the wire width - so the attachment // set - the emitter refuses a point at or above the wire width - so the attachment
// walk needs no frontend FramebufferObject and no m_pushedSyncHandle handshake: the // walk needs no frontend FramebufferObject and no m_pushedSyncHandle handshake: the
@@ -3126,7 +3126,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
}; };
ImageFormatBakeInputs CollectImageFormatBakeInputs(const ProgramBuildSource& src); ImageFormatBakeInputs CollectImageFormatBakeInputs(const ProgramBuildSource& src);
// ---- P5e SEAM (docs/archive/contracts/CONTRACT-P5E.md §4.2, §5.5; declared by c0e, bodied by // ---- P5e SEAM (the contract §4.2, §5.5; declared by c0e, bodied by
// id/pg) --------------------------------------------------------------------------- // id/pg) ---------------------------------------------------------------------------
// //
// THE PROGRAM TWIN, RESOLVED FROM MGPipeApplierState::DrawProgram / DispatchProgram / // THE PROGRAM TWIN, RESOLVED FROM MGPipeApplierState::DrawProgram / DispatchProgram /
@@ -1727,7 +1727,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
const Uint16 uploadTarget = MG_Pipe::MGPipeSubDataUploadTargetOf(record.Target); const Uint16 uploadTarget = MG_Pipe::MGPipeSubDataUploadTargetOf(record.Target);
const IntVec3 extent = MG_Record::StagedTextureUploadExtent(stored->Desc, record); const IntVec3 extent = MG_Record::StagedTextureUploadExtent(stored->Desc, record);
const SizeT runBytes = static_cast<SizeT>(record.Blob.Size); const SizeT runBytes = static_cast<SizeT>(record.Blob.Size);
// P8-E (docs/archive/notes/p8/E.md): THE LEVEL HOLDS A COPY THE CLIENT NEVER SAW // P8-E: THE LEVEL HOLDS A COPY THE CLIENT NEVER SAW
// (FollowCopyImageInStagedStore). The run is the client's shadow, stale everywhere it // (FollowCopyImageInStagedStore). The run is the client's shadow, stale everywhere it
// did not write, so only the texels it names land - its regions, or its union box // did not write, so only the texels it names land - its regions, or its union box
// when it carries none (D-D3's "the box is the whole story"). A run the store cannot // when it carries none (D-D3's "the box is the whole story"). A run the store cannot
@@ -124,7 +124,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
m_forceTextureParamsResync = true; m_forceTextureParamsResync = true;
return; return;
} }
// P9 W2 (docs/archive/notes/p9/W2-REMINT.md): EVERY BYTE THIS RE-MINT REPLAYS IS ALREADY ON THE // P9 W2: EVERY BYTE THIS RE-MINT REPLAYS IS ALREADY ON THE
// SERVER. The GPU image holds what the GPU wrote (render targets, clears, copies, // SERVER. The GPU image holds what the GPU wrote (render targets, clears, copies,
// generated mips, image stores) and the staged store holds what the client uploaded; // generated mips, image stores) and the staged store holds what the client uploaded;
// the client is never asked, so no pull protocol exists. Reading only the store would // the client is never asked, so no pull protocol exists. Reading only the store would
@@ -650,7 +650,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
#if MOBILEGL_BUILD_DISAGGREGATED #if MOBILEGL_BUILD_DISAGGREGATED
// SHARED IMAGES (docs/archive/notes/anland/plan-ahb-dmabuf.md). The client defined // SHARED IMAGES. The client defined
// level 0 as WxH RGBA8 with no data and then attached the image; the record's descriptor // level 0 as WxH RGBA8 with no data and then attached the image; the record's descriptor
// still says so, but the texels are the image's, so nothing below may allocate or upload. // still says so, but the texels are the image's, so nothing below may allocate or upload.
Bool BackendTextureObject::SyncSharedImageStorage(const MG_Pipe::MGPipeResourceRecord& record) { Bool BackendTextureObject::SyncSharedImageStorage(const MG_Pipe::MGPipeResourceRecord& record) {
@@ -1438,7 +1438,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// ===================================================================================== // =====================================================================================
// P5e SEAMS: DECLARED AND REFUSED HERE, BODIED BY THE FAMILY PACKAGES // P5e SEAMS: DECLARED AND REFUSED HERE, BODIED BY THE FAMILY PACKAGES
// (docs/archive/contracts/CONTRACT-P5E.md §4.2; BRIEF-P5E §1's "each such seam is a declared signature // (the contract §4.2; BRIEF-P5E §1's "each such seam is a declared signature
// in c0e so both sides compile from day one") // in c0e so both sides compile from day one")
// ===================================================================================== // =====================================================================================
// //
@@ -73,7 +73,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// (MG_Remote::Client::EmitObjectDeathRecord, CONTRACT-P5C §5.2). // (MG_Remote::Client::EmitObjectDeathRecord, CONTRACT-P5C §5.2).
// //
// WHY THAT MATTERS, measured rather than argued (package L's probe, // WHY THAT MATTERS, measured rather than argued (package L's probe,
// docs/archive/notes/p7/magma-two-process-first-run.md §6): under SPAWN the client process has no // the phase notes §6): under SPAWN the client process has no
// DirectVulkan backend at all, so InstallClientWireTables' own emitter already // DirectVulkan backend at all, so InstallClientWireTables' own emitter already
// answered the notice and CtWireScenario's two death cases PASSED. Under INPROC the // answered the notice and CtWireScenario's two death cases PASSED. Under INPROC the
// server role's backend is a thread of this process, Transport is Split rather than // server role's backend is a thread of this process, Transport is Split rather than
@@ -247,7 +247,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// SPIRV-Reflect rebuild and `ClearProgramResourceCaches`, verbatim; only this build drops // SPIRV-Reflect rebuild and `ClearProgramResourceCaches`, verbatim; only this build drops
// them - and with them the rehash hazard the ordering comment below the block-binding // them - and with them the rehash hazard the ordering comment below the block-binding
// setter documents. Retiring the pull half is the day the member stops needing its guard, // setter documents. Retiring the pull half is the day the member stops needing its guard,
// which is a G1/P13 decision and not a wave-2 one; recorded in docs/archive/notes/p7/magma-c.md. // which is a G1/P13 decision and not a wave-2 one; recorded in the phase notes.
void ClearProgramResourceCaches() { void ClearProgramResourceCaches() {
// Nothing to clear: there is no cache in this build. Kept as an entry point so // Nothing to clear: there is no cache in this build. Kept as an entry point so
// BackendObject_DirectVulkan's two EGL-teardown call sites stay statement for // BackendObject_DirectVulkan's two EGL-teardown call sites stay statement for
@@ -844,7 +844,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// is not the answer either: the transient arena carries no // is not the answer either: the transient arena carries no
// {UNIFORM,STORAGE}_TEXEL_BUFFER usage (VkBufferManager::InitializeTransientArenas), // {UNIFORM,STORAGE}_TEXEL_BUFFER usage (VkBufferManager::InitializeTransientArenas),
// so no VkBufferView can be made over it, and widening a shared per-frame // so no VkBufferView can be made over it, and widening a shared per-frame
// allocation to buy an unreachable path is the wrong trade. See docs/archive/notes/p7/magma-a.md. // allocation to buy an unreachable path is the wrong trade. See the phase notes.
return writable ? false : placeholder(); return writable ? false : placeholder();
} }
VkBufferViewCreateInfo viewInfo{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; VkBufferViewCreateInfo viewInfo{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO};
@@ -973,7 +973,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// record that is the draw/dispatch tail in VulkanRenderer.cpp / WireDraw.cpp, // record that is the draw/dispatch tail in VulkanRenderer.cpp / WireDraw.cpp,
// which belong to wave-2 packages B and C, not to this file. Losing the // which belong to wave-2 packages B and C, not to this file. Losing the
// dispatch with a named line in the role log beats returning stale counters // dispatch with a named line in the role log beats returning stale counters
// with no error at all. docs/archive/notes/p7/magma-a.md carries the recipe. // with no error at all. The phase notes carry the recipe.
MGLOG_E_ONCE("ResolveStorageBufferDescriptor: block '%s' is bound at offset %llu, which is not a " MGLOG_E_ONCE("ResolveStorageBufferDescriptor: block '%s' is bound at offset %llu, which is not a "
"multiple of this device's minStorageBufferOffsetAlignment (%llu); %s ranges cannot be " "multiple of this device's minStorageBufferOffsetAlignment (%llu); %s ranges cannot be "
"expressed as a descriptor and the shader's writes would be dropped by a read-only " "expressed as a descriptor and the shader's writes would be dropped by a read-only "
@@ -1146,7 +1146,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, and that is a multiple of four on every // GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, and that is a multiple of four on every
// device - but GL 4.6 core 6.1.1 puts no such rule on the SIZE, so `copied` is free // device - but GL 4.6 core 6.1.1 puts no such rule on the SIZE, so `copied` is free
// to end mid-word and the Redmi Minecraft run lands there // to end mid-word and the Redmi Minecraft run lands there
// (docs/archive/notes/p5f/magma-inproc-fix.md #5). An unaligned start is not reachable through // An unaligned start is not reachable through
// the public API and only a protocol-level offset can produce one; the sub-word arm // the public API and only a protocol-level offset can produce one; the sub-word arm
// handles it anyway rather than leaving a second shape to trip over later. Both arms // handles it anyway rather than leaving a second shape to trip over later. Both arms
// copy the same bytes to the same place: the sub-word one pays one extra transient // copy the same bytes to the same place: the sub-word one pays one extra transient
@@ -116,7 +116,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// attribute whose base offsets cannot be added is one Vulkan cannot fetch, the // attribute whose base offsets cannot be added is one Vulkan cannot fetch, the
// monolith arm never computes that sum at all, and masking is strictly safer than // monolith arm never computes that sum at all, and masking is strictly safer than
// a Fatal for a number no application can reach on purpose. Recorded in // a Fatal for a number no application can reach on purpose. Recorded in
// docs/archive/notes/p7/magma-c.md rather than silently reconciled. // the phase notes rather than silently reconciled.
const auto describe = [&](const char* reason, VkFormat format) { const auto describe = [&](const char* reason, VkFormat format) {
MGLOG_E_ONCE("Magma wire vertex layout: %s location=%u type=%u size=%u normalized=%u integer=%u " MGLOG_E_ONCE("Magma wire vertex layout: %s location=%u type=%u size=%u normalized=%u integer=%u "
"long=%u bgra=%u stride=%d offset=%llu format=%d bufferWindow=%u+%u activeMask=0x%x", "long=%u bgra=%u stride=%d offset=%llu format=%d bufferWindow=%u+%u activeMask=0x%x",
@@ -585,7 +585,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void MarkWireTextureGpuWritten(MG_Pipe::MGPipeHandle handle, Uint32 mipLevel, Uint32 baseArrayLayer = 0, void MarkWireTextureGpuWritten(MG_Pipe::MGPipeHandle handle, Uint32 mipLevel, Uint32 baseArrayLayer = 0,
Uint32 layerCount = 1); Uint32 layerCount = 1);
// SHARED IMAGES (docs/archive/notes/anland/plan-ahb-dmabuf.md): a server shared image's // SHARED IMAGES: a server shared image's
// AHardwareBuffer bound as a single-level 2D colour image on THIS session's device, on dedicated // AHardwareBuffer bound as a single-level 2D colour image on THIS session's device, on dedicated
// memory imported from the buffer. Android only (false with `why` elsewhere, or when the device // memory imported from the buffer. Android only (false with `why` elsewhere, or when the device
// did not take the AHardwareBuffer extension). The image is born UNDEFINED; whoever uses it // did not take the AHardwareBuffer extension). The image is born UNDEFINED; whoever uses it
@@ -651,7 +651,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// and the default draw framebuffer alike. The CAPABILITY decline inside // and the default draw framebuffer alike. The CAPABILITY decline inside
// ResolveWireDepthStencil (a stencil-only resolve without VK_EXT_shader_stencil_export // ResolveWireDepthStencil (a stencil-only resolve without VK_EXT_shader_stencil_export
// on a device without VK_KHR_depth_stencil_resolve) is still decided per aspect, after // on a device without VK_KHR_depth_stencil_resolve) is still decided per aspect, after
// colour ran; rule I (a) accepts that (docs/archive/notes/p7/magma-b2.md §2.10). // colour ran; rule I (a) accepts that (§2.10).
Bool DeclineWireDepthStencilResolveShape(const WireImage& source, const WireImage& destination, GLint sx0, Bool DeclineWireDepthStencilResolveShape(const WireImage& source, const WireImage& destination, GLint sx0,
GLint sy0, GLint sx1, GLint sy1, GLint dx0, GLint dy0, GLint dx1, GLint sy0, GLint sx1, GLint sy1, GLint dx0, GLint dy0, GLint dx1,
GLint dy1); GLint dy1);
@@ -1439,7 +1439,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// (BlitDepthAcrossFormats, shared with the monolith arm) has no flip either. Both // (BlitDepthAcrossFormats, shared with the monolith arm) has no flip either. Both
// decline by name, each under its OWN once-site (review round 2: one site covered both, // decline by name, each under its OWN once-site (review round 2: one site covered both,
// so after the first X decline a cross-format Y decline logged nothing); §6 in // so after the first X decline a cross-format Y decline logged nothing); §6 in
// docs/archive/notes/p7/magma-b2.md carries them. These are declines of a LEGAL blit - GL would // the phase notes carries them. These are declines of a LEGAL blit - GL would
// raise no error here - so the INVALID_OPERATION is rule I (a)'s named refusal, not // raise no error here - so the INVALID_OPERATION is rule I (a)'s named refusal, not
// GL's answer. // GL's answer.
const Bool mirrorX = (spanX < 0) != (dstSpanX < 0); const Bool mirrorX = (spanX < 0) != (dstSpanX < 0);
@@ -1715,7 +1715,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// so a shader decline (a stencil aspect without VK_EXT_shader_stencil_export, a format // so a shader decline (a stencil aspect without VK_EXT_shader_stencil_export, a format
// that is not SAMPLED_IMAGE + DEPTH_STENCIL_ATTACHMENT, a failed pipeline create - // that is not SAMPLED_IMAGE + DEPTH_STENCIL_ATTACHMENT, a failed pipeline create -
// WireMultisampleResolve.cpp) that lands on the render pass is the resolve most likely // WireMultisampleResolve.cpp) that lands on the render pass is the resolve most likely
// to read back as zeroes with no GL error. A recorded debt (docs/archive/notes/p7/g5-msrbo.md §4). // to read back as zeroes with no GL error. A recorded debt (§4).
if (resolvedByShader) { if (resolvedByShader) {
MGLOG_I_ONCE("DirectVulkan::ResolveWireDepthStencil: resolved by the shader pass " MGLOG_I_ONCE("DirectVulkan::ResolveWireDepthStencil: resolved by the shader pass "
"(prefer-shader=%d, render-pass arm available=%d)", "(prefer-shader=%d, render-pass arm available=%d)",
@@ -9,7 +9,7 @@
#include "VulkanRendererInternal.h" #include "VulkanRendererInternal.h"
namespace MobileGL::MG_Backend::DirectVulkan { namespace MobileGL::MG_Backend::DirectVulkan {
// SHARED IMAGES (docs/archive/notes/anland/plan-ahb-dmabuf.md). The present side's copy is // SHARED IMAGES. The present side's copy is
// WireFramebuffer.cpp's readback, into an image: the same flush, the same write-visibility // WireFramebuffer.cpp's readback, into an image: the same flush, the same write-visibility
// barrier, the same transition of the default framebuffer's image. // barrier, the same transition of the default framebuffer's image.
// //
+1 -1
View File
@@ -85,7 +85,7 @@ namespace MobileGL::MG_Backend {
// (VkBufferManager::RegisterWireResourceOps, VkBufferManager.cpp): under a transport it // (VkBufferManager::RegisterWireResourceOps, VkBufferManager.cpp): under a transport it
// owns buffer stores and claims bit 7 (the P4a mask, see ConsumedSubsystemsFor below); // owns buffer stores and claims bit 7 (the P4a mask, see ConsumedSubsystemsFor below);
// under monolith it registers none and its buffers keep the legacy BufferBackendOps path. // under monolith it registers none and its buffers keep the legacy BufferBackendOps path.
// P5e (docs/archive/contracts/CONTRACT-P5E.md §6.2). THE ONE CONSTANT THE WHOLE PHASE HANGS ON. // P5e (§6.2). THE ONE CONSTANT THE WHOLE PHASE HANGS ON.
// //
// kCapRunAheadApply says "this server applies an unbarriered record without reading // kCapRunAheadApply says "this server applies an unbarriered record without reading
// client memory". That is only true once EVERY per-draw family reads records instead // client memory". That is only true once EVERY per-draw family reads records instead
@@ -301,7 +301,7 @@ namespace MobileGL::MG_Record {
return false; return false;
} }
// ---- P9 (W1, docs/archive/contracts/CONTRACT-P9.md §1): the pack-buffer readbacks ------------------------ // ---- P9 (W1 §1): the pack-buffer readbacks ------------------------
// //
// WHY THE ROWS GO THROUGH THE APPLIER'S BUFFER-WRITE GATE AND NOT THROUGH THE DRIVER'S OWN // WHY THE ROWS GO THROUGH THE APPLIER'S BUFFER-WRITE GATE AND NOT THROUGH THE DRIVER'S OWN
// PBO READ. Monolith binds the driver buffer as GL_PIXEL_PACK_BUFFER and lets glReadPixels // PBO READ. Monolith binds the driver buffer as GL_PIXEL_PACK_BUFFER and lets glReadPixels
@@ -504,7 +504,7 @@ namespace MobileGL::MG_Record {
slot); slot);
} }
// P5b d1 (docs/archive/contracts/CONTRACT-P5B.md §2 d1): draw_vbo's whole cross product. The record // P5b d1 (§2 d1): draw_vbo's whole cross product. The record
// carries the GL call verbatim (rule D) and this body reproduces the backend call the // carries the GL call verbatim (rule D) and this body reproduces the backend call the
// monolith makes for that shape, reading only the record and the backend's own // monolith makes for that shape, reading only the record and the backend's own
// barrier-pulled state; the twenty GL entry points collapse onto the arms below: // barrier-pulled state; the twenty GL entry points collapse onto the arms below:
@@ -815,7 +815,7 @@ namespace MobileGL::MG_Record {
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// P5b: the stubs the four migration packages replace (docs/archive/contracts/CONTRACT-P5B.md). // P5b: the stubs the four migration packages replace.
// //
// Each dies by the GL slot's own name. The record has crossed and been validated by the // Each dies by the GL slot's own name. The record has crossed and been validated by the
// codec by the time one of these runs, so the only thing missing is the backend call, and // codec by the time one of these runs, so the only thing missing is the backend call, and
@@ -824,7 +824,7 @@ namespace MobileGL::MG_Record {
// in the same words), the call, and a tally the lane can assert moved. // in the same words), the call, and a tally the lane can assert moved.
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// ---- i1 ---- (docs/archive/contracts/CONTRACT-P5B.md §2 i1; landed by package p5b/i1) // ---- i1 ---- (§2 i1; landed by package p5b/i1)
// //
// RULE D IN FIVE BODIES. Each reproduces the backend call the monolith makes, from the // RULE D IN FIVE BODIES. Each reproduces the backend call the monolith makes, from the
// record and from server state, and NOTHING ELSE: the backend goes on reading the frontend // record and from server state, and NOTHING ELSE: the backend goes on reading the frontend
@@ -974,7 +974,7 @@ namespace MobileGL::MG_Record {
return true; return true;
} }
// ---- t2 ---- (docs/archive/contracts/CONTRACT-P5B.md §2 t2) // ---- t2 ---- (§2 t2)
// //
// SIX BODIES, SIX BACKEND CALLS, NO STATE OF THEIR OWN. Rule D: the record IS the call, and // SIX BODIES, SIX BACKEND CALLS, NO STATE OF THEIR OWN. Rule D: the record IS the call, and
// everything the backend reads around it - the capture program, the capture-buffer // everything the backend reads around it - the capture program, the capture-buffer
+1 -1
View File
@@ -43,7 +43,7 @@ namespace MobileGL::MG_Record {
Bool OnDrawVbo(const MG_Pipe::MGPDrawInfo& info, const MG_Pipe::MGPDrawRange* ranges, Bool OnDrawVbo(const MG_Pipe::MGPDrawInfo& info, const MG_Pipe::MGPDrawRange* ranges,
const MG_Pipe::MGHostSpan* userIndices, const MG_Pipe::MGPDrawIndirect* indirect) override; const MG_Pipe::MGHostSpan* userIndices, const MG_Pipe::MGPDrawIndirect* indirect) override;
// ---- P5b (docs/archive/contracts/CONTRACT-P5B.md): one override per row a migration package owns. // ---- P5b: one override per row a migration package owns.
// At the contract commit EVERY BODY BELOW IS A STUB that dies // At the contract commit EVERY BODY BELOW IS A STUB that dies
// Fatal{UnmigratedVerb, "<GL slot>"} by the slot's own name - the same line the client's // Fatal{UnmigratedVerb, "<GL slot>"} by the slot's own name - the same line the client's
// class-C table raises and the census greps - so a client flipped ahead of its server // class-C table raises and the census greps - so a client flipped ahead of its server
@@ -519,7 +519,7 @@ namespace MobileGL::MG_Record {
EraseSession(m_driverWritten, session); EraseSession(m_driverWritten, session);
} }
// ---- P8-E (docs/archive/notes/p8/E.md): WHEN THESE BYTES ARE THE LEVEL'S CONTENT ---- // ---- P8-E: WHEN THESE BYTES ARE THE LEVEL'S CONTENT ----
// //
// The store holds what the client uploaded. It is also the only CPU copy of a level the // The store holds what the client uploaded. It is also the only CPU copy of a level the
// server has, so a readback the driver refuses (a format the ES driver will not attach - // server has, so a readback the driver refuses (a format the ES driver will not attach -
+1 -1
View File
@@ -10,7 +10,7 @@
#include <Includes.h> #include <Includes.h>
namespace MobileGL::MG_Backend { namespace MobileGL::MG_Backend {
// SHARED IMAGES (docs/archive/notes/anland/plan-ahb-dmabuf.md): server-allocated colour // SHARED IMAGES: server-allocated colour
// buffers exported to clients as dma-buf descriptors. // buffers exported to clients as dma-buf descriptors.
// //
// The server-side view of one image, as a backend sees it: `NativeBuffer` is the image's // The server-side view of one image, as a backend sees it: `NativeBuffer` is the image's
+1 -1
View File
@@ -8,7 +8,7 @@
// mobilegl_gbm.so: a GBM backend (the loader's backend ABI, gbm_backend_abi.h) whose buffer // mobilegl_gbm.so: a GBM backend (the loader's backend ABI, gbm_backend_abi.h) whose buffer
// objects are MobileGL shared images - colour buffers the MobileGL server allocates and exports // objects are MobileGL shared images - colour buffers the MobileGL server allocates and exports
// as dma-bufs (docs/archive/notes/anland/plan-ahb-dmabuf.md). Selected with // as dma-bufs. Selected with
// GBM_BACKEND=mobilegl; the loader then finds <dir>/mobilegl_gbm.so on its backend path. // GBM_BACKEND=mobilegl; the loader then finds <dir>/mobilegl_gbm.so on its backend path.
// //
// THE DEVICE DESCRIPTOR IS OPAQUE. The fd a gbm_device is created on is only the identity the // THE DEVICE DESCRIPTOR IS OPAQUE. The fd a gbm_device is created on is only the identity the
@@ -8,7 +8,7 @@
#pragma once #pragma once
// WHEN glFlush IS A SHARED-IMAGE BOUNDARY (docs/archive/notes/anland/plan-x11-gpu.md). // WHEN glFlush IS A SHARED-IMAGE BOUNDARY.
// //
// A dma-buf producer that renders into its buffers and hands them on after a glFlush (an X // A dma-buf producer that renders into its buffers and hands them on after a glFlush (an X
// server's glamor committing a window pixmap) relies on implicit sync: whoever samples the buffer // server's glamor committing a window pixmap) relies on implicit sync: whoever samples the buffer
@@ -46,7 +46,7 @@
// call sites below are declarations only, exactly as the frontend's mutators are. // call sites below are declarations only, exactly as the frontend's mutators are.
#include <MG_Pipe/PipeMutation.h> #include <MG_Pipe/PipeMutation.h>
// P9 (W1, docs/archive/contracts/CONTRACT-P9.md §1): AN UNPACK SOURCE IS READ FROM THE BUFFER'S CLIENT SHADOW, // P9 (W1 §1): AN UNPACK SOURCE IS READ FROM THE BUFFER'S CLIENT SHADOW,
// and under a transport a GPU write into that buffer - a read_pixels_to_buffer, which is how a // and under a transport a GPU write into that buffer - a read_pixels_to_buffer, which is how a
// glReadPixels into a pack buffer now crosses, or a shader store - reaches the shadow only through // glReadPixels into a pack buffer now crosses, or a shader store - reaches the shadow only through
// SyncGpuWrites, exactly as glMapBufferRange and glGetBufferSubData already do. Monolith keeps its // SyncGpuWrites, exactly as glMapBufferRange and glGetBufferSubData already do. Monolith keeps its
+1 -1
View File
@@ -8,7 +8,7 @@
#pragma once #pragma once
// GLX WINDOWS PRESENTED THROUGH DRI3 + PRESENT (docs/archive/notes/anland/plan-x11-gpu.md). // GLX WINDOWS PRESENTED THROUGH DRI3 + PRESENT.
// //
// A GLX window's frames are drawn by the server into a pbuffer. Instead of reading each frame back // A GLX window's frames are drawn by the server into a pbuffer. Instead of reading each frame back
// and putting it on the window, the frame is copied GPU-side into one of a few server-allocated // and putting it on the window, the frame is copied GPU-side into one of a few server-allocated
+8 -8
View File
@@ -2113,13 +2113,13 @@ namespace MobileGL::MG_Pipe {
// emission gate is the subsystem bit plus the whole-record hash and nothing else. // emission gate is the subsystem bit plus the whole-record hash and nothing else.
case MGPipeFieldEmitter::SetContextValues: case MGPipeFieldEmitter::SetContextValues:
return kMGPipeSubsystemResidualValues; return kMGPipeSubsystemResidualValues;
// P5e's one emitted row (docs/archive/contracts/CONTRACT-P5E.md §5.6): the indexed buffer // P5e's one emitted row (§5.6): the indexed buffer
// binding points. Written HERE at the contract commit, with the Coverage.def row // binding points. Written HERE at the contract commit, with the Coverage.def row
// and EmittedCallSuppliesTheWholeField's arm beside it, for the reason // and EmittedCallSuppliesTheWholeField's arm beside it, for the reason
// kMGPipeWiredSubsystems' block states one paragraph down - this file belongs to // kMGPipeWiredSubsystems' block states one paragraph down - this file belongs to
// the contract package for the whole phase, and an emitter enumerator whose // the contract package for the whole phase, and an emitter enumerator whose
// dispatch arm lived in the family's own worktree is the merge trap that block // dispatch arm lived in the family's own worktree is the merge trap that block
// exists to close. It is inert until that family's wired constant leaves 0. // exists to close. It is inert until that family's wired constant leaves 0.
case MGPipeFieldEmitter::SetShaderBuffers: case MGPipeFieldEmitter::SetShaderBuffers:
return kMGPipeSubsystemBufferBindings; return kMGPipeSubsystemBufferBindings;
case MGPipeFieldEmitter::kNone: case MGPipeFieldEmitter::kNone:
@@ -2175,7 +2175,7 @@ namespace MobileGL::MG_Pipe {
static_assert(kMGPipeMaxVertexAttribs == MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS, static_assert(kMGPipeMaxVertexAttribs == MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS,
"the MGPipe vertex-attribute capacity and the frontend's have drifted"); "the MGPipe vertex-attribute capacity and the frontend's have drifted");
// P5e (docs/archive/contracts/CONTRACT-P5E.md §1, ruling 10), pinned here for the same reason and in // P5e (§1, ruling 10), pinned here for the same reason and in
// the same place: this translation unit sees the frontend constant and the MG_Pipe one, // the same place: this translation unit sees the frontend constant and the MG_Pipe one,
// and nothing else does. 84 is what the emitter may describe and what the wire carries; // and nothing else does. 84 is what the emitter may describe and what the wire carries;
// the BACKEND clamps to the device's real GL_MAX_UNIFORM_BUFFER_BINDINGS, as it does // the BACKEND clamps to the device's real GL_MAX_UNIFORM_BUFFER_BINDINGS, as it does
+1 -1
View File
@@ -106,7 +106,7 @@ namespace MobileGL::MG_Pipe {
// published ahead of it are wiped by the create that follows. What the draft was // published ahead of it are wiped by the create that follows. What the draft was
// protecting - "a rebuild inside the verb must already see the bindings" - is // protecting - "a rebuild inside the verb must already see the bindings" - is
// satisfied by both records going out at the SAME validate point, ahead of the verb, // satisfied by both records going out at the SAME validate point, ahead of the verb,
// which is what this ordering does. See docs/archive/contracts/CONTRACT-P5E.md §5.5 and the // which is what this ordering does. See the contract §5.5 and the
// record's own comment in PipeApply.h. // record's own comment in PipeApply.h.
if (drawProgram) bytes += EmitProgramBindings(*drawProgram, drawCso); if (drawProgram) bytes += EmitProgramBindings(*drawProgram, drawCso);
// THE COMPOSITE'S SECOND RELEASE PATH is spoken here, not in a destructor: when the // THE COMPOSITE'S SECOND RELEASE PATH is spoken here, not in a destructor: when the
+1 -1
View File
@@ -40,7 +40,7 @@ namespace MobileGL::MG_Pipe {
SetSamplerViews, // P4a - wired (backend debounce deletion: P3b/P4b) SetSamplerViews, // P4a - wired (backend debounce deletion: P3b/P4b)
BindSamplerStates, // P4a - wired (backend debounce deletion: P3b/P4b) BindSamplerStates, // P4a - wired (backend debounce deletion: P3b/P4b)
SetShaderImages, // P4a - wired (backend debounce deletion: P3b/P4b) SetShaderImages, // P4a - wired (backend debounce deletion: P3b/P4b)
// P5e (docs/archive/contracts/CONTRACT-P5E.md §1, ruling 11): THREE SLOTS, ONE PER CLASS, not one // P5e (§1, ruling 11): THREE SLOTS, ONE PER CLASS, not one
// for the call. set_shader_buffers is emitted per Class (Uniform / ShaderStorage / // for the call. set_shader_buffers is emitted per Class (Uniform / ShaderStorage /
// AtomicCounter) because the record's own Class field says which binding-point array // AtomicCounter) because the record's own Class field says which binding-point array
// it describes - so a single slot would make every emission of one class cancel the // it describes - so a single slot would make every emission of one class cancel the
+12 -12
View File
@@ -156,18 +156,18 @@ namespace MobileGL::MG_Pipe {
case MGPipeDirty::NewSamplers: case MGPipeDirty::NewSamplers:
case MGPipeDirty::NewShaderImages: case MGPipeDirty::NewShaderImages:
return kMGPipeSubsystemSamplers; return kMGPipeSubsystemSamplers;
// P5e's three, one subsystem (docs/archive/contracts/CONTRACT-P5E.md §1): the indexed buffer // P5e's three, one subsystem (§1): the indexed buffer
// binding points. Bits 15/16/17 have been computed and counted since P2 and have named // binding points. Bits 15/16/17 have been computed and counted since P2 and have named
// no subsystem since - "the remaining bits have no call of their own until P4b", which // no subsystem since - "the remaining bits have no call of their own until P4b", which
// the default arm below used to say for them. set_shader_buffers is the call, and // the default arm below used to say for them. set_shader_buffers is the call, and
// set_stream_output_targets stays unemitted while riding the same A/B bit, for the // set_stream_output_targets stays unemitted while riding the same A/B bit, for the
// reason kMGPipeDirtyEmittedAtP5e states. // reason kMGPipeDirtyEmittedAtP5e states.
// //
// NAMING THE SUBSYSTEM IS NOT THE SAME AS EMITTING. The emission gate is five // NAMING THE SUBSYSTEM IS NOT THE SAME AS EMITTING. The emission gate is five
// conjuncts (PipeFill.cpp's `wants()`), one of which is kMGPipeWiredSubsystems - and // conjuncts (PipeFill.cpp's `wants()`), one of which is kMGPipeWiredSubsystems - and
// the buffer-binding family's wired constant is 0 until the package that gives the // the buffer-binding family's wired constant is 0 until the package that gives the
// emitter its body sets it, exactly as P4a's four families were. So this map moves // emitter its body sets it, exactly as P4a's four families were. So this map moves
// here, inert, and nothing is emitted and no field is skipped on its account yet. // here, inert, and nothing is emitted and no field is skipped on its account yet.
case MGPipeDirty::NewConstBuffers: case MGPipeDirty::NewConstBuffers:
case MGPipeDirty::NewShaderBuffers: case MGPipeDirty::NewShaderBuffers:
case MGPipeDirty::NewSoTargets: case MGPipeDirty::NewSoTargets:
+1 -1
View File
@@ -152,7 +152,7 @@ namespace MobileGL::MG_Record {
Bool ReadbackReplyIsComplete(Int32 status, Uint64 replySize, Uint64 expected); Bool ReadbackReplyIsComplete(Int32 status, Uint64 replySize, Uint64 expected);
// ============================================================================= // =============================================================================
// P5b d1 - the draw family's record plan (docs/archive/contracts/CONTRACT-P5B.md §2 d1) // P5b d1 - the draw family's record plan (§2 d1)
// ============================================================================= // =============================================================================
// //
// The nineteen indexed / instanced / multi-draw / indirect entry points all ride draw_vbo // The nineteen indexed / instanced / multi-draw / indirect entry points all ride draw_vbo
+1 -1
View File
@@ -6,7 +6,7 @@
* SPDX-License-Identifier: LGPL-3.0-only * SPDX-License-Identifier: LGPL-3.0-only
* End of Source File Header */ * End of Source File Header */
/* SHARED IMAGES, AS A C ABI (docs/archive/notes/anland/plan-ahb-dmabuf.md). /* SHARED IMAGES, AS A C ABI.
* *
* libMobileGL.so exports these on Linux (not Android) in split builds, so a component that is not * libMobileGL.so exports these on Linux (not Android) in split builds, so a component that is not
* a GL entry point - the GBM backend (MG_Gbm), above all - can ask the server for an image and * a GL entry point - the GBM backend (MG_Gbm), above all - can ask the server for an image and
+2 -2
View File
@@ -19,7 +19,7 @@
# monolith DirectGLES. / DirectVulkan. case is on a gated split arm or is named, with a reason # monolith DirectGLES. / DirectVulkan. case is on a gated split arm or is named, with a reason
# class, in scripts/data/split_coverage_exemptions.txt. Deleting a line below reds it BY NAME. # class, in scripts/data/split_coverage_exemptions.txt. Deleting a line below reds it BY NAME.
# The per-case census this list was cut from (inproc / spawn / tcp, junit per arm) is # The per-case census this list was cut from (inproc / spawn / tcp, junit per arm) is
# docs/archive/notes/p8/A.md. # recorded in the phase notes.
# ---- (a) THE AMBIENT CASES ----------------------------------------------------------------- # ---- (a) THE AMBIENT CASES -----------------------------------------------------------------
# #
@@ -191,7 +191,7 @@ set(MGL_P8A_KNOB_FILTER_WidenedPacked16 "CopyImagePacked16Scenario.*")
set(MGL_P8A_KNOB_ENV_WidenedPacked16 "MOBILEGL_ESPRYT_WIDEN_PACKED16_STORAGE=1") set(MGL_P8A_KNOB_ENV_WidenedPacked16 "MOBILEGL_ESPRYT_WIDEN_PACKED16_STORAGE=1")
# ForcedDs keeps the spelling the existing Split/Spawn DepthStencilReadbackMatrix block uses. The # ForcedDs keeps the spelling the existing Split/Spawn DepthStencilReadbackMatrix block uses. The
# default-framebuffer case was left out here while it was red on spawn and tcp; P8-SE fixed it # default-framebuffer case was left out here while it was red on spawn and tcp; P8-SE fixed it
# (docs/archive/notes/p8/SE.md) and it runs under the knob on every arm like the rest. # and it runs under the knob on every arm like the rest.
set(MGL_P8A_KNOB_FILTER_ForcedDs set(MGL_P8A_KNOB_FILTER_ForcedDs
"DepthStencilReadbackScenario.*:DepthStencilReadbackAttachmentShapeScenario.*") "DepthStencilReadbackScenario.*:DepthStencilReadbackAttachmentShapeScenario.*")
set(MGL_P8A_KNOB_ENV_ForcedDs "MOBILEGL_ESPRYT_FORCE_DS_READBACK_EMULATION=1") set(MGL_P8A_KNOB_ENV_ForcedDs "MOBILEGL_ESPRYT_FORCE_DS_READBACK_EMULATION=1")
@@ -7,7 +7,7 @@
// End of Source File Header // End of Source File Header
// //
// Scenario - glCopyImageSubData INTO A LEVEL THE DRIVER WILL NOT READ BACK (P8-E, // Scenario - glCopyImageSubData INTO A LEVEL THE DRIVER WILL NOT READ BACK (P8-E,
// docs/archive/notes/p8/E.md). // the phase notes).
// //
// The formats are the ones an ES driver keeps as texture-only storage: GL_RGB16 (EXT_texture_norm16 // The formats are the ones an ES driver keeps as texture-only storage: GL_RGB16 (EXT_texture_norm16
// makes the three-channel spelling sampleable, never colour-renderable) and the 16-bit SNORM family // makes the three-channel spelling sampleable, never colour-renderable) and the 16-bit SNORM family
@@ -6,7 +6,7 @@
// SPDX-License-Identifier: LGPL-3.0-only // SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header // End of Source File Header
// P5c ct (docs/archive/contracts/CONTRACT-P5C.md §5): the two control records, end to end over inproc. // P5c ct (§5): the two control records, end to end over inproc.
// //
// applier_reset (§5.1): this process's first validate primes the pipe tracker, and the // applier_reset (§5.1): this process's first validate primes the pipe tracker, and the
// FreshlyPrimed edge is the record's producer (MG_Impl/Pipe/PipeFill.cpp). What the scenario // FreshlyPrimed edge is the record's producer (MG_Impl/Pipe/PipeFill.cpp). What the scenario
@@ -167,7 +167,7 @@ namespace MGITest {
// (DirectVulkan.cpp, CONTRACT-P7 §5.5) and emits the same `object_death`. Package L // (DirectVulkan.cpp, CONTRACT-P7 §5.5) and emits the same `object_death`. Package L
// measured that the SPAWN arm already passed once the WireTables install condition // measured that the SPAWN arm already passed once the WireTables install condition
// went backend-agnostic and that the INPROC arm failed here with `deaths` 0 vs 0 // went backend-agnostic and that the INPROC arm failed here with `deaths` 0 vs 0
// (docs/archive/notes/p7/magma-two-process-first-run.md §6); the table is what closes the inproc // (§6); the table is what closes the inproc
// half, and this case is the gate on it. It is also the RED-ONCE for that table: with // half, and this case is the gate on it. It is also the RED-ONCE for that table: with
// the install site short-circuited, both cases red on their `od` assertions below. // the install site short-circuited, both cases red on their `od` assertions below.
const GLubyte red[4] = {255, 0, 0, 255}; const GLubyte red[4] = {255, 0, 0, 255};
@@ -242,7 +242,7 @@ namespace MGITest {
// "A SPLIT BUILD RUNS AT TIER T2 AND DECLINES EVERY ACQUISITION, ALWAYS"; T0/T1 are // "A SPLIT BUILD RUNS AT TIER T2 AND DECLINES EVERY ACQUISITION, ALWAYS"; T0/T1 are
// unimplemented, refused by name at the handshake since P11 A1). So the capability is wired // unimplemented, refused by name at the handshake since P11 A1). So the capability is wired
// AHEAD of its consumer on purpose, and `rsd=` on the PipeStats line is the counter that // AHEAD of its consumer on purpose, and `rsd=` on the PipeStats line is the counter that
// will show the records the day P11 lands a tier that adopts. See docs/archive/notes/p7/magma-c.md. // will show the records the day P11 lands a tier that adopts. See the phase notes.
TEST_F(CtWireScenario, TheServerPublishesTheResidentSubDataCapabilityFromItsOwnTable) { TEST_F(CtWireScenario, TheServerPublishesTheResidentSubDataCapabilityFromItsOwnTable) {
if (!Ready()) return; if (!Ready()) return;
// A REAL WORKLOAD FIRST, and it is not decoration: ScenarioFixture's arming rule // A REAL WORKLOAD FIRST, and it is not decoration: ScenarioFixture's arming rule
@@ -544,7 +544,7 @@ namespace MGITest {
// THE CASE IS ARMED ON THE MAGMA WIRE ARM ONLY, and the two gates below say which of the // THE CASE IS ARMED ON THE MAGMA WIRE ARM ONLY, and the two gates below say which of the
// other arms that discover it (the suite is registered whole on the monolith DirectVulkan // other arms that discover it (the suite is registered whole on the monolith DirectVulkan
// arm and on every DirectGLES arm) owe this picture and do not yet produce it. Both are // arm and on every DirectGLES arm) owe this picture and do not yet produce it. Both are
// recorded debts (docs/archive/notes/p7/magma-b2.md §6), not agreements with the wrong answer: // recorded debts (§6), not agreements with the wrong answer:
// - Espryt (DirectGLES, monolith and split alike): the flipped resolve writes nothing and // - Espryt (DirectGLES, monolith and split alike): the flipped resolve writes nothing and
// raises no error, and the scaled one raises no error either. P3b/P4b. // raises no error, and the scaled one raises no error either. P3b/P4b.
// - the monolith DirectVulkan arm: `VulkanRenderer.cpp` refuses a depth blit with a // - the monolith DirectVulkan arm: `VulkanRenderer.cpp` refuses a depth blit with a
@@ -573,16 +573,15 @@ namespace MGITest {
GTEST_SKIP() << "Espryt (" << Gl().BackendName() GTEST_SKIP() << "Espryt (" << Gl().BackendName()
<< ") does not produce this picture yet: a " << ") does not produce this picture yet: a "
"flipped multisample depth resolve writes nothing with no error and a scaled " "flipped multisample depth resolve writes nothing with no error and a scaled "
"one raises no INVALID_OPERATION - a P3b/P4b debt (docs/archive/notes/p7/magma-b2.md §6)"; "one raises no INVALID_OPERATION - a P3b/P4b debt (§6)";
} }
if (!PeekSplitRuntime().transportResolved) { if (!PeekSplitRuntime().transportResolved) {
GTEST_SKIP() GTEST_SKIP() << "the monolith DirectVulkan transport (this process resolved no split "
<< "the monolith DirectVulkan transport (this process resolved no split " "transport, so BlitFramebuffer takes the monolith arm) refuses a flipped "
"transport, so BlitFramebuffer takes the monolith arm) refuses a flipped " "depth blit (\"depth blits with flipped rectangles are not supported yet\", "
"depth blit (\"depth blits with flipped rectangles are not supported yet\", " "destination untouched, no error) and scales a multisample depth blit GL "
"destination untouched, no error) and scales a multisample depth blit GL " "calls INVALID_OPERATION - a wire-vs-monolith divergence where the wire arm "
"calls INVALID_OPERATION - a wire-vs-monolith divergence where the wire arm " "is the correct one; the monolith fix is P13/G1-bound (§6)";
"is the correct one; the monolith fix is P13/G1-bound (docs/archive/notes/p7/magma-b2.md §6)";
} }
DepthSource multisampled = MakeRenderbufferSource(GL_DEPTH24_STENCIL8, 4); DepthSource multisampled = MakeRenderbufferSource(GL_DEPTH24_STENCIL8, 4);
if (!SourceIsUsable()) { if (!SourceIsUsable()) {
@@ -1255,7 +1255,7 @@ void main() { color = value + tail; }
// The sibling of ShortUniformBufferRangePadsMissingBytes whose bound range does NOT // The sibling of ShortUniformBufferRangePadsMissingBytes whose bound range does NOT
// end on a four-byte boundary. That window is what `uniform-buffer-byte-tail` // end on a four-byte boundary. That window is what `uniform-buffer-byte-tail`
// used to refuse (a named Fatal that took the whole session with it), and it is the // used to refuse (a named Fatal that took the whole session with it), and it is the
// live boundary the Redmi Minecraft run reported (docs/archive/notes/p5f/magma-inproc-fix.md #5). // live boundary the Redmi Minecraft run reported.
// //
// Only the SIZE can land off a word here. glBindBufferRange constrains the offset to // Only the SIZE can land off a word here. glBindBufferRange constrains the offset to
// GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT and records GL_INVALID_VALUE otherwise // GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT and records GL_INVALID_VALUE otherwise
@@ -6,7 +6,7 @@
// SPDX-License-Identifier: LGPL-3.0-only // SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header // End of Source File Header
// //
// P10 (A, docs/archive/contracts/CONTRACT-P10.md §1): FENCE POLLS ANSWERED FROM THE REVERSE CHANNEL. // P10 (A §1): FENCE POLLS ANSWERED FROM THE REVERSE CHANNEL.
// //
// A glClientWaitSync / glGetSynciv(GL_SYNC_STATUS) used to be a kWaitReply record: its answer // A glClientWaitSync / glGetSynciv(GL_SYNC_STATUS) used to be a kWaitReply record: its answer
// came back only after the server had applied every record before it, so a poll was a full // came back only after the server had applied every record before it, so a poll was a full
@@ -7,7 +7,7 @@
// End of Source File Header // End of Source File Header
// //
// Scenario - glGenerateMipmap ON THE FORMATS ESPRYT DOES NOT HAND STRAIGHT TO THE DRIVER // Scenario - glGenerateMipmap ON THE FORMATS ESPRYT DOES NOT HAND STRAIGHT TO THE DRIVER
// (P8-B, docs/archive/notes/p8/B.md). // (P8-B).
// //
// Espryt generates R11F_G11F_B10F and depth chains with per-level blits, and RGB16F / RGB32F // Espryt generates R11F_G11F_B10F and depth chains with per-level blits, and RGB16F / RGB32F
// chains outside glGenerateMipmap because ES refuses a three-channel float format there. Until // chains outside glGenerateMipmap because ES refuses a three-channel float format there. Until
@@ -6,7 +6,7 @@
// SPDX-License-Identifier: LGPL-3.0-only // SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header // End of Source File Header
// //
// Scenario - THE DRAW FAMILY P5b's d1 PUTS ON THE WIRE (docs/archive/contracts/CONTRACT-P5B.md §2 d1): one // Scenario - THE DRAW FAMILY P5b's d1 PUTS ON THE WIRE (§2 d1): one
// VBO, one EBO, one program, one VAO, and one picture per draw entry point whose correctness // VBO, one EBO, one program, one VAO, and one picture per draw entry point whose correctness
// DEPENDS on the fields that entry point adds to draw_vbo. Two quads live in the vertex buffer, // DEPENDS on the fields that entry point adds to draw_vbo. Two quads live in the vertex buffer,
// a left one and a right one, and every case draws exactly one of them or both through a // a left one and a right one, and every case draws exactly one of them or both through a
@@ -611,7 +611,7 @@ void main() { word = 0xC0FFEEu; }
<< window.line; << window.line;
} }
// P11 A2 (docs/archive/contracts/CONTRACT-P11.md §2): WHICH TIER THE ARENA REALLY LANDED IN. The cases above // P11 A2 (§2): WHICH TIER THE ARENA REALLY LANDED IN. The cases above
// are green whether the arena adopted or stayed emulated, so the lane declares the arm // are green whether the arena adopted or stayed emulated, so the lane declares the arm
// (MGITEST_PERSISTENT_MAP_ARM) and this case asserts it, the way // (MGITEST_PERSISTENT_MAP_ARM) and this case asserts it, the way
// PersistentCoherentMapScenario.TheMapLandsInTheArmItsLaneDeclares does for a sub-16-MiB map. // PersistentCoherentMapScenario.TheMapLandsInTheArmItsLaneDeclares does for a sub-16-MiB map.
@@ -666,7 +666,7 @@ void main() { word = 0xC0FFEEu; }
ExpectDeclaredArm(declared, "after a frame of draws, an SSBO binding and a dispatch"); ExpectDeclaredArm(declared, "after a frame of draws, an SSBO binding and a dispatch");
} }
// P11 A1 (docs/archive/contracts/CONTRACT-P11.md §1): THE TCP LANE WITH MOBILEGL_IPC_ADOPT_TIER=0. A stream // P11 A1 (§1): THE TCP LANE WITH MOBILEGL_IPC_ADOPT_TIER=0. A stream
// data plane has no memory the two sides share, so the client refuses the knob by name at its // data plane has no memory the two sides share, so the client refuses the knob by name at its
// handshake - exactly one `Refuse{AdoptTierOnStream, "T0"}` line in its log - and the session // handshake - exactly one `Refuse{AdoptTierOnStream, "T0"}` line in its log - and the session
// runs T2: the other cases in the same `.AdoptTier0.` lane are green and the arena is emulated. // runs T2: the other cases in the same `.AdoptTier0.` lane are green and the arena is emulated.
@@ -703,7 +703,7 @@ void main() { word = 0xC0FFEEu; }
EXPECT_EQ(log.find("Fatal{UnimplementedAdoptTier"), std::string::npos) << log; EXPECT_EQ(log.find("Fatal{UnimplementedAdoptTier"), std::string::npos) << log;
} }
// P11 B2 (docs/archive/contracts/CONTRACT-P11.md B2): A SHARED-SEGMENT SESSION THAT ASKS T0 AND CANNOT RUN IT. // P11 B2 (B2): A SHARED-SEGMENT SESSION THAT ASKS T0 AND CANNOT RUN IT.
// MOBILEGL_IPC_ADOPT_TIER=0 over shared segments asks T0 in the Hello (A1 made it die at the // MOBILEGL_IPC_ADOPT_TIER=0 over shared segments asks T0 in the Hello (A1 made it die at the
// handshake; ruling ID-P11-14 made it this). The lane's server cannot grant it - a host has no // handshake; ruling ID-P11-14 made it this). The lane's server cannot grant it - a host has no
// AHardwareBuffer, or `.AdoptT0Disallowed.` turned its allow switch off - so it refuses by name // AHardwareBuffer, or `.AdoptT0Disallowed.` turned its allow switch off - so it refuses by name
@@ -6,7 +6,7 @@
// SPDX-License-Identifier: LGPL-3.0-only // SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header // End of Source File Header
// //
// P9 (W1, docs/archive/contracts/CONTRACT-P9.md §1): READS INTO A PIXEL PACK BUFFER ARE ANSWERED BY NOTHING. // P9 (W1 §1): READS INTO A PIXEL PACK BUFFER ARE ANSWERED BY NOTHING.
// //
// Under a transport a glReadPixels / glGetTexImage whose destination is a bound // Under a transport a glReadPixels / glGetTexImage whose destination is a bound
// GL_PIXEL_PACK_BUFFER no longer waits for its pixels: it crosses as read_pixels_to_buffer / // GL_PIXEL_PACK_BUFFER no longer waits for its pixels: it crosses as read_pixels_to_buffer /
@@ -6,7 +6,7 @@
// SPDX-License-Identifier: LGPL-3.0-only // SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header // End of Source File Header
// //
// Scenario - A TEXTURE RE-MINT NEEDS NO BYTE FROM THE CLIENT (P9 W2, docs/archive/notes/p9/W2-REMINT.md). // Scenario - A TEXTURE RE-MINT NEEDS NO BYTE FROM THE CLIENT (P9 W2).
// //
// The name is the ROADMAP's: P4a named `texture-remint-pull` the one new stall class of the // The name is the ROADMAP's: P4a named `texture-remint-pull` the one new stall class of the
// split - a texture first bound to an image unit AFTER the backend allocated it has to be // split - a texture first bound to an image unit AFTER the backend allocated it has to be
@@ -33,7 +33,7 @@
// table below. // table below.
// //
// THE CLIENT EMITTER LANDED TOO, and three places in the tree said otherwise until this commit: // THE CLIENT EMITTER LANDED TOO, and three places in the tree said otherwise until this commit:
// this header, the CMake probe's comment, and docs/archive/notes/p4a/p4a-results/gates-v1.md's re-run table. // this header, the CMake probe's comment, and the phase notes' re-run table.
// MG_Impl/Pipe/TextureEmit.h's EmitOneLevel increments CallClass::ClientTextureUploadEmissions on // MG_Impl/Pipe/TextureEmit.h's EmitOneLevel increments CallClass::ClientTextureUploadEmissions on
// every piece it emits, so `ctu=` is a live reading and `ctu == emit` is a live assertion. The // every piece it emits, so `ctu=` is a live reading and `ctu == emit` is a live assertion. The
// CMake probe's `else()` arm is kept - it is what makes the arming decision falsifiable - but it // CMake probe's `else()` arm is kept - it is what makes the arming decision falsifiable - but it
@@ -30,7 +30,7 @@
// That is exactly the shape SSIM and every ordinary pixel case go green over. // That is exactly the shape SSIM and every ordinary pixel case go green over.
// //
// SO THE CLAIM IS ASSERTED ON BOTH CHANNELS AT ONCE, and neither alone is the gate // SO THE CLAIM IS ASSERTED ON BOTH CHANNELS AT ONCE, and neither alone is the gate
// (docs/archive/notes/recovered/wf2/final/part3.md 7.3, "门:新增场景,通过 view 上传、经属主采样(以及反 // (7.3, "门:新增场景,通过 view 上传、经属主采样(以及反
// 向),跨 draw 边界各一次"): // 向),跨 draw 边界各一次"):
// //
// PIXELS an upload through one name must be visible through the other name, in the SAME // PIXELS an upload through one name must be visible through the other name, in the SAME
@@ -51,7 +51,7 @@
// MarkStorageDirtyRegion call PipeNoteLevelDirty on ITSELF instead of forwarding to the owner - // MarkStorageDirtyRegion call PipeNoteLevelDirty on ITSELF instead of forwarding to the owner -
// i.e. build the two-cursor shape the design rejects. Case (a) then goes red on stale OWNER // i.e. build the two-cursor shape the design rejects. Case (a) then goes red on stale OWNER
// texels AND on a SubDataCount that did not move, which is the pair this file exists to make // texels AND on a SubDataCount that did not move, which is the pair this file exists to make
// simultaneous. Recorded in docs/archive/notes/p34b/espryt-d2.md. // simultaneous. Recorded in the phase notes.
// //
// VIEWS ARE OPT-IN ON ESPRYT. DirectGLES withholds GL_ARB_texture_view unless // VIEWS ARE OPT-IN ON ESPRYT. DirectGLES withholds GL_ARB_texture_view unless
// MOBILEGL_ESPRYT_ENABLE_TEXTURE_VIEW=1 (ConfigLoader.cpp:213, Config.h:72), so every lane that // MOBILEGL_ESPRYT_ENABLE_TEXTURE_VIEW=1 (ConfigLoader.cpp:213, Config.h:72), so every lane that
@@ -13,7 +13,7 @@
// in every lane; the DirectGLES.Split. entries run the same two cases with // in every lane; the DirectGLES.Split. entries run the same two cases with
// MOBILEGL_TRANSPORT=inproc, where the same body is the smallest workload that crosses a real // MOBILEGL_TRANSPORT=inproc, where the same body is the smallest workload that crosses a real
// ring. Four things about its shape are decisions rather than defaults, and all four come from // ring. Four things about its shape are decisions rather than defaults, and all four come from
// the measured verb census (docs/archive/notes/p5/verb-census.md): // the measured verb census:
// //
// 1. THE DRAW IS VBO-BACKED AND HAS NO CLIENT-ARRAY INDICES. glDrawArrays against a buffer // 1. THE DRAW IS VBO-BACKED AND HAS NO CLIENT-ARRAY INDICES. glDrawArrays against a buffer
// bound to GL_ARRAY_BUFFER, never glDrawElements with a client pointer. That keeps // bound to GL_ARRAY_BUFFER, never glDrawElements with a client pointer. That keeps
@@ -7,7 +7,7 @@
// End of Source File Header // End of Source File Header
// //
// P8-SV: THE MAGMA WIRE ARM ISSUES glDispatchComputeIndirect FROM THE WIRE STORE, AS THE MONOLITH // P8-SV: THE MAGMA WIRE ARM ISSUES glDispatchComputeIndirect FROM THE WIRE STORE, AS THE MONOLITH
// ARM DOES (docs/archive/notes/p8/SV.md). // ARM DOES.
// //
// Before P8-SV the wire arm read the three group counts through ReadWireBuffer and dispatched them // Before P8-SV the wire arm read the three group counts through ReadWireBuffer and dispatched them
// from the CPU, so a dispatch buffer a shader had written cost a whole-GPU wait per call - the // from the CPU, so a dispatch buffer a shader had written cost a whole-GPU wait per call - the
@@ -6,7 +6,7 @@
// SPDX-License-Identifier: LGPL-3.0-only // SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header // End of Source File Header
// //
// P8-SV: TWO glGenerateMipmap SHAPES THE MAGMA WIRE ARM GOT WRONG (docs/archive/notes/p8/SV.md). // P8-SV: TWO glGenerateMipmap SHAPES THE MAGMA WIRE ARM GOT WRONG.
// //
// * A 3D chain through the NATIVE blit. The wire arm passed the level's depth as the blit's // * A 3D chain through the NATIVE blit. The wire arm passed the level's depth as the blit's
// subresource layerCount on an image with one array layer (VUID-vkCmdBlitImage-srcImage-00240, // subresource layerCount on an image with one array layer (VUID-vkCmdBlitImage-srcImage-00240,
+1 -1
View File
@@ -108,7 +108,7 @@ namespace MobileGL::MG_Pipe {
// the three unit sets // the three unit sets
inline constexpr Uint64 kMGPipeSubsystemPrograms = 1ull << 12; // shader CSO, draw/dispatch inline constexpr Uint64 kMGPipeSubsystemPrograms = 1ull << 12; // shader CSO, draw/dispatch
// program, global constants // program, global constants
// P5e's one (docs/archive/contracts/CONTRACT-P5E.md §1). The INDEXED BUFFER BINDING POINTS: the three // P5e's one (§1). The INDEXED BUFFER BINDING POINTS: the three
// dirty bits NewConstBuffers / NewShaderBuffers / NewSoTargets, the set_shader_buffers // dirty bits NewConstBuffers / NewShaderBuffers / NewSoTargets, the set_shader_buffers
// emitter, and the backend's four binding-point walks. It is its own bit and not part of // emitter, and the backend's four binding-point walks. It is its own bit and not part of
// bit 7's resource family for the reason every other split here has: a UBO/SSBO binding // bit 7's resource family for the reason every other split here has: a UBO/SSBO binding
+5 -5
View File
@@ -130,7 +130,7 @@ namespace MobileGL::MG_Pipe {
// caps adoption after Start; a later snapshot may only disarm it, because records already // caps adoption after Start; a later snapshot may only disarm it, because records already
// published without a wait cannot be taken back. // published without a wait cannot be taken back.
kCapRunAheadApply = 1ull << 10, kCapRunAheadApply = 1ull << 10,
// P11 B2 (docs/archive/contracts/CONTRACT-P11.md B2). THIS SESSION MAY RUN T0: the client asked for // P11 B2 (B2). THIS SESSION MAY RUN T0: the client asked for
// it in its Hello (LinkTerms.adoptTier = 0) on a shared-segment plane, the server's // it in its Hello (LinkTerms.adoptTier = 0) on a shared-segment plane, the server's
// allow switch is on, this platform has AHardwareBuffer, and the backend's POST // allow switch is on, this platform has AHardwareBuffer, and the backend's POST
// self-test of the sustained-lock pattern passed on its live context. Never set in the // self-test of the sustained-lock pattern passed on its live context. Never set in the
@@ -906,7 +906,7 @@ namespace MobileGL::MG_Pipe {
// 0, or Count for the Uniform class under kCapNeedsHostUboBytes (RESERVED, P8-F: 0 today; // 0, or Count for the Uniform class under kCapNeedsHostUboBytes (RESERVED, P8-F: 0 today;
// a range with nothing to ship carries an empty span, so the two arrays stay aligned). // a range with nothing to ship carries an empty span, so the two arrays stay aligned).
// MGPShaderBuffers::Class's three values, and the ONLY spelling of them (P5e, // MGPShaderBuffers::Class's three values, and the ONLY spelling of them (P5e,
// docs/archive/contracts/CONTRACT-P5E.md §1). The payload's comment has named them since P4a and // the contract §1). The payload's comment has named them since P4a and
// nothing numbered them, so the emitter and the applier were one literal each away from // nothing numbered them, so the emitter and the applier were one literal each away from
// disagreeing. Uniform is 0 so a zeroed record describes the uniform binding points, which // disagreeing. Uniform is 0 so a zeroed record describes the uniform binding points, which
// is the class every workload has. // is the class every workload has.
@@ -1520,8 +1520,8 @@ namespace MobileGL::MG_Pipe {
}; };
MGP_ASSERT_POD(MGPFlush, 8); MGP_ASSERT_POD(MGPFlush, 8);
// DAMAGE ON THE WIRE (eglSwapBuffersWithDamage, docs/archive/notes/anland/plan-ahb-dmabuf.md // DAMAGE ON THE WIRE (eglSwapBuffersWithDamage, item 5). At most kMGPMaxDamageRects
// item 5). At most kMGPMaxDamageRects rectangles, each x, y, width, height in GL window // rectangles, each x, y, width, height in GL window
// coordinates - origin at the bottom-left, as EGL hands them over. A count of 0 means the whole // coordinates - origin at the bottom-left, as EGL hands them over. A count of 0 means the whole
// surface, which is also what every record from a client that sends no damage says. // surface, which is also what every record from a client that sends no damage says.
inline constexpr Uint32 kMGPMaxDamageRects = 16; inline constexpr Uint32 kMGPMaxDamageRects = 16;
@@ -1642,7 +1642,7 @@ namespace MobileGL::MG_Pipe {
MGP_ASSERT_POD(MGPCopyFromFramebuffer, 48); MGP_ASSERT_POD(MGPCopyFromFramebuffer, 48);
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
// P5c: the three appended rows (docs/archive/contracts/CONTRACT-P5C.md §5). APPENDED, never inserted: // P5c: the three appended rows (§5). APPENDED, never inserted:
// applier_reset is opcode 77, object_death opcode 78, and set_context_values (rv, §5.3) // applier_reset is opcode 77, object_death opcode 78, and set_context_values (rv, §5.3)
// opcode 79 - and no earlier opcode moved. // opcode 79 - and no earlier opcode moved.
// //
+1 -1
View File
@@ -3270,7 +3270,7 @@ namespace MobileGL::MG_Pipe {
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
// P5e's two entry points, DECLARED BY c0e (docs/archive/contracts/CONTRACT-P5E.md §1) // P5e's two entry points, DECLARED BY c0e (§1)
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
// //
// set_shader_buffers HAS ITS BODY (package sb); set_program_bindings still refuses by name // set_shader_buffers HAS ITS BODY (package sb); set_program_bindings still refuses by name
+3 -3
View File
@@ -11,7 +11,7 @@
#include "MGPipeRenderStateSpans.h" #include "MGPipeRenderStateSpans.h"
#include "MGPipeTypes.h" #include "MGPipeTypes.h"
// P5e (docs/archive/contracts/CONTRACT-P5E.md §2.1): MGPipeBarriered takes an MGPWireOp and reads the // P5e (§2.1): MGPipeBarriered takes an MGPWireOp and reads the
// generated wait-class and call-class tables, all of which live in MGPipe.h. It is a sibling // generated wait-class and call-class tables, all of which live in MGPipe.h. It is a sibling
// header in the same layer - MG_Pipe includes MG_Pipe - so the closure does not move. // header in the same layer - MG_Pipe includes MG_Pipe - so the closure does not move.
#include "MGPipe.h" #include "MGPipe.h"
@@ -90,7 +90,7 @@ namespace MobileGL::MG_Pipe {
const MGPSubRegion* regions); const MGPSubRegion* regions);
void (*TextureRespecify)(MGPipeHandle res, const MGPResourceDesc& desc, const MGPRespecifiedLevel* level); void (*TextureRespecify)(MGPipeHandle res, const MGPResourceDesc& desc, const MGPRespecifiedLevel* level);
void (*TextureDestroy)(MGPipeHandle res); void (*TextureDestroy)(MGPipeHandle res);
// P11 B2 (T0, docs/archive/contracts/CONTRACT-P11.md B2): the two members a backend that can take a // P11 B2 (T0, B2): the two members a backend that can take a
// client's AHardwareBuffer as a store registers. Both null = this backend has no T0 and // client's AHardwareBuffer as a store registers. Both null = this backend has no T0 and
// every session it serves runs T2. Appended after the texture trio for the same reason. // every session it serves runs T2. Appended after the texture trio for the same reason.
// //
@@ -246,7 +246,7 @@ namespace MobileGL::MG_Pipe {
// DirectGLESBufferDrawProbe pair now pins from both sides. // DirectGLESBufferDrawProbe pair now pins from both sides.
Bool HasLiveHostWrites = false; Bool HasLiveHostWrites = false;
// SHARED IMAGES (docs/archive/notes/anland/plan-ahb-dmabuf.md). Nonzero: this // SHARED IMAGES. Nonzero: this
// texture's level-0 storage IS the server's shared image of this id (an EGLImage target), // texture's level-0 storage IS the server's shared image of this id (an EGLImage target),
// set by shared_image's Attach and cleared by the next respecify that redefines storage. // set by shared_image's Attach and cleared by the next respecify that redefines storage.
// The backend resolves the id at its texture sync (MG_Remote::Server::SharedImages::Find) // The backend resolves the id at its texture sync (MG_Remote::Server::SharedImages::Find)
+2 -2
View File
@@ -186,7 +186,7 @@ namespace MobileGL::MG_Pipe {
return false; return false;
} }
// ---- P5c (docs/archive/contracts/CONTRACT-P5C.md §5): the two control records, opcodes 77..78. // ---- P5c (§5): the two control records, opcodes 77..78.
// //
// Same hand-over shape as the P5b rows: the codec validates the record (a fixed-size // Same hand-over shape as the P5b rows: the codec validates the record (a fixed-size
// POD, no blob, no tail) and the SERVER'S sink does the work - OnApplierReset runs the // POD, no blob, no tail) and the SERVER'S sink does the work - OnApplierReset runs the
@@ -218,7 +218,7 @@ namespace MobileGL::MG_Pipe {
return false; return false;
} }
// ---- shared images, opcode 85 (docs/archive/notes/anland/plan-ahb-dmabuf.md). // ---- shared images, opcode 85.
// `seq` is the record's reply-slot id, which an Import's descriptor names on the aux // `seq` is the record's reply-slot id, which an Import's descriptor names on the aux
// socket. True fills `reply`; false is a DECLINED answer. // socket. True fills `reply`; false is a DECLINED answer.
virtual Bool OnSharedImage(const MGPSharedImageOp& op, Uint64 seq, MGPSharedImageReply& reply) { virtual Bool OnSharedImage(const MGPSharedImageOp& op, Uint64 seq, MGPSharedImageReply& reply) {
+1 -1
View File
@@ -379,7 +379,7 @@ inline constexpr MGPipeCallClass MGPipeCallClassFor(MGPWireOp op) {
: kCallClassCount; : kCallClassCount;
} }
// P5e (docs/archive/contracts/CONTRACT-P5E.md 2.2): THE WAIT CLASS OF EVERY OPCODE, indexed the same way. // P5e (2.2): THE WAIT CLASS OF EVERY OPCODE, indexed the same way.
// Index 0 is kWaitClassCount - never a real class - for the flags table's reason: the one // Index 0 is kWaitClassCount - never a real class - for the flags table's reason: the one
// caller that can pass an opcode this catalogue never produced is a decoder holding bytes off // caller that can pass an opcode this catalogue never produced is a decoder holding bytes off
// a stream, and it must reach its own Fatal{ProtocolCorruption} rather than a wait decision. // a stream, and it must reach its own Fatal{ProtocolCorruption} rather than a wait decision.
@@ -57,7 +57,7 @@ namespace MobileGL::MG_Remote::Client {
void ReleaseEGLSurface(EGLSurface surface) override; void ReleaseEGLSurface(EGLSurface surface) override;
void ReleaseEGLResources() override; void ReleaseEGLResources() override;
// ---- shared images (docs/archive/notes/anland/plan-ahb-dmabuf.md) ------------- // ---- shared images -------------
Bool AllocateSharedImage(Uint32 width, Uint32 height, Uint32 fourcc, Bool AllocateSharedImage(Uint32 width, Uint32 height, Uint32 fourcc,
MG_Backend::SharedImageExport* out) override; MG_Backend::SharedImageExport* out) override;
Bool ImportSharedImage(int fd, Uint32 width, Uint32 height, Uint32 fourcc, Uint64* outId) override; Bool ImportSharedImage(int fd, Uint32 width, Uint32 height, Uint32 fourcc, Uint64* outId) override;
+1 -1
View File
@@ -2916,7 +2916,7 @@ namespace MobileGL::MG_Remote::Client {
return m_transport; return m_transport;
} }
// ---- P11 B2: T0 (docs/archive/contracts/CONTRACT-P11.md B2) -------------------------------------------- // ---- P11 B2: T0 (B2) --------------------------------------------
namespace { namespace {
Uint64 T0Key(MG_Pipe::MGPipeHandle handle) { Uint64 T0Key(MG_Pipe::MGPipeHandle handle) {
+2 -2
View File
@@ -228,7 +228,7 @@ namespace MobileGL::MG_Remote::Client {
Int32* statusOut, Uint64* replySizeOut = nullptr, Bool wantReply = true, Int32* statusOut, Uint64* replySizeOut = nullptr, Bool wantReply = true,
Bool willReadReply = true); Bool willReadReply = true);
// ---- P11 B2: T0 (docs/archive/contracts/CONTRACT-P11.md B2) ------------------------------------ // ---- P11 B2: T0 (B2) ------------------------------------
// //
// Does this session adopt persistent stores through T0? Decided ONCE, lazily, at the first // Does this session adopt persistent stores through T0? Decided ONCE, lazily, at the first
// map_persistent - the first moment it matters, and one at which the server's first native // map_persistent - the first moment it matters, and one at which the server's first native
@@ -244,7 +244,7 @@ namespace MobileGL::MG_Remote::Client {
// adopts it as the store's mapping - or null on DECLINED (the store stays T2). // adopts it as the store's mapping - or null on DECLINED (the store stays T2).
void* AdoptPersistentT0(const MG_Pipe::MGPHandleOnly& handle, Uint64 size, const void* seed); void* AdoptPersistentT0(const MG_Pipe::MGPHandleOnly& handle, Uint64 size, const void* seed);
void* AdoptPersistentInProcess(const MG_Pipe::MGPHandleOnly& handle, Uint64 size, const void* seed); void* AdoptPersistentInProcess(const MG_Pipe::MGPHandleOnly& handle, Uint64 size, const void* seed);
// shared_image (docs/archive/notes/anland/plan-ahb-dmabuf.md): emits `op` and waits // shared_image: emits `op` and waits
// for its answer. `sendFd` >= 0 (an Import) is queued on the aux socket for the record's // for its answer. `sendFd` >= 0 (an Import) is queued on the aux socket for the record's
// seq BEFORE the record is published; `receivedFd` non-null (an Allocate) takes the // seq BEFORE the record is published; `receivedFd` non-null (an Allocate) takes the
// descriptor the server queued before its answer. False = DECLINED (the server's log says // descriptor the server queued before its answer. False = DECLINED (the server's log says
+1 -1
View File
@@ -584,7 +584,7 @@ namespace MobileGL::MG_Remote::Client {
// willReadReply IS TRUE AND THAT IS THE WHOLE POINT OF THE WINDOW: this record does // willReadReply IS TRUE AND THAT IS THE WHOLE POINT OF THE WINDOW: this record does
// not wait for its answer, and the drain above reads it later. A P12 no-reply bit // not wait for its answer, and the drain above reads it later. A P12 no-reply bit
// keyed on wantReply would tell the server to skip the very answer this row comes // keyed on wantReply would tell the server to skip the very answer this row comes
// back for (docs/.../p12/CREATE-WINDOW-MEASURED.md section 7). // back for.
const Uint64 seq = const Uint64 seq =
session.EmitAndWaitTails(MGPWireOp::ResourceCreate, payload, sizeof(*payload), nullptr, 0, nullptr, 0, session.EmitAndWaitTails(MGPWireOp::ResourceCreate, payload, sizeof(*payload), nullptr, 0, nullptr, 0,
&status, nullptr, /*wantReply=*/false, /*willReadReply=*/true); &status, nullptr, /*wantReply=*/false, /*willReadReply=*/true);
+1 -1
View File
@@ -320,7 +320,7 @@ namespace MobileGL::MG_Remote::Server {
return true; return true;
} }
// ---- P5c ct (docs/archive/contracts/CONTRACT-P5C.md §5) ------------------------------------------ // ---- P5c ct (§5) ------------------------------------------
// //
// TWO CONTROL RECORDS, NO BACKEND TABLE AND NO DECLINE ARM. Neither body consults // TWO CONTROL RECORDS, NO BACKEND TABLE AND NO DECLINE ARM. Neither body consults
// Table(): the reset belongs to the applier this process owns, and the death release // Table(): the reset belongs to the applier this process owns, and the death release
+2 -2
View File
@@ -151,7 +151,7 @@ namespace MobileGL::MG_Remote::Server {
void ReleaseQueries(); void ReleaseQueries();
Bool OnPresent(const MG_Pipe::MGPPresent& present) override; Bool OnPresent(const MG_Pipe::MGPPresent& present) override;
// ---- P5c ct (docs/archive/contracts/CONTRACT-P5C.md §5): the two control records ---------------- // ---- P5c ct (§5): the two control records ----------------
// //
// REAL BODIES FROM THE DAY THE ROWS EXIST, not the P5b stub shape: the rows were // REAL BODIES FROM THE DAY THE ROWS EXIST, not the P5b stub shape: the rows were
// appended by the same package that lands these bodies, so there is no window in // appended by the same package that lands these bodies, so there is no window in
@@ -177,7 +177,7 @@ namespace MobileGL::MG_Remote::Server {
// rather than a silent bind. Token 0 (the release) is always legal. // rather than a silent bind. Token 0 (the release) is always legal.
Bool OnBindContext(const MG_Pipe::MGPBindContext& bind) override; Bool OnBindContext(const MG_Pipe::MGPBindContext& bind) override;
// shared_image, opcode 85 (docs/archive/notes/anland/plan-ahb-dmabuf.md): the // shared_image, opcode 85: the
// session's image table (allocate / import / release) and the two GL-ordered operations // session's image table (allocate / import / release) and the two GL-ordered operations
// (present the default framebuffer into an image, attach an image to a texture). // (present the default framebuffer into an image, attach an image to a texture).
Bool OnSharedImage(const MG_Pipe::MGPSharedImageOp& op, Uint64 seq, Bool OnSharedImage(const MG_Pipe::MGPSharedImageOp& op, Uint64 seq,
+1 -1
View File
@@ -331,7 +331,7 @@ namespace {
// P12 (D8). A FORKED SESSION CHILD DIES WITH ITS SUPERVISOR. The child used to outlive a supervisor // P12 (D8). A FORKED SESSION CHILD DIES WITH ITS SUPERVISOR. The child used to outlive a supervisor
// that was killed (MobileGLServerService.onDestroy destroys only the supervisor), holding its client // that was killed (MobileGLServerService.onDestroy destroys only the supervisor), holding its client
// and its GPU context until that client went away (docs/archive/notes/p65/code-review-findings.md:9). With the // and its GPU context until that client went away. With the
// parent-death signal the kernel SIGKILLs it the moment the supervisor goes - and the getppid() // parent-death signal the kernel SIGKILLs it the moment the supervisor goes - and the getppid()
// check closes the race of a supervisor that died between fork() and the prctl. Linux (and Android) // check closes the race of a supervisor that died between fork() and the prctl. Linux (and Android)
// only; the signal fires when the THREAD that forked exits, and both fork sites run on the // only; the signal fires when the THREAD that forked exits, and both fork sites run on the
+1 -1
View File
@@ -1105,7 +1105,7 @@ namespace MobileGL::MG_Remote::Server {
std::memory_order_relaxed); std::memory_order_relaxed);
} }
// ---- P11 B2: T0 (docs/archive/contracts/CONTRACT-P11.md B2) ------------------------------------------ // ---- P11 B2: T0 (B2) ------------------------------------------
namespace { namespace {
// THE POST VERDICT IS THE PROCESS'S, like DriverPost's: the driver and the device do not // THE POST VERDICT IS THE PROCESS'S, like DriverPost's: the driver and the device do not
+2 -2
View File
@@ -246,7 +246,7 @@ namespace MobileGL::MG_Remote::Server {
Transport::RoleMemorySample SampleMemory() const; Transport::RoleMemorySample SampleMemory() const;
void LogMemory(const char* phase) const; void LogMemory(const char* phase) const;
// ---- P11 B2: T0 (docs/archive/contracts/CONTRACT-P11.md B2) -------------------------------------- // ---- P11 B2: T0 (B2) --------------------------------------
// //
// The client's Hello asked T0 (LinkTerms.adoptTier = 0 over shared segments). // The client's Hello asked T0 (LinkTerms.adoptTier = 0 over shared segments).
Bool AdoptT0Asked() const { return m_adoptT0Asked; } Bool AdoptT0Asked() const { return m_adoptT0Asked; }
@@ -281,7 +281,7 @@ namespace MobileGL::MG_Remote::Server {
Bool AdoptT0Quiet() const { return m_adoptT0Quiet; } Bool AdoptT0Quiet() const { return m_adoptT0Quiet; }
AdoptInbox& T0Inbox() { return m_adoptInbox; } AdoptInbox& T0Inbox() { return m_adoptInbox; }
// ---- shared images (docs/archive/notes/anland/plan-ahb-dmabuf.md) ------------- // ---- shared images -------------
// The images this session allocated or imported and has not released; emptied when the // The images this session allocated or imported and has not released; emptied when the
// session closes. The control transport is where an allocation's descriptor goes out. // session closes. The control transport is where an allocation's descriptor goes out.
SharedImages::SessionHolder& SharedImageHolder() { return m_sharedImages; } SharedImages::SessionHolder& SharedImageHolder() { return m_sharedImages; }
@@ -8,7 +8,7 @@
// SHARED IMAGES: colour buffers the server allocates and hands to clients as dma-buf descriptors, // SHARED IMAGES: colour buffers the server allocates and hands to clients as dma-buf descriptors,
// so a frame one client renders can be sampled by another (a Wayland window by its compositor) // so a frame one client renders can be sampled by another (a Wayland window by its compositor)
// without leaving GPU memory (docs/archive/notes/anland/plan-ahb-dmabuf.md). // without leaving GPU memory.
// //
// THE SERVER IS THE ALLOCATOR AND THE ONLY IMPORTER. An image is an AHardwareBuffer; what leaves // THE SERVER IS THE ALLOCATOR AND THE ONLY IMPORTER. An image is an AHardwareBuffer; what leaves
// the process is a duplicate of its first native-handle descriptor, which on every Android kernel // the process is a duplicate of its first native-handle descriptor, which on every Android kernel
@@ -174,7 +174,7 @@ namespace MobileGL::MG_Remote::Server::SharedImages {
// Live images, for tests and diagnostics. // Live images, for tests and diagnostics.
SizeT LiveCount(); SizeT LiveCount();
// ---- synchronisation (docs/archive/notes/anland/plan-ahb-dmabuf.md) --------------- // ---- synchronisation ---------------
// //
// THE SERVER ORDERS THE IMAGE BETWEEN ITS SESSIONS, the way a kernel's implicit sync would: // THE SERVER ORDERS THE IMAGE BETWEEN ITS SESSIONS, the way a kernel's implicit sync would:
// a writer publishes the fence of its write and moves on; a reader that finds the generation // a writer publishes the fence of its write and moves on; a reader that finds the generation
+11 -11
View File
@@ -722,7 +722,7 @@ namespace MobileGL::MG_Remote::Wire {
} }
case MGPWireOp::SetProgramBindings: { case MGPWireOp::SetProgramBindings: {
// THREE TAILS, THREE COUNTS, THREE INDEX SPACES (P5e, // THREE TAILS, THREE COUNTS, THREE INDEX SPACES (P5e,
// docs/archive/contracts/CONTRACT-P5E.md §1): Int32[BlockBindingCount] in GL uniform-block index // the contract §1): Int32[BlockBindingCount] in GL uniform-block index
// order, MGPProgramSamplerUnit[SamplerUnitCount] ascending by Location, and // order, MGPProgramSamplerUnit[SamplerUnitCount] ascending by Location, and
// MGPProgramStorageOverride[StorageOverrideCount] whose Name is a host span staged // MGPProgramStorageOverride[StorageOverrideCount] whose Name is a host span staged
// whole - the override map is name-keyed by design. // whole - the override map is name-keyed by design.
@@ -2071,7 +2071,7 @@ namespace MobileGL::MG_Remote::Wire {
return true; return true;
case MGPWireOp::SetShaderBuffers: { case MGPWireOp::SetShaderBuffers: {
// P5e (sb, docs/archive/contracts/CONTRACT-P5E.md §5.6): THE APPLIER ENTRY POINT EXISTS NOW and // P5e (sb §5.6): THE APPLIER ENTRY POINT EXISTS NOW and
// this is the row's sink. The paragraph that stood here said "no applier entry // this is the row's sink. The paragraph that stood here said "no applier entry
// point exists, and P5 does not invent one: the call is on BRIEF §4's exclusion // point exists, and P5 does not invent one: the call is on BRIEF §4's exclusion
// list" - true for the whole of P5 through P5d, and withdrawn by the phase whose // list" - true for the whole of P5 through P5d, and withdrawn by the phase whose
@@ -2108,7 +2108,7 @@ namespace MobileGL::MG_Remote::Wire {
return false; return false;
case MGPWireOp::SetProgramBindings: { case MGPWireOp::SetProgramBindings: {
// P5e, opcode 80 (docs/archive/contracts/CONTRACT-P5E.md §1). c0e wrote the shape check and left // P5e, opcode 80 (§1). c0e wrote the shape check and left
// the arm declining; PACKAGE pg COMPLETES IT. What the record needs before its // the arm declining; PACKAGE pg COMPLETES IT. What the record needs before its
// consumer sees it is its shape - the three declared counts against their bounds // consumer sees it is its shape - the three declared counts against their bounds
// and the three-tail arithmetic, both of which MGPipeWireRecordLayout above has // and the three-tail arithmetic, both of which MGPipeWireRecordLayout above has
@@ -2268,7 +2268,7 @@ namespace MobileGL::MG_Remote::Wire {
case MGPWireOp::ResourceSubDataComplete: case MGPWireOp::ResourceSubDataComplete:
// RETIRED (P9 W2). It was to be the forward terminator of a SERVER-initiated texture // RETIRED (P9 W2). It was to be the forward terminator of a SERVER-initiated texture
// pull (section 7.1), and no such pull exists: a re-mint reads the GPU level and the // pull (section 7.1), and no such pull exists: a re-mint reads the GPU level and the
// server's own staged store (docs/archive/notes/p9/W2-REMINT.md). The row stays because opcodes // server's own staged store. The row stays because opcodes
// only ever grow; no client emits it and a record that claims it is declined. // only ever grow; no client emits it and a record that claims it is declined.
return false; return false;
@@ -2436,12 +2436,12 @@ namespace MobileGL::MG_Remote::Wire {
return m_verbs != nullptr && return m_verbs != nullptr &&
m_verbs->OnCopyFramebufferToTexture(*static_cast<const MGPCopyFromFramebuffer*>(payload)); m_verbs->OnCopyFramebufferToTexture(*static_cast<const MGPCopyFromFramebuffer*>(payload));
// ---- P5c's two control records, opcodes 77..78 (docs/archive/contracts/CONTRACT-P5C.md §5) -------- // ---- P5c's two control records, opcodes 77..78 (§5) --------
// //
// Fixed-size PODs the bounds gate has already proved; neither carries a blob, a tail // Fixed-size PODs the bounds gate has already proved; neither carries a blob, a tail
// or a reply, so each arm hands over and stops. ObjectDeath's null-handle refusal is // or a reply, so each arm hands over and stops. ObjectDeath's null-handle refusal is
// the sink's, not the codec's: the codec proves SHAPES, and "the client emits nothing // the sink's, not the codec's: the codec proves SHAPES, and "the client emits nothing
// for an object that never crossed" (§5.2) is a contract fact about the peer. // for an object that never crossed" (§5.2) is a contract fact about the peer.
case MGPWireOp::ApplierReset: case MGPWireOp::ApplierReset:
return m_verbs != nullptr && m_verbs->OnApplierReset(*static_cast<const MGPApplierReset*>(payload)); return m_verbs != nullptr && m_verbs->OnApplierReset(*static_cast<const MGPApplierReset*>(payload));
@@ -2457,7 +2457,7 @@ namespace MobileGL::MG_Remote::Wire {
case MGPWireOp::BindContext: case MGPWireOp::BindContext:
return m_verbs != nullptr && m_verbs->OnBindContext(*static_cast<const MGPBindContext*>(payload)); return m_verbs != nullptr && m_verbs->OnBindContext(*static_cast<const MGPBindContext*>(payload));
// ---- shared images (docs/archive/notes/anland/plan-ahb-dmabuf.md), opcode 85. // ---- shared images, opcode 85.
// //
// A fixed-size POD; every operation is answered, and a refusal is an answer (DECLINED, // A fixed-size POD; every operation is answered, and a refusal is an answer (DECLINED,
// the sink logs why) rather than a fault: an import of a descriptor this server never // the sink logs why) rather than a fault: an import of a descriptor this server never
@@ -75,7 +75,7 @@ namespace MobileGL::MG_State::GLState {
void NoteBufferChanged() { ++m_anyBufferChangeGeneration; } void NoteBufferChanged() { ++m_anyBufferChangeGeneration; }
Uint64 GetAnyBufferChangeGeneration() const { return m_anyBufferChangeGeneration; } Uint64 GetAnyBufferChangeGeneration() const { return m_anyBufferChangeGeneration; }
// P5e (sb, docs/archive/contracts/CONTRACT-P5E.md §1, §5.6). "DID ANY INDEXED BINDING POINT OF THIS // P5e (sb §1, §5.6). "DID ANY INDEXED BINDING POINT OF THIS
// TARGET MOVE" - one counter per BufferBindPointTargets entry, and it is the P4b hole // TARGET MOVE" - one counter per BufferBindPointTargets entry, and it is the P4b hole
// closed rather than a new convenience. // closed rather than a new convenience.
// //
+1 -1
View File
@@ -300,7 +300,7 @@ TEST_F(FieldOwnershipTest, VerbBoundaryOpsCoverEveryVerbShapedCall) {
EXPECT_EQ(MGPipeVerbForWireOp(MGPWireOp::ResumeStreamOutput), MGPipeVerb::ResumeTransformFeedback); EXPECT_EQ(MGPipeVerbForWireOp(MGPWireOp::ResumeStreamOutput), MGPipeVerb::ResumeTransformFeedback);
EXPECT_EQ(MGPipeVerbForWireOp(MGPWireOp::GenerateMipmap), MGPipeVerb::GenerateMipmap); EXPECT_EQ(MGPipeVerbForWireOp(MGPWireOp::GenerateMipmap), MGPipeVerb::GenerateMipmap);
EXPECT_EQ(MGPipeVerbForWireOp(MGPWireOp::GetTextureImage), MGPipeVerb::GetTextureImage); EXPECT_EQ(MGPipeVerbForWireOp(MGPWireOp::GetTextureImage), MGPipeVerb::GetTextureImage);
// P5b (docs/archive/contracts/CONTRACT-P5B.md): the renamed boundary the file left to "the phase that // P5b: the renamed boundary the file left to "the phase that
// emits it" - resource_copy_region is glCopyImageSubData only - and the five appended verbs, // emits it" - resource_copy_region is glCopyImageSubData only - and the five appended verbs,
// each stamped as the GLFunctionsTable verb it reproduces. copy_framebuffer_to_texture also // each stamped as the GLFunctionsTable verb it reproduces. copy_framebuffer_to_texture also
// carries glCopyTexSubImage2D and stamps CopyTexImage2D for both: one kBlitOrCopy mask. // carries glCopyTexSubImage2D and stamps CopyTexImage2D for both: one kBlitOrCopy mask.
+16 -16
View File
@@ -137,10 +137,10 @@ TEST(PipeCatalogue, GeneratedTablesHoldTheWholeCatalogue) {
EXPECT_EQ(kMGPipeContextCallCount, kMGPipeCallCount - ClassCount<kScreen>()); EXPECT_EQ(kMGPipeContextCallCount, kMGPipeCallCount - ClassCount<kScreen>());
// The per-class counts PipeCalls.def documents in its header. // The per-class counts PipeCalls.def documents in its header.
// kScreen is 11 + P5c's applier_reset (docs/archive/contracts/CONTRACT-P5C.md §5.1); kCtxObject is // kScreen is 11 + P5c's applier_reset (§5.1); kCtxObject is
// 9 + P5c's object_death (§5.2), the framebuffer family's first wire delete opcode. // 9 + P5c's object_death (§5.2), the framebuffer family's first wire delete opcode.
// kCtxState is 17 + P5c rv's set_context_values (§5.3), the residual-value record, + P5e's // kCtxState is 17 + P5c rv's set_context_values (§5.3), the residual-value record, + P5e's
// set_program_bindings (docs/archive/contracts/CONTRACT-P5E.md §1), the post-link binding record. // set_program_bindings (§1), the post-link binding record.
// + P14 S1's bind_context (docs/Disaggregated/design/11-state-ownership.md), the in-band // + P14 S1's bind_context (docs/Disaggregated/design/11-state-ownership.md), the in-band
// context binding - a kScreen row for applier_reset's reason: a context switch is a // context binding - a kScreen row for applier_reset's reason: a context switch is a
// whole-session edge, not a context-family verb. // whole-session edge, not a context-family verb.
@@ -148,9 +148,9 @@ TEST(PipeCatalogue, GeneratedTablesHoldTheWholeCatalogue) {
EXPECT_EQ(ClassCount<kCtxQuery>(), 8u); EXPECT_EQ(ClassCount<kCtxQuery>(), 8u);
EXPECT_EQ(ClassCount<kCtxCso>(), 13u); EXPECT_EQ(ClassCount<kCtxCso>(), 13u);
EXPECT_EQ(ClassCount<kCtxState>(), 19u); EXPECT_EQ(ClassCount<kCtxState>(), 19u);
// + P9's get_texture_image_to_buffer (docs/archive/contracts/CONTRACT-P9.md §1), beside get_texture_image. // + P9's get_texture_image_to_buffer (§1), beside get_texture_image.
EXPECT_EQ(ClassCount<kCtxObject>(), 11u); EXPECT_EQ(ClassCount<kCtxObject>(), 11u);
// 13 + the five P5b-appended verbs (docs/archive/contracts/CONTRACT-P5B.md): bind_shader_image, // 13 + the five P5b-appended verbs: bind_shader_image,
// patch_parameter, bind_stream_output, set_storage_block_binding, // patch_parameter, bind_stream_output, set_storage_block_binding,
// copy_framebuffer_to_texture; + delete_stream_output; + P9's read_pixels_to_buffer. // copy_framebuffer_to_texture; + delete_stream_output; + P9's read_pixels_to_buffer.
EXPECT_EQ(ClassCount<kCtxVerb>(), 20u); EXPECT_EQ(ClassCount<kCtxVerb>(), 20u);
@@ -588,7 +588,7 @@ TEST(PipeCatalogue, LateArrivalsAreAppendedWithoutRenumbering) {
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::QueryTimestamp), 69); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::QueryTimestamp), 69);
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::QueryCounter), 70); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::QueryCounter), 70);
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::FenceWaitServer), 71); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::FenceWaitServer), 71);
// P5b (docs/archive/contracts/CONTRACT-P5B.md) appended five verbs AFTER P0's three late arrivals, by // P5b appended five verbs AFTER P0's three late arrivals, by
// the same rule: opcodes 72..76, and nothing before them moved. The five are pinned by // the same rule: opcodes 72..76, and nothing before them moved. The five are pinned by
// VALUE, because the pin is the protocol - a row inserted ahead of one would silently // VALUE, because the pin is the protocol - a row inserted ahead of one would silently
// re-point every record a P5b package emits at the wrong arm. // re-point every record a P5b package emits at the wrong arm.
@@ -597,7 +597,7 @@ TEST(PipeCatalogue, LateArrivalsAreAppendedWithoutRenumbering) {
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::BindStreamOutput), 74); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::BindStreamOutput), 74);
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::SetStorageBlockBinding), 75); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::SetStorageBlockBinding), 75);
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::CopyFramebufferToTexture), 76); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::CopyFramebufferToTexture), 76);
// P5c (docs/archive/contracts/CONTRACT-P5C.md §5) appended the two control records AFTER P5b's five, by // P5c (§5) appended the two control records AFTER P5b's five, by
// the same rule: opcodes 77..78, and nothing before them moved. applier_reset is a kScreen // the same rule: opcodes 77..78, and nothing before them moved. applier_reset is a kScreen
// row (a make-current is a whole-server edge, exactly as FenceWaitServer is a screen call) // row (a make-current is a whole-server edge, exactly as FenceWaitServer is a screen call)
// and object_death a kCtxObject one; both carry no blob, no reply and no tail. // and object_death a kCtxObject one; both carry no blob, no reply and no tail.
@@ -608,13 +608,13 @@ TEST(PipeCatalogue, LateArrivalsAreAppendedWithoutRenumbering) {
// - fixed POD, no blob, no tail, no reply - with an MGPipeApply* entry point, which the two // - fixed POD, no blob, no tail, no reply - with an MGPipeApply* entry point, which the two
// control records deliberately do not have. // control records deliberately do not have.
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::SetContextValues), 79); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::SetContextValues), 79);
// P5e (docs/archive/contracts/CONTRACT-P5E.md §1) appended ONE more, by the same rule: opcode 80, and // P5e (§1) appended ONE more, by the same rule: opcode 80, and
// nothing before it moved. set_program_bindings is a kCtxState row with THREE tails and a // nothing before it moved. set_program_bindings is a kCtxState row with THREE tails and a
// host span in the third; it lands with a null route and a sink that refuses it by name, // host span in the third; it lands with a null route and a sink that refuses it by name,
// exactly as set_shader_buffers has sat catalogued-and-dead since P4a. // exactly as set_shader_buffers has sat catalogued-and-dead since P4a.
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::SetProgramBindings), 80); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::SetProgramBindings), 80);
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::DeleteStreamOutput), 81); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::DeleteStreamOutput), 81);
// P9 (docs/archive/contracts/CONTRACT-P9.md §1) appended the two pack-buffer readbacks, by the same rule: // P9 (§1) appended the two pack-buffer readbacks, by the same rule:
// opcodes 82..83, one payload, no flag at all - no reply slot, no blob, no tail. // opcodes 82..83, one payload, no flag at all - no reply slot, no blob, no tail.
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::ReadPixelsToBuffer), 82); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::ReadPixelsToBuffer), 82);
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::GetTextureImageToBuffer), 83); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::GetTextureImageToBuffer), 83);
@@ -623,7 +623,7 @@ TEST(PipeCatalogue, LateArrivalsAreAppendedWithoutRenumbering) {
// kScreen control record with the applier_reset shape - one POD, no blob, no tail, no reply // kScreen control record with the applier_reset shape - one POD, no blob, no tail, no reply
// and no MGPipeApply* entry point - so the row beside it is pinned the same way. // and no MGPipeApply* entry point - so the row beside it is pinned the same way.
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::BindContext), 84); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::BindContext), 84);
// Shared images (docs/archive/notes/anland/plan-ahb-dmabuf.md) appended opcode 85 by the // Shared images appended opcode 85 by the
// same rule: a kScreen row with a reply slot - every operation is answered. // same rule: a kScreen row with a reply slot - every operation is answered.
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::SharedImage), 85); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::SharedImage), 85);
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::kOpCount), 86); EXPECT_EQ(static_cast<Uint16>(MGPWireOp::kOpCount), 86);
@@ -729,7 +729,7 @@ TEST(PipeCatalogue, LateArrivalsAreAppendedWithoutRenumbering) {
EXPECT_EQ(kMGPipeClearValueClassUint + 1, kMGPipeClearValueClassCount); EXPECT_EQ(kMGPipeClearValueClassUint + 1, kMGPipeClearValueClassCount);
} }
// ---- P5e: the wait-class column (docs/archive/contracts/CONTRACT-P5E.md §2.2) -------------------------- // ---- P5e: the wait-class column (§2.2) --------------------------
// //
// THE POINT OF THIS CASE IS THAT IT DOES NOT READ PipeCalls.def. Every other statement about // THE POINT OF THIS CASE IS THAT IT DOES NOT READ PipeCalls.def. Every other statement about
// the column - the generated table, the two gates in gen_pipe.py, the static_asserts in // the column - the generated table, the two gates in gen_pipe.py, the static_asserts in
@@ -1044,14 +1044,14 @@ TEST(PipeCatalogue, FloatVectorsCompareBitwise) {
// a cache that read the padding would mint a fresh CSO per call and the verify lane would // a cache that read the padding would mint a fresh CSO per call and the verify lane would
// abort at random. // abort at random.
TEST(PipeCatalogue, SixValueStructsHaveFieldLists) { TEST(PipeCatalogue, SixValueStructsHaveFieldLists) {
// 72 through P5; P5b appended five call payloads (docs/archive/contracts/CONTRACT-P5B.md: MGPImageBind, // 72 through P5; P5b appended five call payloads (the contract: MGPImageBind,
// MGPPatchParameter, MGPStreamOutputBind, MGPStorageBlockBinding, MGPCopyFromFramebuffer), // MGPPatchParameter, MGPStreamOutputBind, MGPStorageBlockBinding, MGPCopyFromFramebuffer),
// each with its own field list, so the comparator sees every one of them: 77. P5c appended // each with its own field list, so the comparator sees every one of them: 77. P5c appended
// applier_reset's MGPApplierReset (CONTRACT-P5C.md §5.1) - object_death reuses // applier_reset's MGPApplierReset (CONTRACT-P5C.md §5.1) - object_death reuses
// MGPHandleOnly, which has had a list since P0 - and rv added set_context_values' // MGPHandleOnly, which has had a list since P0 - and rv added set_context_values'
// MGPContextValues (§5.3): 79. P5e appended set_program_bindings' MGPProgramBindings AND // MGPContextValues (§5.3): 79. P5e appended set_program_bindings' MGPProgramBindings AND
// the two TAIL ELEMENT types beside it, MGPProgramSamplerUnit and MGPProgramStorageOverride // the two TAIL ELEMENT types beside it, MGPProgramSamplerUnit and MGPProgramStorageOverride
// (docs/archive/contracts/CONTRACT-P5E.md §1) - the tails are listed for the same reason MGPBufferRange // (§1) - the tails are listed for the same reason MGPBufferRange
// and MGPVertexAttribWire are: the comparator has to see INTO an element whose members // and MGPVertexAttribWire are: the comparator has to see INTO an element whose members
// include an MGHostSpan and a pad word, or it would memcmp the padding: 82. P9 appended the // include an MGHostSpan and a pad word, or it would memcmp the padding: 82. P9 appended the
// pack-buffer readbacks' one payload, MGPReadbackToBuffer (CONTRACT-P9.md §1): 83. P14 S1 // pack-buffer readbacks' one payload, MGPReadbackToBuffer (CONTRACT-P9.md §1): 83. P14 S1
@@ -1138,7 +1138,7 @@ TEST(PipeCatalogue, PipelineSubsetMembersArePinned) {
// than a claim, since the static_assert beside kMGPipeCallbackCount only proves the two agree. // than a claim, since the static_assert beside kMGPipeCallbackCount only proves the two agree.
// P9 took two more, neither of which ever had a producer: W2 deleted OnTexturePullRequest (a // P9 took two more, neither of which ever had a producer: W2 deleted OnTexturePullRequest (a
// texture re-mint never needs the client's texels - the server reads the GPU level and its own // texture re-mint never needs the client's texels - the server reads the GPU level and its own
// staged store, docs/archive/notes/p9/W2-REMINT.md), and W3 deleted OnLog (the server's log lines are LogLine // staged store), and W3 deleted OnLog (the server's log lines are LogLine
// frames on the control plane, MG_Remote/Transport/LogForward.h, not reverse records). // frames on the control plane, MG_Remote/Transport/LogForward.h, not reverse records).
// //
// THE CASE NAME STAYS "…HasTenCallbacks" DELIBERATELY. G2/G14 say the ctest name set only ever // THE CASE NAME STAYS "…HasTenCallbacks" DELIBERATELY. G2/G14 say the ctest name set only ever
@@ -1457,18 +1457,18 @@ TEST(PipeCatalogue, EveryUnmigratedEmulationIsNamedOnce) {
// new stall class the design admitted. It went because the stall class did: under a transport // new stall class the design admitted. It went because the stall class did: under a transport
// the re-mint is the server's own (RequireImageBindableStorageByHandle reads the GPU level and // the re-mint is the server's own (RequireImageBindableStorageByHandle reads the GPU level and
// replays the staged store), the frontend arm that carried the marker is monolith-only, and no // replays the staged store), the frontend arm that carried the marker is monolith-only, and no
// pull protocol or ResourceSubDataComplete terminator exists (docs/archive/notes/p9/W2-REMINT.md). // pull protocol or ResourceSubDataComplete terminator exists.
// //
// AND THE LIST HAD DRIFTED BY ONE UNTIL P8-B. The tree carried a sixth name this list never // AND THE LIST HAD DRIFTED BY ONE UNTIL P8-B. The tree carried a sixth name this list never
// had: "generate-mipmap-cpu-filter", the split arm's RGB16F/RGB32F refusal in // had: "generate-mipmap-cpu-filter", the split arm's RGB16F/RGB32F refusal in
// GenerateMipmapByRecord. P8-B2 retired it (the server filters its own level, // GenerateMipmapByRecord. P8-B2 retired it (the server filters its own level,
// GenerateThreeChannelFloatMipmapOnServer), and P8-B1 retired the split arm's two // GenerateThreeChannelFloatMipmapOnServer), and P8-B1 retired the split arm's two
// "generate-mipmap-storage" sites (the record's plan is the window). Every name left is on a // "generate-mipmap-storage" sites (the record's plan is the window). Every name left is on a
// MONOLITH arm - the split arms no longer reach an unmigrated emulation (docs/archive/notes/p8/B.md). // MONOLITH arm - the split arms no longer reach an unmigrated emulation.
// //
// THREE, NOT FOUR (P8-SE). "copy-image-shadow-mirror" sat after the mirror's own // THREE, NOT FOUR (P8-SE). "copy-image-shadow-mirror" sat after the mirror's own
// `Transport != Monolith` return, so no transport ever reached it and on monolith it was a // `Transport != Monolith` return, so no transport ever reached it and on monolith it was a
// no-op; the call and the name went together (docs/archive/notes/p8/SE.md). // no-op; the call and the name went together.
// //
// NONE (P13 W6). "get-tex-image-shadow" sat in GetTexImageViaShadowConversion, the monolith // NONE (P13 W6). "get-tex-image-shadow" sat in GetTexImageViaShadowConversion, the monolith
// frontend arm's shadow readback, and the two mipmap names in that arm's storage grow and CPU // frontend arm's shadow readback, and the two mipmap names in that arm's storage grow and CPU
@@ -7,7 +7,7 @@
// End of Source File Header // End of Source File Header
// P5e's set_shader_buffers - the INDEXED BUFFER BINDING POINTS - on both sides of the call // P5e's set_shader_buffers - the INDEXED BUFFER BINDING POINTS - on both sides of the call
// (docs/archive/contracts/CONTRACT-P5E.md §5.6, rulings 10 and 11; package sb). // (§5.6, rulings 10 and 11; package sb).
// //
// WHAT THIS SUITE IS FOR. Three properties of this family are invisible in a picture and are // WHAT THIS SUITE IS FOR. Three properties of this family are invisible in a picture and are
// exactly what an optimisation or a merge deletes: // exactly what an optimisation or a merge deletes:
+1 -1
View File
@@ -352,7 +352,7 @@ namespace {
// the loop above, because "these three, together" is the phase's own scope statement. // the loop above, because "these three, together" is the phase's own scope statement.
// //
// set_stream_output_targets stays UNEMITTED for the whole of P5e (XFB is lockstep by // set_stream_output_targets stays UNEMITTED for the whole of P5e (XFB is lockstep by
// escalation, docs/archive/contracts/CONTRACT-P5E.md §5.7) and still names the subsystem, for the // escalation, the contract §5.7) and still names the subsystem, for the
// same reason: the bit answers "which A/B switch owns this family's legacy arm", not // same reason: the bit answers "which A/B switch owns this family's legacy arm", not
// "is there a record on the wire for me today". // "is there a record on the wire for me today".
EXPECT_EQ(MGPipeSubsystemForDirty(MGPipeDirty::NewConstBuffers), kMGPipeSubsystemBufferBindings); EXPECT_EQ(MGPipeSubsystemForDirty(MGPipeDirty::NewConstBuffers), kMGPipeSubsystemBufferBindings);
+1 -1
View File
@@ -568,7 +568,7 @@ namespace {
} }
// P8-D: the Magma wire arm's indirect-draw bracket. Its short names are what the create // P8-D: the Magma wire arm's indirect-draw bracket. Its short names are what the create
// fixtures' measurement (docs/archive/notes/p8/D.md) reads off the server's line, and its long names are // fixtures' measurement reads off the server's line, and its long names are
// what Harness/WireIndirectPeek.cpp's readers expect in the JSON dump. // what Harness/WireIndirectPeek.cpp's readers expect in the JSON dump.
TEST_F(PipeStatsTest, WireIndirectCountersPrintInTheirOwnBracket) { TEST_F(PipeStatsTest, WireIndirectCountersPrintInTheirOwnBracket) {
PS::AddCalls(PS::CallClass::WireIndirectNativeDraws, 3); PS::AddCalls(PS::CallClass::WireIndirectNativeDraws, 3);
+1 -1
View File
@@ -6,7 +6,7 @@
// SPDX-License-Identifier: LGPL-3.0-only // SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header // End of Source File Header
// P11 B2 (docs/archive/contracts/CONTRACT-P11.md B2). Server::AdoptInbox - T0's Offers matched to their // P11 B2 (B2). Server::AdoptInbox - T0's Offers matched to their
// map_persistent records BY SEQ, never by arrival order - over both aux channels the product has: // map_persistent records BY SEQ, never by arrival order - over both aux channels the product has:
// the in-process queue (inproc) and a real socket pair with SCM_RIGHTS (fork spawn / unix / fd:). // the in-process queue (inproc) and a real socket pair with SCM_RIGHTS (fork spawn / unix / fd:).
// //
@@ -6,7 +6,7 @@
// SPDX-License-Identifier: LGPL-3.0-only // SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header // End of Source File Header
// P11 A1 (docs/archive/contracts/CONTRACT-P11.md §1): MOBILEGL_IPC_ADOPT_TIER=0/1 ON A STREAM DATA PLANE. // P11 A1 (§1): MOBILEGL_IPC_ADOPT_TIER=0/1 ON A STREAM DATA PLANE.
// //
// Real servers on loopback TCP and forked peers (P12ServerRig.h), so the session is the product's // Real servers on loopback TCP and forked peers (P12ServerRig.h), so the session is the product's
// two-process tcp session and each side reads its OWN knob, as on the tcp lane: // two-process tcp session and each side reads its OWN knob, as on the tcp lane:
@@ -17,7 +17,7 @@
// EGL_EXT_image_dma_buf_import + _modifiers (dmabuf_capable), XRGB8888/ARGB8888 importable, // EGL_EXT_image_dma_buf_import + _modifiers (dmabuf_capable), XRGB8888/ARGB8888 importable,
// eglCreateImageKHR(EGL_LINUX_DMA_BUF_EXT) of a shared image's descriptor. // eglCreateImageKHR(EGL_LINUX_DMA_BUF_EXT) of a shared image's descriptor.
// //
// And the implicit-sync flush (docs/archive/notes/anland/plan-x11-gpu.md): the shared_image // And the implicit-sync flush: the shared_image
// Flush verb the client sends from glFlush is answered by the server. // Flush verb the client sends from glFlush is answered by the server.
// //
// Chrome's GPU process on the same kind of display (a GBM one) is the other dma-buf producer, and it // Chrome's GPU process on the same kind of display (a GBM one) is the other dma-buf producer, and it
+5 -5
View File
@@ -1128,7 +1128,7 @@ TEST_F(PipeWireCodecTest, UserIndexSpanExactlyAtSegmentEndReachesTheSink) {
} }
// ===================================================================================== // =====================================================================================
// P5b (docs/archive/contracts/CONTRACT-P5B.md): one round trip per row the four migration packages consume // P5b: one round trip per row the four migration packages consume
// ===================================================================================== // =====================================================================================
// //
// The shape is the one above: encode, pump one record through the ring and the decoder, and // The shape is the one above: encode, pump one record through the ring and the decoder, and
@@ -1335,7 +1335,7 @@ TEST_F(PipeWireCodecTest, BindStreamOutputReachesTheSink) {
} }
// ===================================================================================== // =====================================================================================
// P5c ct (docs/archive/contracts/CONTRACT-P5C.md §5): the two control records round-trip // P5c ct (§5): the two control records round-trip
// ===================================================================================== // =====================================================================================
// //
// Same shape as the P5b rows above: encode, pump, and assert the record reached the RIGHT // Same shape as the P5b rows above: encode, pump, and assert the record reached the RIGHT
@@ -1398,7 +1398,7 @@ TEST_F(PipeWireCodecTest, ObjectDeathReachesTheSinkWithItsHandleAndKind) {
} }
// ===================================================================================== // =====================================================================================
// P5c rv (docs/archive/contracts/CONTRACT-P5C.md §5.3): the residual-value record round-trips // P5c rv (§5.3): the residual-value record round-trips
// ===================================================================================== // =====================================================================================
// //
// Not a sink row: the decoder's arm runs the REAL applier (MGPipeApplySetContextValues), so // Not a sink row: the decoder's arm runs the REAL applier (MGPipeApplySetContextValues), so
@@ -1443,7 +1443,7 @@ TEST_F(PipeWireCodecTest, SetContextValuesRoundTripsIntoPipeInputs) {
} }
// ===================================================================================== // =====================================================================================
// P5b t2 (docs/archive/contracts/CONTRACT-P5B.md §2 t2). c0b's cases above round-trip each row once; these // P5b t2 (§2 t2). c0b's cases above round-trip each row once; these
// pin the fields t2's EMITTERS actually fill and the one ordering property the span family has. // pin the fields t2's EMITTERS actually fill and the one ordering property the span family has.
// ===================================================================================== // =====================================================================================
@@ -3271,7 +3271,7 @@ TEST(FenceWireRoundTrip, MissingConsumerDeclinesWithoutInventingASignaledAnswer)
} }
// ===================================================================================== // =====================================================================================
// P5c ct (docs/archive/contracts/CONTRACT-P5C.md §5): the two control records, through the REAL sink // P5c ct (§5): the two control records, through the REAL sink
// ===================================================================================== // =====================================================================================
// //
// The codec cases above pin the bytes and the dispatch with a recording sink; these pin what // The codec cases above pin the bytes and the dispatch with a recording sink; these pin what
@@ -6,7 +6,7 @@
// SPDX-License-Identifier: LGPL-3.0-only // SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header // End of Source File Header
// P11 B2 (docs/archive/contracts/CONTRACT-P11.md B2): T0'S PROTOCOL ON THE HOST, over a live inproc session. // P11 B2 (B2): T0'S PROTOCOL ON THE HOST, over a live inproc session.
// //
// A host has no AHardwareBuffer, so what these prove is the protocol, the negotiation and the // A host has no AHardwareBuffer, so what these prove is the protocol, the negotiation and the
// fallback - never GPU correctness, which is the device's (B2's device gates). Two halves: // fallback - never GPU correctness, which is the device's (B2's device gates). Two halves:
@@ -1559,7 +1559,7 @@ TEST(RemoteClientControls, ARefusedCreateUnlatchesItsObjectAndItsNextCreateBlock
// //
// THE ASSERTIONS BELOW ARE THEREFORE A DEBT, NOT A SPEC, and they are written to be LOUD about it: // THE ASSERTIONS BELOW ARE THEREFORE A DEBT, NOT A SPEC, and they are written to be LOUD about it:
// they pin today's numbers so that whoever lands the signal sees THIS case go red and knows the // they pin today's numbers so that whoever lands the signal sees THIS case go red and knows the
// repair started working. docs/archive/notes/p12/UNPUBLISH-GUARD-SIGNALS.md §4-§6 has the rest. // repair started working. The phase notes §4-§6 have the rest.
TEST(RemoteClientControls, DroppedApplierRecordsAreNotRepairedTodayAndThisCaseIsTheDebt) { TEST(RemoteClientControls, DroppedApplierRecordsAreNotRepairedTodayAndThisCaseIsTheDebt) {
const auto child = RunInChild([] { const auto child = RunInChild([] {
::setenv("MOBILEGL_PIPE_STATS", "1", 1); ::setenv("MOBILEGL_PIPE_STATS", "1", 1);
+3 -3
View File
@@ -387,7 +387,7 @@ TEST(RemoteEmitTable, SetSwapIntervalIsTheServerForwarderAndNotAFatal) {
#endif // MGTEST_HAVE_FORK #endif // MGTEST_HAVE_FORK
// ---- P5b package i1 (docs/archive/contracts/CONTRACT-P5B.md §2 i1) ------------------------------------- // ---- P5b package i1 (§2 i1) -------------------------------------
TEST(RemoteEmitTable, TheSevenI1SlotsAreClassBAndAreNotTheFatalThunk) { TEST(RemoteEmitTable, TheSevenI1SlotsAreClassBAndAreNotTheFatalThunk) {
// The census's five measured slots plus the two companions that share their rows. Named // The census's five measured slots plus the two companions that share their rows. Named
@@ -899,7 +899,7 @@ TEST(CapsMirrorTest, TheConsumerBlockDoesNotCollideWithTheFeatureBits) {
} }
// ===================================================================================== // =====================================================================================
// P5b d1: the draw family's record plan (docs/archive/contracts/CONTRACT-P5B.md §2 d1). These drive the // P5b d1: the draw family's record plan (§2 d1). These drive the
// PRODUCTION derivation the nineteen emitters call - PlanDrawInfo / PlanDrawRange / // PRODUCTION derivation the nineteen emitters call - PlanDrawInfo / PlanDrawRange /
// PlanDrawIndirect over a RemoteDrawBindings snapshot - so the fields on the wire are pinned // PlanDrawIndirect over a RemoteDrawBindings snapshot - so the fields on the wire are pinned
// here without a GL context (R-16: the production predicate, not a copy). The bindings' READ // here without a GL context (R-16: the production predicate, not a copy). The bindings' READ
@@ -2660,7 +2660,7 @@ TEST(RemoteGuards, ClientPipeInputsFillWithTheApplierIdleIsAllowed) {
// =========================================================================================== // ===========================================================================================
// P5e (ra) - the wait rule, the present credit and gPipeInputs' ownership // P5e (ra) - the wait rule, the present credit and gPipeInputs' ownership
// (docs/archive/contracts/CONTRACT-P5E.md §1, §2.3, §2.4, §3.1, §3.3, §3.5) // (§1, §2.3, §2.4, §3.1, §3.3, §3.5)
// =========================================================================================== // ===========================================================================================
// //
// EVERY CASE BELOW ARMS RUN-AHEAD BY PUBLISHING THE CAP BIT, because that is the only thing // EVERY CASE BELOW ARMS RUN-AHEAD BY PUBLISHING THE CAP BIT, because that is the only thing
+1 -1
View File
@@ -2537,7 +2537,7 @@ TEST(StagedShadowProductionTest, TheStreamingIdiomThroughAPoolReuseIsUploadedNot
// ===================================================================================== // =====================================================================================
// P5b d1: a draw_vbo record of every d1 shape crosses to the REAL ServerVerbSink with its // P5b d1: a draw_vbo record of every d1 shape crosses to the REAL ServerVerbSink with its
// fields intact (docs/archive/contracts/CONTRACT-P5B.md §2 d1). No backend object lives in this process, // fields intact (§2 d1). No backend object lives in this process,
// so each record is DECLINED after the sink has witnessed it - which is exactly the point: // so each record is DECLINED after the sink has witnessed it - which is exactly the point:
// the witness is taken before the backend is consulted, so these cases pin the wire's fields // the witness is taken before the backend is consulted, so these cases pin the wire's fields
// and not a backend call. The emitter half (GL args -> these fields) is RemoteClientTest's // and not a backend call. The emitter half (GL args -> these fields) is RemoteClientTest's
+1 -1
View File
@@ -564,7 +564,7 @@ TEST(SessionTest, PresentAckSerialIsWaitedOnWithGreaterOrEqualAndWakesThroughThe
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// P5e (ra) - SEG_EVENT flow control (docs/archive/contracts/CONTRACT-P5E.md §2.6) // P5e (ra) - SEG_EVENT flow control (§2.6)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// //
// THE DEADLOCK THE CONTRACT ARGUES AWAY HAS TWO HALVES AND THIS IS THE FIRST. A run-ahead // THE DEADLOCK THE CONTRACT ARGUES AWAY HAS TWO HALVES AND THIS IS THE FIRST. A run-ahead
+1 -1
View File
@@ -6,7 +6,7 @@
// SPDX-License-Identifier: LGPL-3.0-only // SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header // End of Source File Header
// Shared images (docs/archive/notes/anland/plan-ahb-dmabuf.md): the server's registry, a // Shared images: the server's registry, a
// session's references, and the aux-socket inbox that carries an import's descriptor beside T0's // session's references, and the aux-socket inbox that carries an import's descriptor beside T0's
// Offers. On a host the image memory is a memfd, which is enough for everything here: what is // Offers. On a host the image memory is a memfd, which is enough for everything here: what is
// under test is that a descriptor which travelled through SCM_RIGHTS still names its image. // under test is that a descriptor which travelled through SCM_RIGHTS still names its image.
@@ -397,7 +397,7 @@ TEST(StagedTextureStoreTest, TheGpuDirtyMarkIsTheServersOwnDirtyAnswer) {
EXPECT_EQ(monolithStore.TrackedResources(), 0u); EXPECT_EQ(monolithStore.TrackedResources(), 0u);
} }
// ---- P8-E (docs/archive/notes/p8/E.md): the store follows glCopyImageSubData ----------- // ---- P8-E: the store follows glCopyImageSubData -----------
// //
// Two 4x4 RGBA8 levels (four bytes a texel), each adopted whole with a distinct byte pattern so a // Two 4x4 RGBA8 levels (four bytes a texel), each adopted whole with a distinct byte pattern so a
// mis-addressed row or a swapped endpoint shows as a wrong byte, not a coincidentally right one. // mis-addressed row or a swapped endpoint shows as a wrong byte, not a coincidentally right one.
+2 -2
View File
@@ -1,6 +1,6 @@
# 设计与架构(索引) # 设计与架构(索引)
> 这一页只有设计要点和章节去向;每一部分的完整设计在 [`design/`](design/)。章节编号 §1–§17、附 A / B 沿用至今,代码注释里写的 `ARCHITECTURE.md §N` 按下表找到对应文件。各阶段的 wire 契约原文已冻结在 `docs/archive/contracts/CONTRACT-*.md`,与设计文字冲突时以更新的契约为准。 > 这一页只有设计要点和章节去向;每一部分的完整设计在 [`design/`](design/)。章节编号 §1–§17、附 A / B 沿用至今,代码注释里写的 `ARCHITECTURE.md §N` 按下表找到对应文件。各阶段的 wire 契约原文见 git 历史,与设计文字冲突时以更新的契约为准。
## 一句话 ## 一句话
@@ -32,5 +32,5 @@
| 12–13 | persistent map 与大缓冲采纳;回读、往返清单、五部分验证门 | [`design/07-memory-readback-verification.md`](design/07-memory-readback-verification.md) | | 12–13 | persistent map 与大缓冲采纳;回读、往返清单、五部分验证门 | [`design/07-memory-readback-verification.md`](design/07-memory-readback-verification.md) |
| 14–15 | 帧节奏与线程;进程、握手、EGL、Android(含上屏 server)、崩溃处理 | [`design/08-runtime-and-platform.md`](design/08-runtime-and-platform.md) | | 14–15 | 帧节奏与线程;进程、握手、EGL、Android(含上屏 server)、崩溃处理 | [`design/08-runtime-and-platform.md`](design/08-runtime-and-platform.md) |
| 16、附 A、附 B | 源码目录与构建选项;全部开关;边界计数器 | [`design/09-build-switches-counters.md`](design/09-build-switches-counters.md) | | 16、附 A、附 B | 源码目录与构建选项;全部开关;边界计数器 | [`design/09-build-switches-counters.md`](design/09-build-switches-counters.md) |
| 17 | 各阶段落地时的形状与仍生效的规则(链到 `docs/archive/notes/`) | [`design/10-phase-shapes.md`](design/10-phase-shapes.md) | | 17 | 各阶段落地时的形状与仍生效的规则(原文见 git 历史) | [`design/10-phase-shapes.md`](design/10-phase-shapes.md) |
| — | 状态归属:多 session / 多 context / share group(anland 统一 server 前置) | [`design/11-state-ownership.md`](design/11-state-ownership.md) | | — | 状态归属:多 session / 多 context / share group(anland 统一 server 前置) | [`design/11-state-ownership.md`](design/11-state-ownership.md) |
+2 -2
View File
@@ -1,6 +1,6 @@
# 当前阶段:P13 已收官(2026-10-07);下一阶段 P14 # 当前阶段:P13 已收官(2026-10-07);下一阶段 P14
> **更新 2026-10-07**。这一页只有摘要;计划与裁定在 [`docs/archive/notes/p13/PLAN-P13.md`](../archive/notes/p13/PLAN-P13.md)、[`docs/archive/notes/p13/INTEGRATOR-DECISIONS-P13.md`](../archive/notes/p13/INTEGRATOR-DECISIONS-P13.md),逐波记录在 [`docs/archive/notes/p13/README.md`](../archive/notes/p13/README.md)。上一阶段 P8 于 09-30 收官,见 [`docs/archive/notes/p8/README.md`](../archive/notes/p8/README.md)。 > **更新 2026-10-07**。这一页只有摘要;计划与裁定见 git 历史。上一阶段 P8 于 09-30 收官。
## 目标 ## 目标
@@ -23,4 +23,4 @@
**P14**:状态归属(同进程多 session / 多 context / share group),设计见 [`design/11-state-ownership.md`](design/11-state-ownership.md)。性能轮(基线 `dev` 构建,定频,FCL MC + anland glmark2,两后端)也排在 P13 之后。 **P14**:状态归属(同进程多 session / 多 context / share group),设计见 [`design/11-state-ownership.md`](design/11-state-ownership.md)。性能轮(基线 `dev` 构建,定频,FCL MC + anland glmark2,两后端)也排在 P13 之后。
**待用户决策**:[`DEBTS.md`](DEBTS.md) 中「需裁定」各项;FCL 无声死亡留给用户(`docs/archive/notes/p13/fcl-soak/README.md`)。 **待用户决策**:[`DEBTS.md`](DEBTS.md) 中「需裁定」各项;FCL 无声死亡留给用户(细节见 git 历史)。
+9 -9
View File
@@ -4,7 +4,7 @@
> >
> **2026-10-07(P13 收官)关闭三行**:ID-P8-13(9 条 monolith 缺陷——monolith 换到记录臂后对应 monolith 登记在集成车道上全过,旧的 monolith 前端臂在 W6 删除)、ID-P8-14(`SyncClientSideVertexArraysForIndirectFetch` 的整 buffer 回读与 Magma monolith 深度 mip 的 view 类型都属于已删的 monolith 前端臂)、`MOBILEGL_PIPE_TEXEL_RETAIN_MB`(W3b 随 pull 构建删除)。新增两行:W9 缓存容量重调与 Magma monolith 性能,都排在 P13 之后的性能轮,基线是 `dev` 构建。 > **2026-10-07(P13 收官)关闭三行**:ID-P8-13(9 条 monolith 缺陷——monolith 换到记录臂后对应 monolith 登记在集成车道上全过,旧的 monolith 前端臂在 W6 删除)、ID-P8-14(`SyncClientSideVertexArraysForIndirectFetch` 的整 buffer 回读与 Magma monolith 深度 mip 的 view 类型都属于已删的 monolith 前端臂)、`MOBILEGL_PIPE_TEXEL_RETAIN_MB`(W3b 随 pull 构建删除)。新增两行:W9 缓存容量重调与 Magma monolith 性能,都排在 P13 之后的性能轮,基线是 `dev` 构建。
> >
> 路线图只列"有债务、看这里"。每条写明去向;已关闭的历史债与当时的完整债务表见 [`docs/archive/notes/p5b/README.md`](../archive/notes/p5b/README.md) 末节。开放问题另见 [`OPEN-QUESTIONS.md`](OPEN-QUESTIONS.md)。更新:2026-09-30(P8 第二波;按债务审查重排。同日:create-indirect 换成派生 fixture `minecraft-1.21.1-neoforge-create-indirect-in-world-align1024`(不是原抓取,16 字节对齐的 SSBO 范围绑定挪到 1024 对齐),ID-P8-14、ID-P8-19 两条关闭——红米两后端 monolith / spawn 全过,Magma spawn 不再丢设备)。去向「需裁定」= 等用户定;「可进行」= 随时可开的小修,不依赖别的阶段。 > 路线图只列"有债务、看这里"。每条写明去向;已关闭的历史债与当时的完整债务表见 git 历史。开放问题另见 [`OPEN-QUESTIONS.md`](OPEN-QUESTIONS.md)。更新:2026-09-30(P8 第二波;按债务审查重排。同日:create-indirect 换成派生 fixture `minecraft-1.21.1-neoforge-create-indirect-in-world-align1024`(不是原抓取,16 字节对齐的 SSBO 范围绑定挪到 1024 对齐),ID-P8-14、ID-P8-19 两条关闭——红米两后端 monolith / spawn 全过,Magma spawn 不再丢设备)。去向「需裁定」= 等用户定;「可进行」= 随时可开的小修,不依赖别的阶段。
| 债务 | 去向 | | 债务 | 去向 |
|---|---| |---|---|
@@ -26,12 +26,12 @@
| P8 转出(E):driver-written 标按整张纹理打(`GenerateMipmap` 也打),驱动拒读时连基级也具名拒绝,偏保守;跨格式拷贝 store 不跟随;拒绝仍是会话 Fatal(要改回包状态才能答 `GL_INVALID_OPERATION`) | 小修(按 level 打标);其余按需 | | P8 转出(E):driver-written 标按整张纹理打(`GenerateMipmap` 也打),驱动拒读时连基级也具名拒绝,偏保守;跨格式拷贝 store 不跟随;拒绝仍是会话 Fatal(要改回包状态才能答 `GL_INVALID_OPERATION`) | 小修(按 level 打标);其余按需 |
| P8 转出(B):`PipeCalls.def:260` `GenerateMipmap` 仍是 `kWaitApplied`,裁定 14 的理由(CPU 滤波碰 client 影子)已不成立,可改 `kWaitNone` | 性能工作(协议行为变更,需单独裁定) | | P8 转出(B):`PipeCalls.def:260` `GenerateMipmap` 仍是 `kWaitApplied`,裁定 14 的理由(CPU 滤波碰 client 影子)已不成立,可改 `kWaitNone` | 性能工作(协议行为变更,需单独裁定) |
| P8 转出(C):server SSBO 标记过近似(窗口内每个绑定的 SSBO 都标);一个留在 SSBO 绑定上又当 restart EBO 用的 buffer 每次 draw 都回读 | 性能工作 | | P8 转出(C):server SSBO 标记过近似(窗口内每个绑定的 SSBO 都标);一个留在 SSBO 绑定上又当 restart EBO 用的 buffer 每次 draw 都回读 | 性能工作 |
| P13 转出(ID-P13-2,P14 更新):Magma monolith 记录臂对 dev(pull)——trace 上已基本追平:rd12 83.8 对 87.0 fps(−4%),openra 747 对 293(dev 在那里等 GPU);P14 最大一项是 `553eb86d`(纹理层上传不再在 CPU 上等 GPU 排空,rd12 70→83)。但 **FCL MC 上仍差**:monolith 171 对 dev 232(−26%),inproc 195;呈现线程 CPU 只占约 2.8 / 5.8 ms 帧,其余是等待——与 trace 不同的另一处等待 | 下一阶段第一项:FCL Magma monolith 做 off-CPU profile(`--trace-offcpu`,同找到上传等待的方法;P14 收官时两次采集都没抓到游戏帧),找出那 3 ms 等待;数字见 `docs/archive/notes/perf-p14/README.md` | | P13 转出(ID-P13-2,P14 更新):Magma monolith 记录臂对 dev(pull)——trace 上已基本追平:rd12 83.8 对 87.0 fps(−4%),openra 747 对 293(dev 在那里等 GPU);P14 最大一项是 `553eb86d`(纹理层上传不再在 CPU 上等 GPU 排空,rd12 70→83)。但 **FCL MC 上仍差**:monolith 171 对 dev 232(−26%),inproc 195;呈现线程 CPU 只占约 2.8 / 5.8 ms 帧,其余是等待——与 trace 不同的另一处等待 | 下一阶段第一项:FCL Magma monolith 做 off-CPU profile(`--trace-offcpu`,同找到上传等待的方法;P14 收官时两次采集都没抓到游戏帧),找出那 3 ms 等待;数字见 git 历史 |
| ~~P13 转出(W9):缓存容量重调~~ **P14 关闭(读数)**:`MOBILEGL_PIPE_STATS` 在 rd12 / openra 上 render-state CSO 稳态每帧新铸 0 个,Magma 管线 memo 命中 99.0% / 92.7%,没有缓存抖动,P8 容量保留 | 已关闭(`docs/archive/notes/perf-p14/BENCH.md` W9 节) | | ~~P13 转出(W9):缓存容量重调~~ **P14 关闭(读数)**:`MOBILEGL_PIPE_STATS` 在 rd12 / openra 上 render-state CSO 稳态每帧新铸 0 个,Magma 管线 memo 命中 99.0% / 92.7%,没有缓存抖动,P8 容量保留 | 已关闭(W9 节,见 git 历史) |
| P14 转出:Espryt monolith 记录臂对 dev(pull)rd12 91.1 对 115.2 fps(−21%);FCL MC 198 对 229(−13%)。渲染线程每帧 CPU 11.56 对 9.07 ms:client half +1.39(validate 0.92:EmitGlobalConstants 0.17、EmitVertexElements 0.13、Tracker::Update 0.12、CopyField 0.10、validate 自身 0.10、EmitVertexBuffers 0.07;verb port 约 0.2)、backend +0.45(SyncNeccessaryTextures +0.14、SyncNeccessaryBuffers +0.08、AdoptUnchangedBufferSets +0.09、BindCurrentProgramWithResources +0.07、SyncCurrentProgramByHandle +0.05)、driver +0.33、applier +0.07。每项都在帧时间 2% 以下;合起来是记录臂的结构成本:pull 的后端在 draw 时按指针读前端对象,push 要检测变化(tracker)、序列化(emitter、uniform span)、应用(applier)、再由后端按句柄经 slot 表重新解析,并且因为后端看不到前端脏位而对每个绑定对象做 clean 检查——每步每 draw 几十 ns、各自是不相干的冷 cache 行,乘以 1471 draw/帧 | 下一阶段:per-(VAO, program) draw-packet 缓存(设计草稿 `docs/archive/notes/perf-p14/NEXT-draw-packet-cache.md`,估计 rd12 Espryt monolith 回收 1.0–1.6 ms/帧,约 91→100–106 fps);先只做 client half 原型量 | | P14 转出:Espryt monolith 记录臂对 dev(pull)rd12 91.1 对 115.2 fps(−21%);FCL MC 198 对 229(−13%)。渲染线程每帧 CPU 11.56 对 9.07 ms:client half +1.39(validate 0.92:EmitGlobalConstants 0.17、EmitVertexElements 0.13、Tracker::Update 0.12、CopyField 0.10、validate 自身 0.10、EmitVertexBuffers 0.07;verb port 约 0.2)、backend +0.45(SyncNeccessaryTextures +0.14、SyncNeccessaryBuffers +0.08、AdoptUnchangedBufferSets +0.09、BindCurrentProgramWithResources +0.07、SyncCurrentProgramByHandle +0.05)、driver +0.33、applier +0.07。每项都在帧时间 2% 以下;合起来是记录臂的结构成本:pull 的后端在 draw 时按指针读前端对象,push 要检测变化(tracker)、序列化(emitter、uniform span)、应用(applier)、再由后端按句柄经 slot 表重新解析,并且因为后端看不到前端脏位而对每个绑定对象做 clean 检查——每步每 draw 几十 ns、各自是不相干的冷 cache 行,乘以 1471 draw/帧 | 下一阶段:per-(VAO, program) draw-packet 缓存(设计草稿(见 git 历史),估计 rd12 Espryt monolith 回收 1.0–1.6 ms/帧,约 91→100–106 fps);先只做 client half 原型量 |
| P14 转出:Espryt monolith 的 driver 项 +0.33 ms/帧(2.9%),全在 `glDrawElements` 内部,GL 调用组合与 dev 相同。`simpleperf stat`(整次运行、渲染线程):feat 比 dev 多执行 16.6% 指令、L1D refill 多 56%、L2D 多 23%(IPC 3.73 对 3.86)。推断:记录臂每 draw 更大的工作集(record、applier 状态、slot 表、twin)把驱动的状态挤出 cache——这是计数器推断,没有在驱动内部测量 | 随 draw-packet 缓存一起验证:落地前后量 L1D refill 与 driver ms/帧;如果 driver 项不降,推断不成立,再单独查 | | P14 转出:Espryt monolith 的 driver 项 +0.33 ms/帧(2.9%),全在 `glDrawElements` 内部,GL 调用组合与 dev 相同。`simpleperf stat`(整次运行、渲染线程):feat 比 dev 多执行 16.6% 指令、L1D refill 多 56%、L2D 多 23%(IPC 3.73 对 3.86)。推断:记录臂每 draw 更大的工作集(record、applier 状态、slot 表、twin)把驱动的状态挤出 cache——这是计数器推断,没有在驱动内部测量 | 随 draw-packet 缓存一起验证:落地前后量 L1D refill 与 driver ms/帧;如果 driver 项不降,推断不成立,再单独查 |
| P14 转出(测过未做):Tracker / residual 的前端变更 epoch 快路径——在每个 `DECLARE_GL_FUNCTION_END` 入口(除 draw、`glBindVertexArray`、浮点 `glUniform*` 外)以及手写入口和 EGL 入口里 bump 一个上下文 epoch;epoch 未动时 validate 只重算 VAO / program 派生的 shutter(上限约 0.07 ms),再经审计哪些 residual 字段依赖 VAO / program 绑定后跳过 residual copy(合计 0.15–0.25 ms,1.5–2%) | 各自低于 2% 门槛,且漏 bump 一个入口就渲染陈旧状态;并入 draw-packet 设计(其 §3 的上下文 epoch 就是它),不单独做 | | P14 转出(测过未做):Tracker / residual 的前端变更 epoch 快路径——在每个 `DECLARE_GL_FUNCTION_END` 入口(除 draw、`glBindVertexArray`、浮点 `glUniform*` 外)以及手写入口和 EGL 入口里 bump 一个上下文 epoch;epoch 未动时 validate 只重算 VAO / program 派生的 shutter(上限约 0.07 ms),再经审计哪些 residual 字段依赖 VAO / program 绑定后跳过 residual copy(合计 0.15–0.25 ms,1.5–2%) | 各自低于 2% 门槛,且漏 bump 一个入口就渲染陈旧状态;并入 draw-packet 设计(其 §3 的上下文 epoch 就是它),不单独做 |
| P13 转出(FCL 浸泡,用户裁定:FCL 暂不改、MobileGL 不做规避):FCL game process can die silently (exit SIGNALED status=34, SIGRTMIN+2): the JVM signal reset after renderer selection drops libcore's AsynchronousCloseMonitor handler, and FCL's okhttp/Okio watchdog then kills the process; renderer-independent (reproduced on P12 and P13 libraries, both backends; untested with other renderers)。浸泡:P13 库 30 次(Magma 22 / Espryt 8)死 18 次、P12 库 10 次死 2 次;P12 / P13 逐次交替的对照(同场景同网络时段)P12 4/10、P13 2/10,时间线(`Renderer:` 行到 MobileGL 首行约 6.2 s、晚死固定在其后约 9.4 s)两库相同,无证据表明 MobileGL 拉高概率;全部 status=34,无 tombstone、无 kgsl;证据与机理见 [`docs/archive/notes/p13/fcl-soak/README.md`](../archive/notes/p13/fcl-soak/README.md) | fix belongs in FCL (save/restore libcore's SIGRTMIN+2 sigaction around JVM creation); left for the user | | P13 转出(FCL 浸泡,用户裁定:FCL 暂不改、MobileGL 不做规避):FCL game process can die silently (exit SIGNALED status=34, SIGRTMIN+2): the JVM signal reset after renderer selection drops libcore's AsynchronousCloseMonitor handler, and FCL's okhttp/Okio watchdog then kills the process; renderer-independent (reproduced on P12 and P13 libraries, both backends; untested with other renderers)。浸泡:P13 库 30 次(Magma 22 / Espryt 8)死 18 次、P12 库 10 次死 2 次;P12 / P13 逐次交替的对照(同场景同网络时段)P12 4/10、P13 2/10,时间线(`Renderer:` 行到 MobileGL 首行约 6.2 s、晚死固定在其后约 9.4 s)两库相同,无证据表明 MobileGL 拉高概率;全部 status=34,无 tombstone、无 kgsl;证据与机理见 git 历史 | fix belongs in FCL (save/restore libcore's SIGRTMIN+2 sigaction around JVM creation); left for the user |
| P8 转出(MD):dev 的 `RingAllocateSlow` 在出错的上下文上无上限地排水(设备上挂在 `glFinish`) | 小修(dev) | | P8 转出(MD):dev 的 `RingAllocateSlow` 在出错的上下文上无上限地排水(设备上挂在 `glFinish`) | 小修(dev) |
| P8 转出:`LogForwardChannel.APeerThatStopsReadingCostsWarnLinesNotTheCallersTime` 在负载下超时(两次),单跑必过 | 小修(放宽时限或隔离) | | P8 转出:`LogForwardChannel.APeerThatStopsReadingCostsWarnLinesNotTheCallersTime` 在负载下超时(两次),单跑必过 | 小修(放宽时限或隔离) |
| P8 转出(SV):`gen_pipe_dirty_surface.py` 扫描集成测试源,测试成员名与 GLContext 成员同名(如 `m_parameters`)会静默弄坏它的自检;`.Mip3DValidation.` 在没装校验层的车道上是失败不是跳过 | 小修 / CI 记录 | | P8 转出(SV):`gen_pipe_dirty_surface.py` 扫描集成测试源,测试成员名与 GLContext 成员同名(如 `m_parameters`)会静默弄坏它的自检;`.Mip3DValidation.` 在没装校验层的车道上是失败不是跳过 | 小修 / CI 记录 |
@@ -42,11 +42,11 @@
| P11 转出(M2,给 dev):dev 的 `DirectVulkan.SplitRecording.` 车道没有 `RESOURCE_LOCK`、其用例读字面日志路径——`-j` 下可能互相截断;P11 线的副本已修(Magma 空 uniform 的重复修复已在 ID-P8-17 合成一条) | 下次向 dev 回流时带上 | | P11 转出(M2,给 dev):dev 的 `DirectVulkan.SplitRecording.` 车道没有 `RESOURCE_LOCK`、其用例读字面日志路径——`-j` 下可能互相截断;P11 线的副本已修(Magma 空 uniform 的重复修复已在 ID-P8-17 合成一条) | 下次向 dev 回流时带上 |
| P11 转出(M2):超过 stage 分块预算的大层按分片发出,没有写入框覆盖的分片仍带整框(server 要靠它拼层图),会把影子盖到 GPU 写过的地方;修法要一个两个 server 都跳过的「只定位」区域写法,控制协议修订 +1(split 专属,早于 P11) | 小包或 P8 | | P11 转出(M2):超过 stage 分块预算的大层按分片发出,没有写入框覆盖的分片仍带整框(server 要靠它拼层图),会把影子盖到 GPU 写过的地方;修法要一个两个 server 都跳过的「只定位」区域写法,控制协议修订 +1(split 专属,早于 P11) | 小包或 P8 |
| P11 转出(M2):上传仍有两种有损形状,各记一次日志——一层的精确写入框超过 4096 个时按存储的矩形表覆盖发出;applier 一个条目累计超过 4096 个区域时并成并集框。纹理带 GPU 写时两者都会把影子盖进空隙 | 小修,无触发报告 | | P11 转出(M2):上传仍有两种有损形状,各记一次日志——一层的精确写入框超过 4096 个时按存储的矩形表覆盖发出;applier 一个条目累计超过 4096 个区域时并成并集框。纹理带 GPU 写时两者都会把影子盖进空隙 | 小修,无触发报告 |
| P10 转出(性能):设备上 tcp loopback 的 rd12 每帧 19.4 ms 中 ~11.2 ms 是生产者在 stream 传输里的停车(发送 + 环 / stage / ack 等待),credit 等待只有 ~0.2 ms(`docs/archive/notes/p10/C-MEASUREMENTS.md` §2,ID-P10-13) | 路线图推完后的性能工作 | | P10 转出(性能):设备上 tcp loopback 的 rd12 每帧 19.4 ms 中 ~11.2 ms 是生产者在 stream 传输里的停车(发送 + 环 / stage / ack 等待),credit 等待只有 ~0.2 ms(见 git 历史 §2,ID-P10-13) | 路线图推完后的性能工作 |
| P11 转出(性能):设备上 MC 26.3,split T2 相对单进程采纳的 p99 Espryt +37–42%、Magma 约 2.5×;其中一部分是线程落位——server apply 线程钉在 6–7 核,client GL 线程多半落到慢核,每帧 CPU 约 2.3×(`docs/archive/notes/p11/A-DEVICE.md`)。RSS 一半已由 B2(T0)交付:峰值内存 Espryt −41–42%、Magma −18–26%(ID-P11-17) | 路线图推完后的性能工作(p99 与线程落位) | | P11 转出(性能):设备上 MC 26.3,split T2 相对单进程采纳的 p99 Espryt +37–42%、Magma 约 2.5×;其中一部分是线程落位——server apply 线程钉在 6–7 核,client GL 线程多半落到慢核,每帧 CPU 约 2.3×(见 git 历史)。RSS 一半已由 B2(T0)交付:峰值内存 Espryt −41–42%、Magma −18–26%(ID-P11-17) | 路线图推完后的性能工作(p99 与线程落位) |
| P11 转出(B2,性能):`glBufferStorage(NULL)` 的采纳先把整块零存储当 `resource_subdata` 发一遍(T2 与 T0 都是;MC 26.3 8 个存储、441.5 MiB) | 路线图推完后的性能工作 | | P11 转出(B2,性能):`glBufferStorage(NULL)` 的采纳先把整块零存储当 `resource_subdata` 发一遍(T2 与 T0 都是;MC 26.3 8 个存储、441.5 MiB) | 路线图推完后的性能工作 |
| P12 未做:DirectGLES `g_Display` / `g_Surface` / `g_Context` 仍是全局(每进程一个会话时不需要);cached-app freezer 的完整处理(文档从未定义);多 context;server 窗口不转发输入 | 等出现第二个会话 / 第二个 context 的需求 | | P12 未做:DirectGLES `g_Display` / `g_Surface` / `g_Context` 仍是全局(每进程一个会话时不需要);cached-app freezer 的完整处理(文档从未定义);多 context;server 窗口不转发输入 | 等出现第二个会话 / 第二个 context 的需求 |
| P9 转出:Magma 每次 draw 对可写 SSBO / texel buffer / XFB 目标发整 buffer 的 `OnGpuWritten`(create-indirect 首帧 7,093 条),client 已自标同一批,冗余无害;`OnMipLevelsGenerated`、`OnCapsInvalidated` 仍无生产者。`OnTextureWriteback` 也无生产者,但别删:CPU 三通道 mip 退路要它(`CONTRACT-P5B.md:255`) | 以后的收窄 / 清理候选(ID-P9-7) | | P9 转出:Magma 每次 draw 对可写 SSBO / texel buffer / XFB 目标发整 buffer 的 `OnGpuWritten`(create-indirect 首帧 7,093 条),client 已自标同一批,冗余无害;`OnMipLevelsGenerated`、`OnCapsInvalidated` 仍无生产者。`OnTextureWriteback` 也无生产者,但别删:CPU 三通道 mip 退路要它(`CONTRACT-P5B.md:255`) | 以后的收窄 / 清理候选(ID-P9-7) |
| 树外脚本:普查跑器、`wsl_p5_gate.sh` 等在 `~/w7/notes/`,git merge 不会传播;`docs/archive/notes/p11/gate.sh` 是事实上的门 | 需要时入库 | | 树外脚本:普查跑器、`wsl_p5_gate.sh` 等在 `~/w7/notes/`,git merge 不会传播;事实上的门脚本见 git 历史 | 需要时入库 |
已关闭的历史债(P5 的 27 个 wrong-answer、`rsp` 残余读、P5b 的 inproc 依赖、ABI 指纹、默认 staging 装不下 128 MiB 上传、184 符号棘轮 CI 门)及当时的完整债务表见 [`docs/archive/notes/p5b/README.md`](../archive/notes/p5b/README.md) 末节。 已关闭的历史债(P5 的 27 个 wrong-answer、`rsp` 残余读、P5b 的 inproc 依赖、ABI 指纹、默认 staging 装不下 128 MiB 上传、184 符号棘轮 CI 门)及当时的完整债务表见 git 历史。
+21 -21
View File
@@ -1,6 +1,6 @@
# 实测(索引) # 实测(索引)
> 这一页只有结论和去向;完整的表、命令、协议与读法在各阶段 `docs/archive/notes/<阶段>/README.md` 的"实测"节。代码和旧笔记里的 `MEASUREMENTS.md §N` 按下表"§"列找到对应阶段(小节编号在那里原样保留)。 > 这一页只有结论和去向;完整的表、命令、协议与读法在各阶段的"实测"节(原文见 git 历史)。代码和旧笔记里的 `MEASUREMENTS.md §N` 按下表"§"列找到对应阶段(小节编号在那里原样保留)。
**口径**:性能只记录、不设门;看**逐线程 CPU 时间**,不看整机帧率。性能对比只用一台手机(Redmi `2f7cbe2e`,Adreno 830),定频、同热窗口、两臂交替跑([`guide/pin-verification-2026-09-07.md`](guide/pin-verification-2026-09-07.md))。 **口径**:性能只记录、不设门;看**逐线程 CPU 时间**,不看整机帧率。性能对比只用一台手机(Redmi `2f7cbe2e`,Adreno 830),定频、同热窗口、两臂交替跑([`guide/pin-verification-2026-09-07.md`](guide/pin-verification-2026-09-07.md))。
@@ -25,29 +25,29 @@
这解释了 handoff §3.6「换快 3.4 倍的链路墙钟不变」:钱花在设备每次唤醒上;handoff §3.2 那 249 s 是在**未定频**的机器上取的,含这份空闲税。 这解释了 handoff §3.6「换快 3.4 倍的链路墙钟不变」:钱花在设备每次唤醒上;handoff §3.2 那 249 s 是在**未定频**的机器上取的,含这份空闲税。
**同一个诊断给出一条可移植修法**:把服务端的自旋预算调大(Activity 的 `env` extra → `MOBILEGL_IPC_SPIN_US=2000`,不需要 root、不需要改代码), **同一个诊断给出一条可移植修法**:把服务端的自旋预算调大(Activity 的 `env` extra → `MOBILEGL_IPC_SPIN_US=2000`,不需要 root、不需要改代码),
那一帧 **221.5 s → 182.8 s(−17%)**;设备定频+关深度空闲则是 **166.5 s(−25%)**。服务端日志会打印 `spin 2000 us` 自证。 那一帧 **221.5 s → 182.8 s(−17%)**;设备定频+关深度空闲则是 **166.5 s(−25%)**。服务端日志会打印 `spin 2000 us` 自证。
见 [`docs/archive/notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md`](../archive/notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md) §2.6–2.10。 见 git 历史 §2.6–2.10。
- **画面正确**:Vulkan 后端真机画面检查 36/36 通过,CTS 五块相对基线没有超过 0.5 个百分点的退步、没有新崩溃(P7);server 自有窗口上屏两后端 SSIM 1.0(P12)。 - **画面正确**:Vulkan 后端真机画面检查 36/36 通过,CTS 五块相对基线没有超过 0.5 个百分点的退步、没有新崩溃(P7);server 自有窗口上屏两后端 SSIM 1.0(P12)。
- **五臂传输对比(2026-09-28,未定频交错 A/B)**:重负载(rd12)下 inproc ≈ spawn+shm 比 monolith **快约 1/3**(run-ahead 流水线并行 + applier 路径探针更少),轻负载(openra)下 split 只付固定开销;**tcp localhost 慢 ~8 倍,瓶颈是 present credit=1 的串行等待(~74%)+ futex 唤醒税**,`MOBILEGL_IPC_SPIN_US=2000` 单项实测 21.7→63.6 fps;跨主机 TCP 的「`eglMakeCurrent` hang」**是测试环境造成的**(主机 v2rayN `xray_tun` 代理终结 TCP 后中继卡住,不是源码 bug);绕开后 P12 出口门 (b) 通过:WSL client 经 Wi-Fi 重放 rd12 世界内 trace,ssim 0.999883,稳态 17–22 fps(`PRESENT_CREDIT` 1/2/3 = 16.9 / 21.3 / 22.1),openra 稳态 105–133 fps;加载帧 2.7 GB 受带宽约束(server 实测 52 MB/s),稳态受往返延迟(20–24 MB/s)。全文 [`docs/archive/notes/perf-five-arm-20260928`](../archive/notes/perf-five-arm-20260928/README.md)。 - **五臂传输对比(2026-09-28,未定频交错 A/B)**:重负载(rd12)下 inproc ≈ spawn+shm 比 monolith **快约 1/3**(run-ahead 流水线并行 + applier 路径探针更少),轻负载(openra)下 split 只付固定开销;**tcp localhost 慢 ~8 倍,瓶颈是 present credit=1 的串行等待(~74%)+ futex 唤醒税**,`MOBILEGL_IPC_SPIN_US=2000` 单项实测 21.7→63.6 fps;跨主机 TCP 的「`eglMakeCurrent` hang」**是测试环境造成的**(主机 v2rayN `xray_tun` 代理终结 TCP 后中继卡住,不是源码 bug);绕开后 P12 出口门 (b) 通过:WSL client 经 Wi-Fi 重放 rd12 世界内 trace,ssim 0.999883,稳态 17–22 fps(`PRESENT_CREDIT` 1/2/3 = 16.9 / 21.3 / 22.1),openra 稳态 105–133 fps;加载帧 2.7 GB 受带宽约束(server 实测 52 MB/s),稳态受往返延迟(20–24 MB/s)。全文见 git 历史。
## 按阶段 ## 按阶段
| § | 阶段 | 一句结论 | 全文 | | § | 阶段 | 一句结论 | 全文 |
|---|---|---|---| |---|---|---|---|
| 1 | P0 | 能从应用进程拉起第二个进程;跨进程共享 GPU 内存只有一条路在所有设备上可用 | [`docs/archive/notes/p0`](../archive/notes/p0/README.md) | | 1 | P0 | 能从应用进程拉起第二个进程;跨进程共享 GPU 内存只有一条路在所有设备上可用 | git 历史 |
| 2 | P1 | 逐 draw 核对推送状态,79 条 trace 零分歧 | [`docs/archive/notes/p1`](../archive/notes/p1/README.md) | | 2 | P1 | 逐 draw 核对推送状态,79 条 trace 零分歧 | git 历史 |
| 3 | P2 | 桌面基准:新 tracker 比它替掉的旧填充更便宜 | [`docs/archive/notes/p2`](../archive/notes/p2/README.md) | | 3 | P2 | 桌面基准:新 tracker 比它替掉的旧填充更便宜 | git 历史 |
| 4 | P3a | 两机真机 Release:接口代价 +6–12%,VAO 切换密集的场景 +27–30% | [`docs/archive/notes/p3a`](../archive/notes/p3a/README.md) | | 4 | P3a | 两机真机 Release:接口代价 +6–12%,VAO 切换密集的场景 +27–30% | git 历史 |
| 5 | P4a | 换到 Redmi;P4a 自己只加 3–6 个百分点 | [`docs/archive/notes/p4a`](../archive/notes/p4a/README.md) | | 5 | P4a | 换到 Redmi;P4a 自己只加 3–6 个百分点 | git 历史 |
| 6 | P5 | 两线程第一帧画对;真机两线程臂还跑不完 | [`docs/archive/notes/p5`](../archive/notes/p5/README.md) | | 6 | P5 | 两线程第一帧画对;真机两线程臂还跑不完 | git 历史 |
| 7 | P5b | 真机两线程跑通四条游戏 trace;两线程额外代价 +6–18% | [`docs/archive/notes/p5b`](../archive/notes/p5b/README.md) | | 7 | P5b | 真机两线程跑通四条游戏 trace;两线程额外代价 +6–18% | git 历史 |
| 8 | P5c | 两线程之间零共享内存后,全部测试仍绿 | [`docs/archive/notes/p5c`](../archive/notes/p5c/README.md) | | 8 | P5c | 两线程之间零共享内存后,全部测试仍绿 | git 历史 |
| 9 | P5d | 游戏内 7–13 → 103–106 fps,client CPU 15.0 → 9.2 ms/帧 | [`docs/archive/notes/p5d`](../archive/notes/p5d/README.md) | | 9 | P5d | 游戏内 7–13 → 103–106 fps,client CPU 15.0 → 9.2 ms/帧 | git 历史 |
| 10–11 | P5e | 发完就走比每条都等快 69%;重负载下与单线程持平 | [`docs/archive/notes/p5e`](../archive/notes/p5e/README.md) | | 10–11 | P5e | 发完就走比每条都等快 69%;重负载下与单线程持平 | git 历史 |
| 12 | P6 | 两进程与两线程持平;每帧数据量与记录数首次实测 | [`docs/archive/notes/p6`](../archive/notes/p6/README.md) | | 12 | P6 | 两进程与两线程持平;每帧数据量与记录数首次实测 | git 历史 |
| 13 | P3b/P4b | 纹理上传形状在四种拓扑下完全一致 | [`docs/archive/notes/p34b`](../archive/notes/p34b/README.md) | | 13 | P3b/P4b | 纹理上传形状在四种拓扑下完全一致 | git 历史 |
| 14 | P6.5 | 跨机 TCP 102/102;断线约 5 s 检测到 | [`docs/archive/notes/p65`](../archive/notes/p65/README.md) | | 14 | P6.5 | 跨机 TCP 102/102;断线约 5 s 检测到 | git 历史 |
| 15 | P7 | 真机画面 36/36;server 内存无界增长收住(主机 825 → 546 MiB) | [`docs/archive/notes/p7`](../archive/notes/p7/README.md) | | 15 | P7 | 真机画面 36/36;server 内存无界增长收住(主机 825 → 546 MiB) | git 历史 |
| 16 | P12 | 审查后真机复测:Espryt SSIM 1.0;Magma 1.0 / 0.999999511;P12 定向 CTest 46/46;纹理上传回包等待 1→0(主机机制门,真机墙钟待测);**P12 已收官(09-29)**:跨机 TCP 门 (b) 通过(rd12 ssim 0.999883、稳态 17–22 fps);FCL 门 (a) 通过(Minecraft 上屏到 render server 窗口,杀 server 后 33–54 ms 闩住 device-lost) | [`docs/archive/notes/p12`](../archive/notes/p12/README.md) | | 16 | P12 | 审查后真机复测:Espryt SSIM 1.0;Magma 1.0 / 0.999999511;P12 定向 CTest 46/46;纹理上传回包等待 1→0(主机机制门,真机墙钟待测);**P12 已收官(09-29)**:跨机 TCP 门 (b) 通过(rd12 ssim 0.999883、稳态 17–22 fps);FCL 门 (a) 通过(Minecraft 上屏到 render server 窗口,杀 server 后 33–54 ms 闩住 device-lost) | git 历史 |
| 17 | 五臂传输测量(2026-09-28,非阶段) | inproc/shm 重负载比 monolith 快 ~1/3;tcp localhost 瓶颈是 credit=1 + 唤醒税(SPIN_US=2000 → 2.9×);跨主机 hang 实为主机 xray TUN 代理造成;直连 Wi-Fi 稳态 rd12 17–22 fps、openra 105–133 fps | [`docs/archive/notes/perf-five-arm-20260928`](../archive/notes/perf-five-arm-20260928/README.md) | | 17 | 五臂传输测量(2026-09-28,非阶段) | inproc/shm 重负载比 monolith 快 ~1/3;tcp localhost 瓶颈是 credit=1 + 唤醒税(SPIN_US=2000 → 2.9×);跨主机 hang 实为主机 xray TUN 代理造成;直连 Wi-Fi 稳态 rd12 17–22 fps、openra 105–133 fps | git 历史 |
| 18 | P11 | 同机零拷贝(T0)MC 26.3 峰值内存 Espryt −41–42%、Magma −18–26%,ssim / 帧时 / CPU 不变;外部 client 走共享内存 rd12 Espryt 约 119 fps(TCP 40–53);split T2 相对单进程采纳 p99 Espryt +37–42%、Magma 约 2.5×。未量:M2 后 split server 上纹理无 GPU 写时 Espryt 自己按存储阈值取舍精确写入框,非 ring 路径可能多发几个小框 | [`docs/archive/notes/p11`](../archive/notes/p11/README.md) | | 18 | P11 | 同机零拷贝(T0)MC 26.3 峰值内存 Espryt −41–42%、Magma −18–26%,ssim / 帧时 / CPU 不变;外部 client 走共享内存 rd12 Espryt 约 119 fps(TCP 40–53);split T2 相对单进程采纳 p99 Espryt +37–42%、Magma 约 2.5×。未量:M2 后 split server 上纹理无 GPU 写时 Espryt 自己按存储阈值取舍精确写入框,非 ring 路径可能多发几个小框 | git 历史 |
| 19 | P8 | 真实内容只 Magma wire indirect 命中(MC 26.3 × Magma inproc 1,300 万 draw CPU 展开)→ 原生后 create-indirect 每次整 GPU 等待 321 → 0;红米 create-instancing × Espryt × monolith 0.870 → 0.99998(Adreno 丢排队环形拷贝,dev + feat 两条阶梯);最大 program archive 355 KB = arena/4 的 4.2 %(不分片);出口设备矩阵 77 格 / 臂无一变差 | [`docs/archive/notes/p8`](../archive/notes/p8/README.md) | | 19 | P8 | 真实内容只 Magma wire indirect 命中(MC 26.3 × Magma inproc 1,300 万 draw CPU 展开)→ 原生后 create-indirect 每次整 GPU 等待 321 → 0;红米 create-instancing × Espryt × monolith 0.870 → 0.99998(Adreno 丢排队环形拷贝,dev + feat 两条阶梯);最大 program archive 355 KB = arena/4 的 4.2 %(不分片);出口设备矩阵 77 格 / 臂无一变差 | git 历史 |
+1 -1
View File
@@ -5,7 +5,7 @@
P0 已回答的不再列出(spike A 的域、spike B 的分档、`posix_spawn` 不可用、OOM 探测惯用法、`GetInteger64i_v`/`GetProgramiv` 退役、D21 与 `RenderbufferObject` lifetime id、动态 accessor 基线)。 P0 已回答的不再列出(spike A 的域、spike B 的分档、`posix_spawn` 不可用、OOM 探测惯用法、`GetInteger64i_v`/`GetProgramiv` 退役、D21 与 `RenderbufferObject` lifetime id、动态 accessor 基线)。
1. **client 侧 dirty 走查的真实每 draw CPU 代价。** 已答(P2–P4a):推送没有在拉取基线之下净减少;Release 下 P2 边界 +6–12%,P3a 在 VAO 切换密的 rd12 上再加 +17–19 pt,P4a 在 Espryt 上 +3.4–5.7 pt(`MEASUREMENTS.md` §3–§5)。用户 2026-09-08 接受,性能自此只记录。 1. **client 侧 dirty 走查的真实每 draw CPU 代价。** 已答(P2–P4a):推送没有在拉取基线之下净减少;Release 下 P2 边界 +6–12%,P3a 在 VAO 切换密的 rd12 上再加 +17–19 pt,P4a 在 Espryt 上 +3.4–5.7 pt(`MEASUREMENTS.md` §3–§5)。用户 2026-09-08 接受,性能自此只记录。
2. **真实语料上纹理重铸拉取的发生率。** 已答(P4a):可忽略,保留 LRU 维持默认 0——79 例 × 两后端 780 个统计窗口里共 2 次(`iris-photon`、`iris-derivative` 各 1,只在 DirectGLES)。但 P5b 下这条路径是具名 Fatal,正是这两条 trace 加 `create-indirect` GLES 的首阻塞(P9)。**P9 W2 关闭**:重铸不需要拉取——server 读 GPU 层、store 补 pending 盒(Espryt),GPU→GPU 拷贝(Magma);77 行 × {monolith, inproc} 普查仍是同两次(都是 store 无字节的渲染目标),`OnTexturePullRequest` 已删([`docs/archive/notes/p9/W2-REMINT.md`](../archive/notes/p9/W2-REMINT.md))。 2. **真实语料上纹理重铸拉取的发生率。** 已答(P4a):可忽略,保留 LRU 维持默认 0——79 例 × 两后端 780 个统计窗口里共 2 次(`iris-photon`、`iris-derivative` 各 1,只在 DirectGLES)。但 P5b 下这条路径是具名 Fatal,正是这两条 trace 加 `create-indirect` GLES 的首阻塞(P9)。**P9 W2 关闭**:重铸不需要拉取——server 读 GPU 层、store 补 pending 盒(Espryt),GPU→GPU 拷贝(Magma);77 行 × {monolith, inproc} 普查仍是同两次(都是 store 无字节的渲染目标),`OnTexturePullRequest` 已删(见 git 历史)。
3. **spike B 的 `untrusted_app` 域复核。** 两台设备的分档在 `shell` 域测得;从应用进程再跑一次 `extmem_probe`(spike A 的 exec 钩子已可用)。P11 前做。**2026-09-22 降级**:只对同机臂的 T0 / T1 有意义,stream 数据面不需要。 3. **spike B 的 `untrusted_app` 域复核。** 两台设备的分档在 `shell` 域测得;从应用进程再跑一次 `extmem_probe`(spike A 的 exec 钩子已可用)。P11 前做。**2026-09-22 降级**:只对同机臂的 T0 / T1 有意义,stream 数据面不需要。
4. **渲染状态的 wire 粒度。** 已答(P2):16 个边界 / 15 个 chunk,7 pipeline 396 B + 8 dynamic 772 B;CSO LRU 64 暂定,P13 重调。 4. **渲染状态的 wire 粒度。** 已答(P2):16 个边界 / 15 个 chunk,7 pipeline 396 B + 8 dynamic 772 B;CSO LRU 64 暂定,P13 重调。
5. **无存储的 capability。** 已答(P2):`FramebufferSrgb`、`DepthClamp`、`TextureCubeMapSeamless` 三个都补了真存储,`sizeof(RenderStateParameters)` 仍 1168。 5. **无存储的 capability。** 已答(P2):`FramebufferSrgb`、`DepthClamp`、`TextureCubeMapSeamless` 三个都补了真存储,`sizeof(RenderStateParameters)` 仍 1168。
+2 -3
View File
@@ -21,10 +21,9 @@
|---|---| |---|---|
| 现在做到哪、下一步 | [`CURRENT_STAGE_PROGRESS.md`](CURRENT_STAGE_PROGRESS.md) | | 现在做到哪、下一步 | [`CURRENT_STAGE_PROGRESS.md`](CURRENT_STAGE_PROGRESS.md) |
| 设计要点与各部分设计 | [`ARCHITECTURE.md`](ARCHITECTURE.md) → [`design/`](design/) | | 设计要点与各部分设计 | [`ARCHITECTURE.md`](ARCHITECTURE.md) → [`design/`](design/) |
| 分几个阶段、每个阶段做了什么 | [`ROADMAP.md`](ROADMAP.md) → [`docs/archive/notes/<阶段>/`](../archive/notes/README.md) | | 分几个阶段、每个阶段做了什么 | [`ROADMAP.md`](ROADMAP.md) |
| 性能与验证的关键数字 | [`MEASUREMENTS.md`](MEASUREMENTS.md) | | 性能与验证的关键数字 | [`MEASUREMENTS.md`](MEASUREMENTS.md) |
| 怎么构建、运行、测试 | [`guide/build-and-run.md`](guide/build-and-run.md) | | 怎么构建、运行、测试 | [`guide/build-and-run.md`](guide/build-and-run.md) |
| 代码在哪 / 术语 / 工程纪律 | [`guide/code-map.md`](guide/code-map.md)、[`guide/glossary.md`](guide/glossary.md)、[`guide/discipline.md`](guide/discipline.md) | | 代码在哪 / 术语 / 工程纪律 | [`guide/code-map.md`](guide/code-map.md)、[`guide/glossary.md`](guide/glossary.md)、[`guide/discipline.md`](guide/discipline.md) |
| 各阶段的原始计划、裁定、报告、证据(已冻结) | [`docs/archive/notes/`](../archive/notes/README.md) |
整理记录:2026-09-24 两次整理——顶层只留索引,设计正文拆到 `design/`,上手与参考放 `guide/`,阶段细节放 `notes/<阶段>/`(2026-10 起冻结在 `docs/archive/notes/`);整理前的版本见提交 `1fb18d9`。更早的设计竞赛与评审稿在 git 历史(`8b31de2f`、`1794ac94`、`8349babe`、`87ee17c6`)。 整理记录:2026-09-24 两次整理——顶层只留索引,设计正文拆到 `design/`,上手与参考放 `guide/`,阶段细节放 `notes/<阶段>/`(这些笔记已从树中删除,见 git 历史);整理前的版本见提交 `1fb18d9`。更早的设计竞赛与评审稿在 git 历史(`8b31de2f`、`1794ac94`、`8349babe`、`87ee17c6`)。
+24 -24
View File
@@ -1,6 +1,6 @@
# 路线图(索引) # 路线图(索引)
> **2026-10-07**:P0 到 P7、P12、P9、P10、P11、P8、**P13** 已完成——拆分路线与单进程路线都走完。P13(退役 pull 路径):单进程也只走记录臂,pull / push 两套构建、`MOBILEGL_PIPE_PUSH` 与 `MOBILEGL_PIPE_LEGACY_MEMOS` 编译期开关、残余值块和后端的前端对象臂全部删除;库拆成按 link ratchet 分区的七个模块,split 构建里 server 一半单独真链接;G1 退役,由零 `MG_Remote` 符号、skip 普查与 recorder 金标接班;性能工作排在其后,基线是 `dev` 构建。下一项是 **P14**(状态归属)。每个阶段的计划、验收结果、实测与报告在 `docs/archive/notes/<阶段>/`(点阶段名进入)。 > **2026-10-07**:P0 到 P7、P12、P9、P10、P11、P8、**P13** 已完成——拆分路线与单进程路线都走完。P13(退役 pull 路径):单进程也只走记录臂,pull / push 两套构建、`MOBILEGL_PIPE_PUSH` 与 `MOBILEGL_PIPE_LEGACY_MEMOS` 编译期开关、残余值块和后端的前端对象臂全部删除;库拆成按 link ratchet 分区的七个模块,split 构建里 server 一半单独真链接;G1 退役,由零 `MG_Remote` 符号、skip 普查与 recorder 金标接班;性能工作排在其后,基线是 `dev` 构建。下一项是 **P14**(状态归属)。每个阶段的计划、验收结果、实测与报告见 git 历史。
## 目标 ## 目标
@@ -15,29 +15,29 @@ client(跑应用的一方)与 server(跑驱动的一方)可以在**不
| 阶段 | 做什么 | 状态 | | 阶段 | 做什么 | 状态 |
|---|---|---| |---|---|---|
| [P0](../archive/notes/p0/README.md) | 打地基:计数器、调用目录与生成器、CI 门;验证 Android 能拉起第二个进程 | ✅ 09-05 | | P0 | 打地基:计数器、调用目录与生成器、CI 门;验证 Android 能拉起第二个进程 | ✅ 09-05 |
| [P0.5](../archive/notes/p05/README.md) | 抽出前后端共用的数据类型头,切断后端对前端头文件的依赖 | ✅ | | P0.5 | 抽出前后端共用的数据类型头,切断后端对前端头文件的依赖 | ✅ |
| [P1](../archive/notes/p1/README.md) | 后端改读一个"输入块",并能逐 draw 核对它与前端真实状态一致 | ✅ | | P1 | 后端改读一个"输入块",并能逐 draw 核对它与前端真实状态一致 | ✅ |
| [P2](../archive/notes/p2/README.md) | 前端开始主动推送渲染状态;接口代价实测 +6–12%,决定继续 | ✅ 09-08 | | P2 | 前端开始主动推送渲染状态;接口代价实测 +6–12%,决定继续 | ✅ 09-08 |
| [P3a](../archive/notes/p3a/README.md) | GLES 后端的 buffer、顶点数组改用句柄 | ✅ 09-08 | | P3a | GLES 后端的 buffer、顶点数组改用句柄 | ✅ 09-08 |
| [P4a](../archive/notes/p4a/README.md) | GLES 后端的帧缓冲、纹理、sampler、program 改用句柄 | ✅ 09-08 | | P4a | GLES 后端的帧缓冲、纹理、sampler、program 改用句柄 | ✅ 09-08 |
| [P5](../archive/notes/p5/README.md) | 第一次拆成两线程:命令队列 + 后端线程(每条命令都等) | ✅ 09-16 | | P5 | 第一次拆成两线程:命令队列 + 后端线程(每条命令都等) | ✅ 09-16 |
| [P5b](../archive/notes/p5b/README.md) | 把剩余命令迁到队列上;真机首次以独立后端线程跑通目标游戏 | ✅ 09-16 | | P5b | 把剩余命令迁到队列上;真机首次以独立后端线程跑通目标游戏 | ✅ 09-16 |
| [P5c](../archive/notes/p5c/README.md) | 两线程之间不再偷偷共享内存,只经队列交换 | ✅ 09-17 | | P5c | 两线程之间不再偷偷共享内存,只经队列交换 | ✅ 09-17 |
| [P5d](../archive/notes/p5d/README.md) | 两线程版本的性能:游戏内 7–13 fps → 103–106 fps | ✅ 09-18 | | P5d | 两线程版本的性能:游戏内 7–13 fps → 103–106 fps | ✅ 09-18 |
| [P5e](../archive/notes/p5e/README.md) | client 发完就走,不再每条命令等后端;重负载下与单线程持平 | ✅ 09-19 | | P5e | client 发完就走,不再每条命令等后端;重负载下与单线程持平 | ✅ 09-19 |
| [P5f](../archive/notes/p5f/README.md) | 所有状态都经队列传递,为拆进程扫清最后障碍;Vulkan 后端也能发完就走 | ✅ 09-20 | | P5f | 所有状态都经队列传递,为拆进程扫清最后障碍;Vulkan 后端也能发完就走 | ✅ 09-20 |
| [P6](../archive/notes/p6/README.md) | 拆成两个进程;真机上两进程与两线程成本持平 | ✅ 09-22 | | P6 | 拆成两个进程;真机上两进程与两线程成本持平 | ✅ 09-22 |
| [P6.5](../archive/notes/p65/README.md) | 传输分控制面 / 数据面;电脑当 client、手机当 server 经 TCP 跑通 | 第一波 ✅,余项交 CI | | P6.5 | 传输分控制面 / 数据面;电脑当 client、手机当 server 经 TCP 跑通 | 第一波 ✅,余项交 CI |
| [Ph](../archive/notes/p7/README.md) | server 能安全地接受外来连接:令牌、限额、坏数据不致崩溃 | 必需项 ✅(随 P7) | | Ph | server 能安全地接受外来连接:令牌、限额、坏数据不致崩溃 | 必需项 ✅(随 P7) |
| [P3b / P4b](../archive/notes/p34b/README.md) | GLES 后端的深化与收尾 | 大部分 ✅,余项并行 | | P3b / P4b | GLES 后端的深化与收尾 | 大部分 ✅,余项并行 |
| [P7](../archive/notes/p7/README.md) | Vulkan 后端完整迁移;真机画面检查 36/36 通过 | ✅ 09-23 | | P7 | Vulkan 后端完整迁移;真机画面检查 36/36 通过 | ✅ 09-23 |
| [**P12**](../archive/notes/p12/README.md) | **server 自己开窗口上屏,client 不需要窗口** | ✅ 09-29:出口门 B(跨机 TCP)✅ 09-28、A(FCL + 杀 server)✅ 09-29;契约 `docs/archive/contracts/CONTRACT-P12.md`;G1 成立;余项进 [`DEBTS.md`](DEBTS.md) | | **P12** | **server 自己开窗口上屏,client 不需要窗口** | ✅ 09-29:出口门 B(跨机 TCP)✅ 09-28、A(FCL + 杀 server)✅ 09-29;契约见 git 历史;G1 成立;余项进 [`DEBTS.md`](DEBTS.md) |
| [**P8**](../archive/notes/p8/README.md) | ~~把剩余的仿真路径挪到正确的一侧,补齐协议~~ → **补齐 server 侧仿真缺口与 split 覆盖** | ✅ 09-30:重定界(原 10 项里 6 项前序已完成);Espryt 生成 mip / 暂存副本与 GPU 写 / 驱动拒读、Magma wire 原生 indirect 与 dispatch;246 例登上 split 三臂(`split_coverage.py`);Create 在 Adreno 上的丢拷贝修到 dev 与 feat;契约 `docs/archive/contracts/CONTRACT-P8.md`;余项进 [`DEBTS.md`](DEBTS.md) | | **P8** | ~~把剩余的仿真路径挪到正确的一侧,补齐协议~~ → **补齐 server 侧仿真缺口与 split 覆盖** | ✅ 09-30:重定界(原 10 项里 6 项前序已完成);Espryt 生成 mip / 暂存副本与 GPU 写 / 驱动拒读、Magma wire 原生 indirect 与 dispatch;246 例登上 split 三臂(`split_coverage.py`);Create 在 Adreno 上的丢拷贝修到 dev 与 feat;契约见 git 历史;余项进 [`DEBTS.md`](DEBTS.md) |
| [**P9**](../archive/notes/p9/README.md) | **反向通道:回读、日志、重铸不再同步等待 client** | ✅ 09-29:PACK-PBO 回读 fire-and-forget(两后端)、日志分级转发、重铸无拉取(`OnLog` / `OnTexturePullRequest` 删,回调 9 → 7),F1 / F2;契约 `docs/archive/contracts/CONTRACT-P9.md`;G1 成立;事件量批处理无实测需求不做;余项进 [`DEBTS.md`](DEBTS.md) | | **P9** | **反向通道:回读、日志、重铸不再同步等待 client** | ✅ 09-29:PACK-PBO 回读 fire-and-forget(两后端)、日志分级转发、重铸无拉取(`OnLog` / `OnTexturePullRequest` 删,回调 9 → 7),F1 / F2;契约见 git 历史;G1 成立;事件量批处理无实测需求不做;余项进 [`DEBTS.md`](DEBTS.md) |
| [**P10**](../archive/notes/p10/README.md) | **同步对象、查询与帧节奏** | ✅ 09-29:fence 轮询由 server 报告本地作答(`kEventFenceSignaled`、`MOBILEGL_IPC_POLL_ESCALATE`;主机 Magma·tcp −37%,Adreno 830 上两后端 0 次往返);`SetSwapInterval` 转发、class C 清零;query / XFB / AsyncCompile 登记 split 各臂;credit 1/2/3 设备 loopback 在噪声内;契约 `docs/archive/contracts/CONTRACT-P10.md`;G1 成立;余项进 [`DEBTS.md`](DEBTS.md) | | **P10** | **同步对象、查询与帧节奏** | ✅ 09-29:fence 轮询由 server 报告本地作答(`kEventFenceSignaled`、`MOBILEGL_IPC_POLL_ESCALATE`;主机 Magma·tcp −37%,Adreno 830 上两后端 0 次往返);`SetSwapInterval` 转发、class C 清零;query / XFB / AsyncCompile 登记 split 各臂;credit 1/2/3 设备 loopback 在噪声内;契约见 git 历史;G1 成立;余项进 [`DEBTS.md`](DEBTS.md) |
| [**P11**](../archive/notes/p11/README.md) | **同机大缓冲零拷贝共享** | ✅ 09-29:T0 零拷贝导入(两后端,默认开,自测不过或 Stream 上静默退回 T2);同机外部 client 经 helper + 令牌 broker 走共享内存(B1);连接按 `PairBind` nonce 配对(修订 5);采纳档位在握手时定;契约 `docs/archive/contracts/CONTRACT-P11.md`;余项进 [`DEBTS.md`](DEBTS.md) | | **P11** | **同机大缓冲零拷贝共享** | ✅ 09-29:T0 零拷贝导入(两后端,默认开,自测不过或 Stream 上静默退回 T2);同机外部 client 经 helper + 令牌 broker 走共享内存(B1);连接按 `PairBind` nonce 配对(修订 5);采纳档位在握手时定;契约见 git 历史;余项进 [`DEBTS.md`](DEBTS.md) |
| [**P13**](../archive/notes/p13/README.md) | **删掉旧的"后端直接读前端"路径** | ✅ 10-07:单进程只走记录臂;pull / push 构建与 `PIPE_PUSH` / `LEGACY_MEMOS` 编译期开关、残余值块、后端前端对象臂删除;七个 OBJECT 模块与 server-only 真链接;link ratchet 172 → 27 具名债务;recorder 金标;G1 退役;FCL 真机两后端冒烟通过;性能轮(基线 `dev`)与余项进 [`DEBTS.md`](DEBTS.md) | | **P13** | **删掉旧的"后端直接读前端"路径** | ✅ 10-07:单进程只走记录臂;pull / push 构建与 `PIPE_PUSH` / `LEGACY_MEMOS` 编译期开关、残余值块、后端前端对象臂删除;七个 OBJECT 模块与 server-only 真链接;link ratchet 172 → 27 具名债务;recorder 金标;G1 退役;FCL 真机两后端冒烟通过;性能轮(基线 `dev`)与余项进 [`DEBTS.md`](DEBTS.md) |
| **P14** | **状态归属:同进程多 session / 多 context / share group**(统一 server 的前提,anland 内置渲染器不做按进程隔离) | 设计 ✅ [`design/11-state-ownership.md`](design/11-state-ownership.md),实现待做 | | **P14** | **状态归属:同进程多 session / 多 context / share group**(统一 server 的前提,anland 内置渲染器不做按进程隔离) | 设计 ✅ [`design/11-state-ownership.md`](design/11-state-ownership.md),实现待做 |
## 另见 ## 另见
@@ -41,7 +41,7 @@
### 3.3 能力位(`MGPCapBit`) ### 3.3 能力位(`MGPCapBit`)
`CallMask` 取代"槽位是否为 null"这一隐式能力探测;`MGPCaps` = `DynamicBackendParameters` + `CallMask` + 格式能力表与 renderer 字符串两个 blob,握手后快照、`MakeCurrent` / `InitCapabilities` 后按 generation 重发布。位包括 viewport array、fp64 顶点、`kCapResidentSubData`、XFB / query 家族、`kCapNeedsHostIndexBytes`、`kCapNeedsHostUboBytes`、`kCapBackendOwnsXfbCapture`、`kCapRunAheadApply`(`MGPipeRunAheadCapBitsFor`:Espryt 自 P5e、Magma 自 P5f 之后的 Magma run-ahead 起发布,后者契约 `docs/archive/contracts/CONTRACT-MAGMA-RUNAHEAD.md`)。**不存在"归属开关"(D-B7)**:multi-draw 分档与 restart 重写永远由 server 拥有,client 只在 caps 要求时提供索引字节。 `CallMask` 取代"槽位是否为 null"这一隐式能力探测;`MGPCaps` = `DynamicBackendParameters` + `CallMask` + 格式能力表与 renderer 字符串两个 blob,握手后快照、`MakeCurrent` / `InitCapabilities` 后按 generation 重发布。位包括 viewport array、fp64 顶点、`kCapResidentSubData`、XFB / query 家族、`kCapNeedsHostIndexBytes`、`kCapNeedsHostUboBytes`、`kCapBackendOwnsXfbCapture`、`kCapRunAheadApply`(`MGPipeRunAheadCapBitsFor`:Espryt 自 P5e、Magma 自 P5f 之后的 Magma run-ahead 起发布,后者契约见 git 历史)。**不存在"归属开关"(D-B7)**:multi-draw 分档与 restart 重写永远由 server 拥有,client 只在 caps 要求时提供索引字节。
## 4. 记录与 payload 约定(`MG_Pipe/MGPipeTypes.h`) ## 4. 记录与 payload 约定(`MG_Pipe/MGPipeTypes.h`)
@@ -55,8 +55,8 @@
- 删除:`OnTexturePullRequest`(与 W3 删除的 `OnLog` 合计,回调 9 → 7)、`texture-remint-pull` 标记。op 50 `ResourceSubDataComplete` 只追加不删,留作退役行(解码拒收)。`MOBILEGL_PIPE_TEXEL_RETAIN_MB` 已无消费者,但在 pull 构建里,随 P13 删(G1)。 - 删除:`OnTexturePullRequest`(与 W3 删除的 `OnLog` 合计,回调 9 → 7)、`texture-remint-pull` 标记。op 50 `ResourceSubDataComplete` 只追加不删,留作退役行(解码拒收)。`MOBILEGL_PIPE_TEXEL_RETAIN_MB` 已无消费者,但在 pull 构建里,随 P13 删(G1)。
- `ImageBindableHint` 仍是预防:hint 在第一次 sync 前到达就直接按 image-bindable 分配,省掉一次 server 回读 + 重传。 - `ImageBindableHint` 仍是预防:hint 在第一次 sync 前到达就直接按 image-bindable 分配,省掉一次 server 回读 + 重传。
- 已知 dev 缺陷(非 P9):monolith Espryt 的前端臂重放 client 影子,覆盖 GPU 写过的纹素。 - 已知 dev 缺陷(非 P9):monolith Espryt 的前端臂重放 client 影子,覆盖 GPU 写过的纹素。
- 普查、覆盖矩阵、门与 red-once:[`docs/archive/notes/p9/W2-REMINT.md`](../../archive/notes/p9/W2-REMINT.md)。 - 普查、覆盖矩阵、门与 red-once:见 git 历史。
### 8.5 XFB scatter 留在 server ### 8.5 XFB scatter 留在 server
补丁循环需要"捕获前的字节",而拆分后权威影子归 server(`StagedShadow`),所以 scatter 在 server 原地跑完;回程只有一条 `OnBufferWriteback`,载补好的整段,按 `SEG_EVENT` 容量的四分之一切片(`MGPipeBufferWritebackSliceBytes`),最后一片落地即蕴含之前每一片。孤儿目标(`HasDefinedContent == 0`)零填充后照常散射。`OnXfbScatterReady` 已删除(回调 10 → 9)。落地论证见 [`docs/archive/notes/p34b/README.md`](../../archive/notes/p34b/README.md)(espryt D1)。 补丁循环需要"捕获前的字节",而拆分后权威影子归 server(`StagedShadow`),所以 scatter 在 server 原地跑完;回程只有一条 `OnBufferWriteback`,载补好的整段,按 `SEG_EVENT` 容量的四分之一切片(`MGPipeBufferWritebackSliceBytes`),最后一片落地即蕴含之前每一片。孤儿目标(`HasDefinedContent == 0`)零填充后照常散射。`OnXfbScatterReady` 已删除(回调 10 → 9)。落地论证见 git 历史(espryt D1)。
@@ -69,4 +69,4 @@ Track V(值类型:render state、pixel store、capability 位、标量)是
### 10.3 索引宿主镜像(`Server/IndexHostMirror`,P8,待重裁) ### 10.3 索引宿主镜像(`Server/IndexHostMirror`,P8,待重裁)
设计:`kCapNeedsHostIndexBytes` 下,server 从本来就要收的 `ResourceCreate/Respecify/SubData` 流增量维护 element-array buffer 的宿主镜像,零额外流量;预算 `MOBILEGL_PIPE_INDEX_MIRROR_MB`(默认 64),超预算退化为逐 draw 经 `MGHostSpan` 传送。**P6 的 a6 审计实测宿主索引 span 无 producer、client 索引已是 owned buffer**,所以 P8 要按真实消费者重新裁定,不照抄本节([`docs/archive/notes/p8/README.md`](../../archive/notes/p8/README.md))。 设计:`kCapNeedsHostIndexBytes` 下,server 从本来就要收的 `ResourceCreate/Respecify/SubData` 流增量维护 element-array buffer 的宿主镜像,零额外流量;预算 `MOBILEGL_PIPE_INDEX_MIRROR_MB`(默认 64),超预算退化为逐 draw 经 `MGHostSpan` 传送。**P6 的 a6 审计实测宿主索引 span 无 producer、client 索引已是 owned buffer**,所以 P8 要按真实消费者重新裁定,不照抄本节(见 git 历史)。
+1 -1
View File
@@ -92,4 +92,4 @@ fence 完成度必须来自真的逐 fence 退休,不是 present 水位(Dire
- 两端是不同二进制:`wireFingerprint`(`PipeFields.def` 派生的逐成员布局摘要 + 目录摘要 + 字节序 / 指针宽度)永远比较;`buildFingerprint` 只在 `Dial == Fork`(或 `MOBILEGL_IPC_REQUIRE_SAME_BUILD=1`)下比较;不一致是 `Refuse`,不是 abort。 - 两端是不同二进制:`wireFingerprint`(`PipeFields.def` 派生的逐成员布局摘要 + 目录摘要 + 字节序 / 指针宽度)永远比较;`buildFingerprint` 只在 `Dial == Fork`(或 `MOBILEGL_IPC_REQUIRE_SAME_BUILD=1`)下比较;不一致是 `Refuse`,不是 abort。
- TCP 上每条 `kWaitReply` 就是一个 RTT、`SEG_STAGE` 字节对的是 30–100 MB/s 的链路:这两列从"记录项"变成可行性数(开放问题 19、20)。 - TCP 上每条 `kWaitReply` 就是一个 RTT、`SEG_STAGE` 字节对的是 30–100 MB/s 的链路:这两列从"记录项"变成可行性数(开放问题 19、20)。
第一波(全 TCP 控制 + stream 数据)已落地;同机混搭(nd `auto` / sd)是第二波。细节 [`docs/archive/notes/p65/README.md`](../../archive/notes/p65/README.md),契约 `docs/archive/contracts/CONTRACT-P65.md`。 第一波(全 TCP 控制 + stream 数据)已落地;同机混搭(nd `auto` / sd)是第二波。细节与契约见 git 历史。
@@ -10,7 +10,7 @@
|---|---|---| |---|---|---|
| T0 | client 分配 `AHardwareBuffer` BLOB,server 导入(Vulkan / GLES) | 唯一在两台设备、两个后端上都完整读写的档(P11 主攻) | | T0 | client 分配 `AHardwareBuffer` BLOB,server 导入(Vulkan / GLES) | 唯一在两台设备、两个后端上都完整读写的档(P11 主攻) |
| T1 | server 导出 opaque fd | 仅 Adreno 的 Vulkan 路径 | | T1 | server 导出 opaque fd | 仅 Adreno 的 Vulkan 路径 |
| T2 | 拒绝,client 侧推送 | 永久正确回退;**今天 split 用的档**(`MOBILEGL_IPC_ADOPT_TIER=2`),stream 数据面上强制(P11 A1:两端握手时 `Transport::SettleAdoptTierAtHandshake` 对 0/1 打一行 `Refuse{AdoptTierOnStream}` 并走 T2;共享段上 client 握手期 `Fatal{UnimplementedAdoptTier}`,[`CONTRACT-P11.md`](../../archive/contracts/CONTRACT-P11.md) §1) | | T2 | 拒绝,client 侧推送 | 永久正确回退;**今天 split 用的档**(`MOBILEGL_IPC_ADOPT_TIER=2`),stream 数据面上强制(P11 A1:两端握手时 `Transport::SettleAdoptTierAtHandshake` 对 0/1 打一行 `Refuse{AdoptTierOnStream}` 并走 T2;共享段上 client 握手期 `Fatal{UnimplementedAdoptTier}`,`CONTRACT-P11.md` §1) |
T2 下 client 侧推送三件套:不做 map/unmap 命令对(payload 带 `hasLiveHostWrites`);在每个 validate 点按 64 KiB 块推送可达的已映射 buffer,脏页追踪 + 哈希抑制只发变化的块(P5d);门 `PersistentCoherentMapScenario`。`mpr` 数的是每一次 `MapPersistent` 发射(铸成或拒绝都算),所以在 monolith 下也可断言。 T2 下 client 侧推送三件套:不做 map/unmap 命令对(payload 带 `hasLiveHostWrites`);在每个 validate 点按 64 KiB 块推送可达的已映射 buffer,脏页追踪 + 哈希抑制只发变化的块(P5d);门 `PersistentCoherentMapScenario`。`mpr` 数的是每一次 `MapPersistent` 发射(铸成或拒绝都算),所以在 monolith 下也可断言。
@@ -42,7 +42,7 @@ TCP `--serve` 的 supervisor(`ServerMain.cpp` 的 `TcpSupervisor`,判定部
- 交付链(spike A 已证):APK 唯一可 exec 的位置是 `lib/<abi>/`,server 以 `add_executable` + `lib*.so` 命名构建;从 `untrusted_app` 进程 `fork`+`execve` 同域、零 avc denial;`posix_spawn` 在 minSdk 26 不可用。一份共享库两个角色(stub `dlopen` + `dlsym("mobilegl_server_main")`)。 - 交付链(spike A 已证):APK 唯一可 exec 的位置是 `lib/<abi>/`,server 以 `add_executable` + `lib*.so` 命名构建;从 `untrusted_app` 进程 `fork`+`execve` 同域、零 avc denial;`posix_spawn` 在 minSdk 26 不可用。一份共享库两个角色(stub `dlopen` + `dlsym("mobilegl_server_main")`)。
- 离屏 server:前台 `MobileGLServerService`(`:mglsrv`),从 `nativeLibraryDir` exec,fork-per-session,EGL 是 pbuffer / surfaceless。 - 离屏 server:前台 `MobileGLServerService`(`:mglsrv`),从 `nativeLibraryDir` exec,fork-per-session,EGL 是 pbuffer / surfaceless。
- **上屏 server(P12 子集)**:窗口归 **server 自己**(client 的窗口不跨进程)。`MobileGLDisplayActivity`(`:mglwin`)持全屏 SurfaceView,在自己的进程里用一个线程跑 TCP server(会话串行、会话间重置闩、后端按进程钉住);`ServerDisplay` 以 acquire / release / 几何三个钩子持有窗口,apply 线程以**租约**使用它。client 设 `MOBILEGL_IPC_SURFACE=server` 后**无头**:`eglCreateWindowSurface(NULL)` 发一帧 `WindowKind::ServerOwned`(控制修订 3),不发 `SetWindowHandle`,尺寸由 reply 带回,resize 变成对 server 窗口的几何请求;client 没给 `EGL_WIDTH/HEIGHT`(SDL)时取 native window 的大小作请求,server 把窗口缓冲固定成它并等比留黑边(不然横屏游戏在竖屏窗口里被裁)。FCL 只能接外部 server(自带 spawn 会把窗口指针发过来,被 Rule H 拒),且要开版本设置「游戏退到后台时不暂停」,否则 FCL 一退后台游戏就暂停(`docs/archive/contracts/CONTRACT-P12.md`)。一台设备同一时刻一个 server;一个会话一种表面模式(`SurfaceModeMismatch`);无显示的 server 对 ServerOwned 具名拒绝(`NoServerDisplay`)。 - **上屏 server(P12 子集)**:窗口归 **server 自己**(client 的窗口不跨进程)。`MobileGLDisplayActivity`(`:mglwin`)持全屏 SurfaceView,在自己的进程里用一个线程跑 TCP server(会话串行、会话间重置闩、后端按进程钉住);`ServerDisplay` 以 acquire / release / 几何三个钩子持有窗口,apply 线程以**租约**使用它。client 设 `MOBILEGL_IPC_SURFACE=server` 后**无头**:`eglCreateWindowSurface(NULL)` 发一帧 `WindowKind::ServerOwned`(控制修订 3),不发 `SetWindowHandle`,尺寸由 reply 带回,resize 变成对 server 窗口的几何请求;client 没给 `EGL_WIDTH/HEIGHT`(SDL)时取 native window 的大小作请求,server 把窗口缓冲固定成它并等比留黑边(不然横屏游戏在竖屏窗口里被裁)。FCL 只能接外部 server(自带 spawn 会把窗口指针发过来,被 Rule H 拒),且要开版本设置「游戏退到后台时不暂停」,否则 FCL 一退后台游戏就暂停(见 git 历史)。一台设备同一时刻一个 server;一个会话一种表面模式(`SurfaceModeMismatch`);无显示的 server 对 ServerOwned 具名拒绝(`NoServerDisplay`)。
- 失窗:`surfaceDestroyed` 有界(3 s)阻塞,直到 apply 线程(批内每条记录前也检查)放掉后端表面并以 `Fatal{ServerWindowLost}` 闩住会话;server 继续监听。进程内会话结束时手动做进程退出本来白给的清理(Espryt twin 与单元影子、swap interval、Magma renderer)。 - 失窗:`surfaceDestroyed` 有界(3 s)阻塞,直到 apply 线程(批内每条记录前也检查)放掉后端表面并以 `Fatal{ServerWindowLost}` 闩住会话;server 继续监听。进程内会话结束时手动做进程退出本来白给的清理(Espryt twin 与单元影子、swap interval、Magma renderer)。
- `HeadlessGL` 的 fork 预检会产生孤儿 server:server 的 EOF 检测即时且无条件退出。 - `HeadlessGL` 的 fork 预检会产生孤儿 server:server 的 EOF 检测即时且无条件退出。
@@ -82,4 +82,4 @@ CMake:`MOBILEGL_BUILD_DISAGGREGATED`(OFF)、`MOBILEGL_BUILD_DISAGGREGATED_
## 附 B:边界计数器(`MobileGL/MG_Util/Metrics/PipeStats.h`) ## 附 B:边界计数器(`MobileGL/MG_Util/Metrics/PipeStats.h`)
关闭时每站点一次全局 load + 一条永不命中的分支。字节类(stage buffer / texture / UBO / client 数组、`pmap`、`resid`、`csob-blob`、`seg` = 写进 `SEG_STAGE` 的字节)、调用类(`draws`、`accessor-calls`、纹理上传 emit / box / rect / jobs、`csom` / `csob`、`mpr`、`trp`、`rsp`、`wrec`、server 应用的控制记录 `ar`(applier_reset)/ `od`(object_death)、`maxrec` / `ringwraps` / `ringpads` / `ringwaits`、门铃 `srv` / `srvpark` / `cli` / `clipark`)与六个 memo 门的 hit/miss。每 `MOBILEGL_PIPE_STATS_PERIOD` 帧一条 `MGPipe stats:` 汇总行,按角色写日志。读法陷阱:`accessor-calls` 是静态下界,判性能只看 CPU 时间;spawn 下 client 不推进帧窗口(`frames=0`),窗口化字段在 spawn client 上无效,run total 仍有效([`docs/archive/notes/p6/README.md`](../../archive/notes/p6/README.md) §12.1)。站点清单(哪些路径**没有**接线)写在 `PipeStats.cpp` 头部,那份清单是契约。 关闭时每站点一次全局 load + 一条永不命中的分支。字节类(stage buffer / texture / UBO / client 数组、`pmap`、`resid`、`csob-blob`、`seg` = 写进 `SEG_STAGE` 的字节)、调用类(`draws`、`accessor-calls`、纹理上传 emit / box / rect / jobs、`csom` / `csob`、`mpr`、`trp`、`rsp`、`wrec`、server 应用的控制记录 `ar`(applier_reset)/ `od`(object_death)、`maxrec` / `ringwraps` / `ringpads` / `ringwaits`、门铃 `srv` / `srvpark` / `cli` / `clipark`)与六个 memo 门的 hit/miss。每 `MOBILEGL_PIPE_STATS_PERIOD` 帧一条 `MGPipe stats:` 汇总行,按角色写日志。读法陷阱:`accessor-calls` 是静态下界,判性能只看 CPU 时间;spawn 下 client 不推进帧窗口(`frames=0`),窗口化字段在 spawn client 上无效,run total 仍有效(见 git 历史 §12.1)。站点清单(哪些路径**没有**接线)写在 `PipeStats.cpp` 头部,那份清单是契约。

Some files were not shown because too many files have changed in this diff Show More