353 lines
18 KiB
HTML
353 lines
18 KiB
HTML
<!DOCTYPE HTML>
|
|
<html lang="en" class="light sidebar-visible" dir="ltr">
|
|
<head>
|
|
<!-- Book generated using mdBook -->
|
|
<meta charset="UTF-8">
|
|
<title>Performance analysis - Filament</title>
|
|
|
|
|
|
<!-- Custom HTML head -->
|
|
|
|
<meta name="description" content="">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="theme-color" content="#ffffff">
|
|
|
|
<link rel="shortcut icon" href="../favicon.png">
|
|
<link rel="stylesheet" href="../css/variables.css">
|
|
<link rel="stylesheet" href="../css/general.css">
|
|
<link rel="stylesheet" href="../css/chrome.css">
|
|
|
|
<!-- Fonts -->
|
|
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
|
|
<link rel="stylesheet" href="../fonts/fonts.css">
|
|
|
|
<!-- Highlight.js Stylesheets -->
|
|
<link rel="stylesheet" href="../highlight.css">
|
|
<link rel="stylesheet" href="../tomorrow-night.css">
|
|
<link rel="stylesheet" href="../ayu-highlight.css">
|
|
|
|
<!-- Custom theme stylesheets -->
|
|
|
|
<!-- MathJax -->
|
|
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
|
|
|
<!-- Provide site root to javascript -->
|
|
<script>
|
|
var path_to_root = "../";
|
|
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "light" : "light";
|
|
</script>
|
|
<!-- Start loading toc.js asap -->
|
|
<script src="../toc.js"></script>
|
|
</head>
|
|
<body>
|
|
<div id="body-container">
|
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
|
<script>
|
|
try {
|
|
var theme = localStorage.getItem('mdbook-theme');
|
|
var sidebar = localStorage.getItem('mdbook-sidebar');
|
|
|
|
if (theme.startsWith('"') && theme.endsWith('"')) {
|
|
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
|
}
|
|
|
|
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
|
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
|
}
|
|
} catch (e) { }
|
|
</script>
|
|
|
|
<!-- Set the theme before any content is loaded, prevents flash -->
|
|
<script>
|
|
var theme;
|
|
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
|
if (theme === null || theme === undefined) { theme = default_theme; }
|
|
const html = document.documentElement;
|
|
html.classList.remove('light')
|
|
html.classList.add(theme);
|
|
html.classList.add("js");
|
|
</script>
|
|
|
|
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
|
|
|
<!-- Hide / unhide sidebar before it is displayed -->
|
|
<script>
|
|
var sidebar = null;
|
|
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
|
if (document.body.clientWidth >= 1080) {
|
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
|
sidebar = sidebar || 'visible';
|
|
} else {
|
|
sidebar = 'hidden';
|
|
}
|
|
sidebar_toggle.checked = sidebar === 'visible';
|
|
html.classList.remove('sidebar-visible');
|
|
html.classList.add("sidebar-" + sidebar);
|
|
</script>
|
|
|
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
|
<div style="display:flex;align-items:center;justify-content:center">
|
|
<img class="flogo" src="../images/filament_logo_small.png"></img>
|
|
</div>
|
|
<!-- populated by js -->
|
|
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
|
|
<noscript>
|
|
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
|
|
</noscript>
|
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
|
<div class="sidebar-resize-indicator"></div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div id="page-wrapper" class="page-wrapper">
|
|
|
|
<div class="page">
|
|
<div id="menu-bar-hover-placeholder"></div>
|
|
<div id="menu-bar" class="menu-bar sticky">
|
|
<div class="left-buttons">
|
|
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
|
<i class="fa fa-bars"></i>
|
|
</label>
|
|
<!-- Filament: disable themes because the markdeep part does not look good for dark themes -->
|
|
<!--
|
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
|
<i class="fa fa-paint-brush"></i>
|
|
</button>
|
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
|
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
|
</ul>
|
|
-->
|
|
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
|
<i class="fa fa-search"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<h1 class="menu-title">Filament</h1>
|
|
|
|
<div class="right-buttons">
|
|
<a href="https://github.com/google/filament" title="Git repository" aria-label="Git repository">
|
|
<i id="git-repository-button" class="fa fa-github"></i>
|
|
</a>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div id="search-wrapper" class="hidden">
|
|
<form id="searchbar-outer" class="searchbar-outer">
|
|
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
|
</form>
|
|
<div id="searchresults-outer" class="searchresults-outer hidden">
|
|
<div id="searchresults-header" class="searchresults-header"></div>
|
|
<ul id="searchresults">
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
|
<script>
|
|
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
|
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
|
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
|
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
|
});
|
|
</script>
|
|
|
|
<div id="content" class="content">
|
|
<main>
|
|
<h1 id="performance-analysis"><a class="header" href="#performance-analysis">Performance Analysis</a></h1>
|
|
<h2 id="android"><a class="header" href="#android">Android</a></h2>
|
|
<h3 id="prerequisites"><a class="header" href="#prerequisites">Prerequisites</a></h3>
|
|
<ul>
|
|
<li>Download and install Android GPU Inspector (AGI). See https://developer.android.com/agi.</li>
|
|
</ul>
|
|
<hr />
|
|
<h4 id="profiling"><a class="header" href="#profiling">Profiling</a></h4>
|
|
<ol>
|
|
<li>
|
|
<p>Before profiling the application or analyzing the performance in a consistent way, ideally
|
|
the <strong>GPU frequency on the target hardware should get locked</strong>. In order to do this, you need to do the following:</p>
|
|
<ol>
|
|
<li>Ensure your device is OEM unlocked. If your phone is carrier-locked, you may need
|
|
to wait a period, such as 60 or 90 days after activation to be eligible for unlocking.
|
|
Some phones don't support this at all. You will need to enable developer options
|
|
(e.g. Settings > About Phone and tap the Build number 7 times). You need to go to
|
|
Settings > System > Developer options and toggle on "OEM unlocking".</li>
|
|
<li>Next, you need to unlock the phone. You will need to install Android SDK Platform
|
|
Tools on you computer, enable "USB debugging" in your phone's Settings > System > Developer options.</li>
|
|
<li>Connect the phone to the computer via a USB cable and run from the command line:
|
|
<pre><code class="language-shell">adb reboot bootloader
|
|
# once the phone is in bootloader mode, run the following to begin the unlocking
|
|
# process:
|
|
fastboot flashing unlock
|
|
</code></pre>
|
|
A warning will appear on your phone's screen. Use the volume buttons to navigate and
|
|
the power button to select the "Unlock the bootloader" option. The phone will perform
|
|
a factory data reset and reboot with an unlocked bootloader.</li>
|
|
<li>You would need to flash an image to the phone with root permissions, such as a *-userdebug or *-eng
|
|
build. One way to do this is with the <a href="https://flash.android.com/">Android Flash Tool</a>. Connect the
|
|
tool to your device and find a build to flash ending in <code>-userdebug</code> or <code>-eng</code>. Once you have that
|
|
selected run <code>Install build</code>.</li>
|
|
<li>Shell into your device as root and configure the gpu frequency to be locked, e.g.:
|
|
<pre><code class="language-shell">adb shell
|
|
su
|
|
# navigate to the system GPU directory. this varies on different phones. One phone might have
|
|
# it at /sys/class/kgsl/kgsl-3d0 and another might be in something similar, maybe with "mali" instead
|
|
# of "kgsl". At the time of writing this for the device at hand it was /sys/devices/platform/1f000000.mali
|
|
cd /sys/devices/platform/1f000000.mali
|
|
# get the current available GPU governors and frequencies.
|
|
# note that some systems may have these at gpu_available_governors and gpu_available_frequencies, but
|
|
# the system at the time of writing this had available_governors and available_frequences
|
|
cat available_governors
|
|
cat available_frequencies
|
|
# depending on the governors, you may want to set it prioritize performance over other things like
|
|
# battery. Some systems allow you to do this with something like (although, for the device used at the
|
|
# time of writing this did not have an equivalent option):
|
|
echo performance > gpu_governor
|
|
# finally, lock your frequency in, usually to something high like 897 MHz. Some systems may have you
|
|
# pipe the value to gpu_min_freq and gpu_max_freq, but the system used at the time of writing this had:
|
|
echo 940000 > hint_min_freq
|
|
echo 940000 > hint_max_freq
|
|
# you can typically verify the GPU is running at that frequency consistently by running something like
|
|
# the following a few times over time, which should show the frequency you want to lock the device to:
|
|
cat cur_freq
|
|
</code></pre>
|
|
</li>
|
|
<li>You may need to re-apply the <code>hint_min_freq</code> just before starting the profiling trace and check before and after
|
|
that the frequency remained at the value expected. Some systems may adjust the frequency on you, but you
|
|
may want to ensure the frequency remains the same through the analysis.</li>
|
|
<li>The GPU frequency settings should be undone after restarting the device, but after you have done your app profiling,
|
|
you can revert the state of the device, such as the OS build image, back to the way you had it
|
|
initially, as needed.</li>
|
|
</ol>
|
|
</li>
|
|
<li>
|
|
<p>Build a release build of Filament with the applicable backend(s) enabled
|
|
<em>(+ any special flags for enabling sys strace. Nothing special is needed for Vulkan or WebGPU aside from
|
|
building a release build with no flags)</em> <em>(debug builds for this are useless)</em></p>
|
|
<pre><code class="language-shell"># the following command assumes you are in the root filament directory
|
|
# and ANDROID_HOME is exported (and possibly also CC and CXX on linux as needed)
|
|
#
|
|
# NOTE: to build with WebGPU support you need to explicitly include the -W flag
|
|
# (it doesn't get compiled in by default), e.g.:
|
|
# ./build.sh -W -p android,desktop -i release
|
|
#
|
|
# Note that you can speed this up a bit (and reduce disk space usage) by limiting the target to just
|
|
# the ABI you plan on testing with the -q flag, e.g. -q arm64-v8a. If you do this, you
|
|
# will need to update the android/gradle.properties file to specify the ABI(s) you are targeting
|
|
# with the com.google.android.filament.abis property.
|
|
# Thus, a build command that would target BOTH Vulkan AND WebGPU AND only target the ARM64 ABI would look something
|
|
# like:
|
|
# ./build.sh -W -q arm64-v8a -p android,desktop -i release
|
|
./build.sh -p android,desktop -i release
|
|
</code></pre>
|
|
</li>
|
|
<li>
|
|
<p>Connect your Android device to your computer via a USB cord with USB debugging enabled and configure
|
|
the system property to default to the desired backend, e.g.
|
|
<em>(to determine how these numbers map to the backends, see the <code>enum class Backend</code>
|
|
definition in <a href="../../../../filament/backend/include/backend/DriverEnums.h">filament/filament/backend/include/backend/DriverEnums.h</a>)</em>:</p>
|
|
<pre><code class="language-shell"># to set the backend to Vulkan:
|
|
adb shell setprop debug.filament.backend 2
|
|
# to set the backend to WebGPU:
|
|
adb shell setprop debug.filament.backend 4
|
|
# to view the current property:
|
|
adb shell getprop debug.filament.backend
|
|
</code></pre>
|
|
</li>
|
|
<li>
|
|
<p>Build and run a sample, e.g. sample-gltf-viewer, on your Android device
|
|
<em>(<a href="https://developer.android.com/studio">Android Studio</a> recommended)</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Run <a href="https://developer.android.com/agi">AGI</a> and follow instructions to profile the app/system
|
|
with trace capture(s). See https://developer.android.com/agi/start for more details to
|
|
get started.</p>
|
|
<ul>
|
|
<li>We typically only run "Capture System Profiler trace" <em>(not necessarily "Capture Frame Profiler trace")</em></li>
|
|
<li>When configuring the trace:
|
|
<ul>
|
|
<li>For both the WebGPU and Vulkan backends configure the profiler for the Vulkan API
|
|
<em>(since WebGPU should be using Vulkan under the hood as well)</em></li>
|
|
<li>Running for ~1 seconds should suffice</li>
|
|
<li>Hit the "Configure" button in Trace objects, select "Switch to advanced mode" and add:
|
|
<pre><code>data_sources {
|
|
config {
|
|
name: "track_event"
|
|
track_event_config {
|
|
disabled_categories: "*"
|
|
enabled_categories: "filament/filament"
|
|
enabled_categories: "filament/jobsystem"
|
|
enabled_categories: "filament/gltfio"
|
|
}
|
|
}
|
|
}
|
|
</code></pre>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li>One you open the trace, zoom into a series of frames to get a sense of generally how long they typically take
|
|
<em>(use <code>W</code>, <code>S</code>, <code>A</code> and <code>D</code> keys and mouse wheel for navigation)</em> and find a representative one.
|
|
We are most interested in the performance of the
|
|
<code>FEngine::loop</code> thread, how long it takes, overlap in activities/processes/commands, reduction in queue submissions,
|
|
etc. Similarly, we can view GPU timeline as it relates to that. We want to see overlapping
|
|
shader invocations and non-interrupted fragment shader runs.</li>
|
|
</ul>
|
|
</li>
|
|
</ol>
|
|
|
|
</main>
|
|
|
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
|
<!-- Mobile navigation buttons -->
|
|
<a rel="prev" href="../notes/coverage.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
<a rel="next prefetch" href="../notes/framegraph.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
|
|
<div style="clear: both"></div>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
|
<a rel="prev" href="../notes/coverage.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
<a rel="next prefetch" href="../notes/framegraph.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
</nav>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
window.playground_copyable = true;
|
|
</script>
|
|
|
|
|
|
<script src="../elasticlunr.min.js"></script>
|
|
<script src="../mark.min.js"></script>
|
|
<script src="../searcher.js"></script>
|
|
|
|
<script src="../clipboard.min.js"></script>
|
|
<script src="../highlight.js"></script>
|
|
<script src="../book.js"></script>
|
|
|
|
<!-- Custom JS scripts -->
|
|
|
|
|
|
</div>
|
|
</body>
|
|
</html>
|