While developing or optimizing Android games, it can often be helpful to
understand which graphics pipeline your engine is using; engines may choose
Vulkan or GLES without clearly developer-accessible signals. Unfortunately,
there are situations where relying on logcat to verify whether a game is
running on Vulkan or has silently fallen back to OpenGL ES can be unreliable.
This guide shows you how to use the Android Performance Analyzer (APA) and custom Perfetto SQL queries to definitively identify a game's active rendering API.
Limitations of log-based verification
- Stripped logs: Production builds often hide initialization and driver-loading footprints.
- False positives: Some game engines load both Vulkan and OpenGL ES libraries during startup, printing initialization logs for both, even if one eventually fails and triggers a fallback.
- Silent fallbacks: If Vulkan initialization fails due to device-specific driver issues, engines frequently fall back to OpenGL ES without throwing critical errors.
Measure using APA
Using the Android Performance Analyzer, you can record a system trace and precisely analyze frame data through SQL queries. Follow these steps to measure your use of Vulkan and GLES:
Capture the trace with APA: Run your game and use APA to capture a system trace during the segment you want to analyze, such as a point during gameplay where you suspect frame drops. After the device is connected and the trace recording is complete, the trace data loads in the APA interface.
Click the SQL tab in APA: When the trace analysis screen is open, in the navigation menu of the UI, click the SQL tab to open the trace processor environment, where you can query the data directly.
Paste the following SQL query in the APA SQL tab: Copy the following SQL query and paste it into the query input field. This query scans the trace for drawing API events, such as
eglSwapBuffers,QueuePresentKHR, andvkQueuePresentKHR. It groups them by process name and calculates the rendering API counts and percentage distribution of Vulkan versus OpenGL ES rendering calls:WITH raw_slices AS ( -- 1. Map each slice (API call) to its corresponding process or package via UTID and UPID SELECT p.name AS process_name, s.name AS slice_name FROM slice s JOIN thread_track tt ON s.track_id = tt.id JOIN thread t USING (utid) JOIN process p USING (upid) WHERE (s.name LIKE 'eglSwapBuffers%' OR s.name IN ('QueuePresentKHR', 'vkQueuePresentKHR')) -- Optional: To isolate your game, uncomment the following and filter by package name and thread name: -- AND p.name = 'com.example.mygame' -- AND t.name = 'RenderThread' ), process_stats AS ( -- 2. Aggregate counts per individual process SELECT process_name, SUM(CASE WHEN slice_name LIKE 'eglSwapBuffers%' THEN 1 ELSE 0 END) AS egl_count, SUM(CASE WHEN slice_name IN ('QueuePresentKHR', 'vkQueuePresentKHR') THEN 1 ELSE 0 END) AS vulkan_count FROM raw_slices GROUP BY process_name ), process_totals AS ( -- 3. Calculate total counts for denominator calculation SELECT process_name, egl_count, vulkan_count, (egl_count + vulkan_count) AS total_count FROM process_stats ) -- 4. Calculate final percentage shares per row, preventing division by zero errors SELECT process_name, egl_count, vulkan_count, total_count, ROUND(CAST(egl_count AS REAL) * 100 / NULLIF(total_count, 0), 2) AS "egl_percentage(%)", ROUND(CAST(vulkan_count AS REAL) * 100 / NULLIF(total_count, 0), 2) AS "vulkan_percentage(%)" FROM process_totals ORDER BY total_count DESC;Run the query: Click the Run Query button near the input field. After the query runs, a table appears in the results pane showing the process name (
process_name), OpenGL ES presentation count (egl_count), Vulkan presentation count (vulkan_count), total presentation count (total_count), and the percentage of each API used (egl_percentage(%)andvulkan_percentage(%)).
[]
Screen showing the executed SQL query and the resulting rendering API metrics displayed in a table
Common pitfalls
Avoid
SurfaceFlingerconfusion: Always scope your search to your game's application thread (RenderThread). System-wide compositor processes likeSurfaceFlingermight show Vulkan or EGL tracks that represent system UI rendering, not your game's internal rendering pipeline. To isolate your game, uncomment the optional filters in the main SQL query'sWHEREclause and replace'com.example.mygame'with your game's package name:-- AND p.name = 'com.example.mygame' -- AND t.name = 'RenderThread'Warm-up period: Always record the trace after the game's main 3D scene has fully loaded. Capturing during splash screens or loading transitions might result in misleading initializations.
LevelUp Exemption Trace Requirements
If you are using the Android Performance Analyzer (APA) to capture a trace to qualify for a Google Play Games LevelUp exemption, there are specific hardware requirements for the trace to be valid.
It is highly preferred that you capture your trace using one of the targeted Level Up reference devices.
Furthermore, to ensure accurate validation, your trace must not be taken on a device utilizing an ANGLE GPU. Specifically, you cannot use the following devices to capture your LevelUp exemption trace:
- Any device where the GPU vendor is SLSI (Samsung), which uses AMD Xclipse GPUs
- The Pixel 11