From 2f1506747b1dad8e89e526058a2951e9734ba99b Mon Sep 17 00:00:00 2001 From: OpenAI Codex Date: Sat, 29 Aug 2026 21:24:58 +0800 Subject: [PATCH] test: add particle gpu ping-pong validation --- .../shaders/gl/particle_gpu_validation.hpp | 54 +++ include/mbgl/shaders/gl/shader_info.hpp | 7 + .../shaders/particle_gpu_validation_ubo.hpp | 16 + include/mbgl/shaders/shader_defines.hpp | 18 + include/mbgl/shaders/shader_manifest.hpp | 1 + include/mbgl/shaders/shader_source.hpp | 1 + .../ParticleCoreLayerValidationActivity.kt | 46 +- ...ctivity_particle_core_layer_validation.xml | 20 + .../src/main/res/values/strings.xml | 7 +- shaders/manifest.json | 7 + shaders/particle_gpu_validation.fragment.glsl | 30 ++ shaders/particle_gpu_validation.vertex.glsl | 8 + src/mbgl/gl/renderer_backend.cpp | 1 + .../render_particle_validation_layer.cpp | 425 ++++++++++++++++-- .../render_particle_validation_layer.hpp | 7 + src/mbgl/shaders/gl/shader_info.cpp | 13 + src/mbgl/shaders/shader_source.cpp | 1 + 17 files changed, 598 insertions(+), 64 deletions(-) create mode 100644 include/mbgl/shaders/gl/particle_gpu_validation.hpp create mode 100644 include/mbgl/shaders/particle_gpu_validation_ubo.hpp create mode 100644 shaders/particle_gpu_validation.fragment.glsl create mode 100644 shaders/particle_gpu_validation.vertex.glsl diff --git a/include/mbgl/shaders/gl/particle_gpu_validation.hpp b/include/mbgl/shaders/gl/particle_gpu_validation.hpp new file mode 100644 index 000000000..0ad7fdc0e --- /dev/null +++ b/include/mbgl/shaders/gl/particle_gpu_validation.hpp @@ -0,0 +1,54 @@ +// Generated code, do not modify this file! +#pragma once +#include + +namespace mbgl { +namespace shaders { + +template <> +struct ShaderSource { + static constexpr const char* name = "ParticleGpuValidationShader"; + static constexpr const char* vertex = R"(layout (location = 0) in vec2 a_pos; + +out vec2 v_uv; + +void main() { + gl_Position = vec4(a_pos * 2.0 - 1.0, 0.0, 1.0); + v_uv = a_pos; +} +)"; + static constexpr const char* fragment = R"(layout (std140) uniform ParticleGpuValidationUBO { + highp vec4 u_pass; + highp vec4 u_marker; +}; + +uniform sampler2D u_previous; +in vec2 v_uv; + +void main() { + vec4 previous = texture(u_previous, v_uv); + float mode = u_pass.x; + + if (mode < 0.5) { + // State pass: deterministic GPU-only state evolution. + fragColor = vec4(fract(previous.r + 0.03125), v_uv, 1.0); + } else if (mode < 1.5) { + // Trail pass: fade the previous trail and add a moving validation marker. + float marker = 1.0 - smoothstep(0.0, u_marker.z, distance(v_uv, u_marker.xy)); + vec3 color = previous.rgb * u_marker.w + marker * vec3(0.08, 0.55, 1.0); + fragColor = vec4(min(color, vec3(1.0)), 1.0); + } else { + // Main pass: composite the latest trail without hiding the validation map. + float intensity = max(previous.r, max(previous.g, previous.b)); + fragColor = vec4(previous.rgb * 0.72, min(intensity * 0.72, 0.72)); + } + +#ifdef OVERDRAW_INSPECTOR + fragColor = vec4(1.0); +#endif +} +)"; +}; + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/gl/shader_info.hpp b/include/mbgl/shaders/gl/shader_info.hpp index f8c111ba4..20fa76e47 100644 --- a/include/mbgl/shaders/gl/shader_info.hpp +++ b/include/mbgl/shaders/gl/shader_info.hpp @@ -149,6 +149,13 @@ struct ShaderInfo { static const std::vector textures; }; +template <> +struct ShaderInfo { + static const std::vector attributes; + static const std::vector uniformBlocks; + static const std::vector textures; +}; + template <> struct ShaderInfo { static const std::vector attributes; diff --git a/include/mbgl/shaders/particle_gpu_validation_ubo.hpp b/include/mbgl/shaders/particle_gpu_validation_ubo.hpp new file mode 100644 index 000000000..7c12f44ec --- /dev/null +++ b/include/mbgl/shaders/particle_gpu_validation_ubo.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include + +namespace mbgl { +namespace shaders { + +// VALIDATION ONLY: parameters for the 30-02 State/Trail ping-pong proof. +struct alignas(16) ParticleGpuValidationUBO { + std::array pass; + std::array marker; +}; +static_assert(sizeof(ParticleGpuValidationUBO) == 2 * 16); + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/shader_defines.hpp b/include/mbgl/shaders/shader_defines.hpp index 862085b49..3a7d6c31d 100644 --- a/include/mbgl/shaders/shader_defines.hpp +++ b/include/mbgl/shaders/shader_defines.hpp @@ -127,6 +127,11 @@ enum { heatmapTextureUBOCount }; +enum { + idParticleGpuValidationUBO = getEnumValue(drawableReservedUBOCount, layerUBOStartId), + particleGpuValidationUBOCount +}; + enum { idHillshadeEvaluatedPropsUBO = getEnumValue(hillshadeLayerSSBOCount, layerUBOStartId), hillshadeLayerUBOCount @@ -268,6 +273,7 @@ static constexpr uint32_t maxUBOCountPerShader = std::max({static_cast static_cast(fillUBOCount), static_cast(fillExtrusionUBOCount), static_cast(heatmapTextureUBOCount), + static_cast(particleGpuValidationUBOCount), static_cast(heatmapUBOCount), static_cast(hillshadePrepareUBOCount), static_cast(hillshadeUBOCount), @@ -332,6 +338,11 @@ enum { heatmapTextureCount }; +enum { + idParticleGpuValidationPreviousTexture, + particleGpuValidationTextureCount +}; + enum { idHillshadeImageTexture, hillshadeTextureCount @@ -376,6 +387,7 @@ static constexpr uint32_t maxTextureCountPerShader = std::max({static_cast(fillTextureCount), static_cast(fillExtrusionTextureCount), static_cast(heatmapTextureCount), + static_cast(particleGpuValidationTextureCount), static_cast(hillshadeTextureCount), static_cast(colorReliefTextureCount), static_cast(lineTextureCount), @@ -389,6 +401,11 @@ enum { backgroundVertexAttributeCount }; +enum { + idParticleGpuValidationPosVertexAttribute, + particleGpuValidationVertexAttributeCount +}; + enum { idCirclePosVertexAttribute, @@ -556,6 +573,7 @@ enum { static constexpr uint32_t maxVertexAttributeCountPerShader = std::max({ static_cast(backgroundVertexAttributeCount), + static_cast(particleGpuValidationVertexAttributeCount), static_cast(circleVertexAttributeCount), static_cast(clippingMaskVertexAttributeCount), static_cast(collisionVertexAttributeCount), diff --git a/include/mbgl/shaders/shader_manifest.hpp b/include/mbgl/shaders/shader_manifest.hpp index 488f015e0..a60fadad9 100644 --- a/include/mbgl/shaders/shader_manifest.hpp +++ b/include/mbgl/shaders/shader_manifest.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/include/mbgl/shaders/shader_source.hpp b/include/mbgl/shaders/shader_source.hpp index 4fdf0c951..12979aa4f 100644 --- a/include/mbgl/shaders/shader_source.hpp +++ b/include/mbgl/shaders/shader_source.hpp @@ -30,6 +30,7 @@ enum class BuiltIn { FillExtrusionPatternInstancedShader, HeatmapShader, HeatmapTextureShader, + ParticleGpuValidationShader, HillshadePrepareShader, ColorReliefShader, HillshadeShader, diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt index 1236a7ac3..11f90ad90 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt @@ -12,11 +12,13 @@ import org.maplibre.android.maps.MapLibreMap import org.maplibre.android.maps.Style import org.maplibre.android.testapp.R -/** VALIDATION ONLY: Android OpenGL host for the 30-01 Core RenderLayer experiment. */ +/** VALIDATION ONLY: Android OpenGL host for the 30-01/30-02 Core RenderLayer experiments. */ class ParticleCoreLayerValidationActivity : AppCompatActivity() { private lateinit var mapView: MapView private lateinit var maplibreMap: MapLibreMap private lateinit var status: TextView + private var active = true + private var enabled = true override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -31,29 +33,47 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() { .target(LatLng(0.0, 0.0)) .zoom(2.0) .build() - loadValidationStyle(active = true) + loadValidationStyle(active = true, enabled = true) } findViewById