fix: freeze particle gpu state in static mode
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled

This commit is contained in:
OpenAI Codex
2026-08-30 07:32:09 +08:00
parent ba488f8702
commit 364b8f381e
2 changed files with 57 additions and 5 deletions

View File

@@ -46,6 +46,7 @@ enum class ValidationPass : uint8_t {
State = 0,
Trail = 1,
Composite = 2,
FrozenComposite = 3,
};
const char* slotName(const uint8_t slot) {
@@ -76,6 +77,7 @@ public:
bool trailSeeded = false;
bool pending = false;
bool contextDestroyed = false;
bool staticFreezeLogged = false;
Size trailSize{};
std::array<RenderTargetPtr, 2> stateTargets;
@@ -147,7 +149,8 @@ public:
drawable.setTexture(source, shaders::idParticleGpuValidationPreviousTexture);
const float frame = static_cast<float>(resources->committedFrame + 1);
const bool frozen = pass == ValidationPass::FrozenComposite;
const float frame = static_cast<float>(resources->committedFrame + (frozen ? 0 : 1));
const float markerX = 0.5f + 0.32f * std::sin(frame * 0.071f);
const float markerY = 0.5f + 0.32f * std::cos(frame * 0.053f);
const shaders::ParticleGpuValidationUBO ubo = {
@@ -156,7 +159,23 @@ public:
};
drawable.mutableUniformBuffers().createOrUpdate(shaders::idParticleGpuValidationUBO, &ubo, parameters.context);
if (pass == ValidationPass::Composite) {
if (pass == ValidationPass::Composite || pass == ValidationPass::FrozenComposite) {
if (pass == ValidationPass::FrozenComposite) {
if (!resources->staticFreezeLogged) {
const auto size = parameters.state.getSize();
std::ostringstream message;
message << "ParticleValidation30_02: STATIC frozen composite generation=" << resources->generation
<< " frame=" << resources->committedFrame << " stateRead=" << slotName(resources->stateRead)
<< " trailRead=" << slotName(resources->trailRead)
<< " offscreenPasses=0 swap=false viewport=" << size.width << 'x' << size.height
<< " zoom=" << parameters.state.getZoom() << " bearing=" << parameters.state.getBearing()
<< " pitch=" << parameters.state.getPitch();
Log::Info(Event::Render, message.str());
resources->staticFreezeLogged = true;
}
return;
}
const auto beforeState = resources->stateRead;
const auto beforeTrail = resources->trailRead;
resources->commit();
@@ -241,8 +260,9 @@ bool buildQuad(gfx::Context& context,
builder->setShader(resources->shader);
builder->setRenderPass(RenderPass::Translucent);
builder->setEnableDepth(false);
builder->setColorMode(pass == ValidationPass::Composite ? gfx::ColorMode::alphaBlended()
: gfx::ColorMode::unblended());
builder->setColorMode(pass == ValidationPass::Composite || pass == ValidationPass::FrozenComposite
? gfx::ColorMode::alphaBlended()
: gfx::ColorMode::unblended());
builder->setCullFaceMode(gfx::CullFaceMode::disabled());
builder->setVertexAttributes(std::move(attributes));
builder->setRawVertices({}, resources->vertices->elements(), gfx::AttributeDataType::Short2);
@@ -345,8 +365,16 @@ void RenderParticleValidationLayer::update(gfx::ShaderRegistry& shaders,
return;
}
const bool active = static_cast<const style::ParticleValidationLayerProperties&>(*evaluatedProperties).active;
auto resources = gpuValidation;
if (!resources) {
if (!active) {
// STATIC without a preceding ACTIVE frame has no trail to show. Do not create,
// clear, or advance offscreen resources merely because the map redraws.
static_cast<LayerGroup&>(*layerGroup).clearDrawables();
return;
}
auto owned = std::make_shared<ParticleGpuValidationResources>();
owned->generation = ++nextGpuGeneration;
owned->shader = context.getGenericShader(shaders, ShaderName);
@@ -371,6 +399,29 @@ void RenderParticleValidationLayer::update(gfx::ShaderRegistry& shaders,
removeTargets(resources->registeredTargets, changes);
resources->registeredTargets.clear();
if (!active) {
// Map gestures must still redraw the main pass, but STATIC is a simulation freeze:
// no State/Trail RenderTarget is registered, no pending swap survives, and the
// composite samples the last committed Trail slot with the current map frame.
resources->pending = false;
auto& compositeGroup = static_cast<LayerGroup&>(*layerGroup);
if (resources->trailSeeded && resources->trailTargets[resources->trailRead]) {
buildQuad(context,
resources,
compositeGroup,
getID() + "-frozen-composite-pass",
resources->trailTargets[resources->trailRead]->getTexture(),
{},
ValidationPass::FrozenComposite,
resources->trailRead,
resources->trailRead);
} else {
compositeGroup.clearDrawables();
}
return;
}
resources->staticFreezeLogged = false;
const auto viewport = validViewportSize(transformState.getSize());
if (!resources->trailTargets[0] || !resources->trailTargets[1] || resources->trailSize != viewport) {
const auto previousSize = resources->trailSize;

View File

@@ -7,7 +7,8 @@ namespace mbgl {
class ParticleGpuValidationResources;
// VALIDATION ONLY: proves Core RenderLayer/frame-transform/repaint integration.
// VALIDATION ONLY: proves Core RenderLayer/GPU ping-pong integration.
// STATIC redraws only the frozen Trail composite; it never advances State/Trail slots.
class RenderParticleValidationLayer final : public RenderLayer {
public:
explicit RenderParticleValidationLayer(Immutable<style::ParticleValidationLayer::Impl>);