mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[MG_Pipe] preserve image-unit slots and publish named storage-binding programs
This commit is contained in:
@@ -2250,16 +2250,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
void DeleteTransformFeedback(GLuint name) {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
// No delete_stream_output opcode exists yet; the client refuses this class-C
|
||||
// verb before emission. Never reinterpret its GL name as a lifetime id.
|
||||
if (MG_Config::Transport != MG_Config::TransportMode::Monolith)
|
||||
MG_Pipe::MGPipeUnmigratedEmulation("delete-transform-feedback");
|
||||
auto& roleState = ActiveXfbState();
|
||||
auto& g_currentXfbState = roleState.Cached;
|
||||
auto& g_xfbObjects = roleState.Objects;
|
||||
auto& g_currentXfbName = roleState.Current;
|
||||
#endif
|
||||
const Bool server = MG_Config::Transport != MG_Config::TransportMode::Monolith;
|
||||
const Uint64 key = server ? MG_Pipe::MGPipeApplier().VerbDeleteStreamOutputLifetimeId : name;
|
||||
// A generated but never-bound name has no native object or lifetime.
|
||||
if (server && key == 0) return;
|
||||
const auto it = g_xfbObjects.find(key);
|
||||
#else
|
||||
const auto it = g_xfbObjects.find(name);
|
||||
#endif
|
||||
if (it == g_xfbObjects.end()) return;
|
||||
if (it->second.esId != 0 && g_GLESFuncs.glDeleteTransformFeedbacks != nullptr) {
|
||||
g_GLESFuncs.glDeleteTransformFeedbacks(1, &it->second.esId);
|
||||
@@ -2267,7 +2269,23 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
g_currentXfbState = nullptr; // erase shifts the probe cluster, moving other entries
|
||||
g_xfbObjects.erase(it);
|
||||
// The frontend reverts to the default object when the bound one is deleted.
|
||||
if (g_currentXfbName == name) {
|
||||
if (g_currentXfbName ==
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
key
|
||||
#else
|
||||
name
|
||||
#endif
|
||||
) {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
if (server) {
|
||||
// The following BindStreamOutput names this context's actual
|
||||
// default lifetime. Never create a native object for key 0.
|
||||
g_currentXfbName = 0;
|
||||
roleState.NeedsBind = true;
|
||||
BufferImpl::InvalidateTransformFeedbackBindingShadows();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
BindTransformFeedback(0);
|
||||
}
|
||||
}
|
||||
@@ -4191,7 +4209,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
if (MG_Config::Transport != MG_Config::TransportMode::Monolith) {
|
||||
for (Uint32 unit = 0; unit < end; ++unit) {
|
||||
if (unit >= st.BoundShaderImages.size()) break;
|
||||
SyncImageTextureBinding(st.BoundShaderImages[unit]);
|
||||
// The union can include a slot no set_shader_images
|
||||
// record has described yet. Its zero-initialized Unit
|
||||
// is not a binding identity: treating it as one unbinds
|
||||
// real unit 0 after binding the current program's images.
|
||||
// Array position identifies both retained and empty slots.
|
||||
auto view = st.BoundShaderImages[unit];
|
||||
view.Unit = unit;
|
||||
SyncImageTextureBinding(view);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
|
||||
#include "../Harness/HeadlessGL.h"
|
||||
#include "../Harness/P4aSeamPeek.h"
|
||||
#include "../Harness/SplitRuntimePeek.h"
|
||||
#include "../Harness/ScenarioFixture.h"
|
||||
|
||||
#ifdef GLAPI
|
||||
@@ -675,6 +676,10 @@ void main() { imageStore(i1, 0, imageLoad(i0, 0) + uvec4(2u, 0u, 0u, 0u)); }
|
||||
glMemoryBarrier(GL_ALL_BARRIER_BITS);
|
||||
EXPECT_EQ(FirstGLError(), 0u) << "the first dispatch leaked a GL error";
|
||||
if (whiteBox) {
|
||||
// A memory-barrier command orders GPU work; run-ahead need not
|
||||
// have applied it before this client-side white-box observation.
|
||||
const auto runtime = PeekSplitRuntime();
|
||||
if (runtime.sessionActive) ASSERT_TRUE(WaitForSplitAppliedForTesting(runtime.emitSeq));
|
||||
PipeShaderImageWindowPeek window{};
|
||||
ASSERT_TRUE(PeekPipeShaderImageWindow(&window));
|
||||
EXPECT_EQ(window.Start, 0u);
|
||||
@@ -688,6 +693,8 @@ void main() { imageStore(i1, 0, imageLoad(i0, 0) + uvec4(2u, 0u, 0u, 0u)); }
|
||||
glMemoryBarrier(GL_ALL_BARRIER_BITS);
|
||||
EXPECT_EQ(FirstGLError(), 0u) << "the second dispatch leaked a GL error";
|
||||
if (whiteBox) {
|
||||
const auto runtime = PeekSplitRuntime();
|
||||
if (runtime.sessionActive) ASSERT_TRUE(WaitForSplitAppliedForTesting(runtime.emitSeq));
|
||||
PipeShaderImageWindowPeek window{};
|
||||
ASSERT_TRUE(PeekPipeShaderImageWindow(&window));
|
||||
EXPECT_EQ(window.Start, 0u);
|
||||
|
||||
@@ -1297,6 +1297,7 @@ namespace MobileGL::MG_Remote::Client {
|
||||
// The backend slot's own first line (DirectGLES.cpp:9201), kept here so a null name
|
||||
// never becomes a zero-size blob - which rule A forbids spelling at all.
|
||||
if (storageBlockName == nullptr) return;
|
||||
BeforeReadOnlyVerb();
|
||||
|
||||
MG_Pipe::MGPStorageBlockBinding record{};
|
||||
record.GlName = static_cast<Uint32>(program);
|
||||
@@ -1305,8 +1306,14 @@ namespace MobileGL::MG_Remote::Client {
|
||||
if (MG_State::pGLContext != nullptr) {
|
||||
const auto& programObject = MG_State::pGLContext->GetProgramObject(program);
|
||||
if (programObject) {
|
||||
record.ShaderCso = MG_Pipe::MGPipeSlots().FindByLifetimeId(
|
||||
MG_Pipe::MGPipeKind::ShaderCso, programObject->GetLifetimeId());
|
||||
// The application may rebind a stage program before it is
|
||||
// current or attached to a pipeline. A minted slot alone does
|
||||
// not publish its archive; this verb must follow that birth.
|
||||
programObject->JoinLinkAndSpirv();
|
||||
Uint64 bytes = 0;
|
||||
auto& emitter = MG_Pipe::MGPipeProgramEmitterInstance();
|
||||
record.ShaderCso = emitter.AcquireShaderCso(*programObject, bytes);
|
||||
emitter.EmitProgramBindings(*programObject, record.ShaderCso);
|
||||
}
|
||||
}
|
||||
// Size = strlen + 1: THE NUL TRAVELS (contract table 0's block-name row). The
|
||||
|
||||
Reference in New Issue
Block a user