feat: draw all raster particle states
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
#include <mbgl/gfx/drawable_tweaker.hpp>
|
||||
#include <mbgl/gfx/index_vector.hpp>
|
||||
#include <mbgl/gfx/shader_registry.hpp>
|
||||
#include <mbgl/gfx/texture2d.hpp>
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
@@ -34,6 +35,7 @@
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
@@ -73,6 +75,7 @@ enum class ValidationPass : uint8_t {
|
||||
Trail = 1,
|
||||
Composite = 2,
|
||||
FrozenComposite = 3,
|
||||
TrailParticles = 4,
|
||||
};
|
||||
|
||||
const char* slotName(const uint8_t slot) {
|
||||
@@ -206,7 +209,10 @@ public:
|
||||
std::shared_ptr<PremultipliedImage> nextFieldImage;
|
||||
std::shared_ptr<PremultipliedImage> maskFixture;
|
||||
std::shared_ptr<gfx::VertexVector<HeatmapTextureLayoutVertex>> vertices;
|
||||
std::shared_ptr<gfx::VertexVector<HeatmapTextureLayoutVertex>> particleVertices;
|
||||
gfx::IndexVectorBasePtr particleIndices;
|
||||
SegmentVector segments;
|
||||
SegmentVector particleSegments;
|
||||
|
||||
uint8_t stateWrite() const { return static_cast<uint8_t>(1 - stateRead); }
|
||||
uint8_t trailWrite() const { return static_cast<uint8_t>(1 - trailRead); }
|
||||
@@ -255,6 +261,33 @@ public:
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr uint32_t MaxParticleVerticesPerSegment = std::numeric_limits<uint16_t>::max() + 1u;
|
||||
|
||||
void rebuildParticleDrawResources(const std::shared_ptr<ParticleGpuResources>& resources) {
|
||||
auto vertices = std::make_shared<gfx::VertexVector<HeatmapTextureLayoutVertex>>();
|
||||
vertices->reserve(resources->particleCount);
|
||||
for (uint32_t particleIndex = 0; particleIndex < resources->particleCount; ++particleIndex) {
|
||||
const auto x = static_cast<int16_t>(particleIndex % resources->stateSize.width);
|
||||
const auto y = static_cast<int16_t>(particleIndex / resources->stateSize.width);
|
||||
vertices->emplace_back(HeatmapBucket::textureVertex({x, y}));
|
||||
}
|
||||
|
||||
auto indices = std::make_shared<gfx::IndexVectorBase>();
|
||||
indices->reserve(std::min(resources->particleCount, MaxParticleVerticesPerSegment));
|
||||
for (uint32_t index = 0; index < std::min(resources->particleCount, MaxParticleVerticesPerSegment); ++index) {
|
||||
indices->extend(1, static_cast<uint16_t>(index));
|
||||
}
|
||||
|
||||
SegmentVector segments;
|
||||
for (uint32_t offset = 0; offset < resources->particleCount; offset += MaxParticleVerticesPerSegment) {
|
||||
const auto count = std::min(resources->particleCount - offset, MaxParticleVerticesPerSegment);
|
||||
segments.emplace_back(offset, 0, count, count);
|
||||
}
|
||||
resources->particleVertices = std::move(vertices);
|
||||
resources->particleIndices = std::move(indices);
|
||||
resources->particleSegments = std::move(segments);
|
||||
}
|
||||
|
||||
class ParticleGpuValidationTweaker final : public gfx::DrawableTweaker {
|
||||
public:
|
||||
ParticleGpuValidationTweaker(std::shared_ptr<ParticleGpuResources> state_,
|
||||
@@ -311,8 +344,8 @@ public:
|
||||
const shaders::ParticleGpuValidationUBO ubo = {
|
||||
.pass = {static_cast<float>(pass), frame, maskMode == 0 ? 0.0f : 1.0f, static_cast<float>(maskMode)},
|
||||
.marker = {markerX, markerY, 0.035f, 0.965f},
|
||||
.mask = {static_cast<float>(resources->maskGeneration),
|
||||
static_cast<float>(worldWrap),
|
||||
.mask = {static_cast<float>(resources->stateSize.width),
|
||||
static_cast<float>(resources->stateSize.height),
|
||||
resources->formalDisplay ? 1.0f : 0.0f,
|
||||
seedState ? 1.0f : 0.0f},
|
||||
.matrix = util::cast<float>(parameters.matrixForTile({worldWrap, {0, 0, 0}})),
|
||||
@@ -527,6 +560,63 @@ bool buildQuad(gfx::Context& context,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool buildParticlePoints(gfx::Context& context,
|
||||
const std::shared_ptr<ParticleGpuResources>& resources,
|
||||
LayerGroup& group,
|
||||
const std::string& name,
|
||||
const gfx::Texture2DPtr& stateTexture,
|
||||
const gfx::Texture2DPtr& target,
|
||||
const uint8_t stateSlot,
|
||||
const uint8_t trailSlot) {
|
||||
if (!resources->particleVertices || !resources->particleIndices || resources->particleSegments.empty() ||
|
||||
!stateTexture || !target) {
|
||||
Log::Error(Event::Render, "ParticleGPU: event=PARTICLE_DRAW_REJECTED reason=MISSING_DRAW_RESOURCES");
|
||||
return false;
|
||||
}
|
||||
auto attributes = context.createVertexAttributeArray();
|
||||
if (const auto& attribute = attributes->set(shaders::idParticleGpuValidationPosVertexAttribute)) {
|
||||
attribute->setSharedRawData(resources->particleVertices,
|
||||
offsetof(HeatmapTextureLayoutVertex, a1),
|
||||
0,
|
||||
sizeof(HeatmapTextureLayoutVertex),
|
||||
gfx::AttributeDataType::Short2);
|
||||
}
|
||||
|
||||
auto builder = context.createDrawableBuilder(name);
|
||||
builder->setShader(resources->shader);
|
||||
builder->setRenderPass(RenderPass::Translucent);
|
||||
builder->setEnableDepth(false);
|
||||
builder->setColorMode(gfx::ColorMode::unblended());
|
||||
builder->setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
builder->setVertexAttributes(std::move(attributes));
|
||||
builder->setRawVertices({}, resources->particleVertices->elements(), gfx::AttributeDataType::Short2);
|
||||
builder->setSegments(gfx::Points(3.0f),
|
||||
resources->particleIndices,
|
||||
resources->particleSegments.data(),
|
||||
resources->particleSegments.size());
|
||||
builder->setTexture(stateTexture, shaders::idParticleGpuValidationPreviousTexture);
|
||||
builder->setTexture(stateTexture, shaders::idParticleGpuValidationStateTexture);
|
||||
builder->addTweaker(std::make_shared<ParticleGpuValidationTweaker>(resources,
|
||||
ValidationPass::TrailParticles,
|
||||
stateSlot,
|
||||
trailSlot,
|
||||
stateTexture,
|
||||
target,
|
||||
resources->maskTexture,
|
||||
stateTexture,
|
||||
0.0f,
|
||||
0,
|
||||
0));
|
||||
builder->flush(context);
|
||||
auto drawables = builder->clearDrawables();
|
||||
if (drawables.size() != 1 || !drawables.front()) {
|
||||
Log::Error(Event::Render, "ParticleGPU: event=PARTICLE_DRAW_REJECTED reason=DRAWABLE_FINALIZE_FAILED");
|
||||
return false;
|
||||
}
|
||||
group.addDrawable(std::move(drawables.front()));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
RenderRasterParticleLayer::RenderRasterParticleLayer(Immutable<style::Layer::Impl> impl_)
|
||||
@@ -596,6 +686,10 @@ void RenderRasterParticleLayer::layerRemoved(UniqueChangeRequestVec& changes) {
|
||||
"ParticleGPU: event=PARTICLE_RESOURCES_RELEASE reason=LAYER_REMOVED particleCount=" +
|
||||
std::to_string(gpuResources->particleCount) +
|
||||
" resourceGeneration=" + std::to_string(gpuResources->generation));
|
||||
Log::Info(Event::Render,
|
||||
"ParticleGPU: event=PARTICLE_DRAW_RESOURCES_RELEASE reason=LAYER_REMOVED trailDrawCount=" +
|
||||
std::to_string(gpuResources->particleVertices ? gpuResources->particleVertices->elements() : 0) +
|
||||
" fullParticleDraw=true resourceGeneration=" + std::to_string(gpuResources->generation));
|
||||
removeTargets(gpuResources->registeredTargets, changes);
|
||||
gpuResources->registeredTargets.clear();
|
||||
}
|
||||
@@ -609,6 +703,10 @@ void RenderRasterParticleLayer::markContextDestroyed() {
|
||||
"ParticleGPU: event=PARTICLE_RESOURCES_RELEASE reason=CONTEXT_DESTROYED particleCount=" +
|
||||
std::to_string(gpuResources->particleCount) +
|
||||
" resourceGeneration=" + std::to_string(gpuResources->generation));
|
||||
Log::Info(Event::Render,
|
||||
"ParticleGPU: event=PARTICLE_DRAW_RESOURCES_RELEASE reason=CONTEXT_DESTROYED trailDrawCount=" +
|
||||
std::to_string(gpuResources->particleVertices ? gpuResources->particleVertices->elements() : 0) +
|
||||
" fullParticleDraw=true resourceGeneration=" + std::to_string(gpuResources->generation));
|
||||
Log::Info(
|
||||
Event::Render,
|
||||
"ParticleValidation30_02: context lost discard generation=" + std::to_string(gpuResources->generation) +
|
||||
@@ -665,6 +763,7 @@ void RenderRasterParticleLayer::update(gfx::ShaderRegistry& shaders,
|
||||
owned->segments = RenderStaticData::heatmapTextureSegments();
|
||||
owned->particleCount = particleCount;
|
||||
owned->stateSize = particleStateSize(owned->particleCount);
|
||||
rebuildParticleDrawResources(owned);
|
||||
for (uint8_t i = 0; i < 2; ++i) {
|
||||
owned->stateTargets[i] = createValidationTarget(
|
||||
context, owned->stateSize, getID() + "-state-" + slotName(i), gfx::TextureFilterType::Nearest);
|
||||
@@ -749,6 +848,13 @@ void RenderRasterParticleLayer::update(gfx::ShaderRegistry& shaders,
|
||||
" effectiveParticleCount=" + std::to_string(resources->particleCount) + " stateGrid=" +
|
||||
std::to_string(resources->stateSize.width) + "x" + std::to_string(resources->stateSize.height) +
|
||||
" resourceGeneration=" + std::to_string(resources->generation));
|
||||
Log::Info(Event::Render,
|
||||
"ParticleGPU: event=PARTICLE_DRAW_RESOURCES_CREATE effectiveParticleCount=" +
|
||||
std::to_string(resources->particleCount) + " stateGrid=" +
|
||||
std::to_string(resources->stateSize.width) + "x" + std::to_string(resources->stateSize.height) +
|
||||
" trailDrawCount=" + std::to_string(resources->particleVertices->elements()) +
|
||||
" particleIndexCount=" + std::to_string(resources->particleVertices->elements()) +
|
||||
" fullParticleDraw=true resourceGeneration=" + std::to_string(resources->generation));
|
||||
Log::Info(
|
||||
Event::Render,
|
||||
"ParticleField: fixture loaded id=" + resources->field.fixtureID + " type=" + resources->field.fieldType +
|
||||
@@ -806,10 +912,15 @@ void RenderRasterParticleLayer::update(gfx::ShaderRegistry& shaders,
|
||||
std::to_string(previousCount) + " stateGrid=" + std::to_string(previousSize.width) + "x" +
|
||||
std::to_string(previousSize.height) +
|
||||
" resourceGeneration=" + std::to_string(resources->generation));
|
||||
Log::Info(Event::Render,
|
||||
"ParticleGPU: event=PARTICLE_DRAW_RESOURCES_RELEASE reason=PARTICLE_COUNT_CHANGE trailDrawCount=" +
|
||||
std::to_string(resources->particleVertices ? resources->particleVertices->elements() : 0) +
|
||||
" fullParticleDraw=true resourceGeneration=" + std::to_string(resources->generation));
|
||||
removeTargets(resources->stateTargets, changes);
|
||||
resources->stateTargets = std::move(replacementTargets);
|
||||
resources->particleCount = particleCount;
|
||||
resources->stateSize = requestedSize;
|
||||
rebuildParticleDrawResources(resources);
|
||||
resources->resetSequence("PARTICLE_COUNT_CHANGE");
|
||||
Log::Info(Event::Render,
|
||||
"ParticleGPU: event=PARTICLE_RESOURCES_REBUILD reason=PARTICLE_COUNT_CHANGE requestedParticleCount=" +
|
||||
@@ -817,6 +928,13 @@ void RenderRasterParticleLayer::update(gfx::ShaderRegistry& shaders,
|
||||
" effectiveParticleCount=" + std::to_string(resources->particleCount) + " stateGrid=" +
|
||||
std::to_string(resources->stateSize.width) + "x" + std::to_string(resources->stateSize.height) +
|
||||
" resourceGeneration=" + std::to_string(resources->generation));
|
||||
Log::Info(Event::Render,
|
||||
"ParticleGPU: event=PARTICLE_DRAW_RESOURCES_REBUILD effectiveParticleCount=" +
|
||||
std::to_string(resources->particleCount) + " stateGrid=" +
|
||||
std::to_string(resources->stateSize.width) + "x" + std::to_string(resources->stateSize.height) +
|
||||
" trailDrawCount=" + std::to_string(resources->particleVertices->elements()) +
|
||||
" particleIndexCount=" + std::to_string(resources->particleVertices->elements()) +
|
||||
" fullParticleDraw=true resourceGeneration=" + std::to_string(resources->generation));
|
||||
}
|
||||
|
||||
const bool sourceChanged = formalSource && sourceField && sourceNextField &&
|
||||
@@ -1028,6 +1146,15 @@ void RenderRasterParticleLayer::update(gfx::ShaderRegistry& shaders,
|
||||
0,
|
||||
maskMode,
|
||||
true);
|
||||
const bool particlesBuilt = !resources->formalDisplay ||
|
||||
buildParticlePoints(context,
|
||||
resources,
|
||||
trailGroup,
|
||||
getID() + "-static-bootstrap-trail-particles",
|
||||
resources->stateTargets[stateWrite]->getTexture(),
|
||||
resources->trailTargets[trailWrite]->getTexture(),
|
||||
stateWrite,
|
||||
trailWrite);
|
||||
compositeGroup.clearDrawables();
|
||||
bool compositeBuilt = true;
|
||||
const auto center = transformState.getLatLng(LatLng::Unwrapped);
|
||||
@@ -1050,7 +1177,7 @@ void RenderRasterParticleLayer::update(gfx::ShaderRegistry& shaders,
|
||||
false) &&
|
||||
compositeBuilt;
|
||||
}
|
||||
if (!stateBuilt || !trailBuilt || !compositeBuilt) {
|
||||
if (!stateBuilt || !trailBuilt || !particlesBuilt || !compositeBuilt) {
|
||||
compositeGroup.clearDrawables();
|
||||
return;
|
||||
}
|
||||
@@ -1136,6 +1263,15 @@ void RenderRasterParticleLayer::update(gfx::ShaderRegistry& shaders,
|
||||
0,
|
||||
maskMode,
|
||||
true);
|
||||
const bool particlesBuilt = !resources->formalDisplay ||
|
||||
buildParticlePoints(context,
|
||||
resources,
|
||||
trailGroup,
|
||||
getID() + "-trail-particles",
|
||||
resources->stateTargets[stateWrite]->getTexture(),
|
||||
resources->trailTargets[trailWrite]->getTexture(),
|
||||
stateWrite,
|
||||
trailWrite);
|
||||
compositeGroup.clearDrawables();
|
||||
bool compositeBuilt = true;
|
||||
const auto center = transformState.getLatLng(LatLng::Unwrapped);
|
||||
@@ -1158,7 +1294,7 @@ void RenderRasterParticleLayer::update(gfx::ShaderRegistry& shaders,
|
||||
false) &&
|
||||
compositeBuilt;
|
||||
}
|
||||
if (!stateBuilt || !trailBuilt || !compositeBuilt) {
|
||||
if (!stateBuilt || !trailBuilt || !particlesBuilt || !compositeBuilt) {
|
||||
compositeGroup.clearDrawables();
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user