mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Fix] (Pipe): the default framebuffer's record names no placeholder surface that only one share group holds.
This commit is contained in:
@@ -524,22 +524,28 @@ namespace MobileGL::MG_Pipe {
|
||||
out.Target = static_cast<Uint8>(target);
|
||||
out.IsDefault = fbo.IsDefaultFramebuffer() ? 1 : 0;
|
||||
|
||||
// THE COLOUR POINTS. A default framebuffer keeps its one colour surface under
|
||||
// BackLeft rather than under Color0, and the record has exactly one place to put
|
||||
// it: Color[0], which is also the index MGPipeDrawBufferIndex maps that token to,
|
||||
// so the array and the draw-buffer indices agree by construction.
|
||||
if (out.IsDefault != 0) {
|
||||
out.Color[0] = SurfaceOf(fbo, FramebufferAttachmentType::BackLeft);
|
||||
} else {
|
||||
// THE SURFACES - and a DEFAULT framebuffer's record names none. Its storage on the
|
||||
// server is the surface the context is current on (the native window or pbuffer,
|
||||
// Magma's swapchain); both servers answer every default-framebuffer question from
|
||||
// IsDefault and never resolve a surface of this record. The frontend's attachments
|
||||
// are placeholders: one process-wide set of textures every context's framebuffer 0
|
||||
// shares, created once, so their records live in the ONE share group that was
|
||||
// bound when they were born. Naming them here sent every other group a handle it
|
||||
// holds no record for ("texture {12, 0} has no applier resource record" on each of
|
||||
// its draws) and marked bind bits on them under whichever context drew next.
|
||||
// Publishing them into every group instead would build a driver texture per group
|
||||
// for storage nothing reads. The extent still comes from them (FillGeometry), and
|
||||
// the draw-buffer indices below still map BackLeft to slot 0.
|
||||
if (out.IsDefault == 0) {
|
||||
for (SizeT i = 0; i < kMGPipeMaxColorAttachments; ++i) {
|
||||
out.Color[i] = SurfaceOf(fbo, static_cast<FramebufferAttachmentType>(
|
||||
static_cast<Int>(FramebufferAttachmentType::Color0) +
|
||||
static_cast<Int>(i)));
|
||||
}
|
||||
out.Depth = SurfaceOf(fbo, FramebufferAttachmentType::Depth);
|
||||
out.Stencil = SurfaceOf(fbo, FramebufferAttachmentType::Stencil);
|
||||
out.ReadSurface = SurfaceOf(fbo, fbo.GetReadBuffer());
|
||||
}
|
||||
out.Depth = SurfaceOf(fbo, FramebufferAttachmentType::Depth);
|
||||
out.Stencil = SurfaceOf(fbo, FramebufferAttachmentType::Stencil);
|
||||
out.ReadSurface = SurfaceOf(fbo, fbo.GetReadBuffer());
|
||||
|
||||
const auto& drawBuffers = fbo.GetDrawBuffers();
|
||||
for (SizeT i = 0; i < kMGPipeMaxColorAttachments; ++i) {
|
||||
|
||||
@@ -245,7 +245,7 @@ TEST(FramebufferEmit, TheEmitterIsOneNeverDestroyedProcessSingleton) {
|
||||
X(FramebufferEmit, EveryNonTexturePointCarriesTheUnknownSentinelsRatherThanZero) \
|
||||
X(FramebufferEmit, ADeadFramebuffersNamedRecordLatchIsRetired) \
|
||||
X(FramebufferEmit, TheRecordsElevenSurfacesAreTheWholePointSetTheServerReads) \
|
||||
X(FramebufferEmit, ADefaultFramebufferResizeReEmitsTheRecordWithItsNewExtent)
|
||||
X(FramebufferEmit, ADefaultFramebufferResizeReEmitsTheRecordWithItsNewExtent) X(FramebufferEmit, TheDefaultFramebuffersRecordNamesNoSurfaceAShareGroupWouldHaveToHold)
|
||||
|
||||
#define MGL_DECLARE_PULL_SKIP(Suite, Name) \
|
||||
TEST(Suite, Name) { GTEST_SKIP() << "compiled only under MOBILEGL_PIPE_PUSH"; }
|
||||
@@ -706,6 +706,46 @@ TEST(FramebufferEmit, ADefaultFramebufferResizeReEmitsTheRecordWithItsNewExtent)
|
||||
EXPECT_EQ(applied->Height, 96u);
|
||||
}
|
||||
|
||||
// THE DEFAULT FRAMEBUFFER'S RECORD NAMES NO SURFACE. Its attachments are the frontend's
|
||||
// placeholders - one process-wide set every context's framebuffer 0 shares, whose records live in
|
||||
// the one share group that was bound when they were born - and the server's default framebuffer
|
||||
// is the surface the context is current on. Red while the record named them: every other share
|
||||
// group was sent texture handles it held no record for, and logged the miss on each draw.
|
||||
TEST(FramebufferEmit, TheDefaultFramebuffersRecordNamesNoSurfaceAShareGroupWouldHaveToHold) {
|
||||
FramebufferScope scope;
|
||||
const auto color = MakeColorTexture(96, 64);
|
||||
const auto depthStencil = MakeShared<TextureObject2D>(97);
|
||||
depthStencil->SetInternalFormat(TextureInternalFormat::Depth32FStencil8);
|
||||
depthStencil->AllocateStorage(TextureUploadTarget::Texture2D, 0,
|
||||
MipmapInput{IntVec3{64, 64, 1}, static_cast<SizeT>(64 * 64 * 8)});
|
||||
const auto fbo0 = MakeShared<FramebufferObject>(0); // what MG_Impl::BuildDefaultFramebuffer builds
|
||||
ASSERT_TRUE(fbo0->IsDefaultFramebuffer());
|
||||
for (const auto point : {FramebufferAttachmentType::Color0, FramebufferAttachmentType::FrontLeft,
|
||||
FramebufferAttachmentType::FrontRight, FramebufferAttachmentType::BackLeft,
|
||||
FramebufferAttachmentType::BackRight}) {
|
||||
fbo0->AttachTexture(point, color, TextureUploadTarget::Texture2D);
|
||||
}
|
||||
fbo0->AttachTexture(FramebufferAttachmentType::Depth, depthStencil, TextureUploadTarget::Texture2D);
|
||||
fbo0->AttachTexture(FramebufferAttachmentType::Stencil, depthStencil, TextureUploadTarget::Texture2D);
|
||||
BindDrawAndRead(fbo0, fbo0);
|
||||
Framebuffers().EmitFramebufferState(Ctx());
|
||||
|
||||
const MGPFramebufferState* const applied = MGPipeApplier().DrawFramebuffer();
|
||||
ASSERT_NE(applied, nullptr) << "the default framebuffer's record did not reach the applier";
|
||||
EXPECT_EQ(applied->IsDefault, 1) << "MGPFramebufferState::IsDefault";
|
||||
for (Uint i = 0; i < kMGPipeMaxColorAttachments; ++i) {
|
||||
EXPECT_EQ(applied->Color[i].Kind, kMGPipeSurfaceKindNone) << "MGPSurface::Kind at colour point " << i;
|
||||
EXPECT_TRUE(MGPipeHandleIsNull(applied->Color[i].Res)) << "MGPSurface::Res at colour point " << i;
|
||||
}
|
||||
EXPECT_EQ(applied->Depth.Kind, kMGPipeSurfaceKindNone) << "MGPSurface::Kind on the depth point";
|
||||
EXPECT_EQ(applied->Stencil.Kind, kMGPipeSurfaceKindNone) << "MGPSurface::Kind on the stencil point";
|
||||
EXPECT_EQ(applied->ReadSurface.Kind, kMGPipeSurfaceKindNone) << "MGPFramebufferState::ReadSurface";
|
||||
// What the record still carries: the extent, and slot 0 as the back buffer's draw buffer.
|
||||
EXPECT_EQ(applied->Width, 64u) << "MGPFramebufferState::Width";
|
||||
EXPECT_EQ(applied->Height, 64u) << "MGPFramebufferState::Height";
|
||||
EXPECT_EQ(applied->DrawBuffers[0], 0) << "MGPFramebufferState::DrawBuffers[0]";
|
||||
}
|
||||
|
||||
// ============================ D-D2 ============================
|
||||
//
|
||||
// RED BEFORE THIS PACKAGE LANDED. RenderbufferObject's three storage setters bump no version
|
||||
|
||||
@@ -454,6 +454,12 @@ namespace {
|
||||
ASSERT_EQ(r.initialized, 1) << "the client hung or did not come up; client log " << logBase << "\n"
|
||||
<< server.Log();
|
||||
ASSERT_EQ(r.finished, 1) << "the client did not finish";
|
||||
// Every record named something its own context's share group holds. The default
|
||||
// framebuffer's placeholder textures were the standing exception: one process-wide set,
|
||||
// recorded in the group bound when they were born and named by every context's draw.
|
||||
const std::string serverLog = server.Log();
|
||||
EXPECT_EQ(serverLog.find("has no applier resource record"), std::string::npos)
|
||||
<< "a record named a texture its share group holds no record for";
|
||||
const int threads = shape == Shape::ReadbackRace ? 1 + kRaceChurners : kThreads;
|
||||
for (int i = 0; i < threads; ++i) {
|
||||
const ThreadReport& t = r.threads[i];
|
||||
|
||||
Reference in New Issue
Block a user