mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Perf] (TLS): pGLContext and gPipeInputs become pointer slots
This commit is contained in:
@@ -115,7 +115,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// addresses again - the cached pointers cannot go stale. Invalidation is
|
||||
// exactly the pointer compare below.
|
||||
using FbBindingSlot =
|
||||
std::remove_reference_t<decltype(MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw))>;
|
||||
std::remove_reference_t<decltype(MG_Pipe::gPipeInputs->GetFramebufferBindingSlot(FramebufferTarget::Draw))>;
|
||||
// P2 step e4. On the {slot, gen} arm this is an ORDINARY read of pushed state and the cache
|
||||
// above is not consulted, which closes the P1 accessor bypass: the cached raw pointer ran
|
||||
// the checked accessor once per context change and then handed out the pointee forever, so
|
||||
@@ -132,10 +132,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// frontend getter still linear-scans, so the cache is exactly the code it was.
|
||||
static inline FbBindingSlot& GetFramebufferBindingSlotChecked(FramebufferTarget target) {
|
||||
if (EsprytSlotTablesEnabled()) {
|
||||
return MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(target);
|
||||
return MG_Pipe::gPipeInputs->GetFramebufferBindingSlot(target);
|
||||
}
|
||||
// No legacy arm compiled: EsprytSlotTablesEnabled() is unconditionally true above.
|
||||
return MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(target);
|
||||
return MG_Pipe::gPipeInputs->GetFramebufferBindingSlot(target);
|
||||
}
|
||||
|
||||
// A4, TAKEN AT THE VERIFICATION ROUND, AND THE FOUR TEMPORARY LATCHES ARE GONE WITH IT.
|
||||
@@ -181,7 +181,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
[[noreturn]] static void RefuseFramebufferBindingSlotRead() {
|
||||
MG_Pipe::MGPipeInputPoisonFatalForVerb(MG_Pipe::MGPipeInputField::GetFramebufferBindingSlot,
|
||||
MG_Pipe::gPipeInputs.CurrentVerb());
|
||||
MG_Pipe::gPipeInputs->CurrentVerb());
|
||||
}
|
||||
|
||||
static Bool IsDualSourceBlendFactor(BlendFactor v) {
|
||||
@@ -1146,7 +1146,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
const SizeT packedStride = program->GetTransformFeedbackPackedStride();
|
||||
const SizeT modelledVertices =
|
||||
static_cast<SizeT>(MG_Pipe::gPipeInputs.GetTransformFeedbackCapturedVertices());
|
||||
static_cast<SizeT>(MG_Pipe::gPipeInputs->GetTransformFeedbackCapturedVertices());
|
||||
const SizeT vertices = std::min<SizeT>(modelledVertices, xfb.scatterCapacityVertices);
|
||||
if (packedStride == 0 || vertices == 0) {
|
||||
// The scatter path redirected the DRIVER's capture into the scratch buffer,
|
||||
@@ -1669,7 +1669,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
auto* twin = ResolveVaoTwin(MG_Pipe::MGPipeApplier().BoundVertexElements);
|
||||
if (twin == nullptr) return;
|
||||
const auto& currentVAO = MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
const auto& currentVAO = MG_Pipe::gPipeInputs->GetBoundVertexArray();
|
||||
if (!currentVAO) return;
|
||||
twin->SyncClientSideAttributesForDrawArrays(currentVAO, first, count);
|
||||
return;
|
||||
@@ -1766,7 +1766,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
for (Uint32 remaining = memo.pendingMask; remaining != 0; remaining &= remaining - 1) {
|
||||
const Uint32 location = static_cast<Uint32>(std::countr_zero(remaining));
|
||||
|
||||
const auto& currentValue = MG_Pipe::gPipeInputs.GetCurrentVertexAttribute(location);
|
||||
const auto& currentValue = MG_Pipe::gPipeInputs->GetCurrentVertexAttribute(location);
|
||||
const auto typeInfo = MG_State::GLState::ClassifyVertexAttribType(program->GetAttribType(location));
|
||||
switch (typeInfo.baseType) {
|
||||
case MG_State::GLState::VertexAttribBaseType::Float:
|
||||
@@ -1909,7 +1909,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// below rather than reading past the end.
|
||||
const GLenum attribType =
|
||||
location < link.attribTypes.size() ? link.attribTypes[location] : 0;
|
||||
const auto& currentValue = MG_Pipe::gPipeInputs.GetCurrentVertexAttribute(location);
|
||||
const auto& currentValue = MG_Pipe::gPipeInputs->GetCurrentVertexAttribute(location);
|
||||
const auto typeInfo = MG_State::GLState::ClassifyVertexAttribType(attribType);
|
||||
switch (typeInfo.baseType) {
|
||||
case MG_State::GLState::VertexAttribBaseType::Float:
|
||||
@@ -1986,7 +1986,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
static void CaptureUnitBindings(Int maxTouchedUnit, Vector<UnitBindingsSnapshot>& out) {
|
||||
out.resize(static_cast<SizeT>(maxTouchedUnit + 1));
|
||||
for (Int unit = 0; unit <= maxTouchedUnit; ++unit) {
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit);
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs->GetTextureUnitObject(unit);
|
||||
auto& snapshot = out[static_cast<SizeT>(unit)];
|
||||
const auto& slots = textureUnit.GetAllBindingSlots();
|
||||
for (SizeT i = 0; i < slots.size(); ++i) {
|
||||
@@ -1999,7 +1999,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
static Bool UnitBindingsUnchanged(Int maxTouchedUnit, const Vector<UnitBindingsSnapshot>& snapshots) {
|
||||
if (snapshots.size() != static_cast<SizeT>(maxTouchedUnit + 1)) return false;
|
||||
for (Int unit = 0; unit <= maxTouchedUnit; ++unit) {
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit);
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs->GetTextureUnitObject(unit);
|
||||
const auto& snapshot = snapshots[static_cast<SizeT>(unit)];
|
||||
const auto& slots = textureUnit.GetAllBindingSlots();
|
||||
for (SizeT i = 0; i < slots.size(); ++i) {
|
||||
@@ -2146,8 +2146,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Util::PipeStats::CountGate(MG_Util::PipeStats::Gate::EsprytUnitBindingsEpoch,
|
||||
/*hit=*/false);
|
||||
}
|
||||
const Uint64 contextId = MG_Pipe::gPipeInputs.GetTextureContextId();
|
||||
const Uint64 bindGeneration = MG_Pipe::gPipeInputs.GetTextureBindGeneration();
|
||||
const Uint64 contextId = MG_Pipe::gPipeInputs->GetTextureContextId();
|
||||
const Uint64 bindGeneration = MG_Pipe::gPipeInputs->GetTextureBindGeneration();
|
||||
if (MG_Util::PipeStats::Enabled()) {
|
||||
// Two accessor calls whichever way the shutter goes; only the unit WALK is
|
||||
// gated, and that walk reads no GLContext accessor of its own.
|
||||
@@ -2366,7 +2366,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
DrawTextureSyncKeys CaptureDrawTextureSyncKeys() {
|
||||
DrawTextureSyncKeys keys;
|
||||
keys.contextId = MG_Pipe::gPipeInputs.GetTextureContextId();
|
||||
keys.contextId = MG_Pipe::gPipeInputs->GetTextureContextId();
|
||||
// Units past the frontend's high-water mark have provably-empty slots.
|
||||
//
|
||||
// P4a e2 DELIBERATELY DOES NOT take this off the sampler-view window's Count, and
|
||||
@@ -2379,8 +2379,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// CLIENT as the count argument and says nothing about re-deriving it server-side.
|
||||
// It is one accessor read per draw; the integrator can move it in one line once a
|
||||
// tree exists where the two can be compared.
|
||||
keys.maxTouchedUnit = MG_Pipe::gPipeInputs.GetMaxTouchedTextureUnit();
|
||||
keys.samplingGeneration = MG_Pipe::gPipeInputs.GetSamplingResolutionGeneration();
|
||||
keys.maxTouchedUnit = MG_Pipe::gPipeInputs->GetMaxTouchedTextureUnit();
|
||||
keys.samplingGeneration = MG_Pipe::gPipeInputs->GetSamplingResolutionGeneration();
|
||||
keys.unitBindingsEpoch = CurrentUnitBindingsEpoch(keys.maxTouchedUnit);
|
||||
if (MG_Util::PipeStats::Enabled()) {
|
||||
// The three reads above; CurrentUnitBindingsEpoch counts its own two when it
|
||||
@@ -3455,7 +3455,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#ifdef TRACY_ENABLE
|
||||
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
||||
#endif
|
||||
Uint16 currentRenderStateVersion = MG_Pipe::gPipeInputs.GetRenderStateParametersVersion();
|
||||
Uint16 currentRenderStateVersion = MG_Pipe::gPipeInputs->GetRenderStateParametersVersion();
|
||||
const Bool forceFullPush = g_forceFullRenderStateResync;
|
||||
g_forceFullRenderStateResync = false;
|
||||
// The alpha discipline for widened colour attachments (see the header comment on
|
||||
@@ -3483,7 +3483,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Util::PipeStats::AddCalls(MG_Util::PipeStats::CallClass::AccessorCalls, 3);
|
||||
}
|
||||
|
||||
const auto& parameters = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
const auto& parameters = MG_Pipe::gPipeInputs->GetRenderStateParameters();
|
||||
|
||||
// The frontend has ONE version for the whole parameter block, so a per-draw blend
|
||||
// toggle used to re-diff all ~40 pieces of state field by field on every draw
|
||||
@@ -3512,7 +3512,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
!g_hasSyncedRenderState || std::memcmp(currentBytes + kBlendSpanEnd, syncedBytes + kBlendSpanEnd,
|
||||
sizeof(RenderStateParameters) - kBlendSpanEnd) != 0;
|
||||
|
||||
IntVec4 backendViewport = MG_Pipe::gPipeInputs.GetViewport();
|
||||
IntVec4 backendViewport = MG_Pipe::gPipeInputs->GetViewport();
|
||||
if (backendViewport.z() <= 0 || backendViewport.w() <= 0) {
|
||||
Int surfaceWidth = 0;
|
||||
Int surfaceHeight = 0;
|
||||
@@ -3595,7 +3595,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// never turns it on, so the driver has to be told to write raw. Without this a render
|
||||
// into an sRGB colour buffer comes back encoded once too often (the shader's own
|
||||
// decode on the next fetch then leaves the value one conversion short).
|
||||
const Bool srgbWrites = MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::FramebufferSrgb);
|
||||
const Bool srgbWrites = MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::FramebufferSrgb);
|
||||
if (g_GLESCapabilities.SupportsSrgbWriteControl &&
|
||||
(forceFullPush || srgbWrites != g_syncedSrgbFramebufferWrites)) {
|
||||
srgbWrites ? g_GLESFuncs.glEnable(GL_FRAMEBUFFER_SRGB)
|
||||
@@ -4505,11 +4505,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
!twin->ImageUnitFormatsStillMatch() ||
|
||||
(twin->GetPassthroughTessControlPatchVertices() >= 0 &&
|
||||
(twin->GetPassthroughTessControlPatchVertices() !=
|
||||
static_cast<Int>(MG_Pipe::gPipeInputs.GetPatchVertices()) ||
|
||||
static_cast<Int>(MG_Pipe::gPipeInputs->GetPatchVertices()) ||
|
||||
!BitwiseEqual(twin->GetPassthroughTessControlOuterLevel(),
|
||||
MG_Pipe::gPipeInputs.GetPatchDefaultOuterLevel()) ||
|
||||
MG_Pipe::gPipeInputs->GetPatchDefaultOuterLevel()) ||
|
||||
!BitwiseEqual(twin->GetPassthroughTessControlInnerLevel(),
|
||||
MG_Pipe::gPipeInputs.GetPatchDefaultInnerLevel())))) {
|
||||
MG_Pipe::gPipeInputs->GetPatchDefaultInnerLevel())))) {
|
||||
twin->SyncToBackendByHandle(cso);
|
||||
}
|
||||
g_currentDrawProgramHandle = cso;
|
||||
@@ -5846,12 +5846,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// times; rasterizer discard means there are no fragments to gate at all, so replaying
|
||||
// would be pure cost with nothing to show for it. Both fall back to a single pass with an
|
||||
// open gate, i.e. to the pre-emulation behaviour, rather than to wrong data.
|
||||
if (MG_Pipe::gPipeInputs.IsTransformFeedbackActive() ||
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::RasterizerDiscard)) {
|
||||
if (MG_Pipe::gPipeInputs->IsTransformFeedbackActive() ||
|
||||
MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::RasterizerDiscard)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const auto& parameters = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
const auto& parameters = MG_Pipe::gPipeInputs->GetRenderStateParameters();
|
||||
Int surfaceWidth = 0;
|
||||
Int surfaceHeight = 0;
|
||||
if (!QueryCurrentSurfaceSize(surfaceWidth, surfaceHeight)) {
|
||||
@@ -6228,7 +6228,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// color must go through glClearBufferfv, which GLES does not clamp.
|
||||
GLbitfield remainingMask = mask;
|
||||
if ((mask & GL_COLOR_BUFFER_BIT) != 0) {
|
||||
const FloatVec4& cc = MG_Pipe::gPipeInputs.GetRenderStateParameters().ClearColor;
|
||||
const FloatVec4& cc = MG_Pipe::gPipeInputs->GetRenderStateParameters().ClearColor;
|
||||
const Bool outOfRange = cc.x() < 0.f || cc.x() > 1.f || cc.y() < 0.f || cc.y() > 1.f || cc.z() < 0.f ||
|
||||
cc.z() > 1.f || cc.w() < 0.f || cc.w() > 1.f;
|
||||
// A widened attachment's stored alpha has to end up 1.0, and glClear applies ONE
|
||||
@@ -6456,13 +6456,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
} // namespace
|
||||
|
||||
RestartSubstitutionKind ResolveRestartSubstitution(GLenum indexType) {
|
||||
if (!MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::PrimitiveRestart) ||
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::PrimitiveRestartFixedIndex)) {
|
||||
if (!MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::PrimitiveRestart) ||
|
||||
MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::PrimitiveRestartFixedIndex)) {
|
||||
return RestartSubstitutionKind::None;
|
||||
}
|
||||
const Uint32 fixedMax = MG_Util::FixedRestartIndexForGLType(indexType);
|
||||
if (fixedMax == 0) return RestartSubstitutionKind::None;
|
||||
const Uint32 restartIndex = MG_Pipe::gPipeInputs.GetPrimitiveRestartIndex();
|
||||
const Uint32 restartIndex = MG_Pipe::gPipeInputs->GetPrimitiveRestartIndex();
|
||||
if (restartIndex == fixedMax) return RestartSubstitutionKind::None;
|
||||
// Strictly greater, never truncated. GL 4.6 core 10.3.6 compares the fetched index
|
||||
// zero-extended against the full 32-bit state, so an index this type cannot hold matches
|
||||
@@ -6502,7 +6502,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
const SizeT sourceIndexSize = MG_Util::GetGLTypeSize(indexType);
|
||||
const Uint32 fixedMax = MG_Util::FixedRestartIndexForGLType(indexType);
|
||||
const Uint32 applicationRestartIndex = MG_Pipe::gPipeInputs.GetPrimitiveRestartIndex();
|
||||
const Uint32 applicationRestartIndex = MG_Pipe::gPipeInputs->GetPrimitiveRestartIndex();
|
||||
|
||||
const Uint8* source = nullptr;
|
||||
SizeT indexCount = 0;
|
||||
@@ -7395,8 +7395,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// restore. Drop the flag so it is not misattributed to the emulation's own work.
|
||||
DrainBlitErrors();
|
||||
|
||||
if (MG_Pipe::gPipeInputs.IsTransformFeedbackActive() &&
|
||||
!MG_Pipe::gPipeInputs.IsTransformFeedbackPaused() && g_GLESFuncs.glPauseTransformFeedback) {
|
||||
if (MG_Pipe::gPipeInputs->IsTransformFeedbackActive() &&
|
||||
!MG_Pipe::gPipeInputs->IsTransformFeedbackPaused() && g_GLESFuncs.glPauseTransformFeedback) {
|
||||
g_GLESFuncs.glPauseTransformFeedback();
|
||||
m_pausedTransformFeedback = true;
|
||||
DrainBlitErrors();
|
||||
@@ -8618,7 +8618,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#ifdef TRACY_ENABLE
|
||||
ZoneScopedNC(__func__, TRACY_ZONECOLOR_BACKEND);
|
||||
#endif
|
||||
auto unit = MG_Pipe::gPipeInputs.GetActiveTextureUnit();
|
||||
auto unit = MG_Pipe::gPipeInputs->GetActiveTextureUnit();
|
||||
|
||||
auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
||||
if (!TextureImpl::IsSupportedTextureTarget(textureTarget)) {
|
||||
@@ -8695,7 +8695,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// The frontend's current PACK parameters, for readbacks the ES driver serves
|
||||
// directly with the client's layout.
|
||||
static PixelStoreImpl::PackState PackStateFromContext() {
|
||||
const auto packParams = MG_Pipe::gPipeInputs.GetPixelStoreParameters(false);
|
||||
const auto packParams = MG_Pipe::gPipeInputs->GetPixelStoreParameters(false);
|
||||
return {static_cast<GLint>(packParams.Alignment), static_cast<GLint>(packParams.RowLength),
|
||||
static_cast<GLint>(packParams.SkipRows), static_cast<GLint>(packParams.SkipPixels)};
|
||||
}
|
||||
@@ -8891,7 +8891,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Util::ConvertGLEnumToString(err).c_str(),
|
||||
MG_Util::ConvertGLEnumToString(target).c_str(),
|
||||
MG_Util::ConvertTextureInternalFormatToString(format).c_str());
|
||||
MG_Pipe::gPipeInputs.RecordError(
|
||||
MG_Pipe::gPipeInputs->RecordError(
|
||||
ConvertGLESErrorToErrorCode(err),
|
||||
MakeUnique<GenericErrorInfo>("DirectGLES", operation,
|
||||
MG_Util::ConvertGLEnumToString(err)));
|
||||
@@ -9407,7 +9407,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
// Bind necessary FBO and texture
|
||||
BindCurrentFBO(FramebufferTarget::Read);
|
||||
Uint activeTextureUnit = MG_Pipe::gPipeInputs.GetActiveTextureUnit();
|
||||
Uint activeTextureUnit = MG_Pipe::gPipeInputs->GetActiveTextureUnit();
|
||||
TextureImpl::BackendTextureObject* dstBackendTexture = nullptr;
|
||||
TextureInternalFormat mgInternalFormat{};
|
||||
// P5c (hd, CONTRACT-P5C §3.4): with an active transport the destination resolves from
|
||||
@@ -9516,7 +9516,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
// Bind necessary FBO and texture
|
||||
BindCurrentFBO(FramebufferTarget::Read);
|
||||
auto activeTextureUnit = MG_Pipe::gPipeInputs.GetActiveTextureUnit();
|
||||
auto activeTextureUnit = MG_Pipe::gPipeInputs->GetActiveTextureUnit();
|
||||
TextureImpl::BackendTextureObject* dstBackendTexture = nullptr;
|
||||
// P5c (hd, CONTRACT-P5C §3.4): see CopyTexImage2D - the record's Dst handle, never the
|
||||
// client's unit binding slot or the client allocator (T2/T4).
|
||||
@@ -10347,7 +10347,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
template <typename FillRow>
|
||||
static Bool StoreReadbackRowsToClient(GLsizei width, GLsizei height, SizeT dstPixelBytes, void* pixels,
|
||||
const char* what, FillRow&& fillRow) {
|
||||
const auto packParams = MG_Pipe::gPipeInputs.GetPixelStoreParameters(false);
|
||||
const auto packParams = MG_Pipe::gPipeInputs->GetPixelStoreParameters(false);
|
||||
const SizeT rowPixels = static_cast<SizeT>(packParams.RowLength > 0 ? packParams.RowLength : width);
|
||||
const SizeT dstRowStride = AlignPixelRow(rowPixels * dstPixelBytes, packParams.Alignment);
|
||||
const SizeT dstOffset = static_cast<SizeT>(std::max(packParams.SkipRows, 0)) * dstRowStride +
|
||||
@@ -11811,7 +11811,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// and legacy GL_RED reads) goes through the wide-format conversion, which picks a wide type
|
||||
// the driver accepts for the current attachment. GL_PACK_SWAP_BYTES has no ES equivalent, so
|
||||
// it always takes the conversion path (which swaps on the CPU).
|
||||
const Bool packSwapBytes = MG_Pipe::gPipeInputs.GetPixelStoreParameters(false).SwapBytes;
|
||||
const Bool packSwapBytes = MG_Pipe::gPipeInputs->GetPixelStoreParameters(false).SwapBytes;
|
||||
// The read buffer is what glReadPixels reads, so the frontend's READ binding is exactly
|
||||
// the right thing to ask here.
|
||||
const Bool forceOpaqueAlpha = FramebufferImpl::IsAlphaWidenedFallbackReadAttachment();
|
||||
|
||||
@@ -7198,9 +7198,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// that needs no work costs the same nothing per draw that any other synced texture does.
|
||||
void BackendTextureObject::StampViewSyncKeys(
|
||||
const SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject) {
|
||||
if (MG_Pipe::gPipeInputs.IsLive()) {
|
||||
m_syncedShapeContextId = MG_Pipe::gPipeInputs.GetTextureContextId();
|
||||
m_syncedShapeGeneration = MG_Pipe::gPipeInputs.GetSamplingResolutionGeneration();
|
||||
if (MG_Pipe::gPipeInputs->IsLive()) {
|
||||
m_syncedShapeContextId = MG_Pipe::gPipeInputs->GetTextureContextId();
|
||||
m_syncedShapeGeneration = MG_Pipe::gPipeInputs->GetSamplingResolutionGeneration();
|
||||
m_syncedShapeParamsVersion = stateTextureObject->GetTextureParamsVersion();
|
||||
}
|
||||
m_syncedContentVersion = stateTextureObject->GetContentVersion();
|
||||
@@ -7349,9 +7349,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// LEGACY ARM ONLY from P4a on: the memos it reads are the pre-handle ones and the
|
||||
// record above answers the same question in one compare.
|
||||
if (pushedStorage == nullptr)
|
||||
if (m_isInitialized && m_syncedShapeContextId != 0 && MG_Pipe::gPipeInputs.IsLive() &&
|
||||
m_syncedShapeContextId == MG_Pipe::gPipeInputs.GetTextureContextId() &&
|
||||
m_syncedShapeGeneration == MG_Pipe::gPipeInputs.GetSamplingResolutionGeneration() &&
|
||||
if (m_isInitialized && m_syncedShapeContextId != 0 && MG_Pipe::gPipeInputs->IsLive() &&
|
||||
m_syncedShapeContextId == MG_Pipe::gPipeInputs->GetTextureContextId() &&
|
||||
m_syncedShapeGeneration == MG_Pipe::gPipeInputs->GetSamplingResolutionGeneration() &&
|
||||
m_syncedContentVersion == stateTextureObject->GetContentVersion() &&
|
||||
m_syncedShapeParamsVersion == stateTextureObject->GetTextureParamsVersion() &&
|
||||
stateTextureObject->GetStorageType() == TextureStorageType::Mipmap) {
|
||||
@@ -7467,9 +7467,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// The probe just proved "fully synced" from the real state, so the cheap
|
||||
// gate may be (re)stamped here: the coarse generation only ever goes stale
|
||||
// from OTHER textures' churn, and this draw re-validated this one.
|
||||
if (MG_Pipe::gPipeInputs.IsLive()) {
|
||||
m_syncedShapeContextId = MG_Pipe::gPipeInputs.GetTextureContextId();
|
||||
m_syncedShapeGeneration = MG_Pipe::gPipeInputs.GetSamplingResolutionGeneration();
|
||||
if (MG_Pipe::gPipeInputs->IsLive()) {
|
||||
m_syncedShapeContextId = MG_Pipe::gPipeInputs->GetTextureContextId();
|
||||
m_syncedShapeGeneration = MG_Pipe::gPipeInputs->GetSamplingResolutionGeneration();
|
||||
m_syncedShapeParamsVersion = stateTextureObject->GetTextureParamsVersion();
|
||||
}
|
||||
return;
|
||||
@@ -8764,9 +8764,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// Same instant, so the cheap gate's keys describe exactly this synced state.
|
||||
// Only Mipmap storage may arm it - the gate refuses other storage types anyway,
|
||||
// but a stale trio must not linger on an object that later switches type.
|
||||
if (MG_Pipe::gPipeInputs.IsLive() && stateTextureObject->GetStorageType() == TextureStorageType::Mipmap) {
|
||||
m_syncedShapeContextId = MG_Pipe::gPipeInputs.GetTextureContextId();
|
||||
m_syncedShapeGeneration = MG_Pipe::gPipeInputs.GetSamplingResolutionGeneration();
|
||||
if (MG_Pipe::gPipeInputs->IsLive() && stateTextureObject->GetStorageType() == TextureStorageType::Mipmap) {
|
||||
m_syncedShapeContextId = MG_Pipe::gPipeInputs->GetTextureContextId();
|
||||
m_syncedShapeGeneration = MG_Pipe::gPipeInputs->GetSamplingResolutionGeneration();
|
||||
m_syncedShapeParamsVersion = stateTextureObject->GetTextureParamsVersion();
|
||||
} else {
|
||||
m_syncedShapeContextId = 0;
|
||||
@@ -9905,7 +9905,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return record && record->ReadSurface.Kind != MG_Pipe::kMGPipeSurfaceKindNone &&
|
||||
IsSnormFormat(static_cast<TextureInternalFormat>(record->ReadSurface.InternalFormat));
|
||||
const auto& readFBO =
|
||||
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||
if (!readFBO) {
|
||||
return false;
|
||||
}
|
||||
@@ -11980,19 +11980,19 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// patch size - so a program built for one value is stale for another. Recorded here
|
||||
// and compared on the draw path (SyncCurrentProgram), the same shape as the
|
||||
// storage-block and image-format signatures next to it.
|
||||
const Uint patchVertices = MG_Pipe::gPipeInputs.IsLive()
|
||||
? MG_Pipe::gPipeInputs.GetPatchVertices()
|
||||
const Uint patchVertices = MG_Pipe::gPipeInputs->IsLive()
|
||||
? MG_Pipe::gPipeInputs->GetPatchVertices()
|
||||
: 3u;
|
||||
m_passthroughTessControlPatchVertices = static_cast<Int>(patchVertices);
|
||||
// PATCH_DEFAULT_{OUTER,INNER}_LEVEL are the same kind of dynamic state and are baked
|
||||
// into the same stage (ES has no such state and no entry point to forward them to), so
|
||||
// they are recorded and compared alongside the patch size - the two move together, as
|
||||
// BuildPassthroughTessControlEssl's contract says.
|
||||
m_passthroughTessControlOuterLevel = MG_Pipe::gPipeInputs.IsLive()
|
||||
? MG_Pipe::gPipeInputs.GetPatchDefaultOuterLevel()
|
||||
m_passthroughTessControlOuterLevel = MG_Pipe::gPipeInputs->IsLive()
|
||||
? MG_Pipe::gPipeInputs->GetPatchDefaultOuterLevel()
|
||||
: FloatVec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
m_passthroughTessControlInnerLevel = MG_Pipe::gPipeInputs.IsLive()
|
||||
? MG_Pipe::gPipeInputs.GetPatchDefaultInnerLevel()
|
||||
m_passthroughTessControlInnerLevel = MG_Pipe::gPipeInputs->IsLive()
|
||||
? MG_Pipe::gPipeInputs->GetPatchDefaultInnerLevel()
|
||||
: FloatVec2(1.0f, 1.0f);
|
||||
|
||||
if (tessEvalShaderIndex < 0 ||
|
||||
|
||||
@@ -44,14 +44,14 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl {
|
||||
// verbatim is already "this batch restarts nowhere".
|
||||
Uint32 RestartSentinelFor(GLenum type) {
|
||||
if (ResolveRestartSubstitution(type) != RestartSubstitutionKind::None) {
|
||||
return MG_Pipe::gPipeInputs.GetPrimitiveRestartIndex();
|
||||
return MG_Pipe::gPipeInputs->GetPrimitiveRestartIndex();
|
||||
}
|
||||
return MG_Util::FixedRestartIndexForGLType(type);
|
||||
}
|
||||
|
||||
Bool RestartActive() {
|
||||
return MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::PrimitiveRestart) ||
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::PrimitiveRestartFixedIndex);
|
||||
return MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::PrimitiveRestart) ||
|
||||
MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::PrimitiveRestartFixedIndex);
|
||||
}
|
||||
|
||||
// Vertices per primitive for the modes whose sub-draws may be concatenated into a
|
||||
|
||||
@@ -2338,7 +2338,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
// Destination layout is computed from the client-side PACK parameters; only the actual pixel
|
||||
// rows are written so skip regions of the destination stay untouched.
|
||||
const auto packParams = MG_Pipe::gPipeInputs.GetPixelStoreParameters(false);
|
||||
const auto packParams = MG_Pipe::gPipeInputs->GetPixelStoreParameters(false);
|
||||
const SizeT rowPixels = static_cast<SizeT>(packParams.RowLength > 0 ? packParams.RowLength : width);
|
||||
const SizeT dstRowStride = AlignReadbackRow(rowPixels * dstPixelBytes, packParams.Alignment);
|
||||
const SizeT imageRows =
|
||||
|
||||
@@ -291,25 +291,25 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ClearBufferfi called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::ClearBufferfi called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::ClearBufferfi called with null GL context");
|
||||
pVulkanRenderer->ClearBufferfi(buffer, drawbuffer, depth, stencil);
|
||||
}
|
||||
|
||||
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ClearBufferfv called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::ClearBufferfv called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::ClearBufferfv called with null GL context");
|
||||
pVulkanRenderer->ClearBufferfv(buffer, drawbuffer, value);
|
||||
}
|
||||
|
||||
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ClearBufferuiv called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::ClearBufferuiv called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::ClearBufferuiv called with null GL context");
|
||||
pVulkanRenderer->ClearBufferuiv(buffer, drawbuffer, value);
|
||||
}
|
||||
|
||||
void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ClearBufferiv called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::ClearBufferiv called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::ClearBufferiv called with null GL context");
|
||||
pVulkanRenderer->ClearBufferiv(buffer, drawbuffer, value);
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
|
||||
GLsizei instancecount, GLint basevertex, GLuint baseinstance) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElementsInstancedBaseVertexBaseInstance called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::DrawElementsInstancedBaseVertexBaseInstance called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::DrawElementsInstancedBaseVertexBaseInstance called with null GL context");
|
||||
|
||||
DrawIndexedCmd payload{};
|
||||
payload.mode = mode;
|
||||
@@ -377,7 +377,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount,
|
||||
GLuint baseinstance) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArraysInstancedBaseInstance called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::DrawArraysInstancedBaseInstance called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::DrawArraysInstancedBaseInstance called with null GL context");
|
||||
|
||||
DrawCmd payload{};
|
||||
payload.mode = mode;
|
||||
@@ -397,13 +397,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height, GLint border) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::CopyTexImage2D called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::CopyTexImage2D called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::CopyTexImage2D called with null GL context");
|
||||
pVulkanRenderer->CopyTexSubImage2D(target, level, 0, 0, x, y, width, height);
|
||||
}
|
||||
void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::CopyTexSubImage2D called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::CopyTexSubImage2D called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::CopyTexSubImage2D called with null GL context");
|
||||
pVulkanRenderer->CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
|
||||
}
|
||||
void CopyImageSubData(const CopyImageEndpoint& src,
|
||||
@@ -412,20 +412,20 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ,
|
||||
GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::CopyImageSubData called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::CopyImageSubData called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::CopyImageSubData called with null GL context");
|
||||
pVulkanRenderer->CopyImageSubData(src, srcTarget, srcLevel, srcX, srcY, srcZ,
|
||||
dst, dstTarget, dstLevel, dstX, dstY, dstZ,
|
||||
srcWidth, srcHeight, srcDepth);
|
||||
}
|
||||
void GenerateMipmap(GLenum target) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::GenerateMipmap called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::GenerateMipmap called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::GenerateMipmap called with null GL context");
|
||||
pVulkanRenderer->GenerateMipmap(target);
|
||||
}
|
||||
|
||||
void DispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DispatchCompute called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::DispatchCompute called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::DispatchCompute called with null GL context");
|
||||
pVulkanRenderer->DispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
void MemoryBarrier(GLbitfield barriers) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MemoryBarrier called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MemoryBarrier called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::MemoryBarrier called with null GL context");
|
||||
pVulkanRenderer->MemoryBarrier(barriers);
|
||||
}
|
||||
|
||||
@@ -530,12 +530,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ReadPixels called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::ReadPixels called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::ReadPixels called with null GL context");
|
||||
pVulkanRenderer->ReadPixels(x, y, width, height, format, type, pixels);
|
||||
}
|
||||
void Clear(GLbitfield mask) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::Clear called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::Clear called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::Clear called with null GL context");
|
||||
pVulkanRenderer->Clear(mask);
|
||||
}
|
||||
|
||||
@@ -582,7 +582,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
void DrawArrays(GLenum mode, GLint first, GLsizei count) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArrays called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::DrawArrays called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::DrawArrays called with null GL context");
|
||||
|
||||
if (mode == GL_LINE_LOOP) {
|
||||
if (count < 2) {
|
||||
@@ -607,7 +607,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElements called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::DrawElements called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::DrawElements called with null GL context");
|
||||
|
||||
if (mode == GL_LINE_LOOP) {
|
||||
Vector<Uint32> closedIndices;
|
||||
@@ -637,7 +637,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
void MultiDrawArrays(GLenum mode, const GLint* first, const GLsizei* count, GLsizei drawcount) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawArrays called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MultiDrawArrays called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::MultiDrawArrays called with null GL context");
|
||||
if (drawcount <= 0) {
|
||||
return;
|
||||
}
|
||||
@@ -743,7 +743,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLint basevertex) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElementsBaseVertex called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::DrawElementsBaseVertex called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::DrawElementsBaseVertex called with null GL context");
|
||||
if (mode == GL_LINE_LOOP) {
|
||||
Vector<Uint32> closedIndices;
|
||||
if (BuildClosedLineLoopIndices(count, type, indices, closedIndices)) {
|
||||
@@ -767,14 +767,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices,
|
||||
GLsizei drawcount, const GLint* basevertex) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElementsBaseVertex called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MultiDrawElementsBaseVertex called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::MultiDrawElementsBaseVertex called with null GL context");
|
||||
MultiDrawElementsImpl(mode, count, type, indices, drawcount, basevertex);
|
||||
}
|
||||
|
||||
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1,
|
||||
GLint dstY1, GLbitfield mask, GLenum filter) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::BlitFramebuffer called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::BlitFramebuffer called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "DirectVulkan::BlitFramebuffer called with null GL context");
|
||||
pVulkanRenderer->BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
||||
}
|
||||
|
||||
@@ -1018,8 +1018,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
MG_Config::Transport == MG_Config::TransportMode::Monolith &&
|
||||
#endif
|
||||
MG_Pipe::gPipeInputs.IsLive()) {
|
||||
primitives += MG_Pipe::gPipeInputs.GetTransformFeedbackPausedPrimitiveCounter() -
|
||||
MG_Pipe::gPipeInputs->IsLive()) {
|
||||
primitives += MG_Pipe::gPipeInputs->GetTransformFeedbackPausedPrimitiveCounter() -
|
||||
query->pausedPrimitiveSnapshot;
|
||||
}
|
||||
*outNanoseconds = primitives;
|
||||
@@ -1069,7 +1069,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
MG_Config::Transport == MG_Config::TransportMode::Monolith &&
|
||||
#endif
|
||||
MG_Pipe::gPipeInputs.IsLive() ? MG_Pipe::gPipeInputs.GetTransformFeedbackPausedPrimitiveCounter() : 0;
|
||||
MG_Pipe::gPipeInputs->IsLive() ? MG_Pipe::gPipeInputs->GetTransformFeedbackPausedPrimitiveCounter() : 0;
|
||||
// Read AFTER StartXfbQueryCapture, which is where a failed reroute-pool creation
|
||||
// disarms: the answer is then what this span will actually do for every draw.
|
||||
query->pausedPrimitivesCountedByGpu = generated && pVulkanRenderer->ArePausedDrawsGpuCounted();
|
||||
|
||||
@@ -858,7 +858,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkDescriptorBufferInfo& outBufferInfo) const {
|
||||
outBufferInfo = {};
|
||||
MOBILEGL_ASSERT(m_bufferManager != nullptr, "ResolveStorageBufferDescriptor: buffer manager is null");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "ResolveStorageBufferDescriptor: GL context is null");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "ResolveStorageBufferDescriptor: GL context is null");
|
||||
MOBILEGL_ASSERT(binding < programObj.storageBlockIndexByBinding.size(),
|
||||
"ResolveStorageBufferDescriptor: binding %u out of range", binding);
|
||||
if ((binding >= programObj.storageBlockIndexByBinding.size() ||
|
||||
@@ -1155,7 +1155,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const void* outData = nullptr;
|
||||
VkDeviceSize outSize = 0;
|
||||
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "ResolveUniformBufferPayload: GL context is null");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs->IsLive(), "ResolveUniformBufferPayload: GL context is null");
|
||||
MOBILEGL_ASSERT(binding < programObj.bindingKinds.size(),
|
||||
"ResolveUniformBufferPayload: binding %u out of range", binding);
|
||||
MOBILEGL_ASSERT(programObj.bindingKinds[binding] == ProgramFactory::DescriptorBindingKind::UniformBufferDynamic,
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (payload.colorEncoding != ClearColorEncoding::Float) return;
|
||||
// With GL_FRAMEBUFFER_SRGB enabled GL performs the encoding itself, so the driver doing it
|
||||
// is exactly right and there is nothing to undo.
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(MobileGL::CapabilityInput::FramebufferSrgb)) return;
|
||||
if (MG_Pipe::gPipeInputs->IsCapabilityEnabled(MobileGL::CapabilityInput::FramebufferSrgb)) return;
|
||||
if (ResolveSrgbAttachmentWriteFormat(destinationFormat, false) == destinationFormat) return;
|
||||
|
||||
// sRGB -> linear (GL 4.6 core 8.24), applied to the colour channels only: alpha is stored
|
||||
|
||||
@@ -526,12 +526,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// round trip), which is why the honest-but-lossy path was kept over widening every
|
||||
// default-framebuffer Y-flip/pre-transform helper to floats. See the KNOWN INFIDELITY
|
||||
// note in MG_IntegrationTest/Scenarios/AdvertisedLimitsScenario.cpp.
|
||||
const FloatVec4& stored = MG_Pipe::gPipeInputs.GetViewportIndexed(index);
|
||||
const FloatVec4& stored = MG_Pipe::gPipeInputs->GetViewportIndexed(index);
|
||||
const IntVec4 viewportState(static_cast<Int>(std::lround(stored.x())),
|
||||
static_cast<Int>(std::lround(stored.y())),
|
||||
static_cast<Int>(std::lround(stored.z())),
|
||||
static_cast<Int>(std::lround(stored.w())));
|
||||
const FloatVec2& depthRange = MG_Pipe::gPipeInputs.GetDepthRangeIndexed(index);
|
||||
const FloatVec2& depthRange = MG_Pipe::gPipeInputs->GetDepthRangeIndexed(index);
|
||||
const IntVec2 logicalExtent = isDefaultFramebuffer
|
||||
? ResolveDefaultFramebufferLogicalExtent(preTransform, framebufferExtent)
|
||||
: framebufferExtent;
|
||||
@@ -586,7 +586,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
static void ApplyBlendConstants(VkCommandBuffer commandBuffer) {
|
||||
const FloatVec4& blendColor = MG_Pipe::gPipeInputs.GetBlendColor();
|
||||
const FloatVec4& blendColor = MG_Pipe::gPipeInputs->GetBlendColor();
|
||||
const float blendConstants[4] = {
|
||||
blendColor.x(),
|
||||
blendColor.y(),
|
||||
@@ -619,8 +619,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
static void ApplyPolygonOffsetState(VkCommandBuffer commandBuffer) {
|
||||
const Float constantFactor = MG_Pipe::gPipeInputs.GetPolygonOffsetUnits();
|
||||
const Float slopeFactor = MG_Pipe::gPipeInputs.GetPolygonOffsetFactor();
|
||||
const Float constantFactor = MG_Pipe::gPipeInputs->GetPolygonOffsetUnits();
|
||||
const Float slopeFactor = MG_Pipe::gPipeInputs->GetPolygonOffsetFactor();
|
||||
auto& shadow = *g_dynamicStateShadow;
|
||||
if (shadow.depthBiasValid && shadow.depthBiasConstantFactor == constantFactor &&
|
||||
shadow.depthBiasSlopeFactor == slopeFactor) {
|
||||
@@ -633,7 +633,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
static void ApplyLineWidthState(VkCommandBuffer commandBuffer) {
|
||||
Float lineWidth = MG_Pipe::gPipeInputs.GetLineWidth();
|
||||
Float lineWidth = MG_Pipe::gPipeInputs->GetLineWidth();
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
// P5c (hd, CONTRACT-P5C §3.7): with an active transport the dynamic parameters are the
|
||||
// SERVER's own backend's - the client caps mirror is client memory (rule E). Monolith
|
||||
@@ -677,7 +677,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// reader of the box asks this first. The resolution matches the viewport's (ComputeGLViewport
|
||||
// resolves a never-written viewport to the current framebuffer's extent).
|
||||
static Bool GLScissorTestClips(Uint32 index = 0) {
|
||||
const RenderStateParameters& parameters = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
const RenderStateParameters& parameters = MG_Pipe::gPipeInputs->GetRenderStateParameters();
|
||||
const Uint32 bit = 1u << index;
|
||||
return (parameters.ScissorTestEnabledMask & bit) != 0 && (parameters.ScissorBoxWrittenMask & bit) != 0;
|
||||
}
|
||||
@@ -748,8 +748,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
static void ApplyStencilState(VkCommandBuffer commandBuffer) {
|
||||
const StencilFaceState& frontStencil = MG_Pipe::gPipeInputs.GetStencilState(StencilFace::Front);
|
||||
const StencilFaceState& backStencil = MG_Pipe::gPipeInputs.GetStencilState(StencilFace::Back);
|
||||
const StencilFaceState& frontStencil = MG_Pipe::gPipeInputs->GetStencilState(StencilFace::Front);
|
||||
const StencilFaceState& backStencil = MG_Pipe::gPipeInputs->GetStencilState(StencilFace::Back);
|
||||
const Uint32 frontReference = static_cast<Uint32>(std::max(frontStencil.Ref, 0));
|
||||
const Uint32 backReference = static_cast<Uint32>(std::max(backStencil.Ref, 0));
|
||||
|
||||
@@ -1116,7 +1116,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
static void RecordTextureCopyError(const char* func, ErrorCode code, const char* message) {
|
||||
MG_Pipe::gPipeInputs.RecordError(code, MakeUnique<GenericErrorInfo>("DirectVulkan", func, message));
|
||||
MG_Pipe::gPipeInputs->RecordError(code, MakeUnique<GenericErrorInfo>("DirectVulkan", func, message));
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -1894,7 +1894,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// glReadPixels final conversion: GL_CLAMP_READ_COLOR defaults to GL_FIXED_ONLY,
|
||||
// clamping fixed-point (normalized) buffers to [0,1] - visible for SNORM reads.
|
||||
if (applyReadColorClamp && wideType == GL_FLOAT) {
|
||||
const GLenum clampMode = MG_Pipe::gPipeInputs.GetClampReadColor();
|
||||
const GLenum clampMode = MG_Pipe::gPipeInputs->GetClampReadColor();
|
||||
const Bool clamp = clampMode == GL_TRUE ||
|
||||
(clampMode == GL_FIXED_ONLY && !IsFloatingPointReadbackFormat(srcFormat));
|
||||
if (clamp) {
|
||||
@@ -2699,9 +2699,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
Uint32 VulkanRenderer::ResolveEffectiveSampleMask(VkSampleCountFlagBits rasterizationSamples) const {
|
||||
constexpr Uint32 kFullCoverage = 0xffffffffu;
|
||||
if (rasterizationSamples == VK_SAMPLE_COUNT_1_BIT) return kFullCoverage;
|
||||
if (!MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::Multisample)) return kFullCoverage;
|
||||
if (!MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::SampleMask)) return kFullCoverage;
|
||||
return MG_Pipe::gPipeInputs.GetRenderStateParameters().SampleMaskValue;
|
||||
if (!MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::Multisample)) return kFullCoverage;
|
||||
if (!MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::SampleMask)) return kFullCoverage;
|
||||
return MG_Pipe::gPipeInputs->GetRenderStateParameters().SampleMaskValue;
|
||||
}
|
||||
|
||||
|
||||
@@ -2716,7 +2716,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
//
|
||||
// Only reached with no render-state CSO bound, and only in a build with no pre-handle
|
||||
// arm to fall back to instead.
|
||||
return MG_Pipe::MGPipeComputePipelineSubsetHash(MG_Pipe::gPipeInputs.GetRenderStateParameters());
|
||||
return MG_Pipe::MGPipeComputePipelineSubsetHash(MG_Pipe::gPipeInputs->GetRenderStateParameters());
|
||||
}
|
||||
|
||||
// A program that runs a geometry shader AND captures transform feedback. Both halves are
|
||||
@@ -2748,7 +2748,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (!(aspects & DrawSetupAspect::IndexBuffer) || pIndexBufferView == nullptr) {
|
||||
return false;
|
||||
}
|
||||
const RenderStateParameters& rsp = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
const RenderStateParameters& rsp = MG_Pipe::gPipeInputs->GetRenderStateParameters();
|
||||
if (rsp.PrimitiveRestartFixedIndexEnabled) {
|
||||
return true;
|
||||
}
|
||||
@@ -2803,7 +2803,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// the VALUE hash of that subset, never the version itself: the version is monotonic, so
|
||||
// per-draw state flips (GL_BLEND toggles) would otherwise miss entries the memo holds.
|
||||
// The version only guards recomputing the hash - unchanged version, unchanged bytes.
|
||||
const Uint renderStateVersion = MG_Pipe::gPipeInputs.GetPipelineStateVersion();
|
||||
const Uint renderStateVersion = MG_Pipe::gPipeInputs->GetPipelineStateVersion();
|
||||
// P2 D12.1. Non-null means the client's render-state CSO handle is this draw's state
|
||||
// key and the hash below is not computed at all; null means the pre-handle arm. The
|
||||
// two arms' entries can never match each other: the handle arm stores hash 0 and a
|
||||
@@ -2996,16 +2996,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
syntheticVertexInputState.pNext = vis.state.pNext;
|
||||
pipelineVertexInputState = &syntheticVertexInputState;
|
||||
}
|
||||
auto cullFaceEnabled = MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::CullFace);
|
||||
auto depthTestEnabled = MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::DepthTest);
|
||||
auto cullFaceEnabled = MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::CullFace);
|
||||
auto depthTestEnabled = MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::DepthTest);
|
||||
auto polygonOffsetFillEnabled =
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::PolygonOffsetFill) &&
|
||||
MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::PolygonOffsetFill) &&
|
||||
DrawModeUsesPolygonFill(mode);
|
||||
auto rasterizerDiscardEnabled =
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::RasterizerDiscard);
|
||||
MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::RasterizerDiscard);
|
||||
auto colorLogicOpEnabled =
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::ColorLogicOp) && m_logicOpFeatureEnabled;
|
||||
auto stencilTestEnabled = MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::StencilTest);
|
||||
MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::ColorLogicOp) && m_logicOpFeatureEnabled;
|
||||
auto stencilTestEnabled = MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::StencilTest);
|
||||
// A framebuffer without a depth (stencil) attachment behaves as if the depth
|
||||
// (stencil) test always passes and nothing is written - even when the bound
|
||||
// image is a packed depth-stencil texture attached through only one half.
|
||||
@@ -3016,10 +3016,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (fbo->Stencil.Kind == MG_Pipe::kMGPipeSurfaceKindNone) stencilTestEnabled = false;
|
||||
}
|
||||
}
|
||||
const StencilFaceState& frontStencil = MG_Pipe::gPipeInputs.GetStencilState(StencilFace::Front);
|
||||
const StencilFaceState& backStencil = MG_Pipe::gPipeInputs.GetStencilState(StencilFace::Back);
|
||||
const StencilFaceState& frontStencil = MG_Pipe::gPipeInputs->GetStencilState(StencilFace::Front);
|
||||
const StencilFaceState& backStencil = MG_Pipe::gPipeInputs->GetStencilState(StencilFace::Back);
|
||||
const VkPolygonMode requestedPolygonMode =
|
||||
MG_Util::ConvertPolygonModeToVkEnum(MG_Pipe::gPipeInputs.GetPolygonModeFront());
|
||||
MG_Util::ConvertPolygonModeToVkEnum(MG_Pipe::gPipeInputs->GetPolygonModeFront());
|
||||
// VK_POLYGON_MODE_LINE/_POINT require the fillModeNonSolid device feature; fall back to
|
||||
// VK_POLYGON_MODE_FILL when the device lacks it.
|
||||
const VkPolygonMode effectivePolygonMode =
|
||||
@@ -3105,18 +3105,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// driver's own rate. Both halves move the render state's PIPELINE version, so a cached
|
||||
// pipeline built at the old rate cannot be handed back for the new one.
|
||||
.sampleShadingEnable = m_sampleRateShadingFeatureEnabled &&
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::SampleShading),
|
||||
.minSampleShading = MG_Pipe::gPipeInputs.GetMinSampleShadingValue(),
|
||||
MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::SampleShading),
|
||||
.minSampleShading = MG_Pipe::gPipeInputs->GetMinSampleShadingValue(),
|
||||
// Word 1 keeps its all-ones initialiser: GL has no state for samples 32..63.
|
||||
.sampleMask = {ResolveEffectiveSampleMask(renderPassEntry.sampleCount), 0xffffffffu},
|
||||
.subpass = 0,
|
||||
.topology = vkTopology,
|
||||
.primitiveRestartEnable = primitiveRestartEnabled,
|
||||
.patchControlPoints = static_cast<Uint32>(MG_Pipe::gPipeInputs.GetPatchVertices()),
|
||||
.patchControlPoints = static_cast<Uint32>(MG_Pipe::gPipeInputs->GetPatchVertices()),
|
||||
.viewportCount = ResolveDrawViewportCount(programObj.writesViewportIndexBuiltin),
|
||||
.polygonMode = effectivePolygonMode,
|
||||
.cullMode = cullFaceEnabled
|
||||
? MG_Util::ConvertCullFaceModeToVkEnum(MG_Pipe::gPipeInputs.GetCullFaceMode(), invertClockwise)
|
||||
? MG_Util::ConvertCullFaceModeToVkEnum(MG_Pipe::gPipeInputs->GetCullFaceMode(), invertClockwise)
|
||||
: VK_CULL_MODE_NONE,
|
||||
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
||||
// Read the geometry stage off the program's own shader list rather than
|
||||
@@ -3130,13 +3130,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
.provokingVertexMode = SelectProvokingVertexMode(
|
||||
vkTopology, ProgramCapturesXfbFromGeometryStage(program)),
|
||||
.depthTestEnable = depthTestEnabled,
|
||||
.depthWriteEnable = depthTestEnabled && MG_Pipe::gPipeInputs.GetDepthMask(),
|
||||
.depthWriteEnable = depthTestEnabled && MG_Pipe::gPipeInputs->GetDepthMask(),
|
||||
.depthBiasEnable = polygonOffsetFillEnabled,
|
||||
.rasterizerDiscardEnable = rasterizerDiscardEnabled,
|
||||
.logicOpEnable = colorLogicOpEnabled,
|
||||
.stencilTestEnable = stencilTestEnabled,
|
||||
.depthCompareOp = MG_Util::ConvertDepthTestFuncToVkEnum(MG_Pipe::gPipeInputs.GetDepthFunc()),
|
||||
.logicOp = MG_Util::ConvertLogicOperationToVkEnum(MG_Pipe::gPipeInputs.GetLogicOp()),
|
||||
.depthCompareOp = MG_Util::ConvertDepthTestFuncToVkEnum(MG_Pipe::gPipeInputs->GetDepthFunc()),
|
||||
.logicOp = MG_Util::ConvertLogicOperationToVkEnum(MG_Pipe::gPipeInputs->GetLogicOp()),
|
||||
.frontStencilFailOp = MG_Util::ConvertStencilOperationToVkEnum(frontStencil.FailOp),
|
||||
.frontStencilPassOp = MG_Util::ConvertStencilOperationToVkEnum(frontStencil.PassDepthPassOp),
|
||||
.frontStencilDepthFailOp = MG_Util::ConvertStencilOperationToVkEnum(frontStencil.PassDepthFailOp),
|
||||
@@ -3172,8 +3172,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// handed back after the application changed them.
|
||||
if (programObj.needsPassthroughTessControl && programObj.passthroughTessControlEmulatable &&
|
||||
vkTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) {
|
||||
const FloatVec4& defaultOuterLevel = MG_Pipe::gPipeInputs.GetPatchDefaultOuterLevel();
|
||||
const FloatVec2& defaultInnerLevel = MG_Pipe::gPipeInputs.GetPatchDefaultInnerLevel();
|
||||
const FloatVec4& defaultOuterLevel = MG_Pipe::gPipeInputs->GetPatchDefaultOuterLevel();
|
||||
const FloatVec2& defaultInnerLevel = MG_Pipe::gPipeInputs->GetPatchDefaultInnerLevel();
|
||||
payload.passthroughTessControlKey = ProgramFactory::ComputePassthroughTessControlKey(
|
||||
payload.patchControlPoints, defaultOuterLevel, defaultInnerLevel,
|
||||
programObj.passthroughPerVertexMembers);
|
||||
@@ -3243,14 +3243,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
BlendFactor dstAlpha = BlendFactor::Zero;
|
||||
BlendEquation colorEquation = BlendEquation::Add;
|
||||
BlendEquation alphaEquation = BlendEquation::Add;
|
||||
MG_Pipe::gPipeInputs.GetBlendFuncIndexed(i, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
MG_Pipe::gPipeInputs.GetBlendEquationIndexed(i, colorEquation, alphaEquation);
|
||||
const Bool blendEnabled = MG_Pipe::gPipeInputs.IsCapabilityEnabledIndexed(CapabilityInput::Blend, i);
|
||||
MG_Pipe::gPipeInputs->GetBlendFuncIndexed(i, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
MG_Pipe::gPipeInputs->GetBlendEquationIndexed(i, colorEquation, alphaEquation);
|
||||
const Bool blendEnabled = MG_Pipe::gPipeInputs->IsCapabilityEnabledIndexed(CapabilityInput::Blend, i);
|
||||
// Per-draw-buffer color write mask (glColorMaski). Divergent per-attachment masks require
|
||||
// the independentBlend device feature; when it is absent, fall back to draw buffer 0's
|
||||
// mask for every attachment (matching the non-indexed glColorMask broadcast).
|
||||
const BoolVec4 bufferMask =
|
||||
MG_Pipe::gPipeInputs.GetColorMaskIndexed(m_independentBlendFeatureEnabled ? i : 0);
|
||||
MG_Pipe::gPipeInputs->GetColorMaskIndexed(m_independentBlendFeatureEnabled ? i : 0);
|
||||
VkColorComponentFlags attachmentColorWriteMask = static_cast<VkColorComponentFlags>(
|
||||
(bufferMask.r() ? VK_COLOR_COMPONENT_R_BIT : 0u) |
|
||||
(bufferMask.g() ? VK_COLOR_COMPONENT_G_BIT : 0u) |
|
||||
@@ -3404,7 +3404,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkRect2D VulkanRenderer::ComputeGLScissorRect(Uint32 index, const IntVec2& extent,
|
||||
VkSurfaceTransformFlagBitsKHR preTransform,
|
||||
Bool isDefaultFbo) const {
|
||||
const auto& parameters = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
const auto& parameters = MG_Pipe::gPipeInputs->GetRenderStateParameters();
|
||||
if (!GLScissorTestClips(index)) {
|
||||
VkRect2D full{};
|
||||
full.offset = {0, 0};
|
||||
@@ -3480,7 +3480,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// counter still would make Espryt skip re-syncing the blend state it just changed.
|
||||
// The second-level DynamicTailKey compare below is therefore what actually absorbs a
|
||||
// pipeline-only change, exactly as it did before P2: one key build, no vkCmd*.
|
||||
const Uint paramsVersion = MG_Pipe::gPipeInputs.GetRenderStateParametersVersion();
|
||||
const Uint paramsVersion = MG_Pipe::gPipeInputs->GetRenderStateParametersVersion();
|
||||
if (shadow.dynamicTailValid && shadow.dynamicTailParamsVersion == paramsVersion &&
|
||||
shadow.dynamicTailExtentX == extent.x() && shadow.dynamicTailExtentY == extent.y() &&
|
||||
shadow.dynamicTailIsDefaultFbo == isDefaultFbo) {
|
||||
@@ -3504,7 +3504,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// re-derive the value its shadow already holds.
|
||||
DynamicStateShadow::DynamicTailKey key;
|
||||
{
|
||||
const RenderStateParameters& p = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
const RenderStateParameters& p = MG_Pipe::gPipeInputs->GetRenderStateParameters();
|
||||
// Viewport 0 and its depth range: ApplyGLViewportState reads exactly those two
|
||||
// (per-index state for indices > 0 is keyed separately, see multiViewportKey below).
|
||||
key.viewport[0] = p.Viewports[0].x();
|
||||
@@ -3763,9 +3763,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (!fbo) MagmaWireFatal("clear-framebuffer-record");
|
||||
ClearAttachmentPayload payload{};
|
||||
payload.mask = mask;
|
||||
payload.color = MG_Pipe::gPipeInputs.GetClearColor();
|
||||
payload.depth = MG_Pipe::gPipeInputs.GetClearDepth();
|
||||
payload.stencil = MG_Pipe::gPipeInputs.GetClearStencil();
|
||||
payload.color = MG_Pipe::gPipeInputs->GetClearColor();
|
||||
payload.depth = MG_Pipe::gPipeInputs->GetClearDepth();
|
||||
payload.stencil = MG_Pipe::gPipeInputs->GetClearStencil();
|
||||
ClearWireFramebuffer(*fbo, payload);
|
||||
return;
|
||||
}
|
||||
@@ -4846,7 +4846,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const SharedPtr<MG_State::GLState::BufferObject> wireReplyHasNoPackBuffer;
|
||||
const auto& pixelPackBufferObject =
|
||||
wireReplyHasNoPackBuffer;
|
||||
const auto packParams = MG_Pipe::gPipeInputs.GetPixelStoreParameters(false);
|
||||
const auto packParams = MG_Pipe::gPipeInputs->GetPixelStoreParameters(false);
|
||||
const SizeT rowPixels = static_cast<SizeT>(packParams.RowLength > 0 ? packParams.RowLength : width);
|
||||
const SizeT packAlignment = packParams.Alignment > 0 ? static_cast<SizeT>(packParams.Alignment) : 1;
|
||||
const SizeT dstRowStride = ((rowPixels * dstPixelBytes) + packAlignment - 1) / packAlignment * packAlignment;
|
||||
@@ -4894,7 +4894,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// resets its counter state, because those bytes describe the previous owner's span.
|
||||
Uint32 VulkanRenderer::CurrentXfbCounterSlot() {
|
||||
constexpr Uint32 kNoSlot = static_cast<Uint32>(kXfbCounterObjectSlots);
|
||||
const Uint64 identity = MG_Pipe::gPipeInputs.GetBoundTransformFeedbackLifetimeId();
|
||||
const Uint64 identity = MG_Pipe::gPipeInputs->GetBoundTransformFeedbackLifetimeId();
|
||||
MOBILEGL_ASSERT(identity != 0,
|
||||
"transform feedback object reported the free-slot sentinel (0) as its identity - "
|
||||
"every slot would then read as 'mine' without ever being claimed");
|
||||
@@ -4943,14 +4943,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
Bool VulkanRenderer::BeginXfbCaptureForDraw(FrameContext::FrameData& frame) {
|
||||
if (!m_transformFeedbackFeatureEnabled || !MG_Pipe::gPipeInputs.IsLive() ||
|
||||
!MG_Pipe::gPipeInputs.IsTransformFeedbackActive()) {
|
||||
if (!m_transformFeedbackFeatureEnabled || !MG_Pipe::gPipeInputs->IsLive() ||
|
||||
!MG_Pipe::gPipeInputs->IsTransformFeedbackActive()) {
|
||||
return false;
|
||||
}
|
||||
// A paused span captures nothing, and the counter buffers keep their values, so the
|
||||
// next resumed draw appends exactly where the last captured one stopped - which is
|
||||
// what pause/resume means (ARB_transform_feedback2).
|
||||
if (MG_Pipe::gPipeInputs.IsTransformFeedbackPaused()) {
|
||||
if (MG_Pipe::gPipeInputs->IsTransformFeedbackPaused()) {
|
||||
return false;
|
||||
}
|
||||
// The bound pipeline's last pre-rasterization stage has to have been declared with Xfb
|
||||
@@ -4993,7 +4993,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
const Uint32 counterSlot = CurrentXfbCounterSlot();
|
||||
const Uint64 generation = MG_Pipe::gPipeInputs.GetTransformFeedbackGeneration();
|
||||
const Uint64 generation = MG_Pipe::gPipeInputs->GetTransformFeedbackGeneration();
|
||||
const Bool resume = m_xfbCountersValid[counterSlot] && m_xfbLastSeenGeneration[counterSlot] == generation;
|
||||
m_xfbLastSeenGeneration[counterSlot] = generation;
|
||||
|
||||
@@ -5667,7 +5667,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
default: break;
|
||||
}
|
||||
if (mergeGranularity != 0) {
|
||||
const RenderStateParameters& rsp = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
const RenderStateParameters& rsp = MG_Pipe::gPipeInputs->GetRenderStateParameters();
|
||||
if (rsp.PrimitiveRestartEnabled || rsp.PrimitiveRestartFixedIndexEnabled) {
|
||||
mergeGranularity = 0;
|
||||
}
|
||||
@@ -6428,8 +6428,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (!m_provokingVertexModePerPipeline) {
|
||||
return VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT;
|
||||
}
|
||||
return (MG_Pipe::gPipeInputs.IsLive() &&
|
||||
MG_Pipe::gPipeInputs.GetProvokingVertexMode() == ProvokingVertexMode::FirstVertex)
|
||||
return (MG_Pipe::gPipeInputs->IsLive() &&
|
||||
MG_Pipe::gPipeInputs->GetProvokingVertexMode() == ProvokingVertexMode::FirstVertex)
|
||||
? VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT
|
||||
: VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT;
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@
|
||||
// Mip generation samples and writes the texture's own color space;
|
||||
// GL_FRAMEBUFFER_SRGB only controls framebuffer operations.
|
||||
if (!mipmap) destination.format = ResolveSrgbAttachmentWriteFormat(destination.format,
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::FramebufferSrgb));
|
||||
MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::FramebufferSrgb));
|
||||
VkFormatProperties destinationProperties{};
|
||||
vkGetPhysicalDeviceFormatProperties(m_physicalDevice.handle, destination.format, &destinationProperties);
|
||||
if (!(destinationProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) return false;
|
||||
|
||||
@@ -248,7 +248,7 @@
|
||||
!(memo.drawFramebuffer == st.BoundFramebuffer[SizeT(MG_Pipe::MGPipeFramebufferTarget::Draw)]) ||
|
||||
memo.textureImageEpoch != m_textureManager->GetTextureImageEpoch() ||
|
||||
memo.resourceEraseEpoch != m_textureManager->GetResourceEraseEpoch() ||
|
||||
memo.framebufferSrgb != MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::FramebufferSrgb))
|
||||
memo.framebufferSrgb != MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::FramebufferSrgb))
|
||||
return false;
|
||||
// The resources are good while the erase epoch holds. Each must still be what the walk
|
||||
// left: in GENERAL and synced to its record's serial with nothing pending.
|
||||
@@ -300,7 +300,7 @@
|
||||
auto& passKey = scratch.passKey;
|
||||
passKey.ResetKeepingCapacity();
|
||||
passKey.isDefault = fbo.IsDefault;
|
||||
passKey.framebufferSrgb = MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::FramebufferSrgb);
|
||||
passKey.framebufferSrgb = MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::FramebufferSrgb);
|
||||
if (fbo.IsDefault) {
|
||||
passKey.swapchain = m_swapchainObject.GetHandle();
|
||||
// A drawing pass on the default framebuffer is what makes the freshly acquired
|
||||
@@ -326,7 +326,7 @@
|
||||
{image.resource, image.storage, surface.Kind == MG_Pipe::kMGPipeSurfaceKindRenderbuffer});
|
||||
if (aspect == VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
image.format = ResolveSrgbAttachmentWriteFormat(image.format,
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::FramebufferSrgb));
|
||||
MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::FramebufferSrgb));
|
||||
const VkImageLayout layout = aspect == VK_IMAGE_ASPECT_COLOR_BIT ?
|
||||
VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_GENERAL;
|
||||
// Already in its attachment layout: its barrier (which closes any open pass) waits until
|
||||
@@ -470,7 +470,7 @@
|
||||
memo.drawFramebuffer = st.BoundFramebuffer[SizeT(MG_Pipe::MGPipeFramebufferTarget::Draw)];
|
||||
memo.textureImageEpoch = m_textureManager->GetTextureImageEpoch();
|
||||
memo.resourceEraseEpoch = m_textureManager->GetResourceEraseEpoch();
|
||||
memo.framebufferSrgb = MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::FramebufferSrgb);
|
||||
memo.framebufferSrgb = MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::FramebufferSrgb);
|
||||
memo.passHash = m_wireDrawPass->hash;
|
||||
memo.marks.assign(scratch.gpuWriteMarks.begin(), scratch.gpuWriteMarks.end());
|
||||
}
|
||||
@@ -522,7 +522,7 @@
|
||||
|
||||
ProgramFactory::CompileOptionFlags flags =
|
||||
ProgramFactory::CompileOptionFlags(GetBaseTransformFlagsRaw(fbo->IsDefault));
|
||||
if (m_transformFeedbackFeatureEnabled && MG_Pipe::gPipeInputs.IsTransformFeedbackActive() &&
|
||||
if (m_transformFeedbackFeatureEnabled && MG_Pipe::gPipeInputs->IsTransformFeedbackActive() &&
|
||||
program.GetTransformFeedbackVaryingCount() > 0)
|
||||
flags |= ProgramFactory::CompileOptionBit::XfbCapture;
|
||||
const auto* programObject = &m_programFactory->GetOrCreateProgram(program, flags);
|
||||
@@ -727,7 +727,7 @@
|
||||
return false;
|
||||
}
|
||||
indexType = width == 4 ? VK_INDEX_TYPE_UINT32 : width == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT8;
|
||||
const auto& restart = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
const auto& restart = MG_Pipe::gPipeInputs->GetRenderStateParameters();
|
||||
const Uint32 fixed = MG_Util::FixedRestartIndexForGLType(indices->indexType);
|
||||
const Bool replaceRestart = restart.PrimitiveRestartEnabled && !restart.PrimitiveRestartFixedIndexEnabled &&
|
||||
restart.PrimitiveRestartIndex < fixed;
|
||||
@@ -864,7 +864,7 @@
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
const void* data = nullptr;
|
||||
VkDeviceSize size = 0;
|
||||
if (!TryGetCurrentVertexAttributeUploadPayload(MG_Pipe::gPipeInputs.GetCurrentVertexAttribute(location),
|
||||
if (!TryGetCurrentVertexAttributeUploadPayload(MG_Pipe::gPipeInputs->GetCurrentVertexAttribute(location),
|
||||
programObj.vertexInputTypes[location], format, data, size)) {
|
||||
MGL_WIRE_DECLINE_AT(CurrentAttributePayload, "a disabled array's current attribute value has no upload payload");
|
||||
return false;
|
||||
@@ -987,7 +987,7 @@
|
||||
const Int32 attachment = fbo.DrawBuffers[i];
|
||||
if (attachment < 0 || attachment >= static_cast<Int32>(MG_Pipe::kMGPipeMaxColorAttachments)) continue;
|
||||
if (!fbo.IsDefault && fbo.Color[attachment].Kind == MG_Pipe::kMGPipeSurfaceKindNone) continue;
|
||||
const auto mask = MG_Pipe::gPipeInputs.GetColorMaskIndexed(i);
|
||||
const auto mask = MG_Pipe::gPipeInputs->GetColorMaskIndexed(i);
|
||||
if (!mask.r() && !mask.g() && !mask.b() && !mask.a()) continue;
|
||||
if (!mask.r() || !mask.g() || !mask.b() || !mask.a()) { all = false; break; }
|
||||
if (i >= key.colorReferences.size() || key.colorReferences[i] == VK_ATTACHMENT_UNUSED ||
|
||||
@@ -1007,7 +1007,7 @@
|
||||
: nullptr;
|
||||
VkImageAspectFlags depthStencilAspects = 0;
|
||||
if (remaining & GL_DEPTH_BUFFER_BIT) {
|
||||
if (!MG_Pipe::gPipeInputs.GetDepthMask()) {
|
||||
if (!MG_Pipe::gPipeInputs->GetDepthMask()) {
|
||||
handled |= GL_DEPTH_BUFFER_BIT; // nothing to write, as on the standalone path
|
||||
} else if (!fbo.IsDefault && fbo.Depth.Kind == MG_Pipe::kMGPipeSurfaceKindNone) {
|
||||
handled |= GL_DEPTH_BUFFER_BIT; // no depth surface: nothing to clear
|
||||
@@ -1018,7 +1018,7 @@
|
||||
}
|
||||
}
|
||||
if (remaining & GL_STENCIL_BUFFER_BIT) {
|
||||
const Uint32 mask = MG_Pipe::gPipeInputs.GetStencilState(StencilFace::Front).WriteMask & 255u;
|
||||
const Uint32 mask = MG_Pipe::gPipeInputs->GetStencilState(StencilFace::Front).WriteMask & 255u;
|
||||
if (mask == 0) {
|
||||
handled |= GL_STENCIL_BUFFER_BIT;
|
||||
} else if (!fbo.IsDefault && fbo.Stencil.Kind == MG_Pipe::kMGPipeSurfaceKindNone) {
|
||||
@@ -1047,7 +1047,7 @@
|
||||
|
||||
VkRect2D area{{0, 0}, {key.width, key.height}};
|
||||
if (GLScissorTestClips()) {
|
||||
const auto& box = MG_Pipe::gPipeInputs.GetScissorBox();
|
||||
const auto& box = MG_Pipe::gPipeInputs->GetScissorBox();
|
||||
const Int32 x0 = std::max(box.x(), 0), y0 = std::max(box.y(), 0);
|
||||
const Int32 x1 = std::min(box.x() + box.z(), static_cast<Int32>(key.width));
|
||||
const Int32 y1 = std::min(box.y() + box.w(), static_cast<Int32>(key.height));
|
||||
|
||||
@@ -370,7 +370,7 @@
|
||||
const Uint64 passHash = active->hash;
|
||||
VkRect2D area{{0, 0}, {key.width, key.height}};
|
||||
if (GLScissorTestClips()) {
|
||||
const auto& box = MG_Pipe::gPipeInputs.GetScissorBox();
|
||||
const auto& box = MG_Pipe::gPipeInputs->GetScissorBox();
|
||||
const Int32 x0 = std::max(box.x(), 0), y0 = std::max(box.y(), 0);
|
||||
const Int32 x1 = std::min(box.x() + box.z(), static_cast<Int32>(key.width));
|
||||
const Int32 y1 = std::min(box.y() + box.w(), static_cast<Int32>(key.height));
|
||||
@@ -394,7 +394,7 @@
|
||||
const Int32 slot = fbo.DrawBuffers[i];
|
||||
if (slot < 0 || slot >= static_cast<Int32>(MG_Pipe::kMGPipeMaxColorAttachments)) continue;
|
||||
if (fbo.Color[slot].Kind == MG_Pipe::kMGPipeSurfaceKindNone) continue;
|
||||
const auto mask = MG_Pipe::gPipeInputs.GetColorMaskIndexed(i);
|
||||
const auto mask = MG_Pipe::gPipeInputs->GetColorMaskIndexed(i);
|
||||
if (!mask.r() && !mask.g() && !mask.b() && !mask.a()) continue;
|
||||
if (!mask.r() || !mask.g() || !mask.b() || !mask.a() || payload.colorEncoding != ClearColorEncoding::Float) {
|
||||
all = false;
|
||||
@@ -429,7 +429,7 @@
|
||||
(key.attachments[key.depthReference].aspect & aspect) != 0;
|
||||
};
|
||||
if (remaining & GL_DEPTH_BUFFER_BIT) {
|
||||
if (!MG_Pipe::gPipeInputs.GetDepthMask() || fbo.Depth.Kind == MG_Pipe::kMGPipeSurfaceKindNone) {
|
||||
if (!MG_Pipe::gPipeInputs->GetDepthMask() || fbo.Depth.Kind == MG_Pipe::kMGPipeSurfaceKindNone) {
|
||||
handled |= GL_DEPTH_BUFFER_BIT;
|
||||
} else if (depthStencilHeld(fbo.Depth, VK_IMAGE_ASPECT_DEPTH_BIT)) {
|
||||
depthStencilAspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
@@ -437,7 +437,7 @@
|
||||
}
|
||||
}
|
||||
if (remaining & GL_STENCIL_BUFFER_BIT) {
|
||||
const Uint32 mask = MG_Pipe::gPipeInputs.GetStencilState(StencilFace::Front).WriteMask & 255u;
|
||||
const Uint32 mask = MG_Pipe::gPipeInputs->GetStencilState(StencilFace::Front).WriteMask & 255u;
|
||||
if (mask == 0 || fbo.Stencil.Kind == MG_Pipe::kMGPipeSurfaceKindNone) {
|
||||
handled |= GL_STENCIL_BUFFER_BIT;
|
||||
} else if (mask == 255u && depthStencilHeld(fbo.Stencil, VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
@@ -472,7 +472,7 @@
|
||||
const Bool scissor = GLScissorTestClips();
|
||||
const auto wholeImage = [&](const WireImage& image) {
|
||||
if (!scissor) return true;
|
||||
const auto& box = MG_Pipe::gPipeInputs.GetScissorBox();
|
||||
const auto& box = MG_Pipe::gPipeInputs->GetScissorBox();
|
||||
return box.x() <= 0 && box.y() <= 0 && box.x() + box.z() >= static_cast<Int32>(image.extent.width) &&
|
||||
box.y() + box.w() >= static_cast<Int32>(image.extent.height);
|
||||
};
|
||||
@@ -498,7 +498,7 @@
|
||||
if (slot < 0 || slot >= static_cast<Int32>(MG_Pipe::kMGPipeMaxColorAttachments)) continue;
|
||||
const auto& surface = fbo.Color[slot];
|
||||
if (surface.Kind == MG_Pipe::kMGPipeSurfaceKindNone) continue;
|
||||
const auto mask = MG_Pipe::gPipeInputs.GetColorMaskIndexed(i);
|
||||
const auto mask = MG_Pipe::gPipeInputs->GetColorMaskIndexed(i);
|
||||
if (!mask.r() && !mask.g() && !mask.b() && !mask.a()) continue;
|
||||
if (!mask.r() || !mask.g() || !mask.b() || !mask.a()) {
|
||||
all = false;
|
||||
@@ -538,13 +538,13 @@
|
||||
return true;
|
||||
};
|
||||
if (remaining & GL_DEPTH_BUFFER_BIT) {
|
||||
if (!MG_Pipe::gPipeInputs.GetDepthMask() || fbo.Depth.Kind == MG_Pipe::kMGPipeSurfaceKindNone)
|
||||
if (!MG_Pipe::gPipeInputs->GetDepthMask() || fbo.Depth.Kind == MG_Pipe::kMGPipeSurfaceKindNone)
|
||||
handled |= GL_DEPTH_BUFFER_BIT;
|
||||
else if (depthStencil(fbo.Depth, VK_IMAGE_ASPECT_DEPTH_BIT))
|
||||
handled |= GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
if (remaining & GL_STENCIL_BUFFER_BIT) {
|
||||
const Uint32 mask = MG_Pipe::gPipeInputs.GetStencilState(StencilFace::Front).WriteMask & 255u;
|
||||
const Uint32 mask = MG_Pipe::gPipeInputs->GetStencilState(StencilFace::Front).WriteMask & 255u;
|
||||
if (mask == 0 || fbo.Stencil.Kind == MG_Pipe::kMGPipeSurfaceKindNone)
|
||||
handled |= GL_STENCIL_BUFFER_BIT;
|
||||
else if (mask == 255u && depthStencil(fbo.Stencil, VK_IMAGE_ASPECT_STENCIL_BIT))
|
||||
@@ -564,7 +564,7 @@
|
||||
|
||||
void VulkanRenderer::ClearWireFramebuffer(const MG_Pipe::MGPFramebufferState& fbo,
|
||||
const ClearAttachmentPayload& clearRequest, GLint drawbuffer) {
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::RasterizerDiscard)) return;
|
||||
if (MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::RasterizerDiscard)) return;
|
||||
// P15 S0: what the draw pass can take is cleared inside it (ClearWireFramebufferInPass,
|
||||
// WireDraw.inc); only the buffers it hands back take the standalone pass below.
|
||||
// P15: in the open pass when it is this framebuffer's (the in-pass clear) or merely holds
|
||||
@@ -586,12 +586,12 @@
|
||||
if (m_wireRetiredObjects.size() >= kRetiredObjectsBeforeSubmit && m_wirePreparationDepth == 0 &&
|
||||
HasPendingRecordedWork())
|
||||
(void)FlushPendingCommands();
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::RasterizerDiscard)) return;
|
||||
if (MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::RasterizerDiscard)) return;
|
||||
const auto clearSurface = [&](const MG_Pipe::MGPSurface& surface, VkImageAspectFlags aspect,
|
||||
Uint32 colorIndex) {
|
||||
if (!fbo.IsDefault && surface.Kind == MG_Pipe::kMGPipeSurfaceKindNone) return;
|
||||
if (aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||
const auto mask = MG_Pipe::gPipeInputs.GetColorMaskIndexed(colorIndex);
|
||||
const auto mask = MG_Pipe::gPipeInputs->GetColorMaskIndexed(colorIndex);
|
||||
if (!mask.r() && !mask.g() && !mask.b() && !mask.a()) return;
|
||||
if (!mask.r() || !mask.g() || !mask.b() || !mask.a()) {
|
||||
MGLOG_W_ONCE("DirectVulkan: glClear with a partial color mask is not supported");
|
||||
@@ -599,10 +599,10 @@
|
||||
}
|
||||
}
|
||||
if (aspect & VK_IMAGE_ASPECT_DEPTH_BIT) {
|
||||
if (!MG_Pipe::gPipeInputs.GetDepthMask()) aspect &= ~VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if (!MG_Pipe::gPipeInputs->GetDepthMask()) aspect &= ~VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
}
|
||||
if (aspect & VK_IMAGE_ASPECT_STENCIL_BIT) {
|
||||
const Uint32 mask = MG_Pipe::gPipeInputs.GetStencilState(StencilFace::Front).WriteMask & 255u;
|
||||
const Uint32 mask = MG_Pipe::gPipeInputs->GetStencilState(StencilFace::Front).WriteMask & 255u;
|
||||
if (!mask) aspect &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
else if (mask != 255u) {
|
||||
MGLOG_W_ONCE("DirectVulkan: glClear with a partial stencil write mask is not supported");
|
||||
@@ -615,7 +615,7 @@
|
||||
m_textureManager->FlushPendingUploads();
|
||||
VkRect2D area{{0, 0}, image.extent};
|
||||
if (GLScissorTestClips()) {
|
||||
const auto& box = MG_Pipe::gPipeInputs.GetScissorBox();
|
||||
const auto& box = MG_Pipe::gPipeInputs->GetScissorBox();
|
||||
const Int32 x0 = std::max(box.x(), 0), y0 = std::max(box.y(), 0);
|
||||
const Int32 x1 = std::min(box.x() + box.z(), static_cast<Int32>(image.extent.width));
|
||||
const Int32 y1 = std::min(box.y() + box.w(), static_cast<Int32>(image.extent.height));
|
||||
@@ -1264,7 +1264,7 @@
|
||||
// The scissor test clips blit writes: intersect the destination rectangle with
|
||||
// the scissor box and shrink the source proportionally.
|
||||
if (GLScissorTestClips()) {
|
||||
const IntVec4& scissor = MG_Pipe::gPipeInputs.GetScissorBox();
|
||||
const IntVec4& scissor = MG_Pipe::gPipeInputs->GetScissorBox();
|
||||
const auto clipAxis = [](GLint& d0, GLint& d1, GLint& s0, GLint& s1, GLint clipLo, GLint clipHi) -> Bool {
|
||||
const Bool dstFlipped = d1 < d0;
|
||||
GLint lo = dstFlipped ? d1 : d0;
|
||||
|
||||
@@ -442,7 +442,7 @@ namespace MobileGL::MG_Pipe {
|
||||
// D10: THE WIDER PREDICATE, and the narrow one was a latent crash rather than a missing
|
||||
// optimisation. Gated on the REHEARSAL, this early-returned for the whole life of a
|
||||
// spawn server - because that knob is off by default and nothing in the spawn shape
|
||||
// turns it on - so the server's gPipeInputs.ContextIdentity() stayed nullptr forever.
|
||||
// turns it on - so the server's gPipeInputs->ContextIdentity() stayed nullptr forever.
|
||||
// DirectGLES' fb-slot memo compares that identity FIRST and with no generation, so a
|
||||
// nullptr against its own nullptr initialiser reads as a CACHE HIT and hands out a slot
|
||||
// that was never filled. `st` lands the named Fatal at that site; this is the gate that
|
||||
@@ -596,12 +596,12 @@ namespace MobileGL::MG_Pipe {
|
||||
// The seven carry no MGP_INPUT_CHECK at all (the declared exception argued at
|
||||
// PipeInputs.h's F-class block), so freshness can never reach them and neither can the
|
||||
// stamp's withdrawal. This is the only thing that puts them in `rsp`.
|
||||
if (!gPipeInputs.ServerStampedVerb()) return;
|
||||
if (!gPipeInputs->ServerStampedVerb()) return;
|
||||
const auto ownership = MGPipeFieldOwnershipOf(field);
|
||||
if (ownership == MGPipeFieldOwnership::kFatal)
|
||||
MGPipeInputPoisonFatalForVerb(field, gPipeInputs.CurrentVerb());
|
||||
MGPipeInputPoisonFatalForVerb(field, gPipeInputs->CurrentVerb());
|
||||
if (ownership == MGPipeFieldOwnership::kBarrierPulled)
|
||||
CountBarrierPull(field, gPipeInputs.CurrentVerb());
|
||||
CountBarrierPull(field, gPipeInputs->CurrentVerb());
|
||||
}
|
||||
#endif // MOBILEGL_BUILD_RECORD_ARM && MOBILEGL_PIPE_POISON
|
||||
|
||||
|
||||
@@ -832,12 +832,18 @@ namespace MobileGL::MG_Pipe {
|
||||
// have. Nothing about the block's contents changed; what changed is that the name resolves to
|
||||
// the SESSION'S block on a thread that belongs to one.
|
||||
//
|
||||
// WHY A THREAD-LOCAL REFERENCE, AND NOT SOMETHING CLEVERER. gPipeInputs is spelled at ~380
|
||||
// sites in MG_Backend/MG_Impl (they read `MG_Pipe::gPipeInputs.` directly since P13 retired the
|
||||
// pull/push switch macro); a reference whose TARGET varies with the calling thread is the
|
||||
// only shape that keeps all of them compiling and all of them correct. The cost is one TLS
|
||||
// address computation per access site - not one per field, and with no guard: the reference is
|
||||
// bound once per thread on its first use.
|
||||
// WHY A THREAD-LOCAL SLOT, AND NOT SOMETHING CLEVERER. gPipeInputs is spelled at ~380
|
||||
// sites in MG_Backend/MG_Impl (they read `MG_Pipe::gPipeInputs->` directly since P13 retired the
|
||||
// pull/push switch macro); a name whose TARGET varies with the calling thread is the only
|
||||
// shape that keeps all of them compiling and all of them correct.
|
||||
//
|
||||
// P15: A POINTER SLOT, NOT A REFERENCE. It used to be a `thread_local PipeInputs&` bound by a
|
||||
// dynamic initializer, and a thread_local with a dynamic initializer is reached through its
|
||||
// TLS init function, which tests two more thread_local guards on every read: three TLS
|
||||
// address calls per access in a dlopen'ed library, at every API level. The slot below is
|
||||
// constant-initialized and trivially destructible, so an access is one TLS address
|
||||
// computation, a load and a null test; the binding itself is unchanged - once per thread, at
|
||||
// its first use, through the same resolver.
|
||||
//
|
||||
// THE RESOLVER IS A HOOK because this header may not know about sessions (MG_Remote/Server
|
||||
// owns them and includes THIS header, not the other way round). It is installed once by the
|
||||
@@ -860,7 +866,27 @@ namespace MobileGL::MG_Pipe {
|
||||
return gPipeInputsDefault;
|
||||
}
|
||||
|
||||
inline thread_local PipeInputs& gPipeInputs = MGPipeServerInputsForCallingThread();
|
||||
class PipeInputsThreadSlot {
|
||||
public:
|
||||
constexpr PipeInputsThreadSlot() = default;
|
||||
PipeInputsThreadSlot(const PipeInputsThreadSlot&) = delete;
|
||||
PipeInputsThreadSlot& operator=(const PipeInputsThreadSlot&) = delete;
|
||||
// The block's address is `&*gPipeInputs`; the slot's own address names nothing.
|
||||
void operator&() const = delete;
|
||||
|
||||
PipeInputs& Get() {
|
||||
PipeInputs* bound = m_bound;
|
||||
if (bound == nullptr) [[unlikely]] bound = m_bound = &MGPipeServerInputsForCallingThread();
|
||||
return *bound;
|
||||
}
|
||||
PipeInputs* operator->() { return &Get(); }
|
||||
PipeInputs& operator*() { return Get(); }
|
||||
operator PipeInputs&() { return Get(); }
|
||||
|
||||
private:
|
||||
PipeInputs* m_bound = nullptr;
|
||||
};
|
||||
inline constinit thread_local PipeInputsThreadSlot gPipeInputs;
|
||||
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
// ============================================================================
|
||||
|
||||
@@ -275,11 +275,11 @@ namespace MobileGL::MG_Record {
|
||||
|
||||
// Save the server-visible pack state, force neutral for the read, restore. Both go through
|
||||
// the applier's own set_pixel_pack_state entry point (MGPipeApplySetPixelPackState writes
|
||||
// gPipeInputs.m_pixelStore[0], which the backend's ReadPixels reads via
|
||||
// gPipeInputs->m_pixelStore[0], which the backend's ReadPixels reads via
|
||||
// gPipeInputs->GetPixelStoreParameters); the read is synchronous on this thread, so the window
|
||||
// in which the pack state is neutral does not outlive the call.
|
||||
const MG_Pipe::PixelStoreParameters savedPack =
|
||||
MG_Pipe::gPipeInputs.GetPixelStoreParameters(/*isUnpack=*/false);
|
||||
MG_Pipe::gPipeInputs->GetPixelStoreParameters(/*isUnpack=*/false);
|
||||
// MG_Pipe owns the constant (MGPipeTypes.h): in a verify build the compare-at-read hook's
|
||||
// oracle for the pack half inside this window is the same value, and a second hand-typed
|
||||
// copy would drift without a build break.
|
||||
@@ -566,7 +566,7 @@ namespace MobileGL::MG_Record {
|
||||
// session child (false = latched, the verb declines); unarmed they still die.
|
||||
Bool CheckUnitWindows(const MG_Pipe::MGPipeApplierState& st, const char* verb) {
|
||||
if (st.SamplerViewCount == 0 && st.SamplerStateCount == 0) return true;
|
||||
const Int maxTouched = MG_Pipe::gPipeInputs.GetMaxTouchedTextureUnit();
|
||||
const Int maxTouched = MG_Pipe::gPipeInputs->GetMaxTouchedTextureUnit();
|
||||
if (maxTouched < 0) return true;
|
||||
const Uint32 required = static_cast<Uint32>(maxTouched) + 1u;
|
||||
if (st.SamplerViewStart != 0 || st.SamplerViewCount < required) {
|
||||
|
||||
@@ -671,7 +671,7 @@ namespace MobileGL::MG_Pipe {
|
||||
}
|
||||
|
||||
void MGPipeVerifyReadHook(const PipeInputs& self, MGPipeInputField field, Uint index0, Uint index1) {
|
||||
if (&self != &gPipeInputs || !g_verify.Enabled) return;
|
||||
if (&self != &*gPipeInputs || !g_verify.Enabled) return;
|
||||
const auto index = static_cast<SizeT>(field);
|
||||
if (kMGPipeInputFieldSticky[index]) return;
|
||||
// P13 W5: the monolith verb port applies records without a server stamp, and its readback
|
||||
@@ -2256,7 +2256,7 @@ namespace MobileGL::MG_Pipe {
|
||||
// static initialisation, by the translation unit that owns the forward.
|
||||
const Bool kCompileEnvHookRegistered = [] {
|
||||
MGPipeSetCompileEnvChangedHook([] {
|
||||
if (gPipeInputs.IsLive()) gPipeInputs.InvalidateCompileEnv();
|
||||
if (gPipeInputs->IsLive()) gPipeInputs->InvalidateCompileEnv();
|
||||
});
|
||||
return true;
|
||||
}();
|
||||
@@ -3134,7 +3134,7 @@ namespace MobileGL::MG_Pipe {
|
||||
// GLContext's m_currentVertexAttributes hold exactly those, so the diff below is
|
||||
// EMPTY on the one walk that must publish everything. The server's mirror is not
|
||||
// default: MGPipeApplierReset() clears the CSO store and the residual block and
|
||||
// leaves gPipeInputs.m_currentVertexAttribute holding the PREVIOUS context's
|
||||
// leaves gPipeInputs->m_currentVertexAttribute holding the PREVIOUS context's
|
||||
// defaults. So the InvalidateAll() a fresh context does to the set-hash
|
||||
// suppressor would have been cancelled two lines later by this diff, and the one
|
||||
// call P2 fully owns would publish nothing across a context change - exactly the
|
||||
|
||||
@@ -32,10 +32,10 @@ namespace MGITest {
|
||||
out->peekAvailable = true;
|
||||
out->roleSplitActive = MGP::MGPipeRoleSplitRehearsalActive();
|
||||
MGP::PipeInputs& client = MGP::MGPipeClientInputs();
|
||||
out->blocksDistinct = &client != &MGP::gPipeInputs;
|
||||
out->blocksDistinct = &client != &*MGP::gPipeInputs;
|
||||
out->clientSerial = client.FilledState().CurrentVerbSerial;
|
||||
out->serverSerial = MGP::gPipeInputs.FilledState().CurrentVerbSerial;
|
||||
out->serverIdentity = MGP::gPipeInputs.ContextIdentity();
|
||||
out->serverSerial = MGP::gPipeInputs->FilledState().CurrentVerbSerial;
|
||||
out->serverIdentity = MGP::gPipeInputs->ContextIdentity();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace MGITest {
|
||||
// verb boundaries; the server block's moves only on a server verb stamp.
|
||||
unsigned long long clientSerial = 0;
|
||||
unsigned long long serverSerial = 0;
|
||||
// gPipeInputs.ContextIdentity(): non-null once the server has stamped a verb boundary
|
||||
// gPipeInputs->ContextIdentity(): non-null once the server has stamped a verb boundary
|
||||
// under the rehearsal (CONTRACT-P5E §3.2's server-owned identity).
|
||||
const void* serverIdentity = nullptr;
|
||||
};
|
||||
|
||||
@@ -1655,8 +1655,40 @@ namespace MobileGL::MG_State {
|
||||
} // namespace GLState
|
||||
|
||||
// Leak-at-exit storage; see GlobalObjects.cpp.
|
||||
thread_local SharedPtr<GLState::GLContext> pGLContext;
|
||||
constinit thread_local CurrentGLContextSlot pGLContext;
|
||||
|
||||
// The reference that keeps the calling thread's pGLContext alive (Core.h). Registered for
|
||||
// destruction on the thread's first assignment; at thread exit it clears the slot first, so
|
||||
// whatever the context's destructor reaches sees no current context rather than one that is
|
||||
// being destroyed.
|
||||
struct CurrentGLContextOwner {
|
||||
SharedPtr<GLState::GLContext> context;
|
||||
~CurrentGLContextOwner() { pGLContext.m_context = nullptr; }
|
||||
};
|
||||
namespace {
|
||||
thread_local CurrentGLContextOwner tCurrentGLContextOwner;
|
||||
}
|
||||
|
||||
const SharedPtr<GLState::GLContext>& CurrentGLContextSlot::Shared() const {
|
||||
return tCurrentGLContextOwner.context;
|
||||
}
|
||||
|
||||
SharedPtr<GLState::GLContext> CurrentGLContextSlot::Take() {
|
||||
m_context = nullptr;
|
||||
return Move(tCurrentGLContextOwner.context);
|
||||
}
|
||||
|
||||
CurrentGLContextSlot& CurrentGLContextSlot::operator=(SharedPtr<GLState::GLContext> context) {
|
||||
auto& owner = tCurrentGLContextOwner;
|
||||
m_context = context.get();
|
||||
// The old context's last reference may run destructors that read pGLContext: the slot
|
||||
// already names the new one, as it did when this was a SharedPtr assignment.
|
||||
SharedPtr<GLState::GLContext> previous = Move(owner.context);
|
||||
owner.context = Move(context);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
thread_local Bool tThreadReleasedLostContext = false;
|
||||
constinit thread_local Bool tThreadReleasedLostContext = false;
|
||||
#endif
|
||||
} // namespace MobileGL::MG_State
|
||||
|
||||
@@ -782,7 +782,53 @@ namespace MobileGL {
|
||||
// thread that never crossed an eglMakeCurrent keeps the process default MG_State::Init()
|
||||
// gave it. NULL on a thread for which neither has happened, the same answer a process
|
||||
// that never reached MG_State::Init() (the spawn server image) has always given.
|
||||
extern thread_local SharedPtr<GLState::GLContext> pGLContext;
|
||||
//
|
||||
// P15: A PLAIN POINTER IN TLS, WITH THE OWNING REFERENCE KEPT BESIDE IT. Every GL entry
|
||||
// point reads this, often several times. A thread_local with a destructor (the SharedPtr
|
||||
// it used to be) is reached through its TLS init function, which tests a second
|
||||
// thread_local guard first: two TLS address calls per read in a dlopen'ed library, at
|
||||
// every API level. This object is trivially destructible and constant-initialized, so a
|
||||
// read is one TLS address computation and a load. The SharedPtr that keeps the context
|
||||
// alive lives in a separate thread_local in Core.cpp, written only by the assignments
|
||||
// below (eglMakeCurrent and the release edge, MG_State::Init(), tests); its destructor
|
||||
// clears this pointer before it drops the reference, so a thread's exit leaves no
|
||||
// dangling pointer behind.
|
||||
//
|
||||
// Assignment, reset() and the SharedPtr conversions touch the owner and belong to the
|
||||
// CALLING THREAD only: never assign through a reference to another thread's slot.
|
||||
class CurrentGLContextSlot {
|
||||
public:
|
||||
constexpr CurrentGLContextSlot() = default;
|
||||
CurrentGLContextSlot(const CurrentGLContextSlot&) = delete;
|
||||
CurrentGLContextSlot& operator=(const CurrentGLContextSlot&) = delete;
|
||||
|
||||
GLState::GLContext* get() const { return m_context; }
|
||||
GLState::GLContext* operator->() const { return m_context; }
|
||||
GLState::GLContext& operator*() const { return *m_context; }
|
||||
explicit operator bool() const { return m_context != nullptr; }
|
||||
|
||||
// The owning reference (cold: a second TLS read).
|
||||
const SharedPtr<GLState::GLContext>& Shared() const;
|
||||
operator const SharedPtr<GLState::GLContext>&() const& { return Shared(); }
|
||||
// A move out of the slot is spelled Take(): std::move of the slot does not compile.
|
||||
operator const SharedPtr<GLState::GLContext>&() const&& = delete;
|
||||
SharedPtr<GLState::GLContext> Take();
|
||||
|
||||
CurrentGLContextSlot& operator=(SharedPtr<GLState::GLContext> context);
|
||||
void reset() { *this = nullptr; }
|
||||
|
||||
friend Bool operator==(const CurrentGLContextSlot& slot, std::nullptr_t) {
|
||||
return slot.m_context == nullptr;
|
||||
}
|
||||
friend Bool operator==(const CurrentGLContextSlot& slot, const SharedPtr<GLState::GLContext>& other) {
|
||||
return slot.m_context == other.get();
|
||||
}
|
||||
|
||||
private:
|
||||
friend struct CurrentGLContextOwner;
|
||||
GLState::GLContext* m_context = nullptr;
|
||||
};
|
||||
extern constinit thread_local CurrentGLContextSlot pGLContext;
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
// True on a thread whose last EGL release let go of a context lost with an ended server
|
||||
// session, until it makes a context current again. The release hands such a thread the
|
||||
@@ -790,7 +836,7 @@ namespace MobileGL {
|
||||
// TLS that state's last owner), so this is what keeps the thread answering as lost: an
|
||||
// application that releases its context before asking glGetGraphicsResetStatus - Qt's
|
||||
// render threads do - still learns that the context is gone and rebuilds it.
|
||||
extern thread_local Bool tThreadReleasedLostContext;
|
||||
extern constinit thread_local Bool tThreadReleasedLostContext;
|
||||
#endif
|
||||
|
||||
// The fallback pGLContext starts at and an EGL release edge restores to: the process's
|
||||
|
||||
@@ -147,17 +147,17 @@ TEST(ContextEpochTest, SameXfbNameInTwoServedContextsDoesNotAliasThePausedSpan)
|
||||
TEST(ContextEpochTest, ServerLivenessDoesNotFollowTheClientContextOrAVerbStamp) {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
DriverScope scope;
|
||||
auto context = Move(MG_State::pGLContext);
|
||||
auto context = MG_State::pGLContext.Take();
|
||||
const Bool previous = MG_Pipe::MGPipeServerContextIsLive();
|
||||
MG_Pipe::MGPipeServerSetContextLive(false);
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
EXPECT_FALSE(MG_Pipe::gPipeInputs.IsLive());
|
||||
EXPECT_FALSE(MG_Pipe::gPipeInputs->IsLive());
|
||||
MG_Pipe::MGPipeServerSetContextLive(true);
|
||||
MG_State::pGLContext.reset();
|
||||
EXPECT_TRUE(MG_Pipe::gPipeInputs.IsLive());
|
||||
EXPECT_TRUE(MG_Pipe::gPipeInputs->IsLive());
|
||||
MG_Pipe::MGPipeServerSetContextLive(false);
|
||||
MG_Pipe::MGPipeServerStampVerbBoundary(MG_Pipe::MGPipeVerb::DrawArrays);
|
||||
EXPECT_FALSE(MG_Pipe::gPipeInputs.IsLive()) << "a stale command resurrected a destroyed server context";
|
||||
EXPECT_FALSE(MG_Pipe::gPipeInputs->IsLive()) << "a stale command resurrected a destroyed server context";
|
||||
MG_Pipe::MGPipeServerClearVerbBoundary();
|
||||
MG_State::pGLContext = Move(context);
|
||||
MG_Pipe::MGPipeServerSetContextLive(previous);
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace {
|
||||
m_blockKb = MG_Config::RecordArm.PersistentBlockKb;
|
||||
m_adoptTier = MG_Config::Ipc.AdoptTier;
|
||||
m_pipeStats = MG_Config::Features.PipeStats;
|
||||
m_context = Move(MG_State::pGLContext);
|
||||
m_context = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
MG_Config::Transport = MG_Config::TransportMode::InProcess;
|
||||
MG_Config::RecordArm.PersistentBlockKb = 64;
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace {
|
||||
class FieldOwnershipTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
m_previous = Move(MG_State::pGLContext);
|
||||
m_previous = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
MG_Config::Ipc.StrictErrors = false;
|
||||
@@ -486,14 +486,14 @@ TEST_F(FieldOwnershipTest, TheResidualFillsSuppliedMemoReKeysOnEveryInputThatMov
|
||||
|
||||
TEST_F(FieldOwnershipTest, AServerStampMakesRecordSuppliedFieldsFreshAndWithdrawsTheRest) {
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::Clear);
|
||||
EXPECT_TRUE(gPipeInputs.ServerStampedVerb());
|
||||
EXPECT_EQ(gPipeInputs.CurrentVerb(), MGPipeVerb::Clear);
|
||||
EXPECT_TRUE(gPipeInputs->ServerStampedVerb());
|
||||
EXPECT_EQ(gPipeInputs->CurrentVerb(), MGPipeVerb::Clear);
|
||||
const MGPipeFieldMask& mask = kMGPipeClassFieldMask[static_cast<SizeT>(
|
||||
kMGPipeVerbClass[static_cast<SizeT>(MGPipeVerb::Clear)])];
|
||||
SizeT stamped = 0;
|
||||
for (SizeT i = 0; i < kMGPipeInputFieldCount; ++i) {
|
||||
const auto field = static_cast<MGPipeInputField>(i);
|
||||
const Bool fresh = MGPipeInputFieldIsFresh(gPipeInputs.FilledState(), field);
|
||||
const Bool fresh = MGPipeInputFieldIsFresh(gPipeInputs->FilledState(), field);
|
||||
// The stamp respects the verb's own may-read table for the client fill's reason: a
|
||||
// field outside the class was never copied for this verb, so answering it would hand
|
||||
// the server the previous verb's value.
|
||||
@@ -512,7 +512,7 @@ TEST_F(FieldOwnershipTest, AServerStampMakesRecordSuppliedFieldsFreshAndWithdraw
|
||||
// `answerable` out of kMGPipeFieldOwnership, so it can only catch a stamp that disagrees
|
||||
// with the table - never a table that is wrong. These four say what the stamp must do for
|
||||
// four fields whose class is an argument of this package rather than a lookup.
|
||||
const MGPipeFilledState& filled = gPipeInputs.FilledState();
|
||||
const MGPipeFilledState& filled = gPipeInputs->FilledState();
|
||||
EXPECT_TRUE(MGPipeInputFieldIsFresh(filled, MGPipeInputField::GetClearColor)); // supplied
|
||||
EXPECT_TRUE(MGPipeInputFieldIsFresh(filled, MGPipeInputField::GetRenderStateParameters));
|
||||
EXPECT_FALSE(MGPipeInputFieldIsFresh(filled, MGPipeInputField::GetFramebufferBindingSlot)); // pulled
|
||||
@@ -525,14 +525,14 @@ TEST_F(FieldOwnershipTest, AServerStampMakesRecordSuppliedFieldsFreshAndWithdraw
|
||||
// changing. Before this, the seven most dangerous fields were exempt by construction.
|
||||
TEST_F(FieldOwnershipTest, TheStickyExemptionIsCancelledByTheServerStamp) {
|
||||
MGPipeValidateForVerb(MGPipeVerb::Clear); // the CLIENT fills and stamps all 63, sticky included
|
||||
EXPECT_TRUE(MGPipeInputFieldIsFresh(gPipeInputs.FilledState(), MGPipeInputField::RecordError));
|
||||
EXPECT_TRUE(MGPipeInputFieldIsFresh(gPipeInputs->FilledState(), MGPipeInputField::RecordError));
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::Clear);
|
||||
for (SizeT i = 0; i < kMGPipeFieldOwnershipForwardCount; ++i) {
|
||||
const MGPipeInputField field = kMGPipeFieldOwnershipForwardField[i];
|
||||
// P5f fe retired the scalar forwards to server-owned answers. Their freshness
|
||||
// comes from that ownership; the remaining client forwards lose the exemption.
|
||||
const Bool serverOwned = MGPipeFieldOwnershipOf(field) == MGPipeFieldOwnership::kApplierDerived;
|
||||
EXPECT_EQ(MGPipeInputFieldIsFresh(gPipeInputs.FilledState(), field), serverOwned)
|
||||
EXPECT_EQ(MGPipeInputFieldIsFresh(gPipeInputs->FilledState(), field), serverOwned)
|
||||
<< kMGPipeInputFieldNames[Index(field)] << " has the wrong server-stamp freshness";
|
||||
}
|
||||
}
|
||||
@@ -543,21 +543,21 @@ TEST_F(FieldOwnershipTest, ARecordSuppliedFieldIsReadableAfterAServerStamp) {
|
||||
ASSERT_EQ(MGPipeFieldOwnershipOf(MGPipeInputField::GetClearColor),
|
||||
MGPipeFieldOwnership::kRecordSupplied);
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::Clear);
|
||||
(void)gPipeInputs.GetClearColor();
|
||||
(void)gPipeInputs.GetRenderStateParameters();
|
||||
(void)gPipeInputs->GetClearColor();
|
||||
(void)gPipeInputs->GetRenderStateParameters();
|
||||
EXPECT_EQ(MGPipeResidualPullCount(), Uint64{0});
|
||||
// The pixel store is in kReadback's class, not kClear's, so its readable half is exercised
|
||||
// under the verb that actually reads it. And P5c rv's record-supplied rows join it there:
|
||||
// GetActiveTextureUnit is exactly the read that used to count into `rsp`.
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::ReadPixels);
|
||||
(void)gPipeInputs.GetPixelStoreParameters(false); // the half that has a carrier
|
||||
(void)gPipeInputs.GetActiveTextureUnit(); // P5c rv: set_context_values carries it
|
||||
(void)gPipeInputs.GetMaxTouchedTextureUnit();
|
||||
(void)gPipeInputs->GetPixelStoreParameters(false); // the half that has a carrier
|
||||
(void)gPipeInputs->GetActiveTextureUnit(); // P5c rv: set_context_values carries it
|
||||
(void)gPipeInputs->GetMaxTouchedTextureUnit();
|
||||
EXPECT_EQ(MGPipeResidualPullCount(), Uint64{0});
|
||||
// And a shutter answers the applier's own Serial under a server stamp (APPLIER-DERIVED),
|
||||
// not the client's residual-fill copy: still zero pulls, and the answer MOVES when the
|
||||
// applier's texture state does.
|
||||
(void)gPipeInputs.GetTextureBindGeneration();
|
||||
(void)gPipeInputs->GetTextureBindGeneration();
|
||||
EXPECT_EQ(MGPipeResidualPullCount(), Uint64{0});
|
||||
}
|
||||
|
||||
@@ -578,16 +578,16 @@ TEST_F(FieldOwnershipTest, SetContextValuesLandsInPipeInputsAndTheShuttersAnswer
|
||||
MGPipeApplySetContextValues(values);
|
||||
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::ReadPixels);
|
||||
EXPECT_EQ(gPipeInputs.GetActiveTextureUnit(), 5);
|
||||
EXPECT_EQ(gPipeInputs.GetMaxTouchedTextureUnit(), 23);
|
||||
EXPECT_EQ(gPipeInputs->GetActiveTextureUnit(), 5);
|
||||
EXPECT_EQ(gPipeInputs->GetMaxTouchedTextureUnit(), 23);
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
EXPECT_EQ(gPipeInputs.GetTouchedBufferBindingPointCount(BufferTarget::Uniform), SizeT{7});
|
||||
EXPECT_EQ(gPipeInputs.GetTouchedBufferBindingPointCount(BufferTarget::Vertex), SizeT{0});
|
||||
EXPECT_TRUE(gPipeInputs.IsTransformFeedbackActive());
|
||||
EXPECT_FALSE(gPipeInputs.IsTransformFeedbackPaused());
|
||||
EXPECT_EQ(gPipeInputs.GetTransformFeedbackGeneration(), 0x1112131415161718ull);
|
||||
EXPECT_EQ(gPipeInputs.GetBoundTransformFeedbackLifetimeId(), 0x2122232425262728ull);
|
||||
EXPECT_EQ(gPipeInputs.GetTransformFeedbackCapturedVertices(), 0x3132333435363738ull);
|
||||
EXPECT_EQ(gPipeInputs->GetTouchedBufferBindingPointCount(BufferTarget::Uniform), SizeT{7});
|
||||
EXPECT_EQ(gPipeInputs->GetTouchedBufferBindingPointCount(BufferTarget::Vertex), SizeT{0});
|
||||
EXPECT_TRUE(gPipeInputs->IsTransformFeedbackActive());
|
||||
EXPECT_FALSE(gPipeInputs->IsTransformFeedbackPaused());
|
||||
EXPECT_EQ(gPipeInputs->GetTransformFeedbackGeneration(), 0x1112131415161718ull);
|
||||
EXPECT_EQ(gPipeInputs->GetBoundTransformFeedbackLifetimeId(), 0x2122232425262728ull);
|
||||
EXPECT_EQ(gPipeInputs->GetTransformFeedbackCapturedVertices(), 0x3132333435363738ull);
|
||||
// Eight record-supplied reads and not one residual pull.
|
||||
EXPECT_EQ(MGPipeResidualPullCount(), Uint64{0});
|
||||
|
||||
@@ -595,12 +595,12 @@ TEST_F(FieldOwnershipTest, SetContextValuesLandsInPipeInputsAndTheShuttersAnswer
|
||||
// SHUTTERS - the value matters only in that it MOVES when the server's texture state does
|
||||
// and never walks backwards - so the pin is the identity with the applier's counters, not
|
||||
// any particular number.
|
||||
EXPECT_EQ(gPipeInputs.GetTextureBindGeneration(), MGPipeApplierTextureShutterSerial());
|
||||
EXPECT_EQ(gPipeInputs.GetSamplingResolutionGeneration(), MGPipeApplierTextureShutterSerial());
|
||||
EXPECT_EQ(gPipeInputs.GetTextureContextId(), MGPipeApplierContextSerial());
|
||||
EXPECT_EQ(gPipeInputs->GetTextureBindGeneration(), MGPipeApplierTextureShutterSerial());
|
||||
EXPECT_EQ(gPipeInputs->GetSamplingResolutionGeneration(), MGPipeApplierTextureShutterSerial());
|
||||
EXPECT_EQ(gPipeInputs->GetTextureContextId(), MGPipeApplierContextSerial());
|
||||
const Uint64 before = MGPipeApplierTextureShutterSerial();
|
||||
MGPipeApplierNoteTextureStateMoved();
|
||||
EXPECT_EQ(gPipeInputs.GetTextureBindGeneration(), before + 1)
|
||||
EXPECT_EQ(gPipeInputs->GetTextureBindGeneration(), before + 1)
|
||||
<< "a texture-state apply moved the serial but the shutter did not answer with it";
|
||||
EXPECT_EQ(MGPipeResidualPullCount(), Uint64{0});
|
||||
}
|
||||
@@ -612,7 +612,7 @@ TEST_F(FieldOwnershipTest, ABarrierPulledReadAfterAServerStampIsCountedNotFatal)
|
||||
const ChildResult r = RunInChild([] {
|
||||
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
(void)gPipeInputs.GetBoundVertexArray();
|
||||
(void)gPipeInputs->GetBoundVertexArray();
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_NE(r.Log.find("Fatal{UnmigratedPipeInput, \"GetBoundVertexArray@DrawArrays\"}"), std::string::npos) << r.Log;
|
||||
@@ -629,7 +629,7 @@ TEST_F(FieldOwnershipTest, AStickyForwardIsCountedAsAResidualPull) {
|
||||
const ChildResult r = RunInChild([] {
|
||||
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::Clear);
|
||||
(void)gPipeInputs.ValidateProgramName(1u);
|
||||
(void)gPipeInputs->ValidateProgramName(1u);
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_NE(r.Log.find("Fatal{UnmigratedPipeInput, \"ValidateProgramName@Clear\"}"), std::string::npos) << r.Log;
|
||||
@@ -644,11 +644,11 @@ TEST_F(FieldOwnershipTest, AStickyForwardIsCountedAsAResidualPull) {
|
||||
// for - and what keeps build-split's monolith lanes behaving as a verify build's do.
|
||||
TEST_F(FieldOwnershipTest, NothingIsCountedOutsideAServerStampedVerb) {
|
||||
MGPipeValidateForVerb(MGPipeVerb::ReadPixels);
|
||||
(void)gPipeInputs.ValidateProgramName(1u);
|
||||
gPipeInputs.InvalidateCompileEnv();
|
||||
(void)gPipeInputs.GetActiveTextureUnit();
|
||||
(void)gPipeInputs->ValidateProgramName(1u);
|
||||
gPipeInputs->InvalidateCompileEnv();
|
||||
(void)gPipeInputs->GetActiveTextureUnit();
|
||||
EXPECT_EQ(MGPipeResidualPullCount(), Uint64{0});
|
||||
EXPECT_FALSE(gPipeInputs.ServerStampedVerb());
|
||||
EXPECT_FALSE(gPipeInputs->ServerStampedVerb());
|
||||
}
|
||||
|
||||
// THE APPLIER'S OWN CLEAR, reached directly rather than through the client's fill. In a spawned
|
||||
@@ -658,13 +658,13 @@ TEST_F(FieldOwnershipTest, NothingIsCountedOutsideAServerStampedVerb) {
|
||||
// InvalidateCompileEnv is reached from backend initialisation under - is gone for good.
|
||||
TEST_F(FieldOwnershipTest, TheAppliersOwnClearDisarmsTheStampWithoutTheClientsFill) {
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::ReadPixels);
|
||||
ASSERT_TRUE(gPipeInputs.ServerStampedVerb());
|
||||
(void)gPipeInputs.GetActiveTextureUnit();
|
||||
ASSERT_TRUE(gPipeInputs->ServerStampedVerb());
|
||||
(void)gPipeInputs->GetActiveTextureUnit();
|
||||
ASSERT_EQ(MGPipeResidualPullCount(), Uint64{0});
|
||||
MGPipeServerClearVerbBoundary();
|
||||
EXPECT_FALSE(gPipeInputs.ServerStampedVerb());
|
||||
(void)gPipeInputs.ValidateProgramName(1u);
|
||||
gPipeInputs.InvalidateCompileEnv();
|
||||
EXPECT_FALSE(gPipeInputs->ServerStampedVerb());
|
||||
(void)gPipeInputs->ValidateProgramName(1u);
|
||||
gPipeInputs->InvalidateCompileEnv();
|
||||
EXPECT_EQ(MGPipeResidualPullCount(), Uint64{0});
|
||||
}
|
||||
|
||||
@@ -677,7 +677,7 @@ TEST_F(FieldOwnershipTest, ABarrierPulledFieldOutsideTheVerbsClassIsStillFatal)
|
||||
#if MGTEST_HAVE_FORK
|
||||
const ChildResult r = RunInChild([] {
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::Clear);
|
||||
(void)gPipeInputs.GetProgramForDraw(); // retired accessor, outside kClear too
|
||||
(void)gPipeInputs->GetProgramForDraw(); // retired accessor, outside kClear too
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_NE(r.Log.find("Fatal{UnmigratedPipeInput, \"GetProgramForDraw@Clear\"}"), std::string::npos)
|
||||
@@ -693,7 +693,7 @@ TEST_F(FieldOwnershipTest, ResidualPullsReachThePublishedPerFrameCounter) {
|
||||
PS::SetEnabledForTesting(true);
|
||||
PS::ResetForTesting();
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
(void)gPipeInputs.GetCurrentVertexAttribute(0);
|
||||
(void)gPipeInputs->GetCurrentVertexAttribute(0);
|
||||
EXPECT_EQ(PS::FrameCalls(PS::CallClass::ResidualPulls), Uint64{0});
|
||||
EXPECT_NE(PS::FormatWindowLine().find(" rsp=0"), std::string::npos) << PS::FormatWindowLine();
|
||||
// Prove the reporting channel did not merely become a constant zero after retirement.
|
||||
@@ -742,9 +742,9 @@ TEST_F(FieldOwnershipTest, SplitBindingPointCapacityNeverConsultsTheFrontend) {
|
||||
RoleSplitArm guard;
|
||||
guard.Arm(true);
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
EXPECT_EQ(gPipeInputs.GetBufferBindingPointCount(BufferTarget::Uniform), 84u);
|
||||
EXPECT_EQ(gPipeInputs.GetBufferBindingPointCount(BufferTarget::TransformFeedback), 84u);
|
||||
EXPECT_EQ(gPipeInputs.GetBufferBindingPointCount(BufferTarget::PixelPack), 0u);
|
||||
EXPECT_EQ(gPipeInputs->GetBufferBindingPointCount(BufferTarget::Uniform), 84u);
|
||||
EXPECT_EQ(gPipeInputs->GetBufferBindingPointCount(BufferTarget::TransformFeedback), 84u);
|
||||
EXPECT_EQ(gPipeInputs->GetBufferBindingPointCount(BufferTarget::PixelPack), 0u);
|
||||
EXPECT_EQ(MGPipeFieldOwnershipOf(MGPipeInputField::GetBufferBindingPointCount),
|
||||
MGPipeFieldOwnership::kApplierDerived);
|
||||
MGPipeServerClearVerbBoundary();
|
||||
@@ -756,16 +756,16 @@ TEST_F(FieldOwnershipTest, SplitOpenSpansAreOwnedByTheApplierAndSurviveOtherBind
|
||||
auto& state = MGPipeApplier();
|
||||
state.StreamOutputSpans.clear();
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
EXPECT_FALSE(gPipeInputs.HasOpenTransformFeedbackSpan(0));
|
||||
EXPECT_FALSE(gPipeInputs.HasOpenTransformFeedbackSpan(11));
|
||||
EXPECT_FALSE(gPipeInputs->HasOpenTransformFeedbackSpan(0));
|
||||
EXPECT_FALSE(gPipeInputs->HasOpenTransformFeedbackSpan(11));
|
||||
state.StreamOutputSpans[11] = {};
|
||||
state.StreamOutputSpans[12] = {};
|
||||
state.BoundStreamOutputLifetimeId = 12;
|
||||
EXPECT_TRUE(gPipeInputs.HasOpenTransformFeedbackSpan(11));
|
||||
EXPECT_TRUE(gPipeInputs.HasOpenTransformFeedbackSpan(12));
|
||||
EXPECT_TRUE(gPipeInputs->HasOpenTransformFeedbackSpan(11));
|
||||
EXPECT_TRUE(gPipeInputs->HasOpenTransformFeedbackSpan(12));
|
||||
state.StreamOutputSpans.erase(12);
|
||||
EXPECT_TRUE(gPipeInputs.HasOpenTransformFeedbackSpan(11));
|
||||
EXPECT_FALSE(gPipeInputs.HasOpenTransformFeedbackSpan(12));
|
||||
EXPECT_TRUE(gPipeInputs->HasOpenTransformFeedbackSpan(11));
|
||||
EXPECT_FALSE(gPipeInputs->HasOpenTransformFeedbackSpan(12));
|
||||
EXPECT_EQ(MGPipeFieldOwnershipOf(MGPipeInputField::HasOpenTransformFeedbackSpan),
|
||||
MGPipeFieldOwnership::kApplierDerived);
|
||||
state.StreamOutputSpans.clear();
|
||||
@@ -793,7 +793,7 @@ TEST_F(FieldOwnershipTest, SplitCaptureSnapshotSurvivesMakeCurrentUntilObjectRel
|
||||
returning.IsTransformFeedbackActive = 1;
|
||||
MGPipeApplySetContextValues(returning);
|
||||
EXPECT_EQ(state.BoundStreamOutputLifetimeId, begin.LifetimeId);
|
||||
EXPECT_TRUE(gPipeInputs.HasOpenTransformFeedbackSpan(begin.LifetimeId));
|
||||
EXPECT_TRUE(gPipeInputs->HasOpenTransformFeedbackSpan(begin.LifetimeId));
|
||||
const auto found = state.StreamOutputSpans.find(begin.LifetimeId);
|
||||
EXPECT_NE(found, state.StreamOutputSpans.end());
|
||||
if (found != state.StreamOutputSpans.end()) {
|
||||
@@ -803,13 +803,13 @@ TEST_F(FieldOwnershipTest, SplitCaptureSnapshotSurvivesMakeCurrentUntilObjectRel
|
||||
EXPECT_EQ(found->second.Targets[3].Size, 64u);
|
||||
}
|
||||
MGPipeApplierReleaseObjectRecords();
|
||||
EXPECT_FALSE(gPipeInputs.HasOpenTransformFeedbackSpan(begin.LifetimeId));
|
||||
EXPECT_FALSE(gPipeInputs->HasOpenTransformFeedbackSpan(begin.LifetimeId));
|
||||
EXPECT_EQ(state.BoundStreamOutputLifetimeId, 0u);
|
||||
}
|
||||
|
||||
TEST_F(FieldOwnershipTest, RoleSplitOffFoldsTheFillSideOntoTheSharedBlock) {
|
||||
EXPECT_FALSE(MGPipeRoleSplitRehearsalActive());
|
||||
EXPECT_EQ(&MGPipeClientInputs(), &gPipeInputs);
|
||||
EXPECT_EQ(&MGPipeClientInputs(), &*gPipeInputs);
|
||||
}
|
||||
|
||||
// The knob alone is not the arm: under monolith transport the two roles are one thread and
|
||||
@@ -820,7 +820,7 @@ TEST_F(FieldOwnershipTest, RoleSplitUnderMonolithTransportIsStillOneBlock) {
|
||||
MG_Config::Ipc.RoleSplitState = true;
|
||||
MG_Config::Transport = MG_Config::TransportMode::Monolith;
|
||||
EXPECT_FALSE(MGPipeRoleSplitRehearsalActive());
|
||||
EXPECT_EQ(&MGPipeClientInputs(), &gPipeInputs);
|
||||
EXPECT_EQ(&MGPipeClientInputs(), &*gPipeInputs);
|
||||
}
|
||||
|
||||
// D1c/D10 (CONTRACT-P6 3.2, 3.4). THE PREDICATE THAT IS TRUE WITHOUT THE KNOB, and the reason
|
||||
@@ -850,38 +850,38 @@ TEST_F(FieldOwnershipTest, MonolithKeepsOneBlockAndTheWiderPredicateSaysSo) {
|
||||
MG_Config::Ipc.RoleSplitState = false;
|
||||
MG_Config::Transport = MG_Config::TransportMode::Monolith;
|
||||
EXPECT_FALSE(MGPipeBlocksAreDistinct());
|
||||
EXPECT_EQ(&MGPipeClientInputs(), &gPipeInputs);
|
||||
EXPECT_EQ(&MGPipeClientInputs(), &*gPipeInputs);
|
||||
}
|
||||
|
||||
TEST_F(FieldOwnershipTest, RoleSplitGivesTheFillSideADistinctBlockTheStampNeverTouches) {
|
||||
RoleSplitArm guard;
|
||||
guard.Arm(true);
|
||||
ASSERT_TRUE(MGPipeRoleSplitRehearsalActive());
|
||||
ASSERT_NE(&MGPipeClientInputs(), &gPipeInputs);
|
||||
ASSERT_NE(&MGPipeClientInputs(), &*gPipeInputs);
|
||||
|
||||
const Uint64 serverSerialBefore = gPipeInputs.FilledState().CurrentVerbSerial;
|
||||
const Uint64 serverSerialBefore = gPipeInputs->FilledState().CurrentVerbSerial;
|
||||
const Uint64 clientSerialBefore = MGPipeClientInputs().FilledState().CurrentVerbSerial;
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
EXPECT_EQ(gPipeInputs.FilledState().CurrentVerbSerial, serverSerialBefore + 1);
|
||||
EXPECT_EQ(gPipeInputs->FilledState().CurrentVerbSerial, serverSerialBefore + 1);
|
||||
EXPECT_EQ(MGPipeClientInputs().FilledState().CurrentVerbSerial, clientSerialBefore)
|
||||
<< "the server's verb stamp reached into the client block";
|
||||
EXPECT_TRUE(gPipeInputs.ServerStampedVerb());
|
||||
EXPECT_TRUE(gPipeInputs->ServerStampedVerb());
|
||||
EXPECT_FALSE(MGPipeClientInputs().ServerStampedVerb());
|
||||
|
||||
// The fill side's clear is the client block's own: it must not disarm the server's stamp,
|
||||
// which is CONTRACT-P5E §3.2's "the server's stamp is server-private" as a fact rather
|
||||
// than as a comment.
|
||||
MGPipeClientClearVerbBoundary();
|
||||
EXPECT_TRUE(gPipeInputs.ServerStampedVerb())
|
||||
EXPECT_TRUE(gPipeInputs->ServerStampedVerb())
|
||||
<< "the client-role clear withdrew the SERVER's stamp";
|
||||
MGPipeServerClearVerbBoundary();
|
||||
EXPECT_FALSE(gPipeInputs.ServerStampedVerb());
|
||||
EXPECT_FALSE(gPipeInputs->ServerStampedVerb());
|
||||
|
||||
// And the server block's identity is server-owned under the rehearsal (§3.2's other half):
|
||||
// the stamp set it, and it is non-null - a null identity reads as a hit against
|
||||
// DirectGLES' zero-initialised fb-slot memo cache, which is the unnamed crash this line
|
||||
// exists to preclude.
|
||||
EXPECT_NE(gPipeInputs.ContextIdentity(), nullptr);
|
||||
EXPECT_NE(gPipeInputs->ContextIdentity(), nullptr);
|
||||
}
|
||||
|
||||
// The fill side's writers land in the client block alone. MGPipeLeaveVerb rather than
|
||||
@@ -891,12 +891,12 @@ TEST_F(FieldOwnershipTest, RoleSplitGivesTheFillSideADistinctBlockTheStampNeverT
|
||||
TEST_F(FieldOwnershipTest, TheClientVerbLeaveWritesTheClientBlockAlone) {
|
||||
RoleSplitArm guard;
|
||||
guard.Arm(true);
|
||||
ASSERT_NE(&MGPipeClientInputs(), &gPipeInputs);
|
||||
const Uint64 serverSerialBefore = gPipeInputs.FilledState().CurrentVerbSerial;
|
||||
ASSERT_NE(&MGPipeClientInputs(), &*gPipeInputs);
|
||||
const Uint64 serverSerialBefore = gPipeInputs->FilledState().CurrentVerbSerial;
|
||||
const Uint64 clientSerialBefore = MGPipeClientInputs().FilledState().CurrentVerbSerial;
|
||||
MGPipeLeaveVerb();
|
||||
EXPECT_EQ(MGPipeClientInputs().FilledState().CurrentVerbSerial, clientSerialBefore + 1);
|
||||
EXPECT_EQ(gPipeInputs.FilledState().CurrentVerbSerial, serverSerialBefore)
|
||||
EXPECT_EQ(gPipeInputs->FilledState().CurrentVerbSerial, serverSerialBefore)
|
||||
<< "a fill-side write reached the server block";
|
||||
EXPECT_EQ(MGPipeClientInputs().CurrentVerb(), MGPipeVerb::kVerbCount);
|
||||
}
|
||||
@@ -909,9 +909,9 @@ TEST_F(FieldOwnershipTest, AClientFreshStampCannotReviveARetiredServerGetter) {
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
// Simulate a regressed writer stamping the old mirror as fresh. FATAL is a
|
||||
// representation verdict, not a freshness verdict, and must still reject it.
|
||||
auto& filled = const_cast<MGPipeFilledState&>(gPipeInputs.FilledState());
|
||||
auto& filled = const_cast<MGPipeFilledState&>(gPipeInputs->FilledState());
|
||||
filled.FilledGen[Index(MGPipeInputField::GetBoundVertexArray)] = filled.CurrentVerbSerial;
|
||||
(void)gPipeInputs.GetBoundVertexArray();
|
||||
(void)gPipeInputs->GetBoundVertexArray();
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_NE(r.Log.find("Fatal{UnmigratedPipeInput, \"GetBoundVertexArray@DrawArrays\"}"),
|
||||
@@ -923,7 +923,7 @@ TEST_F(FieldOwnershipTest, StrictErrorsTurnsABarrierPulledReadIntoANamedAbort) {
|
||||
const ChildResult r = RunInChild([] {
|
||||
MG_Config::Ipc.StrictErrors = true;
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
(void)gPipeInputs.GetBoundVertexArray();
|
||||
(void)gPipeInputs->GetBoundVertexArray();
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_NE(r.Log.find("Fatal{UnmigratedPipeInput, \"GetBoundVertexArray@DrawArrays\"}"), std::string::npos) << r.Log;
|
||||
@@ -936,7 +936,7 @@ TEST_F(FieldOwnershipTest, TheSameReadWithoutStrictErrorsSurvivesAndIsCounted) {
|
||||
const ChildResult r = RunInChild([] {
|
||||
MG_Config::Ipc.StrictErrors = false;
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
(void)gPipeInputs.GetBoundVertexArray();
|
||||
(void)gPipeInputs->GetBoundVertexArray();
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_NE(r.Log.find("Fatal{UnmigratedPipeInput, \"GetBoundVertexArray@DrawArrays\"}"), std::string::npos) << r.Log;
|
||||
@@ -950,7 +950,7 @@ TEST_F(FieldOwnershipTest, AnEscalatedRecordsPullIsAdmittedAndSaysWhy) {
|
||||
MG_Config::Ipc.StrictErrors = true;
|
||||
MGPipeApplierSetCurrentRecordBarrieredByEscalation(true);
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
(void)gPipeInputs.GetBoundVertexArray();
|
||||
(void)gPipeInputs->GetBoundVertexArray();
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_NE(r.Log.find("Fatal{UnmigratedPipeInput, \"GetBoundVertexArray@DrawArrays\"}"), std::string::npos) << r.Log;
|
||||
@@ -963,7 +963,7 @@ TEST_F(FieldOwnershipTest, StrictErrorsReachTheStickyForwardsAndNameThemByField)
|
||||
const ChildResult r = RunInChild([] {
|
||||
MG_Config::Ipc.StrictErrors = true;
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
(void)gPipeInputs.ValidateProgramName(1u);
|
||||
(void)gPipeInputs->ValidateProgramName(1u);
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_NE(r.Log.find("Fatal{UnmigratedPipeInput, \"ValidateProgramName@DrawArrays\"}"), std::string::npos) << r.Log;
|
||||
@@ -976,7 +976,7 @@ TEST_F(FieldOwnershipTest, AnAdmittedBarrierPullIsLoudOnceAndNotFatal) {
|
||||
const ChildResult r = RunInChild([] {
|
||||
MG_Config::Ipc.StrictErrors = true;
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::ReadPixels);
|
||||
(void)gPipeInputs.ValidateProgramName(1u);
|
||||
(void)gPipeInputs->ValidateProgramName(1u);
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_NE(r.Log.find("Fatal{UnmigratedPipeInput, \"ValidateProgramName@ReadPixels\"}"), std::string::npos) << r.Log;
|
||||
@@ -987,7 +987,7 @@ TEST_F(FieldOwnershipTest, AnAdmittedBarrierPullIsLoudOnceAndNotFatal) {
|
||||
TEST_F(FieldOwnershipTest, AFatalClassReadAbortsEvenWithoutStrictErrors) {
|
||||
const ChildResult r = RunInChild([] {
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
(void)gPipeInputs.GetTransformFeedbackPausedPrimitiveCounter();
|
||||
(void)gPipeInputs->GetTransformFeedbackPausedPrimitiveCounter();
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_NE(r.Log.find("Fatal{UnmigratedPipeInput, "
|
||||
@@ -1002,7 +1002,7 @@ TEST_F(FieldOwnershipTest, TheComputeProgramIsServedUnderADispatchStampFromP5bOn
|
||||
const ChildResult r = RunInChild([] {
|
||||
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DispatchCompute);
|
||||
(void)gPipeInputs.GetProgramForDispatch();
|
||||
(void)gPipeInputs->GetProgramForDispatch();
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_NE(r.Log.find("Fatal{UnmigratedPipeInput, \"GetProgramForDispatch@DispatchCompute\"}"), std::string::npos) << r.Log;
|
||||
@@ -1016,7 +1016,7 @@ TEST_F(FieldOwnershipTest, TheComputeProgramIsServedUnderADispatchStampFromP5bOn
|
||||
TEST_F(FieldOwnershipTest, TheUnpackHalfOfThePixelStoreAbortsWhileThePackHalfDoesNot) {
|
||||
const ChildResult fatal = RunInChild([] {
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::ReadPixels);
|
||||
(void)gPipeInputs.GetPixelStoreParameters(true);
|
||||
(void)gPipeInputs->GetPixelStoreParameters(true);
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(fatal)) << DescribeStatus(fatal) << "\n" << fatal.Log;
|
||||
EXPECT_NE(fatal.Log.find("Fatal{UnmigratedPipeInput, \"GetPixelStoreParameters@ReadPixels\"}"),
|
||||
@@ -1032,7 +1032,7 @@ TEST_F(FieldOwnershipTest, TheUnpackHalfOfThePixelStoreAbortsWhileThePackHalfDoe
|
||||
|
||||
const ChildResult ok = RunInChild([] {
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::ReadPixels);
|
||||
(void)gPipeInputs.GetPixelStoreParameters(false);
|
||||
(void)gPipeInputs->GetPixelStoreParameters(false);
|
||||
if (MGPipeResidualPullCount() != 0) ::_exit(7);
|
||||
});
|
||||
ASSERT_TRUE(ExitedWith(ok, 0)) << DescribeStatus(ok) << "\n" << ok.Log;
|
||||
@@ -1067,7 +1067,7 @@ TEST_F(FieldOwnershipTest, DualBlockMakesABarrierPulledReadANamedAbortWithoutStr
|
||||
MG_Config::Ipc.RoleSplitState = true;
|
||||
MG_Config::Ipc.StrictErrors = false;
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
(void)gPipeInputs.GetBoundVertexArray();
|
||||
(void)gPipeInputs->GetBoundVertexArray();
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_NE(r.Log.find("Fatal{UnmigratedPipeInput, \"GetBoundVertexArray@DrawArrays\"}"), std::string::npos) << r.Log;
|
||||
@@ -1081,7 +1081,7 @@ TEST_F(FieldOwnershipTest, DualBlockDoesNotArmUnderMonolithTransport) {
|
||||
MG_Config::Ipc.RoleSplitState = true;
|
||||
// A real monolith fill, not a manufactured server stamp on a monolith process.
|
||||
MGPipeValidateForVerb(MGPipeVerb::DrawArrays);
|
||||
(void)gPipeInputs.GetBoundVertexArray();
|
||||
(void)gPipeInputs->GetBoundVertexArray();
|
||||
if (MGPipeRoleSplitRehearsalActive() || MGPipeResidualPullCount() != 0) ::_exit(7);
|
||||
});
|
||||
ASSERT_TRUE(ExitedWith(r, 0)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
|
||||
@@ -246,7 +246,7 @@ namespace {
|
||||
kMGPipeSubsystemFramebuffer |
|
||||
kMGPipeSubsystemTextureResources |
|
||||
kMGPipeSubsystemSamplers;
|
||||
m_previousContext = Move(MG_State::pGLContext);
|
||||
m_previousContext = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
MGPipeFramebufferEmitterInstance().ResetForTest();
|
||||
MGPipeTextureEmitterInstance().ResetForTest();
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace {
|
||||
class PipeInputsTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
m_previous = Move(MG_State::pGLContext);
|
||||
m_previous = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
MGPipeSetPoisonOmission(nullptr, nullptr);
|
||||
}
|
||||
@@ -85,7 +85,7 @@ namespace {
|
||||
};
|
||||
|
||||
#if MOBILEGL_PIPE_POISON
|
||||
Bool Fresh(MGPipeInputField field) { return MGPipeInputFieldIsFresh(gPipeInputs.FilledState(), field); }
|
||||
Bool Fresh(MGPipeInputField field) { return MGPipeInputFieldIsFresh(gPipeInputs->FilledState(), field); }
|
||||
#endif
|
||||
|
||||
[[maybe_unused]] constexpr const char* kOmittedFatal ="Fatal{UnmigratedPipeInput, \"GetActiveTextureUnit@GenerateMipmap\"}";
|
||||
@@ -147,7 +147,7 @@ TEST_F(PipeInputsTest, OmittingOneFieldForOneVerbLeavesExactlyThatFieldStale) {
|
||||
EXPECT_TRUE(Fresh(MGPipeInputField::GetTextureUnitObject));
|
||||
EXPECT_FALSE(Fresh(MGPipeInputField::GetActiveTextureUnit));
|
||||
// The value was still copied: only the stamp is withheld.
|
||||
EXPECT_EQ(gPipeInputs.CurrentVerb(), MGPipeVerb::GenerateMipmap);
|
||||
EXPECT_EQ(gPipeInputs->CurrentVerb(), MGPipeVerb::GenerateMipmap);
|
||||
// Exactly that field: a field is fresh iff its bit is in kTextureOp's mask and it is not
|
||||
// the omitted one.
|
||||
{
|
||||
@@ -174,7 +174,7 @@ TEST_F(PipeInputsTest, OmittingOneFieldForOneVerbLeavesExactlyThatFieldStale) {
|
||||
}
|
||||
|
||||
// Negative control B, layer 2 (G5): the read itself. The child fills GenerateMipmap with the
|
||||
// omission and reads gPipeInputs.GetActiveTextureUnit(); the parent expects SIGABRT and the
|
||||
// omission and reads gPipeInputs->GetActiveTextureUnit(); the parent expects SIGABRT and the
|
||||
// exact Fatal line, and that nothing else was fatal.
|
||||
TEST_F(PipeInputsTest, ReadingAnOmittedFieldAbortsNamingTheVerb) {
|
||||
#if !MOBILEGL_PIPE_POISON
|
||||
@@ -186,10 +186,10 @@ TEST_F(PipeInputsTest, ReadingAnOmittedFieldAbortsNamingTheVerb) {
|
||||
const ChildResult r = RunInChild([] {
|
||||
MGPipeSetPoisonOmission("GenerateMipmap", "GetActiveTextureUnit");
|
||||
MGPipeValidateForVerb(MGPipeVerb::DrawArrays);
|
||||
(void)gPipeInputs.GetRenderStateParameters(); // a filled field of the preceding draw: must not abort
|
||||
(void)gPipeInputs->GetRenderStateParameters(); // a filled field of the preceding draw: must not abort
|
||||
MGPipeValidateForVerb(MGPipeVerb::GenerateMipmap);
|
||||
(void)gPipeInputs.GetTextureUnitObject(0); // the sibling field: filled, must not abort
|
||||
(void)gPipeInputs.GetActiveTextureUnit(); // the omitted field: Fatal
|
||||
(void)gPipeInputs->GetTextureUnitObject(0); // the sibling field: filled, must not abort
|
||||
(void)gPipeInputs->GetActiveTextureUnit(); // the omitted field: Fatal
|
||||
::_exit(3); // reached only if the poison failed
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
@@ -207,10 +207,10 @@ TEST_F(PipeInputsTest, ReadingAFilledFieldCompletes) {
|
||||
ASSERT_FALSE(g_logPath.empty()) << "main() did not set MOBILEGL_LOG_FILE_PATH";
|
||||
const ChildResult r = RunInChild([] {
|
||||
MGPipeValidateForVerb(MGPipeVerb::DrawArrays);
|
||||
(void)gPipeInputs.GetRenderStateParameters();
|
||||
(void)gPipeInputs->GetRenderStateParameters();
|
||||
MGPipeValidateForVerb(MGPipeVerb::GenerateMipmap);
|
||||
(void)gPipeInputs.GetTextureUnitObject(0);
|
||||
(void)gPipeInputs.GetActiveTextureUnit();
|
||||
(void)gPipeInputs->GetTextureUnitObject(0);
|
||||
(void)gPipeInputs->GetActiveTextureUnit();
|
||||
});
|
||||
ASSERT_TRUE(ExitedWith(r, 0)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_EQ(r.Log.find("Fatal{"), std::string::npos) << r.Log;
|
||||
@@ -229,7 +229,7 @@ TEST_F(PipeInputsTest, ReadingBeforeAnyFillAbortsNamingNoVerb) {
|
||||
GTEST_SKIP() << "no fork() on this platform";
|
||||
#else
|
||||
ASSERT_FALSE(g_logPath.empty()) << "main() did not set MOBILEGL_LOG_FILE_PATH";
|
||||
if (gPipeInputs.FilledState().CurrentVerbSerial != 0) {
|
||||
if (gPipeInputs->FilledState().CurrentVerbSerial != 0) {
|
||||
GTEST_SKIP() << "another case already filled in this process; gtest_discover_tests runs each case alone";
|
||||
}
|
||||
MG_State::pGLContext->SetLineWidth(7.0f); // a live value the default storage (0) does not hold
|
||||
@@ -237,7 +237,7 @@ TEST_F(PipeInputsTest, ReadingBeforeAnyFillAbortsNamingNoVerb) {
|
||||
#if MOBILEGL_PIPE_VERIFY
|
||||
MG_Config::Features.PipeVerify = true;
|
||||
#endif
|
||||
(void)gPipeInputs.GetLineWidth(); // Fatal{UnmigratedPipeInput, "GetLineWidth@<none>"}
|
||||
(void)gPipeInputs->GetLineWidth(); // Fatal{UnmigratedPipeInput, "GetLineWidth@<none>"}
|
||||
::_exit(3); // reached only if the pre-fill window read as fresh
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
@@ -261,8 +261,8 @@ TEST_F(PipeInputsTest, PoisonOmitKnobArmsTheOmission) {
|
||||
const ChildResult r = RunInChild([] {
|
||||
MG_Config::Features.PipePoisonOmit = kOmissionKnob;
|
||||
MGPipeValidateForVerb(MGPipeVerb::GenerateMipmap);
|
||||
(void)gPipeInputs.GetTextureUnitObject(0); // the sibling field: filled, must not abort
|
||||
(void)gPipeInputs.GetActiveTextureUnit(); // the omitted field: Fatal
|
||||
(void)gPipeInputs->GetTextureUnitObject(0); // the sibling field: filled, must not abort
|
||||
(void)gPipeInputs->GetActiveTextureUnit(); // the omitted field: Fatal
|
||||
::_exit(3);
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
@@ -301,9 +301,9 @@ TEST_F(PipeInputsTest, CorruptedSnapshotFieldIsNamedWithItsSerial) {
|
||||
#if !MOBILEGL_PIPE_VERIFY
|
||||
GTEST_SKIP() << "verify not compiled in (MOBILEGL_PIPE_VERIFY=OFF)";
|
||||
#else
|
||||
const Uint64 serialBefore = gPipeInputs.FilledState().CurrentVerbSerial;
|
||||
const Uint64 serialBefore = gPipeInputs->FilledState().CurrentVerbSerial;
|
||||
MGPipeValidateForVerb(MGPipeVerb::DrawArrays);
|
||||
const Uint64 serial = gPipeInputs.FilledState().CurrentVerbSerial;
|
||||
const Uint64 serial = gPipeInputs->FilledState().CurrentVerbSerial;
|
||||
EXPECT_EQ(serial, serialBefore + 1);
|
||||
const MGPipeFieldMask& mask = kMGPipeClassFieldMask[static_cast<SizeT>(MGPipeVerbClass::kDraw)];
|
||||
|
||||
@@ -318,7 +318,7 @@ TEST_F(PipeInputsTest, CorruptedSnapshotFieldIsNamedWithItsSerial) {
|
||||
EXPECT_EQ(field, MGPipeInputField::GetRenderStateParameters);
|
||||
EXPECT_STREQ(kMGPipeInputFieldNames[static_cast<SizeT>(field)], "GetRenderStateParameters");
|
||||
// The serial the report would print is the fill's, and it stamped that field.
|
||||
EXPECT_EQ(gPipeInputs.FilledState().FilledGen[static_cast<SizeT>(field)], serial);
|
||||
EXPECT_EQ(gPipeInputs->FilledState().FilledGen[static_cast<SizeT>(field)], serial);
|
||||
|
||||
// A forwarded field has nothing to corrupt, and the corruption of a field outside the
|
||||
// mask is not seen by a compare over that mask.
|
||||
@@ -341,15 +341,15 @@ TEST_F(PipeInputsTest, MutatedFieldIsNamedAtRead) {
|
||||
#else
|
||||
ASSERT_FALSE(g_logPath.empty()) << "main() did not set MOBILEGL_LOG_FILE_PATH";
|
||||
MGPipeValidateForVerb(MGPipeVerb::Clear); // the parent armed nothing: Features.PipeVerify is false here
|
||||
const Uint64 serial = gPipeInputs.FilledState().CurrentVerbSerial + 1; // the child's DrawArrays fill
|
||||
const Uint64 serial = gPipeInputs->FilledState().CurrentVerbSerial + 1; // the child's DrawArrays fill
|
||||
const ChildResult r = RunInChild([] {
|
||||
MG_Config::Features.PipeVerify = true;
|
||||
MGPipeValidateForVerb(MGPipeVerb::DrawArrays);
|
||||
const Float boundary = gPipeInputs.GetLineWidth(); // boundary == live: completes
|
||||
(void)gPipeInputs.GetRenderStateParameters();
|
||||
const Float boundary = gPipeInputs->GetLineWidth(); // boundary == live: completes
|
||||
(void)gPipeInputs->GetRenderStateParameters();
|
||||
MG_State::pGLContext->SetLineWidth(boundary + 1.0f);
|
||||
if (MG_State::pGLContext->GetLineWidth() == boundary) ::_exit(7); // the mutation did not take
|
||||
(void)gPipeInputs.GetLineWidth(); // the stored value is stale against the live one: Fatal
|
||||
(void)gPipeInputs->GetLineWidth(); // the stored value is stale against the live one: Fatal
|
||||
::_exit(3);
|
||||
});
|
||||
ASSERT_TRUE(DiedOfAbort(r)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
@@ -375,7 +375,7 @@ TEST_F(PipeInputsTest, VerifyCorruptKnobNamesTheFieldAtEntry) {
|
||||
#else
|
||||
ASSERT_FALSE(g_logPath.empty()) << "main() did not set MOBILEGL_LOG_FILE_PATH";
|
||||
MGPipeValidateForVerb(MGPipeVerb::Clear);
|
||||
const Uint64 serial = gPipeInputs.FilledState().CurrentVerbSerial + 1;
|
||||
const Uint64 serial = gPipeInputs->FilledState().CurrentVerbSerial + 1;
|
||||
const ChildResult r = RunInChild([] {
|
||||
MG_Config::Features.PipeVerify = true;
|
||||
MG_Config::Features.PipeVerifyCorrupt = "GetRenderStateParameters";
|
||||
@@ -428,7 +428,7 @@ TEST_F(PipeInputsTest, VerifyFatalOffLogsTheDivergenceAndContinues) {
|
||||
#else
|
||||
ASSERT_FALSE(g_logPath.empty()) << "main() did not set MOBILEGL_LOG_FILE_PATH";
|
||||
MGPipeValidateForVerb(MGPipeVerb::Clear);
|
||||
const Uint64 serial = gPipeInputs.FilledState().CurrentVerbSerial + 1;
|
||||
const Uint64 serial = gPipeInputs->FilledState().CurrentVerbSerial + 1;
|
||||
const ChildResult r = RunInChild([] {
|
||||
MG_Config::Features.PipeVerify = true;
|
||||
MG_Config::Features.PipeVerifyFatal = false;
|
||||
@@ -467,8 +467,8 @@ TEST_F(PipeInputsTest, EveryVerbFillsItsClassAndNothingElse) {
|
||||
<< kMGPipeInputFieldNames[f] << " after " << kMGPipeVerbNames[v];
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(gPipeInputs.ContextIdentity(), static_cast<const void*>(MG_State::pGLContext.get()));
|
||||
EXPECT_TRUE(gPipeInputs.IsLive());
|
||||
EXPECT_EQ(gPipeInputs->ContextIdentity(), static_cast<const void*>(MG_State::pGLContext.get()));
|
||||
EXPECT_TRUE(gPipeInputs->IsLive());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -481,9 +481,9 @@ TEST_F(PipeInputsTest, EveryVerbFillsItsClassAndNothingElse) {
|
||||
TEST_F(PipeInputsTest, AFrontendMutationInsideAVerbRefreshesThePushedField) {
|
||||
auto& ctx = *MG_State::pGLContext;
|
||||
MGPipeValidateForVerb(MGPipeVerb::DrawArrays);
|
||||
ASSERT_EQ(gPipeInputs.GetSamplingResolutionGeneration(), ctx.GetSamplingResolutionGeneration());
|
||||
ASSERT_EQ(gPipeInputs.GetTextureBindGeneration(), ctx.GetTextureBindGeneration());
|
||||
ASSERT_EQ(gPipeInputs.GetMaxTouchedTextureUnit(), ctx.GetMaxTouchedTextureUnit());
|
||||
ASSERT_EQ(gPipeInputs->GetSamplingResolutionGeneration(), ctx.GetSamplingResolutionGeneration());
|
||||
ASSERT_EQ(gPipeInputs->GetTextureBindGeneration(), ctx.GetTextureBindGeneration());
|
||||
ASSERT_EQ(gPipeInputs->GetMaxTouchedTextureUnit(), ctx.GetMaxTouchedTextureUnit());
|
||||
|
||||
// What UniformManager's fallback path does mid-draw: change a sampler object's filter,
|
||||
// which bumps the context-wide sampling-resolution generation (SamplerObject.cpp).
|
||||
@@ -492,7 +492,7 @@ TEST_F(PipeInputsTest, AFrontendMutationInsideAVerbRefreshesThePushedField) {
|
||||
sampler->SetMinFilter(sampler->GetMinFilter() == SamplerFilterMode::Nearest ? SamplerFilterMode::Linear
|
||||
: SamplerFilterMode::Nearest);
|
||||
ASSERT_NE(ctx.GetSamplingResolutionGeneration(), samplingBefore) << "the mutation did not move the counter";
|
||||
EXPECT_EQ(gPipeInputs.GetSamplingResolutionGeneration(), ctx.GetSamplingResolutionGeneration());
|
||||
EXPECT_EQ(gPipeInputs->GetSamplingResolutionGeneration(), ctx.GetSamplingResolutionGeneration());
|
||||
|
||||
// And a bind reached from inside a verb moves both the bind generation and the
|
||||
// high-water mark of touched units (TextureState::NoteUnitTouched).
|
||||
@@ -501,8 +501,8 @@ TEST_F(PipeInputsTest, AFrontendMutationInsideAVerbRefreshesThePushedField) {
|
||||
ctx.NoteTextureUnitTouched(unit);
|
||||
ASSERT_NE(ctx.GetTextureBindGeneration(), bindBefore) << "the bind did not move the counter";
|
||||
ASSERT_EQ(ctx.GetMaxTouchedTextureUnit(), unit);
|
||||
EXPECT_EQ(gPipeInputs.GetTextureBindGeneration(), ctx.GetTextureBindGeneration());
|
||||
EXPECT_EQ(gPipeInputs.GetMaxTouchedTextureUnit(), ctx.GetMaxTouchedTextureUnit());
|
||||
EXPECT_EQ(gPipeInputs->GetTextureBindGeneration(), ctx.GetTextureBindGeneration());
|
||||
EXPECT_EQ(gPipeInputs->GetMaxTouchedTextureUnit(), ctx.GetMaxTouchedTextureUnit());
|
||||
}
|
||||
|
||||
// The notice refreshes the VALUE and never the stamp: a field this verb withheld the stamp
|
||||
@@ -547,7 +547,7 @@ TEST_F(PipeInputsTest, AFrontendMutationInsideAVerbDoesNotDivergeAtRead) {
|
||||
const ChildResult r = RunInChild([] {
|
||||
MG_Config::Features.PipeVerify = true;
|
||||
MGPipeValidateForVerb(MGPipeVerb::DrawArrays);
|
||||
(void)gPipeInputs.GetSamplingResolutionGeneration(); // boundary == live: completes
|
||||
(void)gPipeInputs->GetSamplingResolutionGeneration(); // boundary == live: completes
|
||||
auto& ctx = *MG_State::pGLContext;
|
||||
const Uint64 before = ctx.GetSamplingResolutionGeneration();
|
||||
auto sampler = MakeShared<MG_State::GLState::SamplerObject>(0u);
|
||||
@@ -556,10 +556,10 @@ TEST_F(PipeInputsTest, AFrontendMutationInsideAVerbDoesNotDivergeAtRead) {
|
||||
if (ctx.GetSamplingResolutionGeneration() == before) {
|
||||
::_exit(7); // the mutation did not take: the case would pass for the wrong reason
|
||||
}
|
||||
(void)gPipeInputs.GetSamplingResolutionGeneration(); // Fatal{PipeVerifyDiffer} without the notice
|
||||
(void)gPipeInputs->GetSamplingResolutionGeneration(); // Fatal{PipeVerifyDiffer} without the notice
|
||||
ctx.NoteTextureUnitTouched(ctx.GetMaxTouchedTextureUnit() + 1);
|
||||
(void)gPipeInputs.GetTextureBindGeneration();
|
||||
(void)gPipeInputs.GetMaxTouchedTextureUnit();
|
||||
(void)gPipeInputs->GetTextureBindGeneration();
|
||||
(void)gPipeInputs->GetMaxTouchedTextureUnit();
|
||||
});
|
||||
ASSERT_TRUE(ExitedWith(r, 0)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
EXPECT_NE(r.Log.find("MGPipe: verify armed"), std::string::npos) << r.Log;
|
||||
|
||||
@@ -375,7 +375,7 @@ namespace {
|
||||
m_savedResourceOps = MGPipeGetResourceOps();
|
||||
static const MGPipeResourceOps kEmpty{};
|
||||
MGPipeSetResourceOps(&kEmpty);
|
||||
m_savedContext = Move(MG_State::pGLContext);
|
||||
m_savedContext = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
|
||||
m_savedTable = MG_Backend::gBackendFunctionsTable;
|
||||
|
||||
@@ -146,60 +146,60 @@ namespace {
|
||||
// ---------------------------------------------------------------------------------
|
||||
void ExpectDerivedDrawFieldsMatch(GLContext& ctx, const char* tag) {
|
||||
SCOPED_TRACE(tag);
|
||||
EXPECT_EQ(gPipeInputs.GetBlendColor(), ctx.GetBlendColor());
|
||||
EXPECT_EQ(gPipeInputs->GetBlendColor(), ctx.GetBlendColor());
|
||||
for (Uint i = 0; i < kMGMaxDrawBuffers; ++i) {
|
||||
BlendEquation gotColor{}, gotAlpha{}, wantColor{}, wantAlpha{};
|
||||
gPipeInputs.GetBlendEquationIndexed(i, gotColor, gotAlpha);
|
||||
gPipeInputs->GetBlendEquationIndexed(i, gotColor, gotAlpha);
|
||||
ctx.GetBlendEquationIndexed(i, wantColor, wantAlpha);
|
||||
EXPECT_EQ(gotColor, wantColor) << "blend equation " << i;
|
||||
EXPECT_EQ(gotAlpha, wantAlpha) << "blend equation " << i;
|
||||
|
||||
BlendFactor gotSrcRGB{}, gotDstRGB{}, gotSrcA{}, gotDstA{};
|
||||
BlendFactor wantSrcRGB{}, wantDstRGB{}, wantSrcA{}, wantDstA{};
|
||||
gPipeInputs.GetBlendFuncIndexed(i, gotSrcRGB, gotDstRGB, gotSrcA, gotDstA);
|
||||
gPipeInputs->GetBlendFuncIndexed(i, gotSrcRGB, gotDstRGB, gotSrcA, gotDstA);
|
||||
ctx.GetBlendFuncIndexed(i, wantSrcRGB, wantDstRGB, wantSrcA, wantDstA);
|
||||
EXPECT_EQ(gotSrcRGB, wantSrcRGB) << "blend func " << i;
|
||||
EXPECT_EQ(gotDstRGB, wantDstRGB) << "blend func " << i;
|
||||
EXPECT_EQ(gotSrcA, wantSrcA) << "blend func " << i;
|
||||
EXPECT_EQ(gotDstA, wantDstA) << "blend func " << i;
|
||||
|
||||
EXPECT_EQ(gPipeInputs.GetColorMaskIndexed(i), ctx.GetColorMaskIndexed(i)) << "colour mask " << i;
|
||||
EXPECT_EQ(gPipeInputs.IsCapabilityEnabledIndexed(CapabilityInput::Blend, i),
|
||||
EXPECT_EQ(gPipeInputs->GetColorMaskIndexed(i), ctx.GetColorMaskIndexed(i)) << "colour mask " << i;
|
||||
EXPECT_EQ(gPipeInputs->IsCapabilityEnabledIndexed(CapabilityInput::Blend, i),
|
||||
ctx.IsCapabilityEnabledIndexed(CapabilityInput::Blend, i))
|
||||
<< "indexed blend enable " << i;
|
||||
}
|
||||
EXPECT_EQ(gPipeInputs.GetCullFaceMode(), ctx.GetCullFaceMode());
|
||||
EXPECT_EQ(gPipeInputs.GetDepthFunc(), ctx.GetDepthFunc());
|
||||
EXPECT_EQ(gPipeInputs.GetDepthMask(), ctx.GetDepthMask());
|
||||
EXPECT_EQ(gPipeInputs->GetCullFaceMode(), ctx.GetCullFaceMode());
|
||||
EXPECT_EQ(gPipeInputs->GetDepthFunc(), ctx.GetDepthFunc());
|
||||
EXPECT_EQ(gPipeInputs->GetDepthMask(), ctx.GetDepthMask());
|
||||
for (Uint i = 0; i < RenderStateParameters::MAX_VIEWPORTS; ++i) {
|
||||
EXPECT_EQ(gPipeInputs.GetDepthRangeIndexed(i), ctx.GetDepthRangeIndexed(i)) << "depth range " << i;
|
||||
EXPECT_EQ(gPipeInputs.GetViewportIndexed(i), ctx.GetViewportIndexed(i)) << "viewport " << i;
|
||||
EXPECT_EQ(gPipeInputs.IsCapabilityEnabledIndexed(CapabilityInput::ScissorTest, i),
|
||||
EXPECT_EQ(gPipeInputs->GetDepthRangeIndexed(i), ctx.GetDepthRangeIndexed(i)) << "depth range " << i;
|
||||
EXPECT_EQ(gPipeInputs->GetViewportIndexed(i), ctx.GetViewportIndexed(i)) << "viewport " << i;
|
||||
EXPECT_EQ(gPipeInputs->IsCapabilityEnabledIndexed(CapabilityInput::ScissorTest, i),
|
||||
ctx.IsCapabilityEnabledIndexed(CapabilityInput::ScissorTest, i))
|
||||
<< "indexed scissor enable " << i;
|
||||
}
|
||||
EXPECT_EQ(gPipeInputs.GetLineWidth(), ctx.GetLineWidth());
|
||||
EXPECT_EQ(gPipeInputs.GetLogicOp(), ctx.GetLogicOp());
|
||||
EXPECT_EQ(gPipeInputs.GetMinSampleShadingValue(), ctx.GetMinSampleShadingValue());
|
||||
EXPECT_EQ(gPipeInputs.GetPatchDefaultInnerLevel(), ctx.GetPatchDefaultInnerLevel());
|
||||
EXPECT_EQ(gPipeInputs.GetPatchDefaultOuterLevel(), ctx.GetPatchDefaultOuterLevel());
|
||||
EXPECT_EQ(gPipeInputs.GetPatchVertices(), ctx.GetPatchVertices());
|
||||
EXPECT_EQ(gPipeInputs.GetPolygonModeFront(), ctx.GetPolygonModeFront());
|
||||
EXPECT_EQ(gPipeInputs.GetPolygonOffsetFactor(), ctx.GetPolygonOffsetFactor());
|
||||
EXPECT_EQ(gPipeInputs.GetPolygonOffsetUnits(), ctx.GetPolygonOffsetUnits());
|
||||
EXPECT_EQ(gPipeInputs.GetPrimitiveRestartIndex(), ctx.GetPrimitiveRestartIndex());
|
||||
EXPECT_EQ(gPipeInputs.GetProvokingVertexMode(), ctx.GetProvokingVertexMode());
|
||||
EXPECT_EQ(gPipeInputs.GetScissorBox(), ctx.GetScissorBox());
|
||||
EXPECT_EQ(gPipeInputs.GetViewport(), ctx.GetViewport());
|
||||
EXPECT_EQ(gPipeInputs->GetLineWidth(), ctx.GetLineWidth());
|
||||
EXPECT_EQ(gPipeInputs->GetLogicOp(), ctx.GetLogicOp());
|
||||
EXPECT_EQ(gPipeInputs->GetMinSampleShadingValue(), ctx.GetMinSampleShadingValue());
|
||||
EXPECT_EQ(gPipeInputs->GetPatchDefaultInnerLevel(), ctx.GetPatchDefaultInnerLevel());
|
||||
EXPECT_EQ(gPipeInputs->GetPatchDefaultOuterLevel(), ctx.GetPatchDefaultOuterLevel());
|
||||
EXPECT_EQ(gPipeInputs->GetPatchVertices(), ctx.GetPatchVertices());
|
||||
EXPECT_EQ(gPipeInputs->GetPolygonModeFront(), ctx.GetPolygonModeFront());
|
||||
EXPECT_EQ(gPipeInputs->GetPolygonOffsetFactor(), ctx.GetPolygonOffsetFactor());
|
||||
EXPECT_EQ(gPipeInputs->GetPolygonOffsetUnits(), ctx.GetPolygonOffsetUnits());
|
||||
EXPECT_EQ(gPipeInputs->GetPrimitiveRestartIndex(), ctx.GetPrimitiveRestartIndex());
|
||||
EXPECT_EQ(gPipeInputs->GetProvokingVertexMode(), ctx.GetProvokingVertexMode());
|
||||
EXPECT_EQ(gPipeInputs->GetScissorBox(), ctx.GetScissorBox());
|
||||
EXPECT_EQ(gPipeInputs->GetViewport(), ctx.GetViewport());
|
||||
for (const StencilFace face : {StencilFace::Front, StencilFace::Back}) {
|
||||
const StencilFaceState& got = gPipeInputs.GetStencilState(face);
|
||||
const StencilFaceState& got = gPipeInputs->GetStencilState(face);
|
||||
const StencilFaceState& want = ctx.GetStencilState(face);
|
||||
EXPECT_EQ(std::memcmp(&got, &want, sizeof(StencilFaceState)), 0)
|
||||
<< "stencil face " << static_cast<int>(face);
|
||||
}
|
||||
for (SizeT i = 0; i < static_cast<SizeT>(CapabilityInput::CapabilityInputCount); ++i) {
|
||||
const CapabilityInput cap = static_cast<CapabilityInput>(i);
|
||||
EXPECT_EQ(gPipeInputs.IsCapabilityEnabled(cap), ctx.IsCapabilityEnabled(cap)) << "capability " << i;
|
||||
EXPECT_EQ(gPipeInputs->IsCapabilityEnabled(cap), ctx.IsCapabilityEnabled(cap)) << "capability " << i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ namespace {
|
||||
// the only thing in the suite that covers them.
|
||||
void ExpectAssembledBlockIsTheLiveBlock(GLContext& ctx, const char* tag) {
|
||||
SCOPED_TRACE(tag);
|
||||
EXPECT_EQ(std::memcmp(&gPipeInputs.GetRenderStateParameters(), &ctx.GetRenderStateParameters(),
|
||||
EXPECT_EQ(std::memcmp(&gPipeInputs->GetRenderStateParameters(), &ctx.GetRenderStateParameters(),
|
||||
sizeof(RenderStateParameters)),
|
||||
0)
|
||||
<< "the assembled working block is not byte-identical to the live one - a chunk of "
|
||||
@@ -554,7 +554,7 @@ namespace {
|
||||
// restored on the way out so the case stays independent (SanityTest's idiom).
|
||||
struct ContextGuard {
|
||||
SharedPtr<GLContext> Previous;
|
||||
ContextGuard() : Previous(Move(MG_State::pGLContext)) {
|
||||
ContextGuard() : Previous(MG_State::pGLContext.Take()) {
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
MGPipeApplierReset();
|
||||
}
|
||||
@@ -653,7 +653,7 @@ namespace {
|
||||
// The vacuity guard: the block still holds what the fill copied out of the DEFAULT
|
||||
// context, so it must currently DISAGREE with the live one. If this ever passes, the
|
||||
// comparisons below would be checking the filler against itself.
|
||||
ASSERT_NE(gPipeInputs.GetLineWidth(), ctx.GetLineWidth());
|
||||
ASSERT_NE(gPipeInputs->GetLineWidth(), ctx.GetLineWidth());
|
||||
|
||||
applyWholeBlock();
|
||||
|
||||
@@ -667,7 +667,7 @@ namespace {
|
||||
// would hand the backends a 63-wide rectangle where 64 was asked for. The literal
|
||||
// is std::lround's answer - round half AWAY FROM ZERO, so 1.5 -> 2 and 2.5 -> 3,
|
||||
// not the banker's rounding a nearbyint() transcription would give.
|
||||
EXPECT_EQ(gPipeInputs.GetViewport(), IntVec4(2, 3, 64, 32));
|
||||
EXPECT_EQ(gPipeInputs->GetViewport(), IntVec4(2, 3, 64, 32));
|
||||
} // phase 1, kDraw
|
||||
|
||||
// Phase 2, kClear: the three clear values. The verb's own fill runs FIRST and copies
|
||||
@@ -678,13 +678,13 @@ namespace {
|
||||
ctx.SetClearColor(FloatVec4(0.9f, 0.8f, 0.7f, 0.6f));
|
||||
ctx.SetClearDepth(0.125f);
|
||||
ctx.SetClearStencil(21);
|
||||
ASSERT_NE(gPipeInputs.GetClearDepth(), ctx.GetClearDepth());
|
||||
ASSERT_NE(gPipeInputs->GetClearDepth(), ctx.GetClearDepth());
|
||||
|
||||
applyWholeBlock();
|
||||
|
||||
EXPECT_EQ(gPipeInputs.GetClearColor(), ctx.GetClearColor());
|
||||
EXPECT_EQ(gPipeInputs.GetClearDepth(), ctx.GetClearDepth());
|
||||
EXPECT_EQ(gPipeInputs.GetClearStencil(), ctx.GetClearStencil());
|
||||
EXPECT_EQ(gPipeInputs->GetClearColor(), ctx.GetClearColor());
|
||||
EXPECT_EQ(gPipeInputs->GetClearDepth(), ctx.GetClearDepth());
|
||||
EXPECT_EQ(gPipeInputs->GetClearStencil(), ctx.GetClearStencil());
|
||||
}
|
||||
|
||||
// Phase 3, kReadback: GetClampReadColor, the one derived field no draw and no clear
|
||||
@@ -692,12 +692,12 @@ namespace {
|
||||
{
|
||||
MG_Test::ScopedPipeVerb verb(MGPipeVerb::ReadPixels);
|
||||
ctx.SetClampReadColor(GL_FALSE);
|
||||
ASSERT_NE(gPipeInputs.GetClampReadColor(), ctx.GetClampReadColor());
|
||||
ASSERT_NE(gPipeInputs->GetClampReadColor(), ctx.GetClampReadColor());
|
||||
|
||||
applyWholeBlock();
|
||||
|
||||
EXPECT_EQ(gPipeInputs.GetClampReadColor(), ctx.GetClampReadColor());
|
||||
EXPECT_EQ(gPipeInputs.GetClampReadColor(), static_cast<GLenum>(GL_FALSE));
|
||||
EXPECT_EQ(gPipeInputs->GetClampReadColor(), ctx.GetClampReadColor());
|
||||
EXPECT_EQ(gPipeInputs->GetClampReadColor(), static_cast<GLenum>(GL_FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -764,7 +764,7 @@ namespace {
|
||||
TEST(RenderStateSpans, IncrementalChunksKeepEveryDerivedFieldInStep) {
|
||||
struct ContextGuard {
|
||||
SharedPtr<GLContext> Previous;
|
||||
ContextGuard() : Previous(Move(MG_State::pGLContext)) {
|
||||
ContextGuard() : Previous(MG_State::pGLContext.Take()) {
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
MGPipeApplierReset();
|
||||
}
|
||||
@@ -926,7 +926,7 @@ namespace {
|
||||
// idiom, and the same guard cases 3 and 5 declare inline).
|
||||
struct ApplierContextGuard {
|
||||
SharedPtr<GLContext> Previous;
|
||||
ApplierContextGuard() : Previous(Move(MG_State::pGLContext)) {
|
||||
ApplierContextGuard() : Previous(MG_State::pGLContext.Take()) {
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
MGPipeApplierReset();
|
||||
}
|
||||
@@ -1122,7 +1122,7 @@ namespace {
|
||||
pack.Pack.SkipRows = 5;
|
||||
pack.Pack.SwapBytes = true;
|
||||
MGPipeApplySetPixelPackState(pack);
|
||||
const PixelStoreParameters got = gPipeInputs.GetPixelStoreParameters(false);
|
||||
const PixelStoreParameters got = gPipeInputs->GetPixelStoreParameters(false);
|
||||
EXPECT_EQ(got.Alignment, 8);
|
||||
EXPECT_EQ(got.RowLength, 37);
|
||||
EXPECT_EQ(got.SkipRows, 5);
|
||||
@@ -1155,13 +1155,13 @@ namespace {
|
||||
std::memcpy(tail[1].IntView, secondInt, sizeof(secondInt));
|
||||
MGPipeApplySetVertexAttribDefaults(hdr, tail);
|
||||
|
||||
EXPECT_EQ(gPipeInputs.GetCurrentVertexAttribute(2).floatValue[0], 1.5f);
|
||||
EXPECT_EQ(gPipeInputs.GetCurrentVertexAttribute(2).floatValue[3], 4.5f);
|
||||
EXPECT_EQ(gPipeInputs.GetCurrentVertexAttribute(9).floatValue[2], 0.5f);
|
||||
EXPECT_EQ(gPipeInputs->GetCurrentVertexAttribute(2).floatValue[0], 1.5f);
|
||||
EXPECT_EQ(gPipeInputs->GetCurrentVertexAttribute(2).floatValue[3], 4.5f);
|
||||
EXPECT_EQ(gPipeInputs->GetCurrentVertexAttribute(9).floatValue[2], 0.5f);
|
||||
// ... and the CONVERTED views are the record's, not a memcpy of the float bits:
|
||||
// 1.5f's bits are 0x3FC00000, and the frontend's int view of it is 1.
|
||||
EXPECT_EQ(gPipeInputs.GetCurrentVertexAttribute(2).intValue[0], 1);
|
||||
EXPECT_EQ(gPipeInputs.GetCurrentVertexAttribute(9).intValue[0], -1);
|
||||
EXPECT_EQ(gPipeInputs->GetCurrentVertexAttribute(2).intValue[0], 1);
|
||||
EXPECT_EQ(gPipeInputs->GetCurrentVertexAttribute(9).intValue[0], -1);
|
||||
}
|
||||
|
||||
// delete_render_state: the record stops being live and a bound handle stops being
|
||||
|
||||
@@ -1807,7 +1807,7 @@ namespace {
|
||||
m_previousPush = MG_Config::Features.PipePush;
|
||||
MG_Config::Features.PipePush |= kMGPipeSubsystemResources;
|
||||
MGPipeSetResourceOps(&m_ops);
|
||||
m_previousContext = Move(MG_State::pGLContext);
|
||||
m_previousContext = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
}
|
||||
~PushArm() {
|
||||
|
||||
@@ -231,7 +231,7 @@ namespace {
|
||||
MG_Config::Features.PipePush |= kMGPipeSubsystemResources |
|
||||
kMGPipeSubsystemTextureResources |
|
||||
kMGPipeSubsystemSamplers;
|
||||
m_previousContext = Move(MG_State::pGLContext);
|
||||
m_previousContext = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
MGPipeTextureEmitterInstance().ResetForTest();
|
||||
// AND THE APPLIER IS A PROCESS SINGLETON, so its object records outlive a case. With
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace {
|
||||
class TrackerAggregates : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
m_previous = Move(MG_State::pGLContext);
|
||||
m_previous = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
}
|
||||
void TearDown() override { MG_State::pGLContext = Move(m_previous); }
|
||||
@@ -174,7 +174,7 @@ namespace {
|
||||
}
|
||||
|
||||
TEST_F(TrackerAggregates, ANoteWithoutALiveContextIsANoOp) {
|
||||
SharedPtr<GLContext> held = Move(MG_State::pGLContext);
|
||||
SharedPtr<GLContext> held = MG_State::pGLContext.Take();
|
||||
MGP_NOTE_AGGREGATE(BufferChange); // must not dereference a null context
|
||||
MG_State::pGLContext = Move(held);
|
||||
SUCCEED();
|
||||
@@ -246,7 +246,7 @@ namespace {
|
||||
class TrackerWalk : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
m_previous = Move(MG_State::pGLContext);
|
||||
m_previous = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
m_savedPush = MG_Config::Features.PipePush;
|
||||
ResetTheServerSideSingletons();
|
||||
@@ -904,7 +904,7 @@ namespace {
|
||||
class TrackerAttribPayload : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
m_previous = Move(MG_State::pGLContext);
|
||||
m_previous = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
}
|
||||
void TearDown() override { MG_State::pGLContext = Move(m_previous); }
|
||||
@@ -993,7 +993,7 @@ namespace {
|
||||
class TrackerShippedEmitter : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
m_previous = Move(MG_State::pGLContext);
|
||||
m_previous = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
m_savedPush = MG_Config::Features.PipePush;
|
||||
MG_Config::Features.PipePush = kMGPipeSubsystemsMigratedAtP2;
|
||||
@@ -1166,7 +1166,7 @@ namespace {
|
||||
// that the capability itself reaches the applier's assembled block on the next draw.
|
||||
TEST_F(TrackerShippedEmitter, AClipDistanceEnableReArmsTheResidualBlock) {
|
||||
Draw();
|
||||
ASSERT_FALSE(MobileGL::MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::ClipDistance0))
|
||||
ASSERT_FALSE(MobileGL::MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::ClipDistance0))
|
||||
<< "the premise is gone: a fresh context already has clip distance 0 enabled";
|
||||
|
||||
Ctx().SetCapability(CapabilityInput::ClipDistance0, true);
|
||||
@@ -1177,7 +1177,7 @@ namespace {
|
||||
<< "the premise is gone: a clip-distance enable now moves the pipeline version";
|
||||
EXPECT_EQ(static_cast<Uint16>(Ctx().GetPipelineStateVersion()), pipelineBefore);
|
||||
|
||||
EXPECT_TRUE(MobileGL::MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::ClipDistance0))
|
||||
EXPECT_TRUE(MobileGL::MG_Pipe::gPipeInputs->IsCapabilityEnabled(CapabilityInput::ClipDistance0))
|
||||
<< "a capability change that moves only m_version never reached the applier's block";
|
||||
}
|
||||
|
||||
@@ -1295,7 +1295,7 @@ namespace {
|
||||
// stand into the next verb. A draw with no context is a no-op; its argument must not
|
||||
// outlive it.
|
||||
MGPipeSetPendingBaseInstance(11);
|
||||
SharedPtr<GLContext> parked = Move(MG_State::pGLContext);
|
||||
SharedPtr<GLContext> parked = MG_State::pGLContext.Take();
|
||||
Draw();
|
||||
EXPECT_EQ(MGPipePendingBaseInstance(), 0u)
|
||||
<< "the no-live-context exit left the draw's base instance standing for the next verb";
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace {
|
||||
// case out of the gate's reach.
|
||||
struct EmitterScope {
|
||||
EmitterScope() {
|
||||
m_previousContext = Move(MG_State::pGLContext);
|
||||
m_previousContext = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
MGPipeVertexInputEmitterInstance().Reset();
|
||||
MGPipeVertexInputEmitterInstance().ResetCounters();
|
||||
|
||||
@@ -894,7 +894,7 @@ TEST(DirectVulkanSanity, AdvertisesSubgroupOnlyWhenVulkanReportsUsableSupport) {
|
||||
TEST(DirectVulkanSanity, CapabilityRefreshInvalidatesTheCachedCompileEnvironment) {
|
||||
using namespace MobileGL;
|
||||
|
||||
auto previousContext = Move(MG_State::pGLContext);
|
||||
auto previousContext = MG_State::pGLContext.Take();
|
||||
auto previousBackend = Move(MG_Backend::pActiveBackendObject);
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
|
||||
@@ -1006,7 +1006,7 @@ TEST(GetterSanity, ClampsMaxVertexAttribsToCurrentValueStorageCapacity) {
|
||||
TEST(GetterSanity, ReportsFragmentInterpolationLimitsForFloatAndIntegerQueries) {
|
||||
using namespace MobileGL;
|
||||
|
||||
auto previousContext = Move(MG_State::pGLContext);
|
||||
auto previousContext = MG_State::pGLContext.Take();
|
||||
auto previousBackend = Move(MG_Backend::pActiveBackendObject);
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
|
||||
@@ -1056,7 +1056,7 @@ TEST(GetterSanity, ReportsFragmentInterpolationLimitsForFloatAndIntegerQueries)
|
||||
TEST(GetterSanity, StorageAndUniformBufferOffsetAlignmentsAreSeparateLimits) {
|
||||
using namespace MobileGL;
|
||||
|
||||
auto previousContext = Move(MG_State::pGLContext);
|
||||
auto previousContext = MG_State::pGLContext.Take();
|
||||
auto previousBackend = Move(MG_Backend::pActiveBackendObject);
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
|
||||
@@ -1145,7 +1145,7 @@ TEST(GetterSanity, AtomicCounterQueriesMatchShaderCompilerLimits) {
|
||||
using namespace MobileGL;
|
||||
namespace Transpiler = MG_Util::ShaderTranspiler;
|
||||
|
||||
auto previousContext = Move(MG_State::pGLContext);
|
||||
auto previousContext = MG_State::pGLContext.Take();
|
||||
auto previousBackend = Move(MG_Backend::pActiveBackendObject);
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
MG_Backend::pActiveBackendObject = MakeUnique<DynamicParameterBackend>(MG_Backend::DynamicBackendParameters{});
|
||||
@@ -1224,7 +1224,7 @@ void main() {
|
||||
TEST(GetterSanity, ComputeWorkGroupQueriesMatchShaderCompilerLimits) {
|
||||
using namespace MobileGL;
|
||||
|
||||
auto previousContext = Move(MG_State::pGLContext);
|
||||
auto previousContext = MG_State::pGLContext.Take();
|
||||
auto previousBackend = Move(MG_Backend::pActiveBackendObject);
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
MG_Backend::pActiveBackendObject = MakeUnique<DynamicParameterBackend>(MG_Backend::DynamicBackendParameters{});
|
||||
@@ -1305,7 +1305,7 @@ void main() {
|
||||
TEST(GetterSanity, EveryLimitWithABuiltinAgreesWithItsQuery) {
|
||||
using namespace MobileGL;
|
||||
|
||||
auto previousContext = Move(MG_State::pGLContext);
|
||||
auto previousContext = MG_State::pGLContext.Take();
|
||||
auto previousBackend = Move(MG_Backend::pActiveBackendObject);
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
MG_Backend::pActiveBackendObject =
|
||||
@@ -1404,7 +1404,7 @@ TEST(GetterSanity, EveryLimitWithABuiltinAgreesWithItsQuery) {
|
||||
TEST(GetterSanity, MaxElementIndexIsTheFull32BitIndexCeiling) {
|
||||
using namespace MobileGL;
|
||||
|
||||
auto previousContext = Move(MG_State::pGLContext);
|
||||
auto previousContext = MG_State::pGLContext.Take();
|
||||
auto previousBackend = Move(MG_Backend::pActiveBackendObject);
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
MG_Backend::pActiveBackendObject = MakeUnique<DynamicParameterBackend>(MG_Backend::DynamicBackendParameters{});
|
||||
@@ -1431,7 +1431,7 @@ TEST(GetterSanity, MaxElementIndexIsTheFull32BitIndexCeiling) {
|
||||
TEST(GetterSanity, PerCategoryMultisampleCeilingsAreProbedRatherThanFlooredAtFour) {
|
||||
using namespace MobileGL;
|
||||
|
||||
auto previousContext = Move(MG_State::pGLContext);
|
||||
auto previousContext = MG_State::pGLContext.Take();
|
||||
auto previousBackend = Move(MG_Backend::pActiveBackendObject);
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
|
||||
@@ -1473,7 +1473,7 @@ TEST(GetterSanity, PerCategoryMultisampleCeilingsAreProbedRatherThanFlooredAtFou
|
||||
TEST(ShaderCompilerSanity, ArbCullDistanceIsUsableBelow450) {
|
||||
using namespace MobileGL;
|
||||
|
||||
auto previousContext = Move(MG_State::pGLContext);
|
||||
auto previousContext = MG_State::pGLContext.Take();
|
||||
auto previousBackend = Move(MG_Backend::pActiveBackendObject);
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
MG_Backend::pActiveBackendObject = MakeUnique<DynamicParameterBackend>(MG_Backend::DynamicBackendParameters{});
|
||||
@@ -4579,7 +4579,7 @@ TEST(DirectGLESVertexInputDraw, TheAttributeWalkTakesItsBuffersFromTheRecordNotT
|
||||
// this case exists to catch - gPipeInputs->GetBoundVertexArray()->GetAllAttributes() - has
|
||||
// anything to read at all; a free-standing object would make the revert crash instead of
|
||||
// disagree, which is a red for the wrong reason.
|
||||
SharedPtr<GLContext> previousContext = Move(MG_State::pGLContext);
|
||||
SharedPtr<GLContext> previousContext = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
MG_State::pGLContext->CreateVertexArrayObject(1);
|
||||
MG_State::pGLContext->BindVertexArray(1);
|
||||
@@ -4650,7 +4650,7 @@ TEST(DirectGLESVertexInputDraw, TheIndexArmTakesItsBufferAndItsSerialFromTheReco
|
||||
|
||||
// The frontend's element slot has moved to another buffer with nothing emitted, in a real
|
||||
// context for the reason the case above gives.
|
||||
SharedPtr<GLContext> previousContext = Move(MG_State::pGLContext);
|
||||
SharedPtr<GLContext> previousContext = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<GLContext>();
|
||||
MG_State::pGLContext->CreateVertexArrayObject(1);
|
||||
MG_State::pGLContext->BindVertexArray(1);
|
||||
|
||||
@@ -222,7 +222,7 @@ TEST_F(ContextStateOwnershipTest, DestroyingOneContextLeavesTheOtherAlone) {
|
||||
|
||||
TEST_F(ContextStateOwnershipTest, ReleasingAnEglContextRestoresTheThreadsPreviousGLState) {
|
||||
const auto contextA = NewContext(EGL_NO_CONTEXT);
|
||||
const auto before = MG_State::pGLContext;
|
||||
const auto before = MG_State::pGLContext.Shared();
|
||||
ASSERT_NE(before, nullptr);
|
||||
|
||||
MakeCurrent(contextA);
|
||||
@@ -234,7 +234,7 @@ TEST_F(ContextStateOwnershipTest, ReleasingAnEglContextRestoresTheThreadsPreviou
|
||||
}
|
||||
|
||||
TEST_F(ContextStateOwnershipTest, AThreadWithoutACurrentContextUsesTheProcessDefaultContext) {
|
||||
const auto processDefault = MG_State::pGLContext;
|
||||
const auto processDefault = MG_State::pGLContext.Shared();
|
||||
ASSERT_NE(processDefault, nullptr);
|
||||
EXPECT_EQ(processDefault, MG_State::ProcessDefaultGLContext());
|
||||
|
||||
|
||||
@@ -1469,19 +1469,19 @@ TEST_F(PipeWireCodecTest, SetContextValuesRoundTripsIntoPipeInputs) {
|
||||
// kReadback's class carries the two texture-unit counters, kDraw's the rest
|
||||
// (FillPoints.def) - the stamp is what publishes a RECORD-SUPPLIED field for the read.
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::ReadPixels);
|
||||
EXPECT_EQ(gPipeInputs.GetActiveTextureUnit(), 9);
|
||||
EXPECT_EQ(gPipeInputs.GetMaxTouchedTextureUnit(), 41);
|
||||
EXPECT_EQ(gPipeInputs->GetActiveTextureUnit(), 9);
|
||||
EXPECT_EQ(gPipeInputs->GetMaxTouchedTextureUnit(), 41);
|
||||
MGPipeServerStampVerbBoundary(MGPipeVerb::DrawArrays);
|
||||
for (Uint32 t = 0; t < 15; ++t) {
|
||||
EXPECT_EQ(gPipeInputs.GetTouchedBufferBindingPointCount(static_cast<BufferTarget>(t)),
|
||||
EXPECT_EQ(gPipeInputs->GetTouchedBufferBindingPointCount(static_cast<BufferTarget>(t)),
|
||||
SizeT{100 + t})
|
||||
<< "target " << t;
|
||||
}
|
||||
EXPECT_TRUE(gPipeInputs.IsTransformFeedbackActive());
|
||||
EXPECT_TRUE(gPipeInputs.IsTransformFeedbackPaused());
|
||||
EXPECT_EQ(gPipeInputs.GetTransformFeedbackGeneration(), 0xA1A2A3A4A5A6A7A8ull);
|
||||
EXPECT_EQ(gPipeInputs.GetBoundTransformFeedbackLifetimeId(), 0xB1B2B3B4B5B6B7B8ull);
|
||||
EXPECT_EQ(gPipeInputs.GetTransformFeedbackCapturedVertices(), 0xC1C2C3C4C5C6C7C8ull);
|
||||
EXPECT_TRUE(gPipeInputs->IsTransformFeedbackActive());
|
||||
EXPECT_TRUE(gPipeInputs->IsTransformFeedbackPaused());
|
||||
EXPECT_EQ(gPipeInputs->GetTransformFeedbackGeneration(), 0xA1A2A3A4A5A6A7A8ull);
|
||||
EXPECT_EQ(gPipeInputs->GetBoundTransformFeedbackLifetimeId(), 0xB1B2B3B4B5B6B7B8ull);
|
||||
EXPECT_EQ(gPipeInputs->GetTransformFeedbackCapturedVertices(), 0xC1C2C3C4C5C6C7C8ull);
|
||||
MGPipeServerClearVerbBoundary();
|
||||
}
|
||||
|
||||
|
||||
@@ -816,21 +816,21 @@ TEST(ServerLoopTest, AClearRecordCrossesAndIsStampedAsAVerbBoundary) {
|
||||
ASSERT_TRUE(fixture.StartLoop());
|
||||
|
||||
// The pre-state is the honest one: nothing has stamped yet in this process.
|
||||
ASSERT_NE(MG_Pipe::gPipeInputs.CurrentVerb(), MG_Pipe::MGPipeVerb::Clear);
|
||||
ASSERT_NE(MG_Pipe::gPipeInputs->CurrentVerb(), MG_Pipe::MGPipeVerb::Clear);
|
||||
|
||||
const MG_Pipe::MGPClear clear = WholeFramebufferClear();
|
||||
ASSERT_TRUE(fixture.EmitAndWait(MG_Pipe::MGPWireOp::Clear, &clear, sizeof(clear)));
|
||||
|
||||
Server::ServerLoop& loop = Server::ServerLoopInstance();
|
||||
EXPECT_EQ(loop.DrainedRecords(), 1u);
|
||||
EXPECT_EQ(MG_Pipe::gPipeInputs.CurrentVerb(), MG_Pipe::MGPipeVerb::Clear)
|
||||
EXPECT_EQ(MG_Pipe::gPipeInputs->CurrentVerb(), MG_Pipe::MGPipeVerb::Clear)
|
||||
<< "PipeApplier::StampVerbBoundary did not run, so every server-side PipeInputs read "
|
||||
"would abort on the first field inside SyncRenderState";
|
||||
|
||||
// MANDATORY on leaving the applier (p1's M-5): without it a SPAWNED server latches the flag
|
||||
// for its whole life, every later read is judged against the last verb's mask, and the
|
||||
// sticky forwards start aborting under strict on the very case their exemption exists for.
|
||||
EXPECT_FALSE(MG_Pipe::gPipeInputs.ServerStampedVerb())
|
||||
EXPECT_FALSE(MG_Pipe::gPipeInputs->ServerStampedVerb())
|
||||
<< "MGPipeServerClearVerbBoundary was not called when the apply thread left the applier";
|
||||
|
||||
// No backend object in this process, so the five class-B verbs DECLINE. Asserted rather
|
||||
@@ -1629,7 +1629,7 @@ namespace {
|
||||
// Empty on success, else the step that failed - the harness's SkipReason shape.
|
||||
std::string BringUp() {
|
||||
PinHeadlessEglEnvironment();
|
||||
savedContext = Move(MG_State::pGLContext);
|
||||
savedContext = MG_State::pGLContext.Take();
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
Server::ServerLoop& loop = Server::ServerLoopInstance();
|
||||
// InitSplitRoles step 1: the server's private backend, no GL and no EGL yet; its
|
||||
@@ -1944,13 +1944,13 @@ TEST(ServerLoopEglTest, ServerLivenessFollowsControlFramesAcrossReleaseAndRecrea
|
||||
MGL_EGL_BRING_UP_OR_BAIL(fixture);
|
||||
const auto live = [] {
|
||||
Bool answer = false;
|
||||
EXPECT_EQ(OnApply([&] { answer = MG_Pipe::gPipeInputs.IsLive(); }), MOBILEGL_OK);
|
||||
EXPECT_EQ(OnApply([&] { answer = MG_Pipe::gPipeInputs->IsLive(); }), MOBILEGL_OK);
|
||||
return answer;
|
||||
};
|
||||
EXPECT_FALSE(live()) << "surface creation alone is not a served current context";
|
||||
ASSERT_TRUE(fixture.MakeCurrent());
|
||||
EXPECT_TRUE(live());
|
||||
auto client = Move(MG_State::pGLContext);
|
||||
auto client = MG_State::pGLContext.Take();
|
||||
EXPECT_TRUE(live()) << "server liveness must not consult the client GLContext";
|
||||
MG_State::pGLContext = Move(client);
|
||||
ASSERT_TRUE(fixture.ReleaseCurrent());
|
||||
@@ -2571,7 +2571,7 @@ TEST(ServerLoopTest, AnInstancedBaseVertexDrawRecordReachesTheSinkWithItsFieldsI
|
||||
EXPECT_EQ(seen.FirstRange.IndexBias, 5);
|
||||
EXPECT_FALSE(seen.HadUserIndices);
|
||||
EXPECT_FALSE(seen.HadIndirect);
|
||||
EXPECT_FALSE(MG_Pipe::gPipeInputs.ServerStampedVerb());
|
||||
EXPECT_FALSE(MG_Pipe::gPipeInputs->ServerStampedVerb());
|
||||
|
||||
fixture.Stop();
|
||||
}
|
||||
@@ -2714,7 +2714,7 @@ TEST(P5fReverseChannel, GlErrorsUseTheOwnedCallbackWithoutAResidualPull) {
|
||||
g_fvErrorCalls = 0;
|
||||
MG_Pipe::MGPipeResetResidualPullCountForTesting();
|
||||
MG_Pipe::MGPipeServerStampVerbBoundary(MG_Pipe::MGPipeVerb::Clear);
|
||||
MG_Pipe::gPipeInputs.RecordError(ErrorCode::InvalidOperation,
|
||||
MG_Pipe::gPipeInputs->RecordError(ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("fv", "draw", "driver message"));
|
||||
EXPECT_EQ(g_fvErrorCalls, 1u);
|
||||
EXPECT_EQ(g_fvErrorCode, static_cast<Uint32>(ErrorCode::InvalidOperation));
|
||||
@@ -2780,7 +2780,7 @@ TEST(P5fReverseChannel, RecordErrorWithoutCallbackIsNamedFatal) {
|
||||
MG_Config::Ipc.StrictErrors = true;
|
||||
MG_Config::Ipc.RoleSplitState = true;
|
||||
MG_Pipe::gMGPipeCallbacks.OnGlError = nullptr;
|
||||
MG_Pipe::gPipeInputs.RecordError(ErrorCode::InvalidOperation, nullptr);
|
||||
MG_Pipe::gPipeInputs->RecordError(ErrorCode::InvalidOperation, nullptr);
|
||||
std::_Exit(9);
|
||||
}, ::testing::KilledBySignal(SIGABRT), "");
|
||||
EXPECT_NE(ReadLog().find("OnGlError.callback-missing"), std::string::npos);
|
||||
@@ -2815,7 +2815,7 @@ TEST(P5fReverseChannel, GlErrorMessagesShareFifoWithOtherReverseEvents) {
|
||||
ASSERT_EQ(Server::ServerLoopInstance().RunProbeOnApplyThreadForTesting(
|
||||
+[](void*) -> MobileGLResult {
|
||||
MG_Pipe::MGPipeServerStampVerbBoundary(MG_Pipe::MGPipeVerb::Clear);
|
||||
MG_Pipe::gPipeInputs.RecordError(ErrorCode::InvalidOperation,
|
||||
MG_Pipe::gPipeInputs->RecordError(ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("fv", "driver error"));
|
||||
const MG_Pipe::MGPRange whole{0, MG_Pipe::kMGPipeWholeBuffer};
|
||||
MG_Pipe::gMGPipeCallbacks.OnGpuWritten({17, 3}, 1, &whole);
|
||||
@@ -3165,7 +3165,7 @@ namespace {
|
||||
const MG_Pipe::MGPDrawRange range{0, 3, 0};
|
||||
if (!fixture.EmitAndWaitWithTail(MG_Pipe::MGPWireOp::DrawVbo, &info, sizeof(info), &range, sizeof(range)))
|
||||
::_exit(65);
|
||||
if (MG_Pipe::gPipeInputs.CurrentVerb() == MG_Pipe::MGPipeVerb::Clear) ::_exit(66);
|
||||
if (MG_Pipe::gPipeInputs->CurrentVerb() == MG_Pipe::MGPipeVerb::Clear) ::_exit(66);
|
||||
// A Clear encoded legally and then SHORTENED in the ring before it is published - the
|
||||
// raw-record peer driver's move, in process: its header says 8 bytes, a header and no
|
||||
// MGPClear at all.
|
||||
@@ -3185,7 +3185,7 @@ namespace {
|
||||
Server::ServerLoop& loop = Server::ServerLoopInstance();
|
||||
(void)PollUntil([&] { return !loop.Running(); }, 3000);
|
||||
int failed = 0;
|
||||
if (MG_Pipe::gPipeInputs.CurrentVerb() == MG_Pipe::MGPipeVerb::Clear) failed |= kShortStamped;
|
||||
if (MG_Pipe::gPipeInputs->CurrentVerb() == MG_Pipe::MGPipeVerb::Clear) failed |= kShortStamped;
|
||||
if (!Remote::SessionLatched() || std::strstr(Remote::SessionLatchedLine(), "\"record.Minimum\"") == nullptr)
|
||||
failed |= kShortWrongFault;
|
||||
if (loop.DrainedRecords() != 2) failed |= kShortDrained;
|
||||
|
||||
Reference in New Issue
Block a user