mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Fix] (Espryt): copy before any FBO attach in the packed16 probe - attaching the array relayouts it to the plain order and was neutralizing the subject
This commit is contained in:
@@ -1934,23 +1934,23 @@ namespace MobileGL::MG_Util::SelfTest {
|
|||||||
// 30/15/7 x12; the plain endpoints are 7/3/1), against plain-2D endpoints.
|
// 30/15/7 x12; the plain endpoints are 7/3/1), against plain-2D endpoints.
|
||||||
//
|
//
|
||||||
// WHAT THE DEVICE MEASUREMENTS ACTUALLY SHOWED (round 2): the mirrored field order is
|
// WHAT THE DEVICE MEASUREMENTS ACTUALLY SHOWED (round 2): the mirrored field order is
|
||||||
// a property of the WHOLE ALLOCATION, not of a mip level, and WHICH allocations get
|
// a property of the WHOLE ALLOCATION, not of a mip level - a 30x30x12 packed16 array
|
||||||
// it is a driver heuristic that keys on texture state during the uploads AND on
|
// is born in the mirrored layout at every level, while the small arrays the CTS's
|
||||||
// context history - and the two interact. Measured on the affected Mali, same shape,
|
// passing iterations used (7- and 15-texel bases; its src/dst dim loop is {7, 15}, so
|
||||||
// same data: in a raw standalone context, uploads-on-a-default-state texture mirror
|
// a base-30 array only ever appears at level 1) are born plain, which is why the
|
||||||
// while params-first-NEAREST allocations stay plain; in MobileGL's live context the
|
// failures looked per-mip-level from the QPA alone. AND the layout is not fixed for
|
||||||
// first deployment's params-first array MIRRORED while a later uploads-first one came
|
// the allocation's lifetime: FBO-ATTACHING the array transitions it to the plain
|
||||||
// out PLAIN - the raw ordering rule inverted. One- and two-level allocations and
|
// (renderable) layout, content preserved. That transition is what produced every
|
||||||
// params-first uploads under a mipmapped MIN_FILTER also mirrored raw. The small
|
// seemingly contradictory measurement of this campaign - a probe that direct-read its
|
||||||
// arrays the CTS's passing iterations used (7- and 15-texel bases; its src/dst dim
|
// array before copying relayouted its own subject and reported the device clean in
|
||||||
// loop is {7, 15}, so a base-30 array only ever appears at level 1) land plain, which
|
// the very process whose CTS copies kept mirroring, and the raw matrix's one
|
||||||
// is why the failures looked per-mip-level from the QPA alone. No single allocation
|
// "clean" 30x30x12 array was exactly the one that had been direct-read first. It is
|
||||||
// recipe is therefore entitled to speak for "the" layout: the probe allocates the
|
// also why the CTS's own "source image was not modified" checks always passed: they
|
||||||
// SAME client-visible texture several ways - the minted-backend order (uploads
|
// read through an FBO attach, after the copy already went wrong. So: subject copies
|
||||||
// first), the params-first order, and the CTS copy-test shape (MAX_LEVEL bounded,
|
// FIRST, every control that attaches the array AFTER, and because the driver's
|
||||||
// MIN_FILTER left at its mipmapped default; copy tests never set filters) - measures
|
// allocation heuristic beyond the size threshold is not fully mapped, the probe tries
|
||||||
// IN SITU, and a mirror delivered from ANY level of ANY variant is the finding, each
|
// several allocation recipes of the same client-visible texture and a mirror from ANY
|
||||||
// variant guarded by its own upload round-trip control.
|
// level of ANY recipe is the finding.
|
||||||
constexpr GLsizei kPacked16BaseSize = 30;
|
constexpr GLsizei kPacked16BaseSize = 30;
|
||||||
constexpr GLsizei kPacked16Layers = 12;
|
constexpr GLsizei kPacked16Layers = 12;
|
||||||
constexpr GLsizei kPacked16DstSize = 7;
|
constexpr GLsizei kPacked16DstSize = 7;
|
||||||
@@ -2114,21 +2114,29 @@ namespace MobileGL::MG_Util::SelfTest {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// One recipe's whole measurement: allocate, round-trip control, both subject copies.
|
// One recipe's whole measurement: allocate, both subject copies, THEN the round-trip
|
||||||
// Only a mirror that matches the PREDICTION while the variant's own round trip is
|
// control. The order is load-bearing: FBO-ATTACHING THE ARRAY TRANSITIONS IT to the
|
||||||
// clean counts; everything else is that variant's no-verdict (logged as such).
|
// plain (renderable) layout on the affected driver, so a round-trip read taken before
|
||||||
|
// the copies RELAYOUTS the subject and measures a texture the application's copy
|
||||||
|
// never sees - round two's first deployment did exactly that and reported the device
|
||||||
|
// clean while the CTS bodies kept failing in the same process. Copies first, the
|
||||||
|
// control after: the attach-driven transition preserves content, so the read still
|
||||||
|
// answers "the upload was intact" without disturbing what the copies measured. Only a
|
||||||
|
// mirror that matches the PREDICTION while that control holds counts; everything else
|
||||||
|
// is that recipe's no-verdict (logged as such).
|
||||||
Bool RunPacked16Recipe(const GLESFunctionsTable& gl, Packed16Recipe recipe) {
|
Bool RunPacked16Recipe(const GLESFunctionsTable& gl, Packed16Recipe recipe) {
|
||||||
Bool mirrored = false;
|
Bool mirrored = false;
|
||||||
const GLuint array = MakePacked16ArrayTexture(gl, recipe);
|
const GLuint array = MakePacked16ArrayTexture(gl, recipe);
|
||||||
GLubyte direct[4] = {0, 0, 0, 0};
|
GLubyte direct[4] = {0, 0, 0, 0};
|
||||||
GLubyte level0[4] = {0, 0, 0, 0};
|
GLubyte level0[4] = {0, 0, 0, 0};
|
||||||
GLubyte level1[4] = {0, 0, 0, 0};
|
GLubyte level1[4] = {0, 0, 0, 0};
|
||||||
if (array == 0 || !ReadPacked16Texel(gl, array, true, 1, direct)) {
|
if (array == 0 || !Packed16CopyLandsTexel(gl, array, GL_TEXTURE_2D_ARRAY, 0, level0) ||
|
||||||
MGLOG_I("[driver-bug] %s probe [%s]: no verdict (the array could not be built or "
|
!Packed16CopyLandsTexel(gl, array, GL_TEXTURE_2D_ARRAY, 1, level1)) {
|
||||||
"read back)",
|
MGLOG_I("[driver-bug] %s probe [%s]: no verdict (a subject copy could not run)",
|
||||||
kPacked16CopyProbeName, Packed16RecipeName(recipe));
|
kPacked16CopyProbeName, Packed16RecipeName(recipe));
|
||||||
} else if (!Packed16TexelNear(direct, kPacked16Expected)) {
|
} else if (!ReadPacked16Texel(gl, array, true, 1, direct) ||
|
||||||
// The variant's own round trip: reading the level DIRECTLY decodes the driver's
|
!Packed16TexelNear(direct, kPacked16Expected)) {
|
||||||
|
// The recipe's own round trip: reading the level directly decodes the driver's
|
||||||
// own storage and must deliver the word whatever layout it picked. A wrong
|
// own storage and must deliver the word whatever layout it picked. A wrong
|
||||||
// answer means the UPLOAD is what corrupts - a different defect, and one the
|
// answer means the UPLOAD is what corrupts - a different defect, and one the
|
||||||
// widening's raw-copy reasoning says nothing about.
|
// widening's raw-copy reasoning says nothing about.
|
||||||
@@ -2137,10 +2145,6 @@ namespace MobileGL::MG_Util::SelfTest {
|
|||||||
"copy, is what diverges)",
|
"copy, is what diverges)",
|
||||||
kPacked16CopyProbeName, Packed16RecipeName(recipe), direct[0], direct[1],
|
kPacked16CopyProbeName, Packed16RecipeName(recipe), direct[0], direct[1],
|
||||||
direct[2], direct[3]);
|
direct[2], direct[3]);
|
||||||
} else if (!Packed16CopyLandsTexel(gl, array, GL_TEXTURE_2D_ARRAY, 0, level0) ||
|
|
||||||
!Packed16CopyLandsTexel(gl, array, GL_TEXTURE_2D_ARRAY, 1, level1)) {
|
|
||||||
MGLOG_I("[driver-bug] %s probe [%s]: no verdict (a subject copy could not run)",
|
|
||||||
kPacked16CopyProbeName, Packed16RecipeName(recipe));
|
|
||||||
} else if (Packed16TexelNear(level0, kPacked16Mirrored) ||
|
} else if (Packed16TexelNear(level0, kPacked16Mirrored) ||
|
||||||
Packed16TexelNear(level1, kPacked16Mirrored)) {
|
Packed16TexelNear(level1, kPacked16Mirrored)) {
|
||||||
mirrored = true;
|
mirrored = true;
|
||||||
|
|||||||
@@ -307,29 +307,30 @@ namespace MobileGL::MG_Util::SelfTest {
|
|||||||
//
|
//
|
||||||
// The affected Mali stores SOME 16-bit packed allocations (RGB565 / RGB5_A1 / RGBA4) with
|
// The affected Mali stores SOME 16-bit packed allocations (RGB565 / RGB5_A1 / RGBA4) with
|
||||||
// their fields packed from the other end of the word. The mirrored layout is an
|
// their fields packed from the other end of the word. The mirrored layout is an
|
||||||
// ALLOCATION property, not a mip-level one - the failing device delivers the mirror from
|
// ALLOCATION property, not a mip-level one - the failing device's 30x30x12 array is born
|
||||||
// level 0 and level 1 alike, which is what vetoed the first deployment's "level 0 is the
|
// mirrored at level 0 and level 1 alike, which is what vetoed the first deployment's
|
||||||
// clean control" design - and WHICH allocations get it is a heuristic keying on texture
|
// "level 0 is the clean control" design - and it is not fixed for the allocation's
|
||||||
// state during the uploads and on context history, measured to INVERT between a raw
|
// lifetime either: FBO-ATTACHING the array transitions it to the plain layout, content
|
||||||
// standalone context and MobileGL's live one. No single allocation recipe is therefore
|
// preserved, which is why a probe that direct-reads its array before copying relayouts
|
||||||
// entitled to speak for the layout: the probe builds the CTS's failing shape (three-level
|
// its own subject and measures a texture the application's copies never see (the second
|
||||||
// chains both endpoints: 30/15/7 x12 array, 7/3/1 plain, FUNCTIONAL_TEST_N_LEVELS = 3)
|
// deployment's miss), and why the CTS's "source not modified" checks always passed. The
|
||||||
// with three recipes - uploads-first (the minted-backend-texture order), params-first,
|
// probe builds the CTS's failing shape (three-level chains both endpoints: 30/15/7 x12
|
||||||
// and the CTS copy-test shape (MAX_LEVEL bounded, MIN_FILTER left mipmapped-default) -
|
// array, 7/3/1 plain, FUNCTIONAL_TEST_N_LEVELS = 3) with several allocation recipes,
|
||||||
// in situ, in the very context the application's copies run in. Uploads and readbacks
|
// copies FIRST, in situ, and a mirror delivered from any level of any recipe is the
|
||||||
// decode each image's own layout consistently, so nothing but a raw texel-block move can
|
// finding. Uploads and readbacks decode each image's layout of the moment consistently,
|
||||||
// see the divergence - which is exactly what glCopyImageSubData is defined to be, and why
|
// so nothing but a raw texel-block move can see the divergence - which is exactly what
|
||||||
// the whole KHR-GL4x.copy_image rgb5/rgb5_a1/rgba4 x *2d_array* matrix fails there while
|
// glCopyImageSubData is defined to be, and why the whole KHR-GL4x.copy_image
|
||||||
// every other suite touching these formats passes.
|
// rgb5/rgb5_a1/rgba4 x *2d_array* matrix fails there while every other suite touching
|
||||||
|
// these formats passes.
|
||||||
//
|
//
|
||||||
// CONTROLS. The machinery: an identical copy between two SAME-shape plain-2D images,
|
// CONTROLS. The machinery: an identical copy between two SAME-shape plain-2D images,
|
||||||
// which share a layout whatever it is, so it must deliver the word on any driver that can
|
// which share a layout whatever it is, so it must deliver the word on any driver that can
|
||||||
// run copy_image on these formats - a driver that cannot reaches no verdict instead of
|
// run copy_image on these formats - a driver that cannot reaches no verdict instead of
|
||||||
// being reported as this. And per recipe, the array's own round trip: a direct FBO
|
// being reported as this. And per recipe, AFTER its subject copies, the array's own round
|
||||||
// readback of its level 1 must answer the word, or the UPLOAD is what corrupts - a
|
// trip: a direct FBO readback of its level 1 must answer the word, or the UPLOAD is what
|
||||||
// different defect. The subjects must also match the mirror PREDICTION, not merely differ
|
// corrupts - a different defect. The subjects must also match the mirror PREDICTION, not
|
||||||
// from the word - a copy that delivered anything else is a different defect and reaches
|
// merely differ from the word - a copy that delivered anything else is a different defect
|
||||||
// no verdict either. Restores every piece of GL state it touches.
|
// and reaches no verdict either. Restores every piece of GL state it touches.
|
||||||
Bool ProbeCopyImageMirrorsPacked16FieldOrder(const MG_External::GLESFunctionsTable& gl);
|
Bool ProbeCopyImageMirrorsPacked16FieldOrder(const MG_External::GLESFunctionsTable& gl);
|
||||||
|
|
||||||
// ProbeCopyImageMirrorsPacked16FieldOrder(), evaluated at most once per process. The
|
// ProbeCopyImageMirrorsPacked16FieldOrder(), evaluated at most once per process. The
|
||||||
|
|||||||
Reference in New Issue
Block a user