mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Refactor] (P13 W3b): backends read MG_Pipe::gPipeInputs directly, MGB_CTX and its switch header are gone
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
#include <MG_Util/Classifiers/TextureEnumClassifier.h>
|
||||
#include <MG_Util/Metrics/TextureMetrics.h>
|
||||
#include <MG_State/GLState/Core.h>
|
||||
#include <MG_Pipe/PipeInputsSwitch.h>
|
||||
#include <MG_Backend/MGPipe/PipeInputs.h>
|
||||
// P3a: the applier's vertex-input records the re-keyed draw-buffer memo is validated against.
|
||||
#include <MG_Pipe/PipeApply.h>
|
||||
// P5c ev: the surface-changed event's producer callback, installed by the server session.
|
||||
@@ -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(MGB_CTX->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
|
||||
@@ -128,14 +128,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// slice, so that MOBILEGL_PIPE_PUSH=0 keeps being the faithful all-subsystems-pull control
|
||||
// ConfigLoader.cpp documents - "reproduces P1's behaviour exactly" has to include this
|
||||
// path, or the integrator's A/B measures e4 on both arms and attributes it to neither. In
|
||||
// the pull build MGB_CTX is the live GLContext, there is no poison to bypass and the
|
||||
// the pull build gPipeInputs is the live GLContext, there is no poison to bypass and the
|
||||
// frontend getter still linear-scans, so the cache is exactly the code it was.
|
||||
static inline FbBindingSlot& GetFramebufferBindingSlotChecked(FramebufferTarget target) {
|
||||
if (EsprytSlotTablesEnabled()) {
|
||||
return MGB_CTX->GetFramebufferBindingSlot(target);
|
||||
return MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(target);
|
||||
}
|
||||
// No legacy arm compiled: EsprytSlotTablesEnabled() is unconditionally true above.
|
||||
return MGB_CTX->GetFramebufferBindingSlot(target);
|
||||
return MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(target);
|
||||
}
|
||||
|
||||
// A4, TAKEN AT THE VERIFICATION ROUND, AND THE FOUR TEMPORARY LATCHES ARE GONE WITH IT.
|
||||
@@ -401,7 +401,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
auto drawBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
auto drawBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (drawBuffer) {
|
||||
drawBuffer->SyncPersistentMappedRange();
|
||||
const SizeT commandOffset = reinterpret_cast<SizeT>(indirect);
|
||||
@@ -698,7 +698,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#endif
|
||||
// Only sync up to the high-water mark of app-touched points; the fixed array is 84
|
||||
// deep but apps bind a handful, so the never-touched tail is already at GL default 0.
|
||||
auto bindingPointCnt = MGB_CTX->GetTouchedBufferBindingPointCount(target);
|
||||
auto bindingPointCnt = MG_Pipe::gPipeInputs.GetTouchedBufferBindingPointCount(target);
|
||||
// ...and never past what the ES driver itself can hold. MobileGL advertises the GL 4.5
|
||||
// minimum of 84 uniform binding points while the ES 3.2 minimum is 72, so a frontend
|
||||
// index in that gap would reach glBindBufferBase as GL_INVALID_VALUE. Nothing is lost
|
||||
@@ -711,7 +711,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
static_cast<SizeT>(g_GLESCapabilities.MaxUniformBufferBindings));
|
||||
}
|
||||
for (SizeT i = 0; i < bindingPointCnt; ++i) {
|
||||
auto& point = MGB_CTX->GetBufferBindingPoint(target, i);
|
||||
auto& point = MG_Pipe::gPipeInputs.GetBufferBindingPoint(target, i);
|
||||
auto& obj = point.GetBoundObject();
|
||||
if (!obj) {
|
||||
BindBufferBaseCached(glTarget, static_cast<GLuint>(i), 0);
|
||||
@@ -770,7 +770,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
const SizeT pointCount = std::min<SizeT>(
|
||||
bufferCount, MG_State::GLState::GLContext::MAX_TRANSFORM_FEEDBACK_BUFFERS);
|
||||
for (SizeT i = 0; i < pointCount; ++i) {
|
||||
auto& point = MGB_CTX->GetBufferBindingPoint(BufferTarget::TransformFeedback, i);
|
||||
auto& point = MG_Pipe::gPipeInputs.GetBufferBindingPoint(BufferTarget::TransformFeedback, i);
|
||||
const auto& obj = point.GetBoundObject();
|
||||
// A stride-0 slot (two consecutive gl_NextBuffer entries) captures nothing and
|
||||
// needs no binding; anything else with no buffer never got past the frontend.
|
||||
@@ -822,10 +822,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
if (MG_Config::Transport != MG_Config::TransportMode::Monolith) return;
|
||||
#endif
|
||||
const SizeT bindingPointCnt =
|
||||
MGB_CTX->GetTouchedBufferBindingPointCount(BufferTarget::ShaderStorage);
|
||||
MG_Pipe::gPipeInputs.GetTouchedBufferBindingPointCount(BufferTarget::ShaderStorage);
|
||||
for (SizeT i = 0; i < bindingPointCnt; ++i) {
|
||||
const auto& obj =
|
||||
MGB_CTX->GetBufferBindingPoint(BufferTarget::ShaderStorage, i).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingPoint(BufferTarget::ShaderStorage, i).GetBoundObject();
|
||||
// P3a (D-D): announced on the reverse channel on the handle arm, poked into
|
||||
// the object on the legacy one. MarkBufferGpuWritten is the one place that
|
||||
// decides, so the three announcement sites stay one line each.
|
||||
@@ -903,14 +903,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
const SizeT pointCount = MGB_CTX->GetBufferBindingPointCount(BufferTarget::AtomicCounter);
|
||||
const SizeT pointCount = MG_Pipe::gPipeInputs.GetBufferBindingPointCount(BufferTarget::AtomicCounter);
|
||||
for (const Int glBinding : glBindings) {
|
||||
if (glBinding < 0 || static_cast<SizeT>(glBinding) >= pointCount) continue;
|
||||
const Int esslBinding = esslBindingTop - glBinding;
|
||||
// Already diagnosed once when the block was transpiled; nothing was bound to it
|
||||
// there either, so there is nothing to unbind here.
|
||||
if (esslBinding < 0) continue;
|
||||
auto& point = MGB_CTX->GetBufferBindingPoint(BufferTarget::AtomicCounter,
|
||||
auto& point = MG_Pipe::gPipeInputs.GetBufferBindingPoint(BufferTarget::AtomicCounter,
|
||||
static_cast<Uint>(glBinding));
|
||||
auto& obj = point.GetBoundObject();
|
||||
if (!obj) {
|
||||
@@ -947,7 +947,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#ifdef TRACY_ENABLE
|
||||
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
||||
#endif
|
||||
auto& bufferObject = MGB_CTX->GetBufferBindingSlot(target).GetBoundObject();
|
||||
auto& bufferObject = MG_Pipe::gPipeInputs.GetBufferBindingSlot(target).GetBoundObject();
|
||||
if (!bufferObject) {
|
||||
g_GLESFuncs.glBindBuffer(glTarget, 0);
|
||||
return;
|
||||
@@ -1390,7 +1390,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#endif
|
||||
{
|
||||
auto& possibleIndirectBuffer =
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (possibleIndirectBuffer) {
|
||||
SyncBoundBuffer(BufferTarget::DrawIndirect, GL_DRAW_INDIRECT_BUFFER);
|
||||
}
|
||||
@@ -1842,7 +1842,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
const SizeT packedStride = program->GetTransformFeedbackPackedStride();
|
||||
const SizeT modelledVertices =
|
||||
static_cast<SizeT>(MGB_CTX->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,
|
||||
@@ -2038,10 +2038,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
if (record) program.Archive = record->Archive;
|
||||
}
|
||||
} else {
|
||||
program.Frontend = MGB_CTX->GetTransformFeedbackProgram();
|
||||
program.Frontend = MG_Pipe::gPipeInputs.GetTransformFeedbackProgram();
|
||||
}
|
||||
#else
|
||||
const auto& program = MGB_CTX->GetTransformFeedbackProgram();
|
||||
const auto& program = MG_Pipe::gPipeInputs.GetTransformFeedbackProgram();
|
||||
#endif
|
||||
if (!program) {
|
||||
// The pending flag is deliberately NOT consumed here. It used to be cleared
|
||||
@@ -2076,7 +2076,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
auto& point = MGB_CTX->GetBufferBindingPoint(BufferTarget::TransformFeedback,
|
||||
auto& point = MG_Pipe::gPipeInputs.GetBufferBindingPoint(BufferTarget::TransformFeedback,
|
||||
static_cast<Uint>(i));
|
||||
const auto& bufferObject = point.GetBoundObject();
|
||||
if (!bufferObject) continue;
|
||||
@@ -2490,10 +2490,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// MONOLITH ONLY, and the gate is what keeps a live transport's apply thread out of
|
||||
// the frontend VAO: with a transport the CLIENT owns those bytes and snapshots them
|
||||
// from the GL thread (MG_Impl/Pipe/OwnedDrawInputs.h), so there is nothing for the
|
||||
// server to stage - and reading MGB_CTX there is the role violation this family's
|
||||
// server to stage - and reading gPipeInputs there is the role violation this family's
|
||||
// other monolith glue is guarded against.
|
||||
if (MG_Config::Transport != MG_Config::TransportMode::Monolith) return true;
|
||||
const auto& currentVAO = MGB_CTX->GetBoundVertexArray();
|
||||
const auto& currentVAO = MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
if (!currentVAO) return true;
|
||||
|
||||
// A draw whose attributes all come from buffers has nothing to snapshot, and asking
|
||||
@@ -2527,11 +2527,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
inputs.WantVertices = clientVertexRate;
|
||||
// The driver does its own restart handling; the plan has to know only that the restart
|
||||
// value is not a vertex, or the snapshot would stage an element no primitive fetches.
|
||||
inputs.PrimitiveRestart = MGB_CTX->IsCapabilityEnabled(CapabilityInput::PrimitiveRestart) ||
|
||||
MGB_CTX->IsCapabilityEnabled(CapabilityInput::PrimitiveRestartFixedIndex);
|
||||
inputs.RestartIndex = MGB_CTX->IsCapabilityEnabled(CapabilityInput::PrimitiveRestartFixedIndex)
|
||||
inputs.PrimitiveRestart = MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::PrimitiveRestart) ||
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::PrimitiveRestartFixedIndex);
|
||||
inputs.RestartIndex = MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::PrimitiveRestartFixedIndex)
|
||||
? (indexSize == 1 ? 0xffu : indexSize == 2 ? 0xffffu : 0xffffffffu)
|
||||
: MGB_CTX->GetPrimitiveRestartIndex();
|
||||
: MG_Pipe::gPipeInputs.GetPrimitiveRestartIndex();
|
||||
|
||||
MG_Pipe::MGPipeClientFetchPlan plan;
|
||||
if (!plan.Build(inputs, &ReadClientSnapshotBytes, &sources)) return false;
|
||||
@@ -2586,7 +2586,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// MONOLITH ONLY - see SyncClientSideVertexArraysForFetch; this wrapper's own read of
|
||||
// the bound VAO is the frontend read that must not happen on an apply thread.
|
||||
if (MG_Config::Transport != MG_Config::TransportMode::Monolith) return true;
|
||||
const auto& currentVAO = MGB_CTX->GetBoundVertexArray();
|
||||
const auto& currentVAO = MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
if (!currentVAO) return true;
|
||||
const Uint8 indexSize = static_cast<Uint8>(MG_Util::GetGLTypeSize(type));
|
||||
if (indexSize == 0) return true;
|
||||
@@ -2627,13 +2627,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
auto* twin = ResolveVaoTwin(MG_Pipe::MGPipeApplier().BoundVertexElements);
|
||||
if (twin == nullptr) return;
|
||||
const auto& currentVAO = MGB_CTX->GetBoundVertexArray();
|
||||
const auto& currentVAO = MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
if (!currentVAO) return;
|
||||
twin->SyncClientSideAttributesForDrawArrays(currentVAO, first, count);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
const auto& currentVAO = MGB_CTX->GetBoundVertexArray();
|
||||
const auto& currentVAO = MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
if (!currentVAO) return;
|
||||
auto* backendVAOSlot = g_backendVertexArrayObjects.Find(currentVAO.get());
|
||||
if (backendVAOSlot && *backendVAOSlot) {
|
||||
@@ -2695,7 +2695,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#endif
|
||||
|
||||
const SharedPtr<MG_State::GLState::VertexArrayObject> noVao;
|
||||
const auto& vao = fromRecords ? noVao : MGB_CTX->GetBoundVertexArray();
|
||||
const auto& vao = fromRecords ? noVao : MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
if (!fromRecords && !vao) return;
|
||||
|
||||
const Uint32 activeAttribMask = program->GetActiveAttributeLocationMask();
|
||||
@@ -2759,7 +2759,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 = MGB_CTX->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:
|
||||
@@ -2861,7 +2861,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
|
||||
const SharedPtr<MG_State::GLState::VertexArrayObject> noVao;
|
||||
const auto& vao = fromRecords ? noVao : MGB_CTX->GetBoundVertexArray();
|
||||
const auto& vao = fromRecords ? noVao : MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
if (!fromRecords && !vao) return;
|
||||
|
||||
// ProgramObject::GetActiveAttributeLocationMask, over the archive's own `attribs`:
|
||||
@@ -2922,7 +2922,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 = MGB_CTX->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:
|
||||
@@ -3084,7 +3084,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
const Bool handleArm = MGB_UNIT_BINDINGS_HANDLE_ARM;
|
||||
out.resize(static_cast<SizeT>(maxTouchedUnit + 1));
|
||||
for (Int unit = 0; unit <= maxTouchedUnit; ++unit) {
|
||||
auto& textureUnit = MGB_CTX->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) {
|
||||
@@ -3102,7 +3102,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
if (snapshots.size() != static_cast<SizeT>(maxTouchedUnit + 1)) return false;
|
||||
const Bool handleArm = MGB_UNIT_BINDINGS_HANDLE_ARM;
|
||||
for (Int unit = 0; unit <= maxTouchedUnit; ++unit) {
|
||||
auto& textureUnit = MGB_CTX->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) {
|
||||
@@ -3257,8 +3257,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
/*hit=*/false);
|
||||
}
|
||||
}
|
||||
const Uint64 contextId = MGB_CTX->GetTextureContextId();
|
||||
const Uint64 bindGeneration = MGB_CTX->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.
|
||||
@@ -3490,7 +3490,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
DrawTextureSyncKeys CaptureDrawTextureSyncKeys() {
|
||||
DrawTextureSyncKeys keys;
|
||||
keys.contextId = MGB_CTX->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
|
||||
@@ -3503,8 +3503,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 = MGB_CTX->GetMaxTouchedTextureUnit();
|
||||
keys.samplingGeneration = MGB_CTX->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
|
||||
@@ -3802,7 +3802,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
g_unitTextureSyncListValid = false;
|
||||
g_unitTextureSyncList.clear();
|
||||
for (Int index = 0; index <= maxTouchedUnit; ++index) {
|
||||
auto& unit = MGB_CTX->GetTextureUnitObject(index);
|
||||
auto& unit = MG_Pipe::gPipeInputs.GetTextureUnitObject(index);
|
||||
for (const auto& bindingSlot : unit.GetAllBindingSlots()) {
|
||||
auto& textureObject = bindingSlot.GetBoundObject();
|
||||
// An image-less default texture (name 0) is the slot's initial / "unbound"
|
||||
@@ -4185,7 +4185,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#ifdef TRACY_ENABLE
|
||||
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
||||
#endif
|
||||
auto& imageBinding = MGB_CTX->GetImageTextureBinding(static_cast<Int>(unit));
|
||||
auto& imageBinding = MG_Pipe::gPipeInputs.GetImageTextureBinding(static_cast<Int>(unit));
|
||||
TrackWritableImageBufferUnit(unit, IsWritableImageBufferTexture(imageBinding));
|
||||
if (imageBinding.Texture && unit + 1 > g_imageUnitHighWaterMark) {
|
||||
g_imageUnitHighWaterMark = unit + 1;
|
||||
@@ -4258,7 +4258,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
if (g_writableImageBufferUnitCount == 0) return;
|
||||
for (Uint unit = 0; unit < g_writableImageBufferUnits.size(); ++unit) {
|
||||
if (!g_writableImageBufferUnits[unit]) continue;
|
||||
const auto& imageBinding = MGB_CTX->GetImageTextureBinding(static_cast<Int>(unit));
|
||||
const auto& imageBinding = MG_Pipe::gPipeInputs.GetImageTextureBinding(static_cast<Int>(unit));
|
||||
if (!IsWritableImageBufferTexture(imageBinding)) {
|
||||
TrackWritableImageBufferUnit(unit, false);
|
||||
continue;
|
||||
@@ -5030,7 +5030,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#ifdef TRACY_ENABLE
|
||||
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
||||
#endif
|
||||
Uint16 currentRenderStateVersion = MGB_CTX->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
|
||||
@@ -5058,7 +5058,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Util::PipeStats::AddCalls(MG_Util::PipeStats::CallClass::AccessorCalls, 3);
|
||||
}
|
||||
|
||||
const auto& parameters = MGB_CTX->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
|
||||
@@ -5087,7 +5087,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
!g_hasSyncedRenderState || std::memcmp(currentBytes + kBlendSpanEnd, syncedBytes + kBlendSpanEnd,
|
||||
sizeof(RenderStateParameters) - kBlendSpanEnd) != 0;
|
||||
|
||||
IntVec4 backendViewport = MGB_CTX->GetViewport();
|
||||
IntVec4 backendViewport = MG_Pipe::gPipeInputs.GetViewport();
|
||||
if (backendViewport.z() <= 0 || backendViewport.w() <= 0) {
|
||||
Int surfaceWidth = 0;
|
||||
Int surfaceHeight = 0;
|
||||
@@ -5170,7 +5170,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 = MGB_CTX->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)
|
||||
@@ -6148,11 +6148,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// member set it has to be told.
|
||||
(twin->GetPassthroughTessControlPatchVertices() >= 0 &&
|
||||
(twin->GetPassthroughTessControlPatchVertices() !=
|
||||
static_cast<Int>(MGB_CTX->GetPatchVertices()) ||
|
||||
static_cast<Int>(MG_Pipe::gPipeInputs.GetPatchVertices()) ||
|
||||
!BitwiseEqual(twin->GetPassthroughTessControlOuterLevel(),
|
||||
MGB_CTX->GetPatchDefaultOuterLevel()) ||
|
||||
MG_Pipe::gPipeInputs.GetPatchDefaultOuterLevel()) ||
|
||||
!BitwiseEqual(twin->GetPassthroughTessControlInnerLevel(),
|
||||
MGB_CTX->GetPatchDefaultInnerLevel())))) {
|
||||
MG_Pipe::gPipeInputs.GetPatchDefaultInnerLevel())))) {
|
||||
twin->SyncToBackend(currentProgram);
|
||||
}
|
||||
g_currentDrawFrontendProgram = currentProgram.get();
|
||||
@@ -6219,11 +6219,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
!twin->ImageUnitFormatsStillMatch() ||
|
||||
(twin->GetPassthroughTessControlPatchVertices() >= 0 &&
|
||||
(twin->GetPassthroughTessControlPatchVertices() !=
|
||||
static_cast<Int>(MGB_CTX->GetPatchVertices()) ||
|
||||
static_cast<Int>(MG_Pipe::gPipeInputs.GetPatchVertices()) ||
|
||||
!BitwiseEqual(twin->GetPassthroughTessControlOuterLevel(),
|
||||
MGB_CTX->GetPatchDefaultOuterLevel()) ||
|
||||
MG_Pipe::gPipeInputs.GetPatchDefaultOuterLevel()) ||
|
||||
!BitwiseEqual(twin->GetPassthroughTessControlInnerLevel(),
|
||||
MGB_CTX->GetPatchDefaultInnerLevel())))) {
|
||||
MG_Pipe::gPipeInputs.GetPatchDefaultInnerLevel())))) {
|
||||
twin->SyncToBackendByHandle(cso);
|
||||
}
|
||||
g_currentDrawProgramHandle = cso;
|
||||
@@ -6540,7 +6540,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// frontend VAO always did.
|
||||
const Bool vertexInputFromRecords = BufferImpl::VertexInputReadsRecords();
|
||||
const SharedPtr<MG_State::GLState::VertexArrayObject> noFrontendVao;
|
||||
const auto& currentVAO = vertexInputFromRecords ? noFrontendVao : MGB_CTX->GetBoundVertexArray();
|
||||
const auto& currentVAO = vertexInputFromRecords ? noFrontendVao : MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
VertexArrayImpl::BackendVertexArrayObject* vaoTwin = nullptr;
|
||||
Uint32 vaoConfigVersion = 0;
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
@@ -6570,7 +6570,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// reaches the same "nothing to bind" answers a null frontend program always did.
|
||||
const SharedPtr<MG_State::GLState::ProgramObject> noFrontendProgram;
|
||||
const Bool programFromRecords = DrawProgramFromRecords();
|
||||
const auto& currentProgram = programFromRecords ? noFrontendProgram : MGB_CTX->GetProgramForDraw();
|
||||
const auto& currentProgram = programFromRecords ? noFrontendProgram : MG_Pipe::gPipeInputs.GetProgramForDraw();
|
||||
if (MG_Util::PipeStats::Enabled()) {
|
||||
// THE per-draw denominator for Espryt, plus this function's own two accessor
|
||||
// calls (the VAO and the draw program). Everything the callees below read is
|
||||
@@ -6772,7 +6772,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
};
|
||||
|
||||
for (Int unit = 0; unit <= maxTouchedUnit; ++unit) {
|
||||
auto& textureUnit = MGB_CTX->GetTextureUnitObject(unit);
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit);
|
||||
Array<Bool, (SizeT)TextureTarget::TextureTargetCount> boundBackendTargets{};
|
||||
Array<TextureTarget, (SizeT)TextureTarget::TextureTargetCount> claimedByFrontendTarget{};
|
||||
claimedByFrontendTarget.fill(TextureTarget::Unknown);
|
||||
@@ -7081,7 +7081,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
if (!walkedFromRecords)
|
||||
{
|
||||
for (Int unit = 0; unit <= maxTouchedUnit; ++unit) {
|
||||
const auto& samplerObject = MGB_CTX->GetTextureUnitObject(unit).GetSamplerObject();
|
||||
const auto& samplerObject = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit).GetSamplerObject();
|
||||
if (samplerObject) {
|
||||
if (auto* backendSampler = ResolveUnitSamplerBackend(unit, samplerObject)) {
|
||||
backendSampler->Bind(unit);
|
||||
@@ -7356,7 +7356,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// transport and therefore take the frontend arm below unchanged.
|
||||
const SharedPtr<MG_State::GLState::ProgramObject> noFrontendProgram;
|
||||
BindCurrentTextures(TextureImpl::CaptureDrawTextureSyncKeys(),
|
||||
DrawProgramFromRecords() ? noFrontendProgram : MGB_CTX->GetProgramForDraw());
|
||||
DrawProgramFromRecords() ? noFrontendProgram : MG_Pipe::gPipeInputs.GetProgramForDraw());
|
||||
}
|
||||
|
||||
// Binds the current program's backend object and re-establishes its per-program
|
||||
@@ -7644,7 +7644,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
auto& point = MGB_CTX->GetBufferBindingPoint(BufferTarget::Uniform, binding);
|
||||
auto& point = MG_Pipe::gPipeInputs.GetBufferBindingPoint(BufferTarget::Uniform, binding);
|
||||
auto& bufferObj = point.GetBoundObject();
|
||||
auto range = point.GetRange();
|
||||
|
||||
@@ -7837,7 +7837,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
auto& textureUnit = MGB_CTX->GetTextureUnitObject(unit);
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit);
|
||||
auto& samplerObject = textureUnit.GetSamplerObject();
|
||||
const auto& texture2D =
|
||||
textureUnit.GetBindingSlot(TextureTarget::Texture2D).GetBoundObject();
|
||||
@@ -7964,7 +7964,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
return PrgramImpl::ResolveProgramTwin(cso);
|
||||
}
|
||||
const auto& currentProgram = MGB_CTX->GetProgramForDraw();
|
||||
const auto& currentProgram = MG_Pipe::gPipeInputs.GetProgramForDraw();
|
||||
if (!currentProgram || !currentProgram->GetLinkStatus() || !currentProgram->GetSpirvStatus()) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -8034,7 +8034,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
return program->ReadsDrawID() || (batchCarriesBaseVertices && program->ReadsBaseVertex());
|
||||
}
|
||||
const auto& currentProgram = MGB_CTX->GetProgramForDraw();
|
||||
const auto& currentProgram = MG_Pipe::gPipeInputs.GetProgramForDraw();
|
||||
if (!currentProgram || program->GetSyncedLinkVersion() != currentProgram->GetLinkVersion()) {
|
||||
return true;
|
||||
}
|
||||
@@ -8141,12 +8141,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 (MGB_CTX->IsTransformFeedbackActive() ||
|
||||
MGB_CTX->IsCapabilityEnabled(CapabilityInput::RasterizerDiscard)) {
|
||||
if (MG_Pipe::gPipeInputs.IsTransformFeedbackActive() ||
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::RasterizerDiscard)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const auto& parameters = MGB_CTX->GetRenderStateParameters();
|
||||
const auto& parameters = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
Int surfaceWidth = 0;
|
||||
Int surfaceHeight = 0;
|
||||
if (!QueryCurrentSurfaceSize(surfaceWidth, surfaceHeight)) {
|
||||
@@ -8476,7 +8476,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// the 7 strict-lane entries of GetProgramForDispatch@DispatchCompute.
|
||||
const SharedPtr<MG_State::GLState::ProgramObject> noFrontendProgram;
|
||||
const auto& currentProgram =
|
||||
DrawProgramFromRecords() ? noFrontendProgram : MGB_CTX->GetProgramForDispatch();
|
||||
DrawProgramFromRecords() ? noFrontendProgram : MG_Pipe::gPipeInputs.GetProgramForDispatch();
|
||||
const TextureImpl::DrawTextureSyncKeys textureKeys = TextureImpl::CaptureDrawTextureSyncKeys();
|
||||
|
||||
BufferImpl::SyncComputeBuffers(includeDispatchIndirectBuffer);
|
||||
@@ -8528,12 +8528,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// P5f (fr): no declaration, dispatch-table slot or caller remains for this legacy
|
||||
// helper. Exclude it from the server-capable build; retain non-D-P bytes for G1.
|
||||
GLuint GetBackendProgramId(GLuint program) {
|
||||
if (!MGB_CTX->ValidateProgramName(program)) {
|
||||
if (!MG_Pipe::gPipeInputs.ValidateProgramName(program)) {
|
||||
MGLOG_E_ONCE("Invalid frontend program object: %u", program);
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto& programObject = MGB_CTX->GetProgramObject(program);
|
||||
auto& programObject = MG_Pipe::gPipeInputs.GetProgramObject(program);
|
||||
if (!programObject) {
|
||||
MGLOG_E_ONCE("Program object %u is null.", program);
|
||||
return 0;
|
||||
@@ -8602,7 +8602,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 = MGB_CTX->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
|
||||
@@ -8679,7 +8679,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#endif
|
||||
{
|
||||
const auto& feFbo =
|
||||
MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
if (feFbo) {
|
||||
feIdx = feFbo->GetExternalIndex();
|
||||
feVer = feFbo->GetObjectVersion();
|
||||
@@ -8869,7 +8869,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
const SharedPtr<MG_State::GLState::BufferObject>& BoundElementArrayBuffer() {
|
||||
static const SharedPtr<MG_State::GLState::BufferObject> none;
|
||||
RefuseElementArrayBufferFromTheFrontend("BoundElementArrayBuffer");
|
||||
const auto& vao = MGB_CTX->GetBoundVertexArray();
|
||||
const auto& vao = MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
if (!vao) return none;
|
||||
return vao->GetIndexBufferBindingSlot().GetBoundObject();
|
||||
}
|
||||
@@ -8886,13 +8886,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
} // namespace
|
||||
|
||||
RestartSubstitutionKind ResolveRestartSubstitution(GLenum indexType) {
|
||||
if (!MGB_CTX->IsCapabilityEnabled(CapabilityInput::PrimitiveRestart) ||
|
||||
MGB_CTX->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 = MGB_CTX->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
|
||||
@@ -8932,7 +8932,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
const SizeT sourceIndexSize = MG_Util::GetGLTypeSize(indexType);
|
||||
const Uint32 fixedMax = MG_Util::FixedRestartIndexForGLType(indexType);
|
||||
const Uint32 applicationRestartIndex = MGB_CTX->GetPrimitiveRestartIndex();
|
||||
const Uint32 applicationRestartIndex = MG_Pipe::gPipeInputs.GetPrimitiveRestartIndex();
|
||||
|
||||
const Uint8* source = nullptr;
|
||||
SizeT indexCount = 0;
|
||||
@@ -9258,7 +9258,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
? SharedPtr<MG_State::GLState::BufferObject>(nullptr)
|
||||
:
|
||||
#endif
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
ExecuteIndexedIndirectCommands(mode, type, indexSize, commandBytes, reinterpret_cast<SizeT>(indirect),
|
||||
drawIndirectBuffer, drawcount, stride, "MultiDrawElementsIndirect");
|
||||
}
|
||||
@@ -9348,8 +9348,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
#endif
|
||||
|
||||
auto drawBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
auto parameterBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::Parameter).GetBoundObject();
|
||||
auto drawBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
auto parameterBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::Parameter).GetBoundObject();
|
||||
if (!drawBuffer) {
|
||||
MGLOG_E_ONCE("MultiDrawElementsIndirectCount skipped: no GL_DRAW_INDIRECT_BUFFER is bound");
|
||||
return;
|
||||
@@ -9427,7 +9427,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
? SharedPtr<MG_State::GLState::BufferObject>(nullptr)
|
||||
:
|
||||
#endif
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
ExecuteArraysIndirectCommands(mode, commandBytes, reinterpret_cast<SizeT>(indirect), drawIndirectBuffer,
|
||||
drawcount, stride, "MultiDrawArraysIndirect");
|
||||
}
|
||||
@@ -9512,8 +9512,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
#endif
|
||||
|
||||
auto drawBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
auto parameterBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::Parameter).GetBoundObject();
|
||||
auto drawBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
auto parameterBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::Parameter).GetBoundObject();
|
||||
if (!drawBuffer) {
|
||||
MGLOG_E_ONCE("MultiDrawArraysIndirectCount skipped: no GL_DRAW_INDIRECT_BUFFER is bound");
|
||||
return;
|
||||
@@ -9698,7 +9698,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
? SharedPtr<MG_State::GLState::BufferObject>(nullptr)
|
||||
:
|
||||
#endif
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
ExecuteIndexedIndirectCommands(mode, type, indexSize, commandBytes, reinterpret_cast<SizeT>(indirect),
|
||||
drawIndirectBuffer, 1, sizeof(DrawElementsIndirectCommand),
|
||||
"DrawElementsIndirect");
|
||||
@@ -9747,7 +9747,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
? SharedPtr<MG_State::GLState::BufferObject>(nullptr)
|
||||
:
|
||||
#endif
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
ExecuteArraysIndirectCommands(mode, commandBytes, reinterpret_cast<SizeT>(indirect), drawIndirectBuffer, 1,
|
||||
sizeof(DrawArraysIndirectCommand), "DrawArraysIndirect");
|
||||
}
|
||||
@@ -9995,8 +9995,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// restore. Drop the flag so it is not misattributed to the emulation's own work.
|
||||
DrainBlitErrors();
|
||||
|
||||
if (MGB_CTX->IsTransformFeedbackActive() &&
|
||||
!MGB_CTX->IsTransformFeedbackPaused() && g_GLESFuncs.glPauseTransformFeedback) {
|
||||
if (MG_Pipe::gPipeInputs.IsTransformFeedbackActive() &&
|
||||
!MG_Pipe::gPipeInputs.IsTransformFeedbackPaused() && g_GLESFuncs.glPauseTransformFeedback) {
|
||||
g_GLESFuncs.glPauseTransformFeedback();
|
||||
m_pausedTransformFeedback = true;
|
||||
DrainBlitErrors();
|
||||
@@ -11055,8 +11055,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
} else
|
||||
#endif
|
||||
mask &= ~BlitLayeredDestinationAspects(
|
||||
MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject(),
|
||||
MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(), srcX0, srcY0,
|
||||
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject(),
|
||||
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(), srcX0, srcY0,
|
||||
srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask);
|
||||
if (mask != 0) {
|
||||
IssueBlitWithResolveFallback(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
||||
@@ -11118,9 +11118,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#ifdef TRACY_ENABLE
|
||||
ZoneScopedNC(__func__, TRACY_ZONECOLOR_BACKEND);
|
||||
#endif
|
||||
auto unit = MGB_CTX->GetActiveTextureUnit();
|
||||
auto unit = MG_Pipe::gPipeInputs.GetActiveTextureUnit();
|
||||
#if !MOBILEGL_BUILD_DISAGGREGATED
|
||||
auto& textureUnit = MGB_CTX->GetTextureUnitObject(unit);
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit);
|
||||
#endif
|
||||
|
||||
auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
||||
@@ -11154,7 +11154,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
#endif
|
||||
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
auto& textureUnit = MGB_CTX->GetTextureUnitObject(unit);
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit);
|
||||
#endif
|
||||
const auto& bindingSlot = textureUnit.GetBindingSlot(textureTarget);
|
||||
{
|
||||
@@ -11224,7 +11224,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 = MGB_CTX->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)};
|
||||
}
|
||||
@@ -11497,7 +11497,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Util::ConvertGLEnumToString(err).c_str(),
|
||||
MG_Util::ConvertGLEnumToString(target).c_str(),
|
||||
MG_Util::ConvertTextureInternalFormatToString(format).c_str());
|
||||
MGB_CTX->RecordError(
|
||||
MG_Pipe::gPipeInputs.RecordError(
|
||||
ConvertGLESErrorToErrorCode(err),
|
||||
MakeUnique<GenericErrorInfo>("DirectGLES", operation,
|
||||
MG_Util::ConvertGLEnumToString(err)));
|
||||
@@ -12316,7 +12316,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
// Bind necessary FBO and texture
|
||||
BindCurrentFBO(FramebufferTarget::Read);
|
||||
Uint activeTextureUnit = MGB_CTX->GetActiveTextureUnit();
|
||||
Uint activeTextureUnit = MG_Pipe::gPipeInputs.GetActiveTextureUnit();
|
||||
TextureImpl::BackendTextureObject* dstBackendTexture = nullptr;
|
||||
TextureInternalFormat mgInternalFormat{};
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
@@ -12346,7 +12346,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
const auto& textureObject = MGB_CTX->GetTextureUnitObject((Int)activeTextureUnit)
|
||||
const auto& textureObject = MG_Pipe::gPipeInputs.GetTextureUnitObject((Int)activeTextureUnit)
|
||||
.GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target))
|
||||
.GetBoundObject();
|
||||
if (textureObject) TextureImpl::NoteDriverSideTextureWrite(textureObject);
|
||||
@@ -12443,7 +12443,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
// Bind necessary FBO and texture
|
||||
BindCurrentFBO(FramebufferTarget::Read);
|
||||
auto activeTextureUnit = MGB_CTX->GetActiveTextureUnit();
|
||||
auto activeTextureUnit = MG_Pipe::gPipeInputs.GetActiveTextureUnit();
|
||||
TextureImpl::BackendTextureObject* dstBackendTexture = nullptr;
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
// P5c (hd, CONTRACT-P5C §3.4): see CopyTexImage2D - the record's Dst handle, never the
|
||||
@@ -12464,7 +12464,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
const auto& textureObject = MGB_CTX->GetTextureUnitObject(activeTextureUnit)
|
||||
const auto& textureObject = MG_Pipe::gPipeInputs.GetTextureUnitObject(activeTextureUnit)
|
||||
.GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target))
|
||||
.GetBoundObject();
|
||||
if (textureObject) TextureImpl::NoteDriverSideTextureWrite(textureObject);
|
||||
@@ -12910,8 +12910,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
auto unitIndex = MGB_CTX->GetActiveTextureUnit();
|
||||
auto& unit = MGB_CTX->GetTextureUnitObject(unitIndex);
|
||||
auto unitIndex = MG_Pipe::gPipeInputs.GetActiveTextureUnit();
|
||||
auto& unit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unitIndex);
|
||||
auto& slot = unit.GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target));
|
||||
auto& texture = slot.GetBoundObject();
|
||||
MOBILEGL_ASSERT(texture != nullptr, "GenerateMipmap requires a bound texture.");
|
||||
@@ -13450,8 +13450,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (!MGB_CTX->ValidateProgramName(program)) return;
|
||||
auto& programObject = MGB_CTX->GetProgramObject(program);
|
||||
if (!MG_Pipe::gPipeInputs.ValidateProgramName(program)) return;
|
||||
auto& programObject = MG_Pipe::gPipeInputs.GetProgramObject(program);
|
||||
if (!programObject) return;
|
||||
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
@@ -13652,7 +13652,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 = MGB_CTX->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 +
|
||||
@@ -13664,7 +13664,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Config::Transport != MG_Config::TransportMode::Monolith
|
||||
? SplitReadbackPackBuffer() :
|
||||
#endif
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
const SizeT pboOffset = reinterpret_cast<SizeT>(pixels);
|
||||
if (pixelPackBufferObject && pboOffset + packedSize > pixelPackBufferObject->GetSize()) {
|
||||
MGLOG_E_ONCE("ReadPixels: %s readback PBO is too small", what);
|
||||
@@ -14685,7 +14685,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Config::Transport != MG_Config::TransportMode::Monolith
|
||||
? SplitReadbackPackBuffer() :
|
||||
#endif
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
if (!pixelPackBufferObject && pixels == nullptr) {
|
||||
return true;
|
||||
}
|
||||
@@ -14941,7 +14941,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
"active transport there is no client shadow to fall back to - the read is "
|
||||
"DECLINED and the destination keeps its bytes",
|
||||
static_cast<unsigned>(uploadTarget), level);
|
||||
MGB_CTX->RecordError(
|
||||
MG_Pipe::gPipeInputs.RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>(
|
||||
"DirectGLES", "GetTexImage",
|
||||
@@ -14956,7 +14956,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Config::Transport != MG_Config::TransportMode::Monolith
|
||||
? SplitReadbackPackBuffer() :
|
||||
#endif
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
if (!pixelPackBufferObject && pixels == nullptr) {
|
||||
return true;
|
||||
}
|
||||
@@ -15232,7 +15232,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 = MGB_CTX->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();
|
||||
@@ -15279,7 +15279,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Config::Transport != MG_Config::TransportMode::Monolith
|
||||
? SplitReadbackPackBuffer() :
|
||||
#endif
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
Bool usePBO = false;
|
||||
GLuint packBufferId = 0;
|
||||
if (pixelPackBufferObject) {
|
||||
@@ -15389,10 +15389,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MGLOG_D("GetTexImage: SyncCurrentFBO()");
|
||||
FramebufferImpl::SyncCurrentFBO();
|
||||
|
||||
auto activeTextureUnit = MGB_CTX->GetActiveTextureUnit();
|
||||
auto activeTextureUnit = MG_Pipe::gPipeInputs.GetActiveTextureUnit();
|
||||
MGLOG_D("GetTexImage: active texture unit = %u", activeTextureUnit);
|
||||
|
||||
const auto& textureObject = MGB_CTX->GetTextureUnitObject(activeTextureUnit)
|
||||
const auto& textureObject = MG_Pipe::gPipeInputs.GetTextureUnitObject(activeTextureUnit)
|
||||
.GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target))
|
||||
.GetBoundObject();
|
||||
|
||||
@@ -15625,7 +15625,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// Each slice is packed as its own 2D image, so the per-slice call must not apply
|
||||
// GL_PACK_SKIP_IMAGES / GL_PACK_IMAGE_HEIGHT itself - this walks the destination
|
||||
// over them, using the same layout StoreWideRowsToClient computes.
|
||||
const auto packParams = MGB_CTX->GetPixelStoreParameters(false);
|
||||
const auto packParams = MG_Pipe::gPipeInputs.GetPixelStoreParameters(false);
|
||||
const SizeT dstPixelBytes = GetReadbackDstPixelSize(conversionMapping, type);
|
||||
const SizeT rowPixels =
|
||||
static_cast<SizeT>(packParams.RowLength > 0 ? packParams.RowLength : size.x());
|
||||
@@ -15726,7 +15726,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Config::Transport != MG_Config::TransportMode::Monolith
|
||||
? SplitReadbackPackBuffer() :
|
||||
#endif
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
Bool usePBO = false;
|
||||
GLuint packBufferId = 0;
|
||||
if (pixelPackBufferObject) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
// End of Source File Header
|
||||
|
||||
#include "Managers.h"
|
||||
#include <MG_Pipe/PipeInputsSwitch.h>
|
||||
#include <MG_Backend/MGPipe/PipeInputs.h>
|
||||
// P3a: the handle-shaped resource op table, the applier's records and the reverse channel.
|
||||
// Both headers are compiled into the library only under push, so they are included here
|
||||
// under the same condition - a pull build must gain no declaration it cannot link.
|
||||
@@ -7767,9 +7767,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 (MGB_CTX_LIVE) {
|
||||
m_syncedShapeContextId = MGB_CTX->GetTextureContextId();
|
||||
m_syncedShapeGeneration = MGB_CTX->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();
|
||||
@@ -8453,9 +8453,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 && MGB_CTX_LIVE &&
|
||||
m_syncedShapeContextId == MGB_CTX->GetTextureContextId() &&
|
||||
m_syncedShapeGeneration == MGB_CTX->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) {
|
||||
@@ -8573,9 +8573,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 (MGB_CTX_LIVE) {
|
||||
m_syncedShapeContextId = MGB_CTX->GetTextureContextId();
|
||||
m_syncedShapeGeneration = MGB_CTX->GetSamplingResolutionGeneration();
|
||||
if (MG_Pipe::gPipeInputs.IsLive()) {
|
||||
m_syncedShapeContextId = MG_Pipe::gPipeInputs.GetTextureContextId();
|
||||
m_syncedShapeGeneration = MG_Pipe::gPipeInputs.GetSamplingResolutionGeneration();
|
||||
m_syncedShapeParamsVersion = stateTextureObject->GetTextureParamsVersion();
|
||||
}
|
||||
return;
|
||||
@@ -9878,9 +9878,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 (MGB_CTX_LIVE && stateTextureObject->GetStorageType() == TextureStorageType::Mipmap) {
|
||||
m_syncedShapeContextId = MGB_CTX->GetTextureContextId();
|
||||
m_syncedShapeGeneration = MGB_CTX->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;
|
||||
@@ -10895,7 +10895,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// read buffer names no colour attachment at all.
|
||||
static const MG_State::GLState::FramebufferAttachmentObject* GetReadColorAttachment() {
|
||||
const auto& readFBO =
|
||||
MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||
if (!readFBO) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -11306,7 +11306,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
#endif
|
||||
const auto& readFBO =
|
||||
MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||
if (!readFBO) {
|
||||
return false;
|
||||
}
|
||||
@@ -12969,7 +12969,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return static_cast<Uint>(st.BoundShaderImages[static_cast<SizeT>(unit)].InternalFormat);
|
||||
}
|
||||
#endif
|
||||
return static_cast<Uint>(MGB_CTX->GetImageTextureBinding(unit).Format);
|
||||
return static_cast<Uint>(MG_Pipe::gPipeInputs.GetImageTextureBinding(unit).Format);
|
||||
}
|
||||
|
||||
// Combines one (unit, format) pair into a running digest. Commutative, so the order
|
||||
@@ -13932,19 +13932,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 = MGB_CTX_LIVE
|
||||
? MGB_CTX->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 = MGB_CTX_LIVE
|
||||
? MGB_CTX->GetPatchDefaultOuterLevel()
|
||||
m_passthroughTessControlOuterLevel = MG_Pipe::gPipeInputs.IsLive()
|
||||
? MG_Pipe::gPipeInputs.GetPatchDefaultOuterLevel()
|
||||
: FloatVec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
m_passthroughTessControlInnerLevel = MGB_CTX_LIVE
|
||||
? MGB_CTX->GetPatchDefaultInnerLevel()
|
||||
m_passthroughTessControlInnerLevel = MG_Pipe::gPipeInputs.IsLive()
|
||||
? MG_Pipe::gPipeInputs.GetPatchDefaultInnerLevel()
|
||||
: FloatVec2(1.0f, 1.0f);
|
||||
|
||||
if (tessEvalShaderIndex < 0 ||
|
||||
@@ -15777,8 +15777,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MGLOG_E_ONCE("Renderbuffer %u storage allocation ran out of memory: %dx%d, samples=%d, format=%s",
|
||||
stateRBOObject->GetExternalIndex(), width, height, samples,
|
||||
MG_Util::ConvertGLEnumToString(glInternalFormat).c_str());
|
||||
if (MGB_CTX_LIVE) {
|
||||
MGB_CTX->RecordError(
|
||||
if (MG_Pipe::gPipeInputs.IsLive()) {
|
||||
MG_Pipe::gPipeInputs.RecordError(
|
||||
ErrorCode::OutOfMemory,
|
||||
MakeUnique<GenericErrorInfo>("DirectGLES", "BackendRenderbufferObject::SyncToBackend",
|
||||
"The ES driver could not allocate the renderbuffer storage."));
|
||||
@@ -15868,7 +15868,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Util::ConvertGLEnumToString(glInternalFormat).c_str());
|
||||
// NO RecordError HERE. The object form reports the OOM to the application
|
||||
// through the live GLContext; on this arm there is no application on this side
|
||||
// of the wire to report it to, and MGB_CTX->RecordError is itself one of the
|
||||
// of the wire to report it to, and gPipeInputs->RecordError is itself one of the
|
||||
// BARRIER-PULLED rows (FieldOwnership.def) that rule F forbids an unbarriered
|
||||
// apply to touch. The client raises its own errors from its own validator.
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "MultiDraw.h"
|
||||
#include "Managers.h"
|
||||
#include <MG_State/GLState/Core.h>
|
||||
#include <MG_Pipe/PipeInputsSwitch.h>
|
||||
#include <MG_Backend/MGPipe/PipeInputs.h>
|
||||
#include <MG_Util/Metrics/PipeStats.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
@@ -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 MGB_CTX->GetPrimitiveRestartIndex();
|
||||
return MG_Pipe::gPipeInputs.GetPrimitiveRestartIndex();
|
||||
}
|
||||
return MG_Util::FixedRestartIndexForGLType(type);
|
||||
}
|
||||
|
||||
Bool RestartActive() {
|
||||
return MGB_CTX->IsCapabilityEnabled(CapabilityInput::PrimitiveRestart) ||
|
||||
MGB_CTX->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
|
||||
@@ -95,7 +95,7 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl {
|
||||
// PrepareForDraw leave on GL_ELEMENT_ARRAY_BUFFER (and how big is its store)", and
|
||||
// "give me its bytes on the CPU" - and until now it asked all three of the FRONTEND
|
||||
// VAO, on the apply thread, once per indexed multi-draw. That was the last unguarded
|
||||
// `MGB_CTX->GetBoundVertexArray()` in the backend: package vi retired the ordinary
|
||||
// `gPipeInputs->GetBoundVertexArray()` in the backend: package vi retired the ordinary
|
||||
// draw path's copy (DirectGLES.cpp's SyncCurrentVertexAttributeValues / PrepareForDraw)
|
||||
// and this one survived only because these batches used to die earlier, on the
|
||||
// framebuffer row fb has since retired.
|
||||
@@ -221,7 +221,7 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl {
|
||||
}
|
||||
#endif
|
||||
// MONOLITH GLUE from here down, token for token what each call site did before.
|
||||
const auto& vao = MGB_CTX->GetBoundVertexArray();
|
||||
const auto& vao = MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
if (!vao) return view;
|
||||
const auto& ibo = vao->GetIndexBufferBindingSlot().GetBoundObject();
|
||||
if (!ibo) return view;
|
||||
@@ -269,7 +269,7 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl {
|
||||
//
|
||||
// This was the LAST unguarded frontend read on the multi-draw apply path, and it sat
|
||||
// twenty lines above the function that retired its neighbour. It asked
|
||||
// `MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect)` and then
|
||||
// `gPipeInputs->GetBufferBindingSlot(BufferTarget::DrawIndirect)` and then
|
||||
// `EnsureBufferResource(<frontend object>)` - a registry lookup keyed by the client's
|
||||
// identity, which is §4.4's rule and not only the allocator's. Under run-ahead that is
|
||||
// `Fatal{UnmigratedPipeInput, "GetBufferBindingSlot@DrawArrays"}` on every batch the
|
||||
@@ -306,7 +306,7 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl {
|
||||
#endif
|
||||
// MONOLITH GLUE from here down, token for token what this function did before.
|
||||
const auto& indirect =
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (!indirect) return 0;
|
||||
const auto* resource = BufferImpl::EnsureBufferResource(indirect);
|
||||
return resource ? resource->id : 0;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <Config.h>
|
||||
|
||||
#include <MG_State/GLState/Core.h>
|
||||
#include <MG_Pipe/PipeInputsSwitch.h>
|
||||
#include <MG_Backend/MGPipe/PipeInputs.h>
|
||||
#include <MG_Util/BackendLoaders/OpenGL/Loader.h>
|
||||
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
|
||||
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
|
||||
@@ -2366,11 +2366,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MG_Config::Transport != MG_Config::TransportMode::Monolith
|
||||
? SplitReadbackPackBuffer() :
|
||||
#endif
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
|
||||
// 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 = MGB_CTX->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 =
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "SubgroupSupportPolicy.h"
|
||||
#include "MG_State/GLState/FramebufferState/FramebufferObject.h"
|
||||
#include "MG_State/GLState/Core.h"
|
||||
#include <MG_Pipe/PipeInputsSwitch.h>
|
||||
#include <MG_Backend/MGPipe/PipeInputs.h>
|
||||
#include "MG_State/GLState/TextureState/TextureState.h"
|
||||
#include "MG_Util/Classifiers/TextureEnumClassifier.h"
|
||||
#include "MG_Util/Converters/MGToGL/TextureEnumConverter.h"
|
||||
@@ -462,8 +462,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
UpdateDynamicBackendParameters();
|
||||
UpdateAdvertisedExtensions();
|
||||
if (MGB_CTX_LIVE) {
|
||||
MGB_CTX->InvalidateCompileEnv();
|
||||
if (MG_Pipe::gPipeInputs.IsLive()) {
|
||||
MG_Pipe::gPipeInputs.InvalidateCompileEnv();
|
||||
}
|
||||
PopulateFormatCapabilities(physicalDevice.handle, vkGetPhysicalDeviceFormatProperties, m_vulkanCaps,
|
||||
MutableFormatCapabilities());
|
||||
@@ -1079,8 +1079,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
m_vulkanCaps = capabilities;
|
||||
UpdateDynamicBackendParameters();
|
||||
UpdateAdvertisedExtensions();
|
||||
if (MGB_CTX_LIVE) {
|
||||
MGB_CTX->InvalidateCompileEnv();
|
||||
if (MG_Pipe::gPipeInputs.IsLive()) {
|
||||
MG_Pipe::gPipeInputs.InvalidateCompileEnv();
|
||||
}
|
||||
MutableFormatCapabilities().Clear();
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "DirectVulkanResourceState.h"
|
||||
#include "MG_Backend/BackendObjects.h"
|
||||
#include "MG_State/GLState/Core.h"
|
||||
#include <MG_Pipe/PipeInputsSwitch.h>
|
||||
#include <MG_Backend/MGPipe/PipeInputs.h>
|
||||
#include "MG_State/GLState/ErrorState/ErrorInfo.h"
|
||||
#include "MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h"
|
||||
#include "MG_Util/Converters/GLToMG/TextureEnumConverter.h"
|
||||
@@ -459,15 +459,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
#endif
|
||||
|
||||
MG_State::GLState::ProgramObject* TryGetDirectVulkanProgram(GLuint program) {
|
||||
if (!MGB_CTX->ValidateProgramName(program)) {
|
||||
if (!MG_Pipe::gPipeInputs.ValidateProgramName(program)) {
|
||||
return nullptr;
|
||||
}
|
||||
auto& programObject = MGB_CTX->GetProgramObject(program);
|
||||
auto& programObject = MG_Pipe::gPipeInputs.GetProgramObject(program);
|
||||
return programObject.get();
|
||||
}
|
||||
|
||||
const Uint8* ResolveIndirectCommandBytes(const void* indirect, SizeT requiredBytes, const char* label) {
|
||||
auto drawBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
auto drawBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (drawBuffer) {
|
||||
drawBuffer->SyncPersistentMappedRange();
|
||||
// A command block a compute shader wrote is the case this whole shape exists
|
||||
@@ -595,53 +595,53 @@ 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(MGB_CTX_LIVE, "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(MGB_CTX_LIVE, "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(MGB_CTX_LIVE, "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(MGB_CTX_LIVE, "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);
|
||||
}
|
||||
|
||||
void ClearNamedFramebufferfv(const SharedPtr<MG_State::GLState::FramebufferObject>& framebuffer, GLenum buffer,
|
||||
GLint drawbuffer, const GLfloat* value) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ClearNamedFramebufferfv called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::ClearNamedFramebufferfv called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::ClearNamedFramebufferfv called with null GL context");
|
||||
pVulkanRenderer->ClearNamedFramebufferfv(framebuffer, buffer, drawbuffer, value);
|
||||
}
|
||||
|
||||
void ClearNamedFramebufferiv(const SharedPtr<MG_State::GLState::FramebufferObject>& framebuffer, GLenum buffer,
|
||||
GLint drawbuffer, const GLint* value) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ClearNamedFramebufferiv called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::ClearNamedFramebufferiv called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::ClearNamedFramebufferiv called with null GL context");
|
||||
pVulkanRenderer->ClearNamedFramebufferiv(framebuffer, buffer, drawbuffer, value);
|
||||
}
|
||||
|
||||
void ClearNamedFramebufferuiv(const SharedPtr<MG_State::GLState::FramebufferObject>& framebuffer, GLenum buffer,
|
||||
GLint drawbuffer, const GLuint* value) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ClearNamedFramebufferuiv called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::ClearNamedFramebufferuiv called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::ClearNamedFramebufferuiv called with null GL context");
|
||||
pVulkanRenderer->ClearNamedFramebufferuiv(framebuffer, buffer, drawbuffer, value);
|
||||
}
|
||||
|
||||
void ClearNamedFramebufferfi(const SharedPtr<MG_State::GLState::FramebufferObject>& framebuffer, GLenum buffer,
|
||||
GLint drawbuffer, GLfloat depth, GLint stencil) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ClearNamedFramebufferfi called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::ClearNamedFramebufferfi called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::ClearNamedFramebufferfi called with null GL context");
|
||||
pVulkanRenderer->ClearNamedFramebufferfi(framebuffer, buffer, drawbuffer, depth, stencil);
|
||||
}
|
||||
|
||||
@@ -653,7 +653,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
#endif
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElementsIndirect called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::MultiDrawElementsIndirect called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MultiDrawElementsIndirect called with null GL context");
|
||||
pVulkanRenderer->MultiDrawElementsIndirect(mode, type, indirect, drawcount, stride);
|
||||
}
|
||||
void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) {
|
||||
@@ -664,7 +664,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
#endif
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawArraysIndirect called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::MultiDrawArraysIndirect called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MultiDrawArraysIndirect called with null GL context");
|
||||
|
||||
if (drawcount <= 0) {
|
||||
return;
|
||||
@@ -672,7 +672,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
// With a bound GL_DRAW_INDIRECT_BUFFER the command parameters may be GPU-written
|
||||
// (e.g. by a compute shader), so consume them natively on the GPU.
|
||||
auto drawBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
auto drawBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (drawBuffer) {
|
||||
pVulkanRenderer->MultiDrawArraysIndirect(mode, indirect, drawcount, stride);
|
||||
return;
|
||||
@@ -721,7 +721,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
#endif
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElementsIndirectCount called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::MultiDrawElementsIndirectCount called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MultiDrawElementsIndirectCount called with null GL context");
|
||||
pVulkanRenderer->MultiDrawElementsIndirectCount(mode, type, indirect, drawcount, maxdrawcount, stride);
|
||||
}
|
||||
void MultiDrawArraysIndirectCount(GLenum mode, const void* indirect, GLintptr drawcount,
|
||||
@@ -733,7 +733,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
#endif
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawArraysIndirectCount called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::MultiDrawArraysIndirectCount called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MultiDrawArraysIndirectCount called with null GL context");
|
||||
|
||||
if (maxdrawcount <= 0) {
|
||||
return;
|
||||
@@ -747,7 +747,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return;
|
||||
}
|
||||
|
||||
auto parameterBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::Parameter).GetBoundObject();
|
||||
auto parameterBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::Parameter).GetBoundObject();
|
||||
if (!parameterBuffer || drawcount < 0 || static_cast<SizeT>(drawcount) + sizeof(Uint32) > parameterBuffer->GetSize()) {
|
||||
MGLOG_E_ONCE("MultiDrawArraysIndirectCount skipped: invalid GL_PARAMETER_BUFFER binding or range");
|
||||
return;
|
||||
@@ -778,7 +778,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(MGB_CTX_LIVE, "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;
|
||||
@@ -811,7 +811,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
#endif
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElementsIndirect called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::DrawElementsIndirect called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::DrawElementsIndirect called with null GL context");
|
||||
|
||||
const SizeT indexSize = MG_Util::GetGLTypeSize(type);
|
||||
if (indexSize == 0) {
|
||||
@@ -821,7 +821,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
// With a bound GL_DRAW_INDIRECT_BUFFER the command parameters may be GPU-written
|
||||
// (e.g. by a compute shader), so consume them natively on the GPU.
|
||||
auto drawBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
auto drawBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (drawBuffer) {
|
||||
pVulkanRenderer->MultiDrawElementsIndirect(mode, type, indirect, 1, 0);
|
||||
return;
|
||||
@@ -855,7 +855,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(MGB_CTX_LIVE, "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;
|
||||
@@ -876,11 +876,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
#endif
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArraysIndirect called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::DrawArraysIndirect called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::DrawArraysIndirect called with null GL context");
|
||||
|
||||
// With a bound GL_DRAW_INDIRECT_BUFFER the command parameters may be GPU-written
|
||||
// (e.g. by a compute shader), so consume them natively on the GPU.
|
||||
auto drawBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
auto drawBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (drawBuffer) {
|
||||
pVulkanRenderer->MultiDrawArraysIndirect(mode, indirect, 1, 0);
|
||||
return;
|
||||
@@ -910,13 +910,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(MGB_CTX_LIVE, "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(MGB_CTX_LIVE, "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,
|
||||
@@ -925,20 +925,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(MGB_CTX_LIVE, "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(MGB_CTX_LIVE, "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(MGB_CTX_LIVE, "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);
|
||||
}
|
||||
|
||||
@@ -954,13 +954,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
#endif
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DispatchComputeIndirect called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::DispatchComputeIndirect called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::DispatchComputeIndirect called with null GL context");
|
||||
pVulkanRenderer->DispatchComputeIndirect(indirect);
|
||||
}
|
||||
|
||||
void MemoryBarrier(GLbitfield barriers) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MemoryBarrier called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::MemoryBarrier called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MemoryBarrier called with null GL context");
|
||||
pVulkanRenderer->MemoryBarrier(barriers);
|
||||
}
|
||||
|
||||
@@ -1053,7 +1053,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
? pActiveBackendObject->GetDynamicParameters().MaxShaderStorageBufferBindings
|
||||
: 0;
|
||||
if (storageBlockBinding >= static_cast<GLuint>(maxBindings)) {
|
||||
MGB_CTX->RecordError(
|
||||
MG_Pipe::gPipeInputs.RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("DirectVulkan", __func__, "Shader storage binding is out of range."));
|
||||
return;
|
||||
@@ -1100,24 +1100,24 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
#endif
|
||||
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(MGB_CTX_LIVE, "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 GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::GetTexImage called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::GetTexImage called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::GetTexImage called with null GL context");
|
||||
pVulkanRenderer->GetTexImage(target, level, format, type, pixels);
|
||||
}
|
||||
void GetTextureImage(const SharedPtr<MG_State::GLState::ITextureObject>& texture, TextureUploadTarget uploadTarget,
|
||||
GLint level, GLenum format, GLenum type, GLsizei bufSize, GLvoid* pixels) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::GetTextureImage called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::GetTextureImage called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::GetTextureImage called with null GL context");
|
||||
pVulkanRenderer->GetTextureImage(texture, uploadTarget, level, format, type, bufSize, pixels);
|
||||
}
|
||||
|
||||
void Clear(GLbitfield mask) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::Clear called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::Clear called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::Clear called with null GL context");
|
||||
pVulkanRenderer->Clear(mask);
|
||||
}
|
||||
|
||||
@@ -1169,7 +1169,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return false;
|
||||
}
|
||||
const Uint8* indexBytes = nullptr;
|
||||
const auto& vao = *MGB_CTX->GetBoundVertexArray();
|
||||
const auto& vao = *MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
const auto& indexBufferShared = vao.GetIndexBufferBindingSlot().GetBoundObject();
|
||||
if (indexBufferShared != nullptr) {
|
||||
const SizeT offset = reinterpret_cast<SizeT>(indices);
|
||||
@@ -1200,7 +1200,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(MGB_CTX_LIVE, "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) {
|
||||
@@ -1225,7 +1225,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(MGB_CTX_LIVE, "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;
|
||||
@@ -1250,7 +1250,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// the next vkCmd* records into a command buffer that is no longer the frame's. Reconciling
|
||||
// HERE, before SetupDraw starts recording, keeps the wait out of the recording.
|
||||
if (MG_Config::Transport == MG_Config::TransportMode::Monolith) {
|
||||
const auto& currentVAO = MGB_CTX->GetBoundVertexArray();
|
||||
const auto& currentVAO = MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
Bool clientArray = false;
|
||||
if (currentVAO) {
|
||||
for (const auto& attribute : currentVAO->GetAllAttributes()) {
|
||||
@@ -1272,7 +1272,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(MGB_CTX_LIVE, "DirectVulkan::MultiDrawArrays called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MultiDrawArrays called with null GL context");
|
||||
if (drawcount <= 0) {
|
||||
return;
|
||||
}
|
||||
@@ -1321,10 +1321,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
const Bool noIndexBuffer = MG_Config::Transport != MG_Config::TransportMode::Monolith
|
||||
? MG_Pipe::MGPipeHandleIsNull(MG_Pipe::MGPipeApplier().IndexBuffer.Res)
|
||||
: MGB_CTX->GetBoundVertexArray()->GetIndexBufferBindingSlot().GetBoundObject() == nullptr;
|
||||
: MG_Pipe::gPipeInputs.GetBoundVertexArray()->GetIndexBufferBindingSlot().GetBoundObject() == nullptr;
|
||||
if (noIndexBuffer) {
|
||||
#else
|
||||
const auto& vao = *MGB_CTX->GetBoundVertexArray();
|
||||
const auto& vao = *MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
if (vao.GetIndexBufferBindingSlot().GetBoundObject() == nullptr) {
|
||||
#endif
|
||||
for (GLsizei i = 0; i < drawcount; ++i) {
|
||||
@@ -1386,13 +1386,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
void MultiDrawElements(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices,
|
||||
GLsizei drawcount) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElements called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "DirectVulkan::MultiDrawElements called with null GL context");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "DirectVulkan::MultiDrawElements called with null GL context");
|
||||
MultiDrawElementsImpl(mode, count, type, indices, drawcount, nullptr);
|
||||
}
|
||||
|
||||
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLint basevertex) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElementsBaseVertex called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "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)) {
|
||||
@@ -1416,14 +1416,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(MGB_CTX_LIVE, "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(MGB_CTX_LIVE, "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);
|
||||
}
|
||||
|
||||
@@ -1660,8 +1660,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
MG_Config::Transport == MG_Config::TransportMode::Monolith &&
|
||||
#endif
|
||||
MGB_CTX_LIVE) {
|
||||
primitives += MGB_CTX->GetTransformFeedbackPausedPrimitiveCounter() -
|
||||
MG_Pipe::gPipeInputs.IsLive()) {
|
||||
primitives += MG_Pipe::gPipeInputs.GetTransformFeedbackPausedPrimitiveCounter() -
|
||||
query->pausedPrimitiveSnapshot;
|
||||
}
|
||||
*outNanoseconds = primitives;
|
||||
@@ -1711,7 +1711,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
MG_Config::Transport == MG_Config::TransportMode::Monolith &&
|
||||
#endif
|
||||
MGB_CTX_LIVE ? MGB_CTX->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();
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "MG_Backend/DirectVulkan/DirectVulkanResourceState.h"
|
||||
#include "MG_State/GLState/Core.h"
|
||||
#include <MG_Pipe/PipeInputsSwitch.h>
|
||||
#include <MG_Backend/MGPipe/PipeInputs.h>
|
||||
// P5c ev: the GPU-write announcement routes through the reverse channel (R2).
|
||||
#include <MG_Impl/Pipe/ResourceTracker.h>
|
||||
#include "MG_State/GLState/ProgramState/ProgramObject.h"
|
||||
@@ -946,7 +946,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// alive through the draw via GL binding state. Only the fallback path needs a SharedPtr to
|
||||
// keep the fallback texture alive for the rest of this call.
|
||||
MG_State::GLState::ITextureObject* texture = ResolveSamplerTextureRaw(program, programObj, binding, element);
|
||||
auto& textureUnit = MGB_CTX->GetTextureUnitObject(unit);
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit);
|
||||
const auto& samplerOverride = textureUnit.GetSamplerObject();
|
||||
const auto preferredTarget = programObj.samplerTextureTargetByBinding[binding];
|
||||
SharedPtr<MG_State::GLState::ITextureObject> fallbackHolder;
|
||||
@@ -995,7 +995,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return false;
|
||||
}
|
||||
if (!IsValidSampledImageLayout(resource->layout)) {
|
||||
auto drawFbo = MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
auto drawFbo = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
FramebufferAttachmentType attachmentType = FramebufferAttachmentType::None;
|
||||
Int attachmentLevel = 0;
|
||||
if (drawFbo &&
|
||||
@@ -1225,7 +1225,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// filtering - which a single-level view can still have. Resolve the sampler exactly
|
||||
// the way ResolveSamplerDescriptor does and bail if anisotropy would apply.
|
||||
const Int unit = ResolveSamplerUnitIndex(program, location, binding);
|
||||
const auto& samplerOverride = MGB_CTX->GetTextureUnitObject(unit).GetSamplerObject();
|
||||
const auto& samplerOverride = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit).GetSamplerObject();
|
||||
const auto* effectiveSampler =
|
||||
samplerOverride ? samplerOverride.get() : texture->GetSamplerObject().get();
|
||||
if (effectiveSampler == nullptr) return false;
|
||||
@@ -1255,7 +1255,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const ProgramFactory::VkProgramObject& programObj, Uint32 binding,
|
||||
SharedPtr<MG_State::GLState::ITextureObject>& outTexture) {
|
||||
outTexture.reset();
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "ResolveSamplerTexture: GL context is null");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "ResolveSamplerTexture: GL context is null");
|
||||
MOBILEGL_ASSERT(binding < programObj.samplerUniformLocationByBinding.size(),
|
||||
"ResolveSamplerTexture: sampler location binding %u out of range", binding);
|
||||
MOBILEGL_ASSERT(binding < programObj.samplerTextureTargetByBinding.size(),
|
||||
@@ -1264,7 +1264,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const Int location = programObj.samplerUniformLocationByBinding[binding];
|
||||
const Int unit = ResolveSamplerUnitIndex(program, location, binding);
|
||||
|
||||
auto& textureUnit = MGB_CTX->GetTextureUnitObject(unit);
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit);
|
||||
const TextureTarget preferredTarget = programObj.samplerTextureTargetByBinding[binding];
|
||||
outTexture = textureUnit.GetBindingSlot(preferredTarget).GetBoundObject();
|
||||
// The slot always holds at least the target's default texture (name 0). While that
|
||||
@@ -1280,7 +1280,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
MG_State::GLState::ITextureObject* UniformManager::ResolveSamplerTextureRaw(
|
||||
const MagmaProgramSource& program, const ProgramFactory::VkProgramObject& programObj,
|
||||
Uint32 binding, Uint32 element) {
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "ResolveSamplerTextureRaw: GL context is null");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "ResolveSamplerTextureRaw: GL context is null");
|
||||
MOBILEGL_ASSERT(binding < programObj.samplerUniformLocationByBinding.size(),
|
||||
"ResolveSamplerTextureRaw: sampler location binding %u out of range", binding);
|
||||
MOBILEGL_ASSERT(binding < programObj.samplerTextureTargetByBinding.size(),
|
||||
@@ -1290,7 +1290,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
ResolveDescriptorElementLocation(program, programObj.samplerUniformLocationByBinding[binding], element);
|
||||
const Int unit = ResolveSamplerUnitIndex(program, location, binding);
|
||||
|
||||
auto& textureUnit = MGB_CTX->GetTextureUnitObject(unit);
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit);
|
||||
const TextureTarget preferredTarget = programObj.samplerTextureTargetByBinding[binding];
|
||||
// GetBoundObject() returns the SharedPtr by const ref; .get() reads the pointer without
|
||||
// touching the refcount (no atomic inc/dec per binding per draw).
|
||||
@@ -1547,7 +1547,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
#endif
|
||||
outBufferView = VK_NULL_HANDLE;
|
||||
MOBILEGL_ASSERT(m_bufferManager != nullptr, "ResolveStorageTexelBufferDescriptor: buffer manager is null");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "ResolveStorageTexelBufferDescriptor: GL context is null");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "ResolveStorageTexelBufferDescriptor: GL context is null");
|
||||
MOBILEGL_ASSERT(frameIndex < m_frames.size(),
|
||||
"ResolveStorageTexelBufferDescriptor: frame index out of range");
|
||||
MOBILEGL_ASSERT(binding < programObj.samplerUniformLocationByBinding.size(),
|
||||
@@ -1571,7 +1571,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
MOBILEGL_ASSERT(binding < programObj.samplerNumericDomainByBinding.size(),
|
||||
"ResolveStorageTexelBufferDescriptor: numeric domain binding %u out of range", binding);
|
||||
|
||||
auto& imageBinding = MGB_CTX->GetImageTextureBinding(imageUnit);
|
||||
auto& imageBinding = MG_Pipe::gPipeInputs.GetImageTextureBinding(imageUnit);
|
||||
const auto& texture = imageBinding.Texture;
|
||||
if (texture == nullptr) {
|
||||
// An image unit with no texture on it is legal GL (4.6 core 8.26): loads return zero
|
||||
@@ -1709,7 +1709,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkDescriptorBufferInfo& outBufferInfo) const {
|
||||
outBufferInfo = {};
|
||||
MOBILEGL_ASSERT(m_bufferManager != nullptr, "ResolveStorageBufferDescriptor: buffer manager is null");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "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 MOBILEGL_BUILD_DISAGGREGATED
|
||||
@@ -1837,12 +1837,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
#endif
|
||||
const Uint32 bindingPointCount =
|
||||
static_cast<Uint32>(MGB_CTX->GetBufferBindingPointCount(bufferTarget));
|
||||
static_cast<Uint32>(MG_Pipe::gPipeInputs.GetBufferBindingPointCount(bufferTarget));
|
||||
MOBILEGL_ASSERT(frontendBinding < bindingPointCount,
|
||||
"ResolveStorageBufferDescriptor: frontend binding %u out of range for block '%s'",
|
||||
frontendBinding, blockName.c_str());
|
||||
|
||||
auto& bindingPoint = MGB_CTX->GetBufferBindingPoint(bufferTarget, frontendBinding);
|
||||
auto& bindingPoint = MG_Pipe::gPipeInputs.GetBufferBindingPoint(bufferTarget, frontendBinding);
|
||||
const auto& bufferObject = bindingPoint.GetBoundObject();
|
||||
if (bufferObject == nullptr) {
|
||||
// NOT an error, and above all not a reason to lose the draw. GL 4.6 core 7.8 lets a
|
||||
@@ -1919,7 +1919,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
#endif
|
||||
outImageInfo = {};
|
||||
MOBILEGL_ASSERT(m_textureManager != nullptr, "ResolveStorageImageDescriptor: texture manager is null");
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "ResolveStorageImageDescriptor: GL context is null");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "ResolveStorageImageDescriptor: GL context is null");
|
||||
MOBILEGL_ASSERT(binding < programObj.samplerUniformLocationByBinding.size(),
|
||||
"ResolveStorageImageDescriptor: binding %u out of range", binding);
|
||||
|
||||
@@ -1948,7 +1948,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& imageBinding = MGB_CTX->GetImageTextureBinding(imageUnit);
|
||||
auto& imageBinding = MG_Pipe::gPipeInputs.GetImageTextureBinding(imageUnit);
|
||||
if (imageBinding.Texture == nullptr) {
|
||||
// Legal GL: an image unit with no texture bound makes loads return zero and discards
|
||||
// stores (4.6 core 8.26). It is not a reason to lose the draw, which is what returning
|
||||
@@ -2304,7 +2304,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// Open-coded ResolveSamplerTextureRaw so the unit is resolved once for both the
|
||||
// texture and the sampler override - this runs per binding per full-path draw,
|
||||
// and program-alternating draw streams take the full path on every draw.
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "ResolveSampledBinding: GL context is null");
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(), "ResolveSampledBinding: GL context is null");
|
||||
MOBILEGL_ASSERT(binding < programObj.samplerUniformLocationByBinding.size(),
|
||||
"ResolveSampledBinding: sampler location binding %u out of range", binding);
|
||||
MOBILEGL_ASSERT(binding < programObj.samplerTextureTargetByBinding.size(),
|
||||
@@ -2315,7 +2315,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return false;
|
||||
}
|
||||
const Int unit = ResolveSamplerUnitIndex(program, location, binding);
|
||||
auto& textureUnit = MGB_CTX->GetTextureUnitObject(unit);
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(unit);
|
||||
const TextureTarget preferredTarget = programObj.samplerTextureTargetByBinding[binding];
|
||||
MG_State::GLState::ITextureObject* texture =
|
||||
textureUnit.GetBindingSlot(preferredTarget).GetBoundObject().get();
|
||||
@@ -2468,7 +2468,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (program.IsWire()) { outTextures.clear(); return true; }
|
||||
#endif
|
||||
outTextures.clear();
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE,
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(),
|
||||
"CollectStorageImageTextures: GL context is null");
|
||||
// Same as the sampled walk: a declined program is refused at bind time, and its declined
|
||||
// binding has no uniform location to reach an image unit through.
|
||||
@@ -2512,7 +2512,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* texture = MGB_CTX->GetImageTextureBinding(imageUnit).Texture.get();
|
||||
auto* texture = MG_Pipe::gPipeInputs.GetImageTextureBinding(imageUnit).Texture.get();
|
||||
if (texture == nullptr) {
|
||||
// ResolveStorageImageDescriptor will substitute the placeholder image for this
|
||||
// binding; include it here for the same reason the sampled walk includes the
|
||||
@@ -2553,7 +2553,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (program.IsWire()) { outBindings.clear(); return true; }
|
||||
#endif
|
||||
outBindings.clear();
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE,
|
||||
MOBILEGL_ASSERT(MG_Pipe::gPipeInputs.IsLive(),
|
||||
"CollectSamplerImageFeedback: GL context is null");
|
||||
if (programObj.declinedDescriptors) return true;
|
||||
|
||||
@@ -2603,7 +2603,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (imageUnit < 0 || imageUnit >= MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS) {
|
||||
return false;
|
||||
}
|
||||
const auto& image = MGB_CTX->GetImageTextureBinding(imageUnit);
|
||||
const auto& image = MG_Pipe::gPipeInputs.GetImageTextureBinding(imageUnit);
|
||||
// A sampler view exposes all layers of its target; equal texture plus an
|
||||
// overlapping mip therefore aliases the writable image subresource.
|
||||
if (image.Texture.get() == sampledTexture &&
|
||||
@@ -2730,7 +2730,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const void* outData = nullptr;
|
||||
VkDeviceSize outSize = 0;
|
||||
|
||||
MOBILEGL_ASSERT(MGB_CTX_LIVE, "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,
|
||||
@@ -2787,12 +2787,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return ResolveWireUniformBufferPayload(program, static_cast<Uint32>(blockIndex), frontendBinding, out);
|
||||
#endif
|
||||
const Uint32 uniformBindingPointCount =
|
||||
static_cast<Uint32>(MGB_CTX->GetBufferBindingPointCount(BufferTarget::Uniform));
|
||||
static_cast<Uint32>(MG_Pipe::gPipeInputs.GetBufferBindingPointCount(BufferTarget::Uniform));
|
||||
MOBILEGL_ASSERT(frontendBinding < uniformBindingPointCount,
|
||||
"ResolveUniformBufferPayload: frontend UBO binding %u out of range for block '%s'",
|
||||
frontendBinding, program.GetUniformBlockName(static_cast<Uint32>(blockIndex)).c_str());
|
||||
|
||||
auto& bindingPoint = MGB_CTX->GetBufferBindingPoint(BufferTarget::Uniform, frontendBinding);
|
||||
auto& bindingPoint = MG_Pipe::gPipeInputs.GetBufferBindingPoint(BufferTarget::Uniform, frontendBinding);
|
||||
const auto& bufferObject = bindingPoint.GetBoundObject();
|
||||
static thread_local Vector<Uint8> paddedUbo;
|
||||
if (bufferObject == nullptr) {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "VkTextureManager.h"
|
||||
|
||||
#include "MG_State/GLState/Core.h"
|
||||
#include <MG_Pipe/PipeInputsSwitch.h>
|
||||
#include <MG_Backend/MGPipe/PipeInputs.h>
|
||||
#include "MG_Util/Converters/MGToStr/FramebufferEnumConverter.h"
|
||||
#include "MG_Util/Converters/MGToStr/TextureEnumConverter.h"
|
||||
|
||||
@@ -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 (MGB_CTX->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
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "MG_Util/Converters/MGToStr/FramebufferEnumConverter.h"
|
||||
#include "MG_Util/Converters/MGToVk/TextureEnumConverter.h"
|
||||
#include "MG_Util/Metrics/TextureMetrics.h"
|
||||
#include <MG_Pipe/PipeInputsSwitch.h>
|
||||
#include <MG_Backend/MGPipe/PipeInputs.h>
|
||||
|
||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
static Bool TryResolveSampleCountFlagBits(Int requestedSamples, VkSampleCountFlagBits& outSampleCount) {
|
||||
@@ -614,7 +614,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// sRGB attachments switch between their sRGB and UNORM-twin views with this
|
||||
// capability (ResolveSrgbAttachmentWriteFormat), changing the render pass formats.
|
||||
const Bool framebufferSrgbEnabled =
|
||||
MGB_CTX->IsCapabilityEnabled(MobileGL::CapabilityInput::FramebufferSrgb);
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(MobileGL::CapabilityInput::FramebufferSrgb);
|
||||
XXHASH_VERIFY(XXH64_update(m_hashState, &framebufferSrgbEnabled, sizeof(framebufferSrgbEnabled)));
|
||||
auto& drawBuffers = fbo.GetDrawBuffers();
|
||||
XXHASH_VERIFY(XXH64_update(m_hashState, drawBuffers.data(), drawBuffers.size() * sizeof(drawBuffers[0])));
|
||||
@@ -966,7 +966,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
const VkImageLayout trackedRbLayout = rbResource->layout;
|
||||
const Bool rbFramebufferSrgb =
|
||||
MGB_CTX->IsCapabilityEnabled(MobileGL::CapabilityInput::FramebufferSrgb);
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(MobileGL::CapabilityInput::FramebufferSrgb);
|
||||
const VkFormat rbAttachmentFormat =
|
||||
ResolveSrgbAttachmentWriteFormat(rbResource->format, rbFramebufferSrgb);
|
||||
rbDesc.flags = 0;
|
||||
@@ -1112,7 +1112,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
textureResources.emplace_back(textureResource);
|
||||
desc.format = ResolveSrgbAttachmentWriteFormat(
|
||||
textureResource->format,
|
||||
MGB_CTX->IsCapabilityEnabled(MobileGL::CapabilityInput::FramebufferSrgb));
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(MobileGL::CapabilityInput::FramebufferSrgb));
|
||||
attachmentSampleCount = textureResource->sampleCount;
|
||||
trackedColorLayout = textureResource->layout;
|
||||
trackedAttachmentLayouts.emplace_back(TrackedAttachmentLayoutInfo {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "ProgramFactory.h"
|
||||
|
||||
#include "MG_State/GLState/Core.h"
|
||||
#include <MG_Pipe/PipeInputsSwitch.h>
|
||||
#include <MG_Backend/MGPipe/PipeInputs.h>
|
||||
#include "MG_Util/Converters/MGToStr/TextureEnumConverter.h"
|
||||
#include "MG_Util/Converters/MGToVk/TextureEnumConverter.h"
|
||||
#include "MG_Util/Metrics/PipeStats.h"
|
||||
@@ -873,7 +873,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// sampled-texture sync scan the entire alive-texture map per draw.
|
||||
if (aliveIt == m_aliveObjects.end()) {
|
||||
WeakPtr<MG_State::GLState::ITextureObject> aliveTexture;
|
||||
const auto& liveTexture = MGB_CTX->GetTextureObject(texture.GetExternalIndex());
|
||||
const auto& liveTexture = MG_Pipe::gPipeInputs.GetTextureObject(texture.GetExternalIndex());
|
||||
if (liveTexture && liveTexture.get() == &texture) {
|
||||
aliveTexture = liveTexture;
|
||||
} else {
|
||||
@@ -1016,7 +1016,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
const Bool framebufferSrgbEnabled =
|
||||
MGB_CTX->IsCapabilityEnabled(MobileGL::CapabilityInput::FramebufferSrgb);
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(MobileGL::CapabilityInput::FramebufferSrgb);
|
||||
const VkFormat baseAttachmentFormat =
|
||||
viewFormatOverride != VK_FORMAT_UNDEFINED ? viewFormatOverride : resource->format;
|
||||
const VkFormat attachmentFormat =
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "VertexInputStateBuilder.h"
|
||||
|
||||
#include "MG_State/GLState/Core.h"
|
||||
#include <MG_Pipe/PipeInputsSwitch.h>
|
||||
#include <MG_Backend/MGPipe/PipeInputs.h>
|
||||
// P5c ev: the GPU-write announcement routes through the reverse channel (R2).
|
||||
#include <MG_Impl/Pipe/ResourceTracker.h>
|
||||
#include "MG_State/GLState/ProgramState/ProgramObject.h"
|
||||
@@ -596,12 +596,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 = MGB_CTX->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 = MGB_CTX->GetDepthRangeIndexed(index);
|
||||
const FloatVec2& depthRange = MG_Pipe::gPipeInputs.GetDepthRangeIndexed(index);
|
||||
const IntVec2 logicalExtent = isDefaultFramebuffer
|
||||
? ResolveDefaultFramebufferLogicalExtent(preTransform, framebufferExtent)
|
||||
: framebufferExtent;
|
||||
@@ -656,7 +656,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
static void ApplyBlendConstants(VkCommandBuffer commandBuffer) {
|
||||
const FloatVec4& blendColor = MGB_CTX->GetBlendColor();
|
||||
const FloatVec4& blendColor = MG_Pipe::gPipeInputs.GetBlendColor();
|
||||
const float blendConstants[4] = {
|
||||
blendColor.x(),
|
||||
blendColor.y(),
|
||||
@@ -689,8 +689,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
static void ApplyPolygonOffsetState(VkCommandBuffer commandBuffer) {
|
||||
const Float constantFactor = MGB_CTX->GetPolygonOffsetUnits();
|
||||
const Float slopeFactor = MGB_CTX->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) {
|
||||
@@ -703,7 +703,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
static void ApplyLineWidthState(VkCommandBuffer commandBuffer) {
|
||||
Float lineWidth = MGB_CTX->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
|
||||
@@ -806,8 +806,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
static void ApplyStencilState(VkCommandBuffer commandBuffer) {
|
||||
const StencilFaceState& frontStencil = MGB_CTX->GetStencilState(StencilFace::Front);
|
||||
const StencilFaceState& backStencil = MGB_CTX->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));
|
||||
|
||||
@@ -1400,11 +1400,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
static void RecordClearBufferError(const char* func, ErrorCode code, const char* message) {
|
||||
MGB_CTX->RecordError(code, MakeUnique<GenericErrorInfo>("DirectVulkan", func, message));
|
||||
MG_Pipe::gPipeInputs.RecordError(code, MakeUnique<GenericErrorInfo>("DirectVulkan", func, message));
|
||||
}
|
||||
|
||||
static void RecordTextureCopyError(const char* func, ErrorCode code, const char* message) {
|
||||
MGB_CTX->RecordError(code, MakeUnique<GenericErrorInfo>("DirectVulkan", func, message));
|
||||
MG_Pipe::gPipeInputs.RecordError(code, MakeUnique<GenericErrorInfo>("DirectVulkan", func, message));
|
||||
}
|
||||
|
||||
static Bool HasDistinctCompleteDepthStencilTextureAttachments(
|
||||
@@ -1460,7 +1460,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
static void RecordUnsupportedFramebufferError(const char* func) {
|
||||
MGB_CTX->RecordError(
|
||||
MG_Pipe::gPipeInputs.RecordError(
|
||||
ErrorCode::InvalidFramebufferOperation,
|
||||
MakeUnique<GenericErrorInfo>(
|
||||
"DirectVulkan", func,
|
||||
@@ -3000,7 +3000,7 @@ void main() {
|
||||
// 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 = MGB_CTX->GetClampReadColor();
|
||||
const GLenum clampMode = MG_Pipe::gPipeInputs.GetClampReadColor();
|
||||
const Bool clamp = clampMode == GL_TRUE ||
|
||||
(clampMode == GL_FIXED_ONLY && !IsFloatingPointReadbackFormat(srcFormat));
|
||||
if (clamp) {
|
||||
@@ -3223,11 +3223,11 @@ void main() {
|
||||
const Bool wire = MG_Config::Transport != MG_Config::TransportMode::Monolith;
|
||||
const auto* wireFbo = wire ? MG_Pipe::MGPipeApplier().DrawFramebuffer() : nullptr;
|
||||
const auto currentDrawFBO = wire ? SharedPtr<MG_State::GLState::FramebufferObject>{} :
|
||||
MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
const Bool isDefault = wire ? (wireFbo && wireFbo->IsDefault) :
|
||||
(currentDrawFBO && currentDrawFBO->IsDefaultFramebuffer());
|
||||
#else
|
||||
const auto& currentDrawFBO = MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
const auto& currentDrawFBO = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
const Bool isDefault = currentDrawFBO != nullptr && currentDrawFBO->IsDefaultFramebuffer();
|
||||
#endif
|
||||
if (isDefault) {
|
||||
@@ -3732,8 +3732,8 @@ void main() {
|
||||
// with restart off it is a legitimate index and excluding it would truncate the
|
||||
// converted stream by exactly that vertex.
|
||||
const Bool primitiveRestartActive =
|
||||
MGB_CTX->IsCapabilityEnabled(CapabilityInput::PrimitiveRestart) ||
|
||||
MGB_CTX->IsCapabilityEnabled(CapabilityInput::PrimitiveRestartFixedIndex);
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::PrimitiveRestart) ||
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::PrimitiveRestartFixedIndex);
|
||||
const Uint32 restartSentinel = indexSize == 1 ? 0xFFu : indexSize == 2 ? 0xFFFFu : 0xFFFFFFFFu;
|
||||
Uint32 maxIndex = 0;
|
||||
Bool sawIndex = false;
|
||||
@@ -4307,7 +4307,7 @@ void main() {
|
||||
}
|
||||
|
||||
const auto glType = programObj.vertexInputTypes[location];
|
||||
const auto& currentValue = MGB_CTX->GetCurrentVertexAttribute(location);
|
||||
const auto& currentValue = MG_Pipe::gPipeInputs.GetCurrentVertexAttribute(location);
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
const void* sourceData = nullptr;
|
||||
VkDeviceSize sourceSize = 0;
|
||||
@@ -4441,7 +4441,7 @@ void main() {
|
||||
Bool substituteRestart = false;
|
||||
// One bulk parameters fetch instead of up to three accessor calls per indexed
|
||||
// draw; all three inputs are pure reads of these fields.
|
||||
const RenderStateParameters& rsp = MGB_CTX->GetRenderStateParameters();
|
||||
const RenderStateParameters& rsp = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
if (rsp.PrimitiveRestartEnabled && !rsp.PrimitiveRestartFixedIndexEnabled) {
|
||||
const Uint32 restartIndex = rsp.PrimitiveRestartIndex;
|
||||
const Uint32 fixedMax = MG_Util::FixedRestartIndexForGLType(pIndexBufferView->indexType);
|
||||
@@ -5297,9 +5297,9 @@ void main() {
|
||||
Uint32 VulkanRenderer::ResolveEffectiveSampleMask(VkSampleCountFlagBits rasterizationSamples) const {
|
||||
constexpr Uint32 kFullCoverage = 0xffffffffu;
|
||||
if (rasterizationSamples == VK_SAMPLE_COUNT_1_BIT) return kFullCoverage;
|
||||
if (!MGB_CTX->IsCapabilityEnabled(CapabilityInput::Multisample)) return kFullCoverage;
|
||||
if (!MGB_CTX->IsCapabilityEnabled(CapabilityInput::SampleMask)) return kFullCoverage;
|
||||
return MGB_CTX->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;
|
||||
}
|
||||
|
||||
|
||||
@@ -5314,7 +5314,7 @@ void main() {
|
||||
//
|
||||
// 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(MGB_CTX->GetRenderStateParameters());
|
||||
return MG_Pipe::MGPipeComputePipelineSubsetHash(MG_Pipe::gPipeInputs.GetRenderStateParameters());
|
||||
}
|
||||
|
||||
// A program that runs a geometry shader AND captures transform feedback. Both halves are
|
||||
@@ -5346,7 +5346,7 @@ void main() {
|
||||
if (!(aspects & DrawSetupAspect::IndexBuffer) || pIndexBufferView == nullptr) {
|
||||
return false;
|
||||
}
|
||||
const RenderStateParameters& rsp = MGB_CTX->GetRenderStateParameters();
|
||||
const RenderStateParameters& rsp = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
if (rsp.PrimitiveRestartFixedIndexEnabled) {
|
||||
return true;
|
||||
}
|
||||
@@ -5422,7 +5422,7 @@ void main() {
|
||||
// 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 = MGB_CTX->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
|
||||
@@ -5617,16 +5617,16 @@ void main() {
|
||||
syntheticVertexInputState.pNext = vis.state.pNext;
|
||||
pipelineVertexInputState = &syntheticVertexInputState;
|
||||
}
|
||||
auto cullFaceEnabled = MGB_CTX->IsCapabilityEnabled(CapabilityInput::CullFace);
|
||||
auto depthTestEnabled = MGB_CTX->IsCapabilityEnabled(CapabilityInput::DepthTest);
|
||||
auto cullFaceEnabled = MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::CullFace);
|
||||
auto depthTestEnabled = MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::DepthTest);
|
||||
auto polygonOffsetFillEnabled =
|
||||
MGB_CTX->IsCapabilityEnabled(CapabilityInput::PolygonOffsetFill) &&
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::PolygonOffsetFill) &&
|
||||
DrawModeUsesPolygonFill(mode);
|
||||
auto rasterizerDiscardEnabled =
|
||||
MGB_CTX->IsCapabilityEnabled(CapabilityInput::RasterizerDiscard);
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::RasterizerDiscard);
|
||||
auto colorLogicOpEnabled =
|
||||
MGB_CTX->IsCapabilityEnabled(CapabilityInput::ColorLogicOp) && m_logicOpFeatureEnabled;
|
||||
auto stencilTestEnabled = MGB_CTX->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.
|
||||
@@ -5642,7 +5642,7 @@ void main() {
|
||||
#endif
|
||||
{
|
||||
const auto& gatingFbo =
|
||||
MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
if (gatingFbo != nullptr && !gatingFbo->IsDefaultFramebuffer()) {
|
||||
const auto& depthAtt = gatingFbo->GetAttachment(MobileGL::FramebufferAttachmentType::Depth);
|
||||
const auto& stencilAtt = gatingFbo->GetAttachment(MobileGL::FramebufferAttachmentType::Stencil);
|
||||
@@ -5655,10 +5655,10 @@ void main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
const StencilFaceState& frontStencil = MGB_CTX->GetStencilState(StencilFace::Front);
|
||||
const StencilFaceState& backStencil = MGB_CTX->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(MGB_CTX->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 =
|
||||
@@ -5746,18 +5746,18 @@ void main() {
|
||||
// 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 &&
|
||||
MGB_CTX->IsCapabilityEnabled(CapabilityInput::SampleShading),
|
||||
.minSampleShading = MGB_CTX->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>(MGB_CTX->GetPatchVertices()),
|
||||
.patchControlPoints = static_cast<Uint32>(MG_Pipe::gPipeInputs.GetPatchVertices()),
|
||||
.viewportCount = ResolveDrawViewportCount(programObj.writesViewportIndexBuiltin),
|
||||
.polygonMode = effectivePolygonMode,
|
||||
.cullMode = cullFaceEnabled
|
||||
? MG_Util::ConvertCullFaceModeToVkEnum(MGB_CTX->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
|
||||
@@ -5771,13 +5771,13 @@ void main() {
|
||||
.provokingVertexMode = SelectProvokingVertexMode(
|
||||
vkTopology, ProgramCapturesXfbFromGeometryStage(program)),
|
||||
.depthTestEnable = depthTestEnabled,
|
||||
.depthWriteEnable = depthTestEnabled && MGB_CTX->GetDepthMask(),
|
||||
.depthWriteEnable = depthTestEnabled && MG_Pipe::gPipeInputs.GetDepthMask(),
|
||||
.depthBiasEnable = polygonOffsetFillEnabled,
|
||||
.rasterizerDiscardEnable = rasterizerDiscardEnabled,
|
||||
.logicOpEnable = colorLogicOpEnabled,
|
||||
.stencilTestEnable = stencilTestEnabled,
|
||||
.depthCompareOp = MG_Util::ConvertDepthTestFuncToVkEnum(MGB_CTX->GetDepthFunc()),
|
||||
.logicOp = MG_Util::ConvertLogicOperationToVkEnum(MGB_CTX->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),
|
||||
@@ -5813,8 +5813,8 @@ void main() {
|
||||
// handed back after the application changed them.
|
||||
if (programObj.needsPassthroughTessControl && programObj.passthroughTessControlEmulatable &&
|
||||
vkTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) {
|
||||
const FloatVec4& defaultOuterLevel = MGB_CTX->GetPatchDefaultOuterLevel();
|
||||
const FloatVec2& defaultInnerLevel = MGB_CTX->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);
|
||||
@@ -5869,10 +5869,10 @@ void main() {
|
||||
const auto* wireFbo = MG_Config::Transport != MG_Config::TransportMode::Monolith ?
|
||||
MG_Pipe::MGPipeApplier().DrawFramebuffer() : nullptr;
|
||||
const auto drawFboBinding = wireFbo ? SharedPtr<MG_State::GLState::FramebufferObject>{} :
|
||||
MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
#else
|
||||
const auto& drawFboBinding =
|
||||
MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
#endif
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
MOBILEGL_ASSERT(wireFbo != nullptr || drawFboBinding != nullptr, "GetOrCreatePipeline: draw framebuffer is null");
|
||||
@@ -5917,14 +5917,14 @@ void main() {
|
||||
BlendFactor dstAlpha = BlendFactor::Zero;
|
||||
BlendEquation colorEquation = BlendEquation::Add;
|
||||
BlendEquation alphaEquation = BlendEquation::Add;
|
||||
MGB_CTX->GetBlendFuncIndexed(i, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
MGB_CTX->GetBlendEquationIndexed(i, colorEquation, alphaEquation);
|
||||
const Bool blendEnabled = MGB_CTX->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 =
|
||||
MGB_CTX->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) |
|
||||
@@ -6375,7 +6375,7 @@ void main() {
|
||||
VkRect2D VulkanRenderer::ComputeGLScissorRect(Uint32 index, const IntVec2& extent,
|
||||
VkSurfaceTransformFlagBitsKHR preTransform,
|
||||
Bool isDefaultFbo) const {
|
||||
const auto& parameters = MGB_CTX->GetRenderStateParameters();
|
||||
const auto& parameters = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
if ((parameters.ScissorTestEnabledMask & (1u << index)) == 0) {
|
||||
VkRect2D full{};
|
||||
full.offset = {0, 0};
|
||||
@@ -6451,7 +6451,7 @@ void main() {
|
||||
// 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 = MGB_CTX->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) {
|
||||
@@ -6475,7 +6475,7 @@ void main() {
|
||||
// re-derive the value its shadow already holds.
|
||||
DynamicStateShadow::DynamicTailKey key;
|
||||
{
|
||||
const RenderStateParameters& p = MGB_CTX->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();
|
||||
@@ -6557,7 +6557,7 @@ void main() {
|
||||
}
|
||||
#endif
|
||||
const auto& fbo =
|
||||
MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
return isDefaultFbo == (fbo != nullptr && fbo->IsDefaultFramebuffer());
|
||||
}(),
|
||||
"GetBaseTransformFlagsRaw: isDefaultFbo does not match the bound draw framebuffer");
|
||||
@@ -6581,7 +6581,7 @@ void main() {
|
||||
// Entry select: by the draw program's lifetime id, MRU first (the id pins
|
||||
// the entry; every other fact is re-guarded below, so probing a stale
|
||||
// entry can only decline, never serve stale state).
|
||||
const auto& program = *MGB_CTX->GetProgramForDraw();
|
||||
const auto& program = *MG_Pipe::gPipeInputs.GetProgramForDraw();
|
||||
const Uint64 programLifetimeId = program.GetLifetimeId();
|
||||
SetupDrawSnapshot* snapPtr = nullptr;
|
||||
{
|
||||
@@ -6629,7 +6629,7 @@ void main() {
|
||||
// captured draw after glBeginTransformFeedback would bind the undecorated
|
||||
// variant and silently capture nothing while the CPU bookkeeping advances.
|
||||
const Bool wantsXfbCapture = m_transformFeedbackFeatureEnabled &&
|
||||
MGB_CTX->IsTransformFeedbackActive() &&
|
||||
MG_Pipe::gPipeInputs.IsTransformFeedbackActive() &&
|
||||
program.GetTransformFeedbackVaryingCount() > 0;
|
||||
const Bool snapHasXfbCapture =
|
||||
static_cast<Bool>(ProgramFactory::CompileOptionFlags(snap.resolvedTransformFlags) &
|
||||
@@ -6643,7 +6643,7 @@ void main() {
|
||||
// buffer binds (re-run every draw anyway). Declining here would send every
|
||||
// draw of a VAO-cycling stream (Minecraft chunk rendering) through the full
|
||||
// path, re-resolving descriptors and texture layouts nothing invalidated.
|
||||
const auto& vao = *MGB_CTX->GetBoundVertexArray();
|
||||
const auto& vao = *MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
// P2 D12.4: the handle replaces the (address, lifetime id) pair here too - one
|
||||
// compare instead of two, and the same identity the VAO draw memo is keyed on, so
|
||||
// the two cannot disagree about whether "the VAO moved". The config version stays:
|
||||
@@ -6656,7 +6656,7 @@ void main() {
|
||||
vao.GetLifetimeId() != snap.vaoLifetimeId ||
|
||||
vao.GetConfigVersion() != snap.vaoConfigVersion);
|
||||
const auto& drawFbo =
|
||||
MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
if (static_cast<const void*>(drawFbo.get()) != snap.drawFbo ||
|
||||
drawFbo->GetLifetimeId() != snap.drawFboLifetimeId ||
|
||||
drawFbo->GetObjectVersion() != snap.fboVersion) {
|
||||
@@ -6667,8 +6667,8 @@ void main() {
|
||||
// back on what the snapshot already describes (a GL_BLEND toggle between
|
||||
// two draws, a redundant glBindSampler), and declining here sends every
|
||||
// such draw through the full SetupDraw.
|
||||
const Uint renderStateVersion = MGB_CTX->GetPipelineStateVersion();
|
||||
const Uint64 bindGeneration = MGB_CTX->GetTextureBindGeneration();
|
||||
const Uint renderStateVersion = MG_Pipe::gPipeInputs.GetPipelineStateVersion();
|
||||
const Uint64 bindGeneration = MG_Pipe::gPipeInputs.GetTextureBindGeneration();
|
||||
const Bool renderStateMoved = renderStateVersion != snap.renderStateVersion;
|
||||
const Bool bindsMoved = bindGeneration != snap.bindGeneration;
|
||||
if (renderStateMoved) {
|
||||
@@ -6676,7 +6676,7 @@ void main() {
|
||||
// flavor input (depth/stencil participation); a flip of that must take
|
||||
// the full path's pass selection. One bulk parameters fetch instead of
|
||||
// two capability-accessor calls; both are pure reads of the same fields.
|
||||
const RenderStateParameters& rsp = MGB_CTX->GetRenderStateParameters();
|
||||
const RenderStateParameters& rsp = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
const Bool drawUsesDepthStencil = rsp.DepthTestEnabled || rsp.StencilTestEnabled;
|
||||
if (drawUsesDepthStencil != snap.drawUsesDepthStencil) {
|
||||
return false;
|
||||
@@ -6850,7 +6850,7 @@ void main() {
|
||||
if (contentSum != snap.sampledContentSum || paramsSum != snap.sampledParamsSum) {
|
||||
return false;
|
||||
}
|
||||
const Uint64 samplingResolutionGeneration = MGB_CTX->GetSamplingResolutionGeneration();
|
||||
const Uint64 samplingResolutionGeneration = MG_Pipe::gPipeInputs.GetSamplingResolutionGeneration();
|
||||
if (samplingResolutionGeneration != snap.samplingResolutionGeneration) {
|
||||
// Decline, not re-arm: snap.resolvedTransformFlags bakes the
|
||||
// ExplicitLod0Sampling verdict, which reads the effective sampler's
|
||||
@@ -7004,7 +7004,7 @@ void main() {
|
||||
// was cancelled has no usable optimized module - and on an in-place
|
||||
// SanitizeAndOptimizeBinary failure GetGeneratedSpirv() still holds the RAW
|
||||
// glslang words, which must never reach vkCreateShaderModule. Drop the draw.
|
||||
const auto& drawProgram = *MGB_CTX->GetProgramForDraw();
|
||||
const auto& drawProgram = *MG_Pipe::gPipeInputs.GetProgramForDraw();
|
||||
if (!drawProgram.GetLinkStatus() || !drawProgram.GetSpirvStatus()) {
|
||||
MGLOG_D("SetupDraw skipped: program=%u is linked=%d spirv=%d",
|
||||
drawProgram.GetExternalIndex(), static_cast<int>(drawProgram.GetLinkStatus()),
|
||||
@@ -7034,15 +7034,15 @@ void main() {
|
||||
MG_Util::PipeStats::AddCalls(MG_Util::PipeStats::CallClass::AccessorCalls, 3);
|
||||
}
|
||||
const auto& drawFbo =
|
||||
MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
if (drawFbo != nullptr && IsUnsupportedFramebufferForDirectVulkan(*drawFbo)) {
|
||||
// Nothing was mutated: other entries' per-probe guards (FBO identity +
|
||||
// version among them) stay authoritative, so none need invalidating.
|
||||
RecordUnsupportedFramebufferError(__func__);
|
||||
return false;
|
||||
}
|
||||
const auto& vao = *MGB_CTX->GetBoundVertexArray();
|
||||
const auto& program = *MGB_CTX->GetProgramForDraw();
|
||||
const auto& vao = *MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
const auto& program = *MG_Pipe::gPipeInputs.GetProgramForDraw();
|
||||
// The fast path declined (or had no entry for this program): whatever THIS
|
||||
// program's entry saw may be stale, and the full path below mutates state as
|
||||
// it goes, so the entry must not stay matchable if that path fails mid-way.
|
||||
@@ -7082,7 +7082,7 @@ void main() {
|
||||
ProgramFactory::CompileOptionFlags transformFlags =
|
||||
ProgramFactory::CompileOptionFlags(GetBaseTransformFlagsRaw(drawFboIsDefault));
|
||||
// Captured draws take the xfb-decorated program variant.
|
||||
if (m_transformFeedbackFeatureEnabled && MGB_CTX->IsTransformFeedbackActive() &&
|
||||
if (m_transformFeedbackFeatureEnabled && MG_Pipe::gPipeInputs.IsTransformFeedbackActive() &&
|
||||
program.GetTransformFeedbackVaryingCount() > 0) {
|
||||
transformFlags |= ProgramFactory::CompileOptionBit::XfbCapture;
|
||||
}
|
||||
@@ -7096,13 +7096,13 @@ void main() {
|
||||
{
|
||||
const Uint64 lodProgramLifetimeId = program.GetLifetimeId();
|
||||
const Uint32 lodProgramVersion = program.GetBackendStateVersion();
|
||||
const Uint64 lodBindGeneration = MGB_CTX->GetTextureBindGeneration();
|
||||
const Uint64 lodBindGeneration = MG_Pipe::gPipeInputs.GetTextureBindGeneration();
|
||||
// The probe also reads the EFFECTIVE sampler's filters/aniso/LOD range
|
||||
// (ProgramSamplesOnlySingleLevelTextures), and those setters bump ONLY the
|
||||
// sampling-resolution generation - not the texture params version the sum
|
||||
// below covers. Without this key a filter/aniso change would keep serving
|
||||
// the stale verdict.
|
||||
const Uint64 lodSamplingGeneration = MGB_CTX->GetSamplingResolutionGeneration();
|
||||
const Uint64 lodSamplingGeneration = MG_Pipe::gPipeInputs.GetSamplingResolutionGeneration();
|
||||
Bool lodMemoHit = false;
|
||||
if (m_lastLodDecisionValid && m_lastSampledSetValid &&
|
||||
m_lastLodProgramLifetimeId == lodProgramLifetimeId &&
|
||||
@@ -7220,7 +7220,7 @@ void main() {
|
||||
{
|
||||
const Uint64 programLifetimeId = program.GetLifetimeId();
|
||||
const Uint32 programVersion = program.GetBackendStateVersion();
|
||||
const Uint64 bindGeneration = MGB_CTX->GetTextureBindGeneration();
|
||||
const Uint64 bindGeneration = MG_Pipe::gPipeInputs.GetTextureBindGeneration();
|
||||
// The bind generation alone stopped covering this set the moment ResolveSampledBinding
|
||||
// started asking SamplesAsIncompleteTexture: membership now depends on the effective
|
||||
// sampler PARAMETERS (MIN_FILTER decides whether the mip chain is read at all) and on
|
||||
@@ -7239,7 +7239,7 @@ void main() {
|
||||
// object a unit carries goes through TextureUnit::SetSamplerObject and moves the bind
|
||||
// generation instead. Same term the SetupDrawSnapshot fast path and the LOD memo
|
||||
// already carry.
|
||||
const Uint64 samplingGeneration = MGB_CTX->GetSamplingResolutionGeneration();
|
||||
const Uint64 samplingGeneration = MG_Pipe::gPipeInputs.GetSamplingResolutionGeneration();
|
||||
const Bool sampledSetUnchanged =
|
||||
m_lastSampledSetValid && m_lastSampledSetProgramLifetimeId == programLifetimeId &&
|
||||
m_lastSampledSetProgramVersion == programVersion &&
|
||||
@@ -7409,8 +7409,8 @@ void main() {
|
||||
// pass flavor (GL: a disabled depth/stencil test neither reads nor writes
|
||||
// its buffer).
|
||||
const Bool drawUsesDepthStencil =
|
||||
MGB_CTX->IsCapabilityEnabled(CapabilityInput::DepthTest) ||
|
||||
MGB_CTX->IsCapabilityEnabled(CapabilityInput::StencilTest);
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::DepthTest) ||
|
||||
MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::StencilTest);
|
||||
auto* renderPassEntry = m_renderPassManager->GetOrCreateRenderPass(
|
||||
*drawFbo, DefaultFramebufferWriteIndex(drawFbo->IsDefaultFramebuffer()), drawUsesDepthStencil);
|
||||
// nullptr: the framebuffer has an attachment DirectVulkan cannot represent (a texture the
|
||||
@@ -7556,8 +7556,8 @@ void main() {
|
||||
snap.fboVersion = drawFbo->GetObjectVersion();
|
||||
snap.drawFboIsDefault = drawFboIsDefault;
|
||||
snap.viewportCount = ResolveDrawViewportCount(programObj.writesViewportIndexBuiltin);
|
||||
snap.renderStateVersion = MGB_CTX->GetPipelineStateVersion();
|
||||
snap.bindGeneration = MGB_CTX->GetTextureBindGeneration();
|
||||
snap.renderStateVersion = MG_Pipe::gPipeInputs.GetPipelineStateVersion();
|
||||
snap.bindGeneration = MG_Pipe::gPipeInputs.GetTextureBindGeneration();
|
||||
snap.baseTransformFlags = GetBaseTransformFlagsRaw(drawFboIsDefault);
|
||||
snap.resolvedTransformFlags = transformFlags.GetRaw();
|
||||
snap.renderPassHash = nowActiveRenderPass->hash;
|
||||
@@ -7583,7 +7583,7 @@ void main() {
|
||||
snap.programObj = nullptr;
|
||||
snap.programFactoryEpoch = 0;
|
||||
}
|
||||
snap.samplingResolutionGeneration = MGB_CTX->GetSamplingResolutionGeneration();
|
||||
snap.samplingResolutionGeneration = MG_Pipe::gPipeInputs.GetSamplingResolutionGeneration();
|
||||
Uint64 snapContentSum = 0;
|
||||
Uint64 snapParamsSum = 0;
|
||||
// Per-entry copies of this draw's sampled set (the scratch vectors
|
||||
@@ -7630,7 +7630,7 @@ void main() {
|
||||
auto& frame = m_frameContext.GetCurrent();
|
||||
// The DISPATCH accessor: with a pipeline bound this is its compute stage program
|
||||
// itself, never the graphics composite (which carries no compute stage at all).
|
||||
const auto& program = *MGB_CTX->GetProgramForDispatch();
|
||||
const auto& program = *MG_Pipe::gPipeInputs.GetProgramForDispatch();
|
||||
if (!program.GetLinkStatus() || !program.GetSpirvStatus()) {
|
||||
MGLOG_E_ONCE("DispatchCompute skipped: program=%u has no optimized SPIR-V",
|
||||
program.GetExternalIndex());
|
||||
@@ -7695,7 +7695,7 @@ void main() {
|
||||
m_textureManager->CollectGarbage();
|
||||
auto& frame = m_frameContext.GetCurrent();
|
||||
// See DispatchCompute: the dispatch accessor, not the draw one.
|
||||
const auto& program = *MGB_CTX->GetProgramForDispatch();
|
||||
const auto& program = *MG_Pipe::gPipeInputs.GetProgramForDispatch();
|
||||
if (!program.GetLinkStatus() || !program.GetSpirvStatus()) {
|
||||
MGLOG_E_ONCE("DispatchComputeIndirect skipped: program=%u has no optimized SPIR-V",
|
||||
program.GetExternalIndex());
|
||||
@@ -7741,7 +7741,7 @@ void main() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto indirectBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::DispatchIndirect).GetBoundObject();
|
||||
auto indirectBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DispatchIndirect).GetBoundObject();
|
||||
if (!indirectBuffer) {
|
||||
MGLOG_E_ONCE("DispatchComputeIndirect skipped: GL_DISPATCH_INDIRECT_BUFFER is not bound");
|
||||
return;
|
||||
@@ -7826,10 +7826,10 @@ void main() {
|
||||
|
||||
VkClearRect clearRect{};
|
||||
clearRect.rect = framebuffer.IsDefaultFramebuffer()
|
||||
? MakeDefaultFramebufferScissorRect(MGB_CTX->GetScissorBox(),
|
||||
? MakeDefaultFramebufferScissorRect(MG_Pipe::gPipeInputs.GetScissorBox(),
|
||||
renderPassEntry->extent,
|
||||
m_swapchainObject.GetPreTransform())
|
||||
: MakeClampedScissorRect(MGB_CTX->GetScissorBox(), renderPassEntry->extent);
|
||||
: MakeClampedScissorRect(MG_Pipe::gPipeInputs.GetScissorBox(), renderPassEntry->extent);
|
||||
clearRect.baseArrayLayer = 0;
|
||||
// GL 3.3 §4.4.7: clearing a layered framebuffer clears every layer.
|
||||
clearRect.layerCount = renderPassEntry->layers;
|
||||
@@ -7968,9 +7968,9 @@ void main() {
|
||||
if (!fbo) MagmaWireFatal("clear-framebuffer-record");
|
||||
ClearAttachmentPayload payload{};
|
||||
payload.mask = mask;
|
||||
payload.color = MGB_CTX->GetClearColor();
|
||||
payload.depth = MGB_CTX->GetClearDepth();
|
||||
payload.stencil = MGB_CTX->GetClearStencil();
|
||||
payload.color = MG_Pipe::gPipeInputs.GetClearColor();
|
||||
payload.depth = MG_Pipe::gPipeInputs.GetClearDepth();
|
||||
payload.stencil = MG_Pipe::gPipeInputs.GetClearStencil();
|
||||
ClearWireFramebuffer(*fbo, payload);
|
||||
return;
|
||||
}
|
||||
@@ -7980,10 +7980,10 @@ void main() {
|
||||
return;
|
||||
}
|
||||
// GL 3.3 §3.1: when RASTERIZER_DISCARD is enabled, Clear and ClearBuffer* are ignored.
|
||||
if (MGB_CTX->IsCapabilityEnabled(CapabilityInput::RasterizerDiscard)) {
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::RasterizerDiscard)) {
|
||||
return;
|
||||
}
|
||||
auto* fbo = MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject().get();
|
||||
auto* fbo = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject().get();
|
||||
MOBILEGL_ASSERT(fbo, "VulkanRenderer::Clear: draw framebuffer not found (fbo == nullptr)");
|
||||
if (IsUnsupportedFramebufferForDirectVulkan(*fbo)) {
|
||||
RecordUnsupportedFramebufferError(__func__);
|
||||
@@ -7991,16 +7991,16 @@ void main() {
|
||||
}
|
||||
|
||||
ClearFramebufferPayload payload {
|
||||
.color = MGB_CTX->GetClearColor(),
|
||||
.depth = MGB_CTX->GetClearDepth(),
|
||||
.stencil = MGB_CTX->GetClearStencil()
|
||||
.color = MG_Pipe::gPipeInputs.GetClearColor(),
|
||||
.depth = MG_Pipe::gPipeInputs.GetClearDepth(),
|
||||
.stencil = MG_Pipe::gPipeInputs.GetClearStencil()
|
||||
};
|
||||
|
||||
// A render-pass loadOp clear always covers the complete attachment, while
|
||||
// OpenGL glClear is clipped by GL_SCISSOR_TEST. Blaze3D relies on this for
|
||||
// GuiItemAtlas: animated items clear only their atlas slot before being
|
||||
// redrawn. Queueing that clear as a loadOp erases every cached static item.
|
||||
if (MGB_CTX->IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
VkClearRect clearRect{};
|
||||
switch (PrepareScissoredClear(*fbo, clearRect)) {
|
||||
case ScissoredClearPrep::NoOp:
|
||||
@@ -8023,7 +8023,7 @@ void main() {
|
||||
continue;
|
||||
}
|
||||
|
||||
const BoolVec4 colorMask = MGB_CTX->GetColorMaskIndexed(drawBufferIndex);
|
||||
const BoolVec4 colorMask = MG_Pipe::gPipeInputs.GetColorMaskIndexed(drawBufferIndex);
|
||||
if (!colorMask.r() && !colorMask.g() && !colorMask.b() && !colorMask.a()) {
|
||||
continue;
|
||||
}
|
||||
@@ -8050,7 +8050,7 @@ void main() {
|
||||
}
|
||||
|
||||
VkImageAspectFlags depthStencilAspects = 0;
|
||||
if ((mask & GL_DEPTH_BUFFER_BIT) != 0 && MGB_CTX->GetDepthMask()) {
|
||||
if ((mask & GL_DEPTH_BUFFER_BIT) != 0 && MG_Pipe::gPipeInputs.GetDepthMask()) {
|
||||
const auto& depthAttachment = fbo->GetAttachment(FramebufferAttachmentType::Depth);
|
||||
if (depthAttachment.IsComplete()) {
|
||||
depthStencilAspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
@@ -8063,7 +8063,7 @@ void main() {
|
||||
// vkCmdClearAttachments writes every bit, so only a full (8-bit stencil) or
|
||||
// zero mask can be expressed; treat a partial mask like a partial color mask.
|
||||
const Uint32 stencilWriteMask =
|
||||
MGB_CTX->GetStencilState(StencilFace::Front).WriteMask;
|
||||
MG_Pipe::gPipeInputs.GetStencilState(StencilFace::Front).WriteMask;
|
||||
if ((stencilWriteMask & 0xFFu) == 0xFFu) {
|
||||
depthStencilAspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
} else if (stencilWriteMask != 0) {
|
||||
@@ -8092,11 +8092,11 @@ void main() {
|
||||
// gating for the deferred path: drop fully-masked planes, warn on partial
|
||||
// masks vkCmdClear*/loadOp clears cannot express.
|
||||
GLbitfield deferredMask = mask;
|
||||
if ((deferredMask & GL_DEPTH_BUFFER_BIT) != 0 && !MGB_CTX->GetDepthMask()) {
|
||||
if ((deferredMask & GL_DEPTH_BUFFER_BIT) != 0 && !MG_Pipe::gPipeInputs.GetDepthMask()) {
|
||||
deferredMask &= ~static_cast<GLbitfield>(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
if ((deferredMask & GL_STENCIL_BUFFER_BIT) != 0) {
|
||||
const Uint32 stencilWriteMask = MGB_CTX->GetStencilState(StencilFace::Front).WriteMask;
|
||||
const Uint32 stencilWriteMask = MG_Pipe::gPipeInputs.GetStencilState(StencilFace::Front).WriteMask;
|
||||
if ((stencilWriteMask & 0xFFu) != 0xFFu) {
|
||||
if (stencilWriteMask != 0) {
|
||||
MGLOG_W_ONCE("DirectVulkan: deferred glClear with a partial stencil write mask is not supported");
|
||||
@@ -8112,7 +8112,7 @@ void main() {
|
||||
if (drawBuffers[drawBufferIndex] == FramebufferAttachmentType::None) {
|
||||
continue;
|
||||
}
|
||||
const BoolVec4 colorMask = MGB_CTX->GetColorMaskIndexed(drawBufferIndex);
|
||||
const BoolVec4 colorMask = MG_Pipe::gPipeInputs.GetColorMaskIndexed(drawBufferIndex);
|
||||
const Bool full = colorMask.r() && colorMask.g() && colorMask.b() && colorMask.a();
|
||||
if (full) {
|
||||
anyFullMask = true;
|
||||
@@ -8133,7 +8133,7 @@ void main() {
|
||||
if (attachmentType == FramebufferAttachmentType::None) {
|
||||
continue;
|
||||
}
|
||||
const BoolVec4 colorMask = MGB_CTX->GetColorMaskIndexed(drawBufferIndex);
|
||||
const BoolVec4 colorMask = MG_Pipe::gPipeInputs.GetColorMaskIndexed(drawBufferIndex);
|
||||
if (!(colorMask.r() && colorMask.g() && colorMask.b() && colorMask.a())) {
|
||||
continue;
|
||||
}
|
||||
@@ -8176,7 +8176,7 @@ void main() {
|
||||
const ClearAttachmentPayload& clearPayload) {
|
||||
m_clearManager->CollectGarbage();
|
||||
// GL 3.3 §3.1: when RASTERIZER_DISCARD is enabled, Clear and ClearBuffer* are ignored.
|
||||
if (MGB_CTX->IsCapabilityEnabled(CapabilityInput::RasterizerDiscard)) {
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::RasterizerDiscard)) {
|
||||
return;
|
||||
}
|
||||
if (IsUnsupportedFramebufferForDirectVulkan(framebuffer)) {
|
||||
@@ -8218,7 +8218,7 @@ void main() {
|
||||
}
|
||||
|
||||
// GL 3.3 §4.2.3: ClearBuffer* is clipped by GL_SCISSOR_TEST exactly like Clear.
|
||||
if (MGB_CTX->IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
VkClearRect clearRect{};
|
||||
switch (PrepareScissoredClear(framebuffer, clearRect)) {
|
||||
case ScissoredClearPrep::NoOp:
|
||||
@@ -8250,9 +8250,9 @@ void main() {
|
||||
|
||||
// GL 3.3 §4.2.3: ClearBuffer* honors the write masks like Clear. Deferred
|
||||
// clears cannot express partial masks; warn and skip those.
|
||||
const auto depthClearAllowed = [&]() -> Bool { return MGB_CTX->GetDepthMask(); };
|
||||
const auto depthClearAllowed = [&]() -> Bool { return MG_Pipe::gPipeInputs.GetDepthMask(); };
|
||||
const auto stencilClearAllowed = [&]() -> Bool {
|
||||
const Uint32 stencilWriteMask = MGB_CTX->GetStencilState(StencilFace::Front).WriteMask;
|
||||
const Uint32 stencilWriteMask = MG_Pipe::gPipeInputs.GetStencilState(StencilFace::Front).WriteMask;
|
||||
if ((stencilWriteMask & 0xFFu) == 0xFFu) {
|
||||
return true;
|
||||
}
|
||||
@@ -8264,7 +8264,7 @@ void main() {
|
||||
|
||||
switch (buffer) {
|
||||
case GL_COLOR: {
|
||||
const BoolVec4 colorMask = MGB_CTX->GetColorMaskIndexed(static_cast<Uint32>(drawbuffer));
|
||||
const BoolVec4 colorMask = MG_Pipe::gPipeInputs.GetColorMaskIndexed(static_cast<Uint32>(drawbuffer));
|
||||
if (!colorMask.r() && !colorMask.g() && !colorMask.b() && !colorMask.a()) {
|
||||
return;
|
||||
}
|
||||
@@ -8321,7 +8321,7 @@ void main() {
|
||||
if (!attachment.IsComplete()) {
|
||||
return;
|
||||
}
|
||||
const BoolVec4 colorMask = MGB_CTX->GetColorMaskIndexed(static_cast<Uint>(drawbuffer));
|
||||
const BoolVec4 colorMask = MG_Pipe::gPipeInputs.GetColorMaskIndexed(static_cast<Uint>(drawbuffer));
|
||||
if (!colorMask.r() && !colorMask.g() && !colorMask.b() && !colorMask.a()) {
|
||||
return;
|
||||
}
|
||||
@@ -8339,7 +8339,7 @@ void main() {
|
||||
MakeVkClearColorValue(clearPayload, ColorFormatLacksAlpha(colorTexture));
|
||||
} else {
|
||||
VkImageAspectFlags aspects = 0;
|
||||
if ((clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0 && MGB_CTX->GetDepthMask() &&
|
||||
if ((clearPayload.mask & GL_DEPTH_BUFFER_BIT) != 0 && MG_Pipe::gPipeInputs.GetDepthMask() &&
|
||||
framebuffer.GetAttachment(FramebufferAttachmentType::Depth).IsComplete()) {
|
||||
aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
}
|
||||
@@ -8347,7 +8347,7 @@ void main() {
|
||||
framebuffer.GetAttachment(FramebufferAttachmentType::Stencil).IsComplete()) {
|
||||
// GL 3.3 §4.2.3: the clear is masked by the front stencil write mask (see Clear).
|
||||
const Uint32 stencilWriteMask =
|
||||
MGB_CTX->GetStencilState(StencilFace::Front).WriteMask;
|
||||
MG_Pipe::gPipeInputs.GetStencilState(StencilFace::Front).WriteMask;
|
||||
if ((stencilWriteMask & 0xFFu) == 0xFFu) {
|
||||
aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
} else if (stencilWriteMask != 0) {
|
||||
@@ -8374,7 +8374,7 @@ void main() {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
auto* fbo = MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject().get();
|
||||
auto* fbo = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject().get();
|
||||
if (!fbo) {
|
||||
return;
|
||||
}
|
||||
@@ -9511,8 +9511,8 @@ void main() {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
auto readFbo = MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||
auto drawFbo = MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
auto readFbo = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||
auto drawFbo = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
BlitNamedFramebuffer(readFbo, drawFbo, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
||||
}
|
||||
|
||||
@@ -9544,8 +9544,8 @@ void main() {
|
||||
|
||||
// The scissor test clips blit writes: intersect the destination rectangle with
|
||||
// the scissor box and shrink the source proportionally.
|
||||
if (MGB_CTX->IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
const IntVec4& scissor = MGB_CTX->GetScissorBox();
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
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;
|
||||
@@ -10169,7 +10169,7 @@ void main() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& textureUnit = MGB_CTX->GetTextureUnitObject(MGB_CTX->GetActiveTextureUnit());
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(MG_Pipe::gPipeInputs.GetActiveTextureUnit());
|
||||
auto destinationTexture = textureUnit.GetBindingSlot(textureTarget).GetBoundObject();
|
||||
if (destinationTexture == nullptr) {
|
||||
RecordTextureCopyError(__func__, ErrorCode::InvalidOperation,
|
||||
@@ -10177,7 +10177,7 @@ void main() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto readFbo = MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||
auto readFbo = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||
if (readFbo == nullptr) {
|
||||
RecordTextureCopyError(__func__, ErrorCode::InvalidOperation,
|
||||
"CopyTexSubImage2D requires a framebuffer bound to GL_READ_FRAMEBUFFER.");
|
||||
@@ -11076,7 +11076,7 @@ void main() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto readFbo = MGB_CTX->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||
auto readFbo = MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||
if (readFbo == nullptr) {
|
||||
MGLOG_E_ONCE("DirectVulkan::ReadPixels skipped: no read framebuffer is bound");
|
||||
return;
|
||||
@@ -11771,8 +11771,8 @@ void main() {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
MG_Config::Transport != MG_Config::TransportMode::Monolith ? wireReplyHasNoPackBuffer :
|
||||
#endif
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
const auto packParams = MGB_CTX->GetPixelStoreParameters(false);
|
||||
MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
|
||||
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;
|
||||
@@ -11802,7 +11802,7 @@ void main() {
|
||||
void VulkanRenderer::GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
|
||||
const auto textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
||||
const auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
||||
auto& activeUnit = MGB_CTX->GetTextureUnitObject(MGB_CTX->GetActiveTextureUnit());
|
||||
auto& activeUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(MG_Pipe::gPipeInputs.GetActiveTextureUnit());
|
||||
auto textureObject = activeUnit.GetBindingSlot(textureTarget).GetBoundObject();
|
||||
GetTextureImage(textureObject, textureUploadTarget, level, format, type, -1, pixels);
|
||||
}
|
||||
@@ -12074,7 +12074,7 @@ void main() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& textureUnit = MGB_CTX->GetTextureUnitObject(MGB_CTX->GetActiveTextureUnit());
|
||||
auto& textureUnit = MG_Pipe::gPipeInputs.GetTextureUnitObject(MG_Pipe::gPipeInputs.GetActiveTextureUnit());
|
||||
auto texture = textureUnit.GetBindingSlot(textureTarget).GetBoundObject();
|
||||
MOBILEGL_ASSERT(texture != nullptr, "GenerateMipmap requires a bound texture.");
|
||||
MOBILEGL_ASSERT(texture->IsComplete(), "GenerateMipmap requires a complete texture.");
|
||||
@@ -12380,7 +12380,7 @@ void main() {
|
||||
// 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 = MGB_CTX->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");
|
||||
@@ -12397,7 +12397,7 @@ void main() {
|
||||
Uint32 slot = freeSlot;
|
||||
if (slot == kNoSlot) {
|
||||
for (Uint32 candidate = 0; candidate < kNoSlot; ++candidate) {
|
||||
if (MGB_CTX->HasOpenTransformFeedbackSpan(m_xfbCounterSlotOwner[candidate])) {
|
||||
if (MG_Pipe::gPipeInputs.HasOpenTransformFeedbackSpan(m_xfbCounterSlotOwner[candidate])) {
|
||||
continue;
|
||||
}
|
||||
if (slot == kNoSlot || m_xfbCounterSlotLastUse[candidate] < m_xfbCounterSlotLastUse[slot]) {
|
||||
@@ -12428,14 +12428,14 @@ void main() {
|
||||
}
|
||||
|
||||
Bool VulkanRenderer::BeginXfbCaptureForDraw(FrameContext::FrameData& frame) {
|
||||
if (!m_transformFeedbackFeatureEnabled || !MGB_CTX_LIVE ||
|
||||
!MGB_CTX->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 (MGB_CTX->IsTransformFeedbackPaused()) {
|
||||
if (MG_Pipe::gPipeInputs.IsTransformFeedbackPaused()) {
|
||||
return false;
|
||||
}
|
||||
// The bound pipeline's last pre-rasterization stage has to have been declared with Xfb
|
||||
@@ -12455,7 +12455,7 @@ void main() {
|
||||
if (MG_Config::Transport != MG_Config::TransportMode::Monolith)
|
||||
return BeginWireXfbCaptureForDraw(frame);
|
||||
#endif
|
||||
const auto& program = MGB_CTX->GetTransformFeedbackProgram();
|
||||
const auto& program = MG_Pipe::gPipeInputs.GetTransformFeedbackProgram();
|
||||
if (!program || program->GetTransformFeedbackVaryingCount() == 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -12469,7 +12469,7 @@ void main() {
|
||||
VkDeviceSize sizes[4] = {};
|
||||
for (SizeT i = 0; i < bufferCount; ++i) {
|
||||
if (!program->GetTransformFeedbackStride(static_cast<Uint>(i))) continue;
|
||||
auto& point = MGB_CTX->GetBufferBindingPoint(BufferTarget::TransformFeedback,
|
||||
auto& point = MG_Pipe::gPipeInputs.GetBufferBindingPoint(BufferTarget::TransformFeedback,
|
||||
static_cast<Uint>(i));
|
||||
const auto& bufferObject = point.GetBoundObject();
|
||||
if (bufferObject == nullptr) {
|
||||
@@ -12525,7 +12525,7 @@ void main() {
|
||||
}
|
||||
|
||||
const Uint32 counterSlot = CurrentXfbCounterSlot();
|
||||
const Uint64 generation = MGB_CTX->GetTransformFeedbackGeneration();
|
||||
const Uint64 generation = MG_Pipe::gPipeInputs.GetTransformFeedbackGeneration();
|
||||
const Bool resume = m_xfbCountersValid[counterSlot] && m_xfbLastSeenGeneration[counterSlot] == generation;
|
||||
m_xfbLastSeenGeneration[counterSlot] = generation;
|
||||
|
||||
@@ -13199,7 +13199,7 @@ void main() {
|
||||
default: break;
|
||||
}
|
||||
if (mergeGranularity != 0) {
|
||||
const RenderStateParameters& rsp = MGB_CTX->GetRenderStateParameters();
|
||||
const RenderStateParameters& rsp = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
if (rsp.PrimitiveRestartEnabled || rsp.PrimitiveRestartFixedIndexEnabled) {
|
||||
mergeGranularity = 0;
|
||||
}
|
||||
@@ -13277,7 +13277,7 @@ void main() {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& vao = *MGB_CTX->GetBoundVertexArray();
|
||||
const auto& vao = *MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
const auto* indexBuffer = vao.GetIndexBufferBindingSlot().GetBoundObject().get();
|
||||
if (!indexBuffer) {
|
||||
MGLOG_E_ONCE("MultiDrawElementsIndirectCount skipped: no element array buffer is bound");
|
||||
@@ -13287,13 +13287,13 @@ void main() {
|
||||
const SizeT commandOffset = reinterpret_cast<SizeT>(indirect);
|
||||
const SizeT commandBytes = commandOffset +
|
||||
static_cast<SizeT>(stride) * static_cast<SizeT>(maxdrawcount - 1) + kGLDrawElementsIndirectCommandBytes;
|
||||
auto drawBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
auto drawBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (!drawBuffer || commandBytes > drawBuffer->GetSize()) {
|
||||
MGLOG_E_ONCE("MultiDrawElementsIndirectCount skipped: invalid GL_DRAW_INDIRECT_BUFFER binding or range");
|
||||
return;
|
||||
}
|
||||
|
||||
auto parameterBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::Parameter).GetBoundObject();
|
||||
auto parameterBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::Parameter).GetBoundObject();
|
||||
if (!parameterBuffer || static_cast<SizeT>(drawcount) + sizeof(Uint32) > parameterBuffer->GetSize()) {
|
||||
MGLOG_E_ONCE("MultiDrawElementsIndirectCount skipped: invalid GL_PARAMETER_BUFFER binding or range");
|
||||
return;
|
||||
@@ -13378,7 +13378,7 @@ void main() {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& vao = *MGB_CTX->GetBoundVertexArray();
|
||||
const auto& vao = *MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
const auto* indexBuffer = vao.GetIndexBufferBindingSlot().GetBoundObject().get();
|
||||
if (!indexBuffer) {
|
||||
MGLOG_E_ONCE("MultiDrawElementsIndirect skipped: no element array buffer is bound");
|
||||
@@ -13388,7 +13388,7 @@ void main() {
|
||||
const SizeT commandOffset = reinterpret_cast<SizeT>(indirect);
|
||||
const SizeT commandBytes = commandOffset +
|
||||
static_cast<SizeT>(stride) * static_cast<SizeT>(drawcount - 1) + kGLDrawElementsIndirectCommandBytes;
|
||||
auto drawBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
auto drawBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (!drawBuffer || commandBytes > drawBuffer->GetSize()) {
|
||||
MGLOG_E_ONCE("MultiDrawElementsIndirect skipped: invalid GL_DRAW_INDIRECT_BUFFER binding or range");
|
||||
return;
|
||||
@@ -13458,7 +13458,7 @@ void main() {
|
||||
const SizeT commandOffset = reinterpret_cast<SizeT>(indirect);
|
||||
const SizeT commandBytes = commandOffset +
|
||||
static_cast<SizeT>(stride) * static_cast<SizeT>(drawcount - 1) + kGLDrawArraysIndirectCommandBytes;
|
||||
auto drawBuffer = MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
auto drawBuffer = MG_Pipe::gPipeInputs.GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (!drawBuffer || commandBytes > drawBuffer->GetSize()) {
|
||||
MGLOG_E_ONCE("MultiDrawArraysIndirect skipped: invalid GL_DRAW_INDIRECT_BUFFER binding or range");
|
||||
return;
|
||||
@@ -13475,7 +13475,7 @@ void main() {
|
||||
// MONOLITH ONLY: with a transport the frontend VAO is not this side's to read at all
|
||||
// (the client owns those bytes and stages them itself), and this runs on the apply thread.
|
||||
if (MG_Config::Transport == MG_Config::TransportMode::Monolith) {
|
||||
const auto& currentVAO = MGB_CTX->GetBoundVertexArray();
|
||||
const auto& currentVAO = MG_Pipe::gPipeInputs.GetBoundVertexArray();
|
||||
Bool clientArray = false;
|
||||
if (currentVAO) {
|
||||
for (const auto& attribute : currentVAO->GetAllAttributes()) {
|
||||
@@ -14347,8 +14347,8 @@ void main() {
|
||||
if (!m_provokingVertexModePerPipeline) {
|
||||
return VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT;
|
||||
}
|
||||
return (MGB_CTX_LIVE &&
|
||||
MGB_CTX->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;
|
||||
}
|
||||
|
||||
@@ -176,7 +176,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,
|
||||
MGB_CTX->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;
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
|
||||
ProgramFactory::CompileOptionFlags flags =
|
||||
ProgramFactory::CompileOptionFlags(GetBaseTransformFlagsRaw(fbo->IsDefault));
|
||||
if (m_transformFeedbackFeatureEnabled && MGB_CTX->IsTransformFeedbackActive() &&
|
||||
if (m_transformFeedbackFeatureEnabled && MG_Pipe::gPipeInputs.IsTransformFeedbackActive() &&
|
||||
program.GetTransformFeedbackVaryingCount() > 0)
|
||||
flags |= ProgramFactory::CompileOptionBit::XfbCapture;
|
||||
const auto* programObject = &m_programFactory->GetOrCreateProgram(program, flags);
|
||||
@@ -399,7 +399,7 @@
|
||||
return false;
|
||||
}
|
||||
indexType = width == 4 ? VK_INDEX_TYPE_UINT32 : width == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT8;
|
||||
const auto& restart = MGB_CTX->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;
|
||||
@@ -485,7 +485,7 @@
|
||||
Uint64 passHash = 0;
|
||||
WireDrawPassKey passKey{};
|
||||
passKey.isDefault = fbo->IsDefault;
|
||||
passKey.framebufferSrgb = MGB_CTX->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
|
||||
@@ -500,7 +500,7 @@
|
||||
m_textureManager->FlushPendingUploads();
|
||||
if (aspect == VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
image.format = ResolveSrgbAttachmentWriteFormat(image.format,
|
||||
MGB_CTX->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
|
||||
@@ -632,7 +632,7 @@
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
const void* data = nullptr;
|
||||
VkDeviceSize size = 0;
|
||||
if (!TryGetCurrentVertexAttributeUploadPayload(MGB_CTX->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;
|
||||
|
||||
@@ -240,12 +240,12 @@
|
||||
if (m_wireRetiredObjects.size() >= kRetiredObjectsBeforeSubmit && m_wirePreparationDepth == 0 &&
|
||||
HasPendingRecordedWork())
|
||||
(void)FlushPendingCommands();
|
||||
if (MGB_CTX->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 = MGB_CTX->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");
|
||||
@@ -253,10 +253,10 @@
|
||||
}
|
||||
}
|
||||
if (aspect & VK_IMAGE_ASPECT_DEPTH_BIT) {
|
||||
if (!MGB_CTX->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 = MGB_CTX->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");
|
||||
@@ -268,8 +268,8 @@
|
||||
if (!image.image) return;
|
||||
m_textureManager->FlushPendingUploads();
|
||||
VkRect2D area{{0, 0}, image.extent};
|
||||
if (MGB_CTX->IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
const auto& box = MGB_CTX->GetScissorBox();
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
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));
|
||||
@@ -917,8 +917,8 @@
|
||||
RetireWireDrawPass();
|
||||
// The scissor test clips blit writes: intersect the destination rectangle with
|
||||
// the scissor box and shrink the source proportionally.
|
||||
if (MGB_CTX->IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
const IntVec4& scissor = MGB_CTX->GetScissorBox();
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
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;
|
||||
|
||||
@@ -37,9 +37,9 @@ namespace MobileGL::MG_Pipe {
|
||||
// TABLE 2 (CONTRACT-P5.md section 3, R-7): the four ownership classes, one per field, plus
|
||||
// the seven sticky forwards' own rows. Included HERE rather than from MG_Pipe/MGPipe.h with
|
||||
// gen_pipe.py's seven outputs, deliberately: MGPipe.h is in the PULL build's include closure
|
||||
// and G1 admits no symbol motion there, while this header is reached only through
|
||||
// PipeInputsSwitch.h's MOBILEGL_PIPE_PUSH arm. It is also exactly the header the poison check
|
||||
// below and the server's verb stamp both already see.
|
||||
// and G1 admitted no symbol motion there (until P13 retired the pull build), while this header is
|
||||
// what the backends include directly. It is also exactly the header the poison check below and the
|
||||
// server's verb stamp both already see.
|
||||
#include <MG_Pipe/generated/PipeFieldOwnership.inc>
|
||||
|
||||
// PipeInputs.cpp. The poison Fatal with the verb's name ("<none>" before the first
|
||||
@@ -255,11 +255,11 @@ namespace MobileGL::MG_Pipe {
|
||||
};
|
||||
|
||||
// ---- identity / liveness (not fields) ----
|
||||
// Whether a live GLContext exists. Forwarded (PipeFill.cpp): under push MGB_CTX_LIVE
|
||||
// Whether a live GLContext exists. Forwarded (PipeFill.cpp): under push gPipeInputs
|
||||
// must be true as soon as a context exists, fill or no fill, which is what today's
|
||||
// null-context guards test.
|
||||
Bool IsLive() const;
|
||||
// The live GLContext's address at the last fill; serves MGB_CTX_IDENTITY.
|
||||
// The live GLContext's address at the last fill; serves gPipeInputs.
|
||||
const void* ContextIdentity() const { return m_contextIdentity; }
|
||||
// The verb of the last fill, kVerbCount before the first one.
|
||||
MGPipeVerb CurrentVerb() const { return m_currentVerb; }
|
||||
@@ -442,7 +442,7 @@ namespace MobileGL::MG_Pipe {
|
||||
// BufferTarget, and Coverage.def:62-69 already rules that such a field stays ONE row.
|
||||
// Only [0] (pack) has a carrier - set_pixel_pack_state, which the applier writes
|
||||
// (PipeApply.cpp:1373) - so the field is APPLIER-DERIVED and the UNPACK half is FATAL:
|
||||
// every MGB_CTX->GetPixelStoreParameters site in the tree passes false
|
||||
// every gPipeInputs->GetPixelStoreParameters site in the tree passes false
|
||||
// (DirectGLES.cpp:7924, :9399, :10893, :11272, Utils.cpp:2302,
|
||||
// VulkanRenderer.cpp:10980), and PipeFill.cpp's EmitPixelPackState says the same from
|
||||
// the other side: "nothing on the far side of the boundary reads unpack state".
|
||||
@@ -822,7 +822,7 @@ namespace MobileGL::MG_Pipe {
|
||||
TextureUnit* m_textureUnitBase = nullptr;
|
||||
};
|
||||
|
||||
// The single global the backends read through MGB_CTX (ARCHITECTURE.md 9.2). An inline
|
||||
// The single global the backends read through gPipeInputs (ARCHITECTURE.md 9.2). An inline
|
||||
// variable: no .cpp is needed for the definition.
|
||||
//
|
||||
// P14 S2: IT IS THE PROCESS-WIDE BLOCK, and `gPipeInputs` below is the name every reader
|
||||
@@ -850,15 +850,15 @@ namespace MobileGL::MG_Pipe {
|
||||
// ============================================================================
|
||||
//
|
||||
// ONE PROCESS, SEVERAL SERVED SESSIONS. The applier writes this block and the backend reads it
|
||||
// through MGB_CTX, both on the SAME apply thread - the block IS "the state the record in hand
|
||||
// through gPipeInputs, both on the SAME apply thread - the block IS "the state the record in hand
|
||||
// carries". Two sessions applying concurrently on two apply threads through one block would
|
||||
// read each other's render state, which is the cross-talk a multi-session server must not
|
||||
// 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. MGB_CTX is
|
||||
// `(&::MobileGL::MG_Pipe::gPipeInputs)` (MG_Pipe/PipeInputsSwitch.h) and is spelled at ~380
|
||||
// sites in MG_Backend/MG_Impl; a reference whose TARGET varies with the calling thread is the
|
||||
// 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.
|
||||
@@ -902,7 +902,7 @@ namespace MobileGL::MG_Pipe {
|
||||
// dual-block arm, PipeInputs.cpp) instead of a silent cross-role answer.
|
||||
//
|
||||
// THE READ SIDE'S SPELLING DOES NOT MOVE. gPipeInputs remains the server-role block, so the
|
||||
// 379 MGB_CTX sites and PipeApply.cpp's applier writes are untouched; the only new spelling
|
||||
// 379 gPipeInputs sites and PipeApply.cpp's applier writes are untouched; the only new spelling
|
||||
// is on the fill side (MG_Impl/Pipe/PipeFill.cpp), which asks MGPipeClientInputs(). Under
|
||||
// monolith transport - every unit and integration-gpu lane of a split build - the selection
|
||||
// folds back to the single shared block and behaviour is byte-for-byte the old one.
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
// THE CONTEXT ID IS GLContext::GetTextureContextId() AND NOTHING ELSE - the tree's existing
|
||||
// never-reused per-context id (TextureState::AllocateContextId; PipeInputs carries it as
|
||||
// m_textureContextId at seven fill points and the backends' own per-context memos key on it).
|
||||
// Deliberately NOT the GLContext ADDRESS that MGB_CTX_IDENTITY and MGPipeTracker::m_context
|
||||
// Deliberately NOT the GLContext ADDRESS that gPipeInputs and MGPipeTracker::m_context
|
||||
// compare, because Core.h states the reason that id exists at all: a context freed and remade
|
||||
// lands on the old heap address, which would put this same defect back one context recreation
|
||||
// later.
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
// emit[fbe= sve= sse= sie= ctu=] bracket therefore carries a NON-ZERO total.
|
||||
//
|
||||
// off (MOBILEGL_PIPE_PUSH=0x1ff, P3a's default = P4a's four subsystems cleared)
|
||||
// The frontend dispatch falls through to the legacy MGB_CTX-reading arms, nothing is emitted
|
||||
// The frontend dispatch falls through to the legacy gPipeInputs-reading arms, nothing is emitted
|
||||
// through any of the four families, and every one of those five counters must read ZERO.
|
||||
// This is the reading a dead switch fails: with the bits ignored, this lane would report the
|
||||
// same non-zero counts as the other one.
|
||||
@@ -540,7 +540,7 @@ void main() { oColor = texture(uTex, vUv); }
|
||||
} else if (m_lane == kLaneOff) {
|
||||
EXPECT_EQ(total, 0)
|
||||
<< "with bits 9|10|11|12 CLEARED (MOBILEGL_PIPE_PUSH=0x1ff, P3a's default) the "
|
||||
"frontend dispatch must fall through to the legacy MGB_CTX-reading arms and "
|
||||
"frontend dispatch must fall through to the legacy (&MG_Pipe::gPipeInputs)-reading arms and "
|
||||
"emit nothing through any of the four P4a families, so every counter in the "
|
||||
"emit[] bracket must be zero. A non-zero count here is the dead-switch "
|
||||
"reading: the bits are being ignored, both arms run the same code, and every "
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
// as GetBufferBindingSlot is m_bufferBindingSlot[15] indexed by its BufferTarget. Only [0]
|
||||
// (pack) has a carrier, and the applier writes it.
|
||||
//
|
||||
// AND THE UNPACK HALF HAS NO BACKEND READER AT ALL. Every MGB_CTX->GetPixelStoreParameters
|
||||
// AND THE UNPACK HALF HAS NO BACKEND READER AT ALL. Every gPipeInputs->GetPixelStoreParameters
|
||||
// call site in the tree passes `false`: DirectGLES.cpp:7924, :9399, :10893, :11272,
|
||||
// Utils.cpp:2302 and VulkanRenderer.cpp:10980 - six, not the five the scout named, and the
|
||||
// scout did not open them. PipeFill.cpp's own EmitPixelPackState says the same thing from
|
||||
@@ -80,7 +80,7 @@
|
||||
// way it is a named abort on the first read.
|
||||
#define MGP_FIELD_OWNERSHIP_ARG_LIST(X) \
|
||||
X(GetPixelStoreParameters, 1, FATAL, \
|
||||
"the unpack half has no carrier AND no backend reader; all six MGB_CTX sites pass false")
|
||||
"the unpack half has no carrier AND no backend reader; all six (&MG_Pipe::gPipeInputs) sites pass false")
|
||||
|
||||
// X(WireOp, Verb) - WHERE THE SERVER STAMPS.
|
||||
//
|
||||
|
||||
@@ -1538,7 +1538,7 @@ namespace MobileGL::MG_Pipe {
|
||||
// DstGlName CopyImageSubData takes two CopyImageEndpoints, each a frontend SharedPtr,
|
||||
// and the server has none. Under inproc and the verb barrier the server
|
||||
// rebuilds a TEXTURE endpoint from the GL name through the barrier-pulled
|
||||
// sticky forward MGB_CTX->GetTextureObject(name) (counted in `rsp`,
|
||||
// sticky forward gPipeInputs->GetTextureObject(name) (counted in `rsp`,
|
||||
// retired by P7 / P3b-P4b when the backend takes handles). A GL name is
|
||||
// NEVER an identity (section 4.2.1); it is the lookup key of a pull the
|
||||
// handle beside it will replace. No forward hands out a renderbuffer,
|
||||
|
||||
@@ -218,7 +218,7 @@ struct MGPipeFieldArgumentOwnership {
|
||||
inline constexpr SizeT kMGPipeFieldArgumentOwnershipCount = 1;
|
||||
inline constexpr MGPipeFieldArgumentOwnership
|
||||
kMGPipeFieldArgumentOwnership[kMGPipeFieldArgumentOwnershipCount] = {
|
||||
{MGPipeInputField::GetPixelStoreParameters, 1u, MGPipeFieldOwnership::kFatal}, // the unpack half has no carrier AND no backend reader; all six MGB_CTX sites pass false
|
||||
{MGPipeInputField::GetPixelStoreParameters, 1u, MGPipeFieldOwnership::kFatal}, // the unpack half has no carrier AND no backend reader; all six gPipeInputs sites pass false
|
||||
};
|
||||
|
||||
constexpr MGPipeFieldOwnership MGPipeFieldOwnershipOf(MGPipeInputField field) {
|
||||
|
||||
@@ -2308,7 +2308,7 @@ namespace MobileGL::MG_Remote::Client {
|
||||
//
|
||||
// WITH ONE NAMED EXCEPTION, FOUND BY ITS OWN FATAL (P5d round 3): generate_mipmap is
|
||||
// catalogued kCtxObject, but its sink is the backend's GenerateMipmap, which reads
|
||||
// MGB_CTX->GetActiveTextureUnit() and the unit's binding slot - residual inputs whose
|
||||
// gPipeInputs->GetActiveTextureUnit() and the unit's binding slot - residual inputs whose
|
||||
// freshness is the CLIENT's verb serial. Published without a wait, the record sits in
|
||||
// the ring while this thread runs the next verb's MGPipeValidateForVerb, which moves
|
||||
// that serial and withdraws the server stamp; the apply thread then reads the unit
|
||||
@@ -2317,7 +2317,7 @@ namespace MobileGL::MG_Remote::Client {
|
||||
// spin no longer read the clock). So it waits, exactly as the four stamping verbs
|
||||
// do. The rule this encodes: a record may skip its wait only if its apply reads
|
||||
// nothing the residual fill writes - the value carried in the payload is the whole
|
||||
// input. No other kCtxObject row has a backend body behind it that reads MGB_CTX
|
||||
// input. No other kCtxObject row has a backend body behind it that reads gPipeInputs
|
||||
// (set_texture_params, resource_subdata, resource_readback and get_texture_image
|
||||
// own reply slots and wait anyway; the resource_* transfers and object_death resolve
|
||||
// by handle).
|
||||
|
||||
@@ -1266,7 +1266,7 @@ namespace MobileGL::MG_Remote::Client {
|
||||
// The unit's binding is the frontend's and has just been written by the caller, so
|
||||
// the texture this record names is the one the server's SyncImageTextureBinding
|
||||
// will pull for the same unit. Read from MG_State::pGLContext and NOT through
|
||||
// MGB_CTX: on this side of a split MGB_CTX is gPipeInputs, which is the SERVER's
|
||||
// gPipeInputs: on this side of a split gPipeInputs is gPipeInputs, which is the SERVER's
|
||||
// view, and the client asking it a question is how the two halves come to disagree.
|
||||
if (MG_State::pGLContext != nullptr) {
|
||||
record.Res = PublishedTextureHandle(
|
||||
|
||||
@@ -573,7 +573,7 @@ namespace MobileGL::MG_Remote::Server {
|
||||
// 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
|
||||
// MGB_CTX->GetPixelStoreParameters); the read is synchronous on this thread, so the window
|
||||
// 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);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// session per process was a property of every file that named them. This slice gives each served
|
||||
// session its own {ServerSession, ServerLoop, PipeInputs} triple, held here, and resolves the two
|
||||
// singleton accessors through the CALLING THREAD's session - which is what makes the ~900 sites
|
||||
// that spell gPipeInputs, MGB_CTX, ServerSession::Active() or ServerLoopInstance() find the right
|
||||
// that spell gPipeInputs, gPipeInputs, ServerSession::Active() or ServerLoopInstance() find the right
|
||||
// one without one line of any of them moving.
|
||||
//
|
||||
// WHO IS A SESSION THREAD. Two threads per session, both created by the session itself:
|
||||
@@ -78,7 +78,7 @@ namespace MobileGL::MG_Remote::Server {
|
||||
void InstallSessionRuntimeHooks();
|
||||
|
||||
// THE SCOPE. Makes `runtime` the calling thread's session for as long as it lives: the
|
||||
// session/loop the singleton accessors answer with, the PipeInputs block MGB_CTX reads,
|
||||
// session/loop the singleton accessors answer with, the PipeInputs block gPipeInputs reads,
|
||||
// this session's segment resolver and this session's latch domain. Restores what was there
|
||||
// before on the way out (two nested scopes are not a shape anything uses, but a thread that
|
||||
// served one session and is then reused must not keep answering with the dead one).
|
||||
|
||||
@@ -5262,7 +5262,7 @@ TEST(DirectGLESVertexInputDraw, TheAttributeWalkTakesItsBuffersFromTheRecordNotT
|
||||
// THE FRONTEND, MOVED ON: every enabled attribute now points at C, and nothing was
|
||||
// re-emitted. A walk that read GetAllAttributes() answers {C}. The VAO is BOUND IN A REAL
|
||||
// CONTEXT rather than free-standing, because that is the only shape in which the revert
|
||||
// this case exists to catch - MGB_CTX->GetBoundVertexArray()->GetAllAttributes() - has
|
||||
// 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);
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace MobileGL::MG_Test {
|
||||
//
|
||||
// A unit test that constructs a GLContext by hand and then calls a BACKEND helper
|
||||
// directly enters through no GL entry point, so no MGP_FILL ever fires (P1 brief D7) and
|
||||
// in a push build the PipeInputs block the helper's MGB_CTX reads is empty and unstamped:
|
||||
// in a push build the PipeInputs block the helper's gPipeInputs reads is empty and unstamped:
|
||||
// its first accessor read is Fatal{UnmigratedPipeInput, "Field@<none>"}. The test is
|
||||
// right and the poison is right - what was missing is the verb, and this object is how a
|
||||
// test states it. Constructing it runs the real filler for `verb`, exactly the call
|
||||
@@ -30,7 +30,7 @@ namespace MobileGL::MG_Test {
|
||||
// scope ends. That matters when the suite runs as one process (a developer running
|
||||
// the test binary directly, rather than one ctest entry per case): without it, one
|
||||
// case's declaration would cover a later case that forgot to make one;
|
||||
// - it is a no-op in the pull build, where MGB_CTX is the live context and there is
|
||||
// - it is a no-op in the pull build, where gPipeInputs is the live context and there is
|
||||
// nothing to fill, so the pull build stays byte-identical.
|
||||
//
|
||||
// Place it the way MGP_FILL is placed in production (P1 brief D7): immediately BEFORE the
|
||||
|
||||
+4
-4
@@ -32,7 +32,7 @@ from the catalogue (they all consume the same .def).
|
||||
Both modes refuse a catalogue whose call payload has no field list in PipeFields.def: a
|
||||
payload the G4 comparator cannot see is a payload MOBILEGL_PIPE_VERIFY is blind to. Both
|
||||
also refuse a field list that does not name every data member of its struct (or names one
|
||||
that is not a member), and a backend accessor read through MGB_CTX-> / pGLContext-> that
|
||||
that is not a member), and a backend accessor read through gPipeInputs-> / pGLContext-> that
|
||||
has no Coverage.def row (P1 brief D8, D12).
|
||||
"""
|
||||
|
||||
@@ -463,10 +463,10 @@ def check_field_lists_cover_struct_members(field_lists, payloads, header_texts=N
|
||||
sys.exit("PipeFields.def does not cover its structs:\n " + "\n ".join(problems))
|
||||
|
||||
|
||||
ACCESSOR_READ_RE = re.compile(r"\b(?:MGB_CTX|pGLContext)\s*->\s*(\w+)")
|
||||
ACCESSOR_READ_RE = re.compile(r"\b(?:gPipeInputs\.|pGLContext)\s*->\s*(\w+)")
|
||||
|
||||
|
||||
# The scanner's NAMED exemptions: accessors a backend reads through MGB_CTX-> / pGLContext->
|
||||
# The scanner's NAMED exemptions: accessors a backend reads through gPipeInputs-> / pGLContext->
|
||||
# that are NOT PipeInputs fields and never will be, each with the reason written down. A name
|
||||
# here is a DEBT ENTRY, not a silence: it exists so the gate can tell "scoped, named, phased"
|
||||
# from "forgot the row".
|
||||
@@ -486,7 +486,7 @@ SCAN_EXEMPT_ACCESSORS = {
|
||||
|
||||
|
||||
def scan_live_accessors(accessors, backend_dir=None, verbose=True):
|
||||
"""Every accessor a backend reads through MGB_CTX-> or pGLContext-> (comments and
|
||||
"""Every accessor a backend reads through gPipeInputs-> or pGLContext-> (comments and
|
||||
strings masked) must have a Coverage.def row - a read without a row is a PipeInputs
|
||||
field that does not exist. Rows no backend reads are printed, not refused (the dead
|
||||
GetBoundTransformFeedbackName row is deliberate). Returns the set of names read."""
|
||||
|
||||
Reference in New Issue
Block a user