This will update and force push the tag.","breadcrumbs":"Technical Notes » Versioning » Release Guide » Update the release branch (if needed).","id":"121","title":"Update the release branch (if needed)."},"122":{"body":"Navigate to Filament's release workflow . Hit the Run workflow dropdown. Modify Platform to build and Release tag to build , then hit Run workflow . This will initiate a new release run.","breadcrumbs":"Technical Notes » Versioning » Release Guide » Re-run the GitHub release workflow","id":"122","title":"Re-run the GitHub release workflow"},"123":{"body":"Navigate to Filament's npm deploy workflow . Hit the Run workflow dropdown. Modify Release tag to deploy to the tag corresponding to this release (for example, v1.42.2). Navigate to Filament's CocoaPods deploy workflow . Hit the Run workflow dropdown. Modify Release tag to deploy to the tag corresponding to this release (for example, v1.42.2).","breadcrumbs":"Technical Notes » Versioning » Release Guide » 11. Kick off the npm and CocoaPods release jobs","id":"123","title":"11. Kick off the npm and CocoaPods release jobs"},"124":{"body":"Filament's documentation (which you are reading) is a collection of pages created with mdBook .","breadcrumbs":"Technical Notes » Documentation » Documentation","id":"124","title":"Documentation"},"125":{"body":"","breadcrumbs":"Technical Notes » Documentation » How the book is created and updated","id":"125","title":"How the book is created and updated"},"126":{"body":"Install mdBook for your platform There is a script docs_src/build/install_mdbook.sh that might help. It is best practice to install the python dependencies in a virtual python environment. You can start such an environment by python3 -m venv venv\n. venv/bin/activate After that you may install deps and run the build script. selenium package for python python3 -m pip install selenium","breadcrumbs":"Technical Notes » Documentation » Prerequisites","id":"126","title":"Prerequisites"},"127":{"body":"We wrote a python script to gather and transform the different documents in the project tree into a single book. This script can be found in docs_src/build/run.py . In addition, docs_src/build/duplicates.json is used to describe the markdown files that are copied and transformed from the source tree. These copies are placed into docs_src/src_mdbook/src/dup. To collect the pages and generate the book, run the following cd docs_src\npython3 build/run.py","breadcrumbs":"Technical Notes » Documentation » Generate","id":"127","title":"Generate"},"128":{"body":"docs is the github-specfic directory for producing a web frontend (i.e. documentation) for a project. (To be completed)","breadcrumbs":"Technical Notes » Documentation » Copy to docs","id":"128","title":"Copy to docs"},"129":{"body":"We list the different document sources and how they are copied and processed into the collection of markdown files that are then processed with mdBook.","breadcrumbs":"Technical Notes » Documentation » Document sources","id":"129","title":"Document sources"},"13":{"body":"You must create an Engine, a Renderer and a SwapChain. The SwapChain is created from a native window pointer (an NSView on macOS or a HWND on Windows for instance): Engine* engine = Engine::create();\nSwapChain* swapChain = engine->createSwapChain(nativeWindow);\nRenderer* renderer = engine->createRenderer(); To render a frame you must then create a View, a Scene and a Camera: Camera* camera = engine->createCamera(EntityManager::get().create());\nView* view = engine->createView();\nScene* scene = engine->createScene(); view->setCamera(camera);\nview->setScene(scene); Renderables are added to the scene: Entity renderable = EntityManager::get().create();\n// build a quad\nRenderableManager::Builder(1) .boundingBox({{ -1, -1, -1 }, { 1, 1, 1 }}) .material(0, materialInstance) .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vertexBuffer, indexBuffer, 0, 6) .culling(false) .build(*engine, renderable);\nscene->addEntity(renderable); The material instance is obtained from a material, itself loaded from a binary blob generated by matc: Material* material = Material::Builder() .package((void*) BAKED_MATERIAL_PACKAGE, sizeof(BAKED_MATERIAL_PACKAGE)) .build(*engine);\nMaterialInstance* materialInstance = material->createInstance(); To learn more about materials and matc, please refer to the materials documentation . To render, simply pass the View to the Renderer: // beginFrame() returns false if we need to skip a frame\nif (renderer->beginFrame(swapChain)) { // for each View renderer->render(view); renderer->endFrame();\n} For complete examples of Linux, macOS and Windows Filament applications, look at the source files in the samples/ directory. These samples are all based on libs/filamentapp/ which contains the code that creates a native window with SDL2 and initializes the Filament engine, renderer and views. For more information on how to prepare environment maps for image-based lighting please refer to BUILDING.md .","breadcrumbs":"Introduction » Native Linux, macOS and Windows","id":"13","title":"Native Linux, macOS and Windows"},"130":{"body":"The github landing page for Filament displays an extensive introduction to Filament. It links to BUILDING.md and CONTRIBUTING.md, which are conventional pages for building or contributing to the project. We copy these pages from their respective locations in the project tree into docs_src/src_mdbook/src/dup. Moreover, to restore valid linkage between the pages, we need to perform a number of URL replacements in addition to the copy. These replacements are described in docs_src/build/duplicates.json .","breadcrumbs":"Technical Notes » Documentation » Introductory docs","id":"130","title":"Introductory docs"},"131":{"body":"The primary design of Filament as a phyiscally-based renderer and details of its materials system are described in Filament.md.html and Materials.md.html, respectively. These two documents are written in markdeep . To embed them into our book, we Convert the markdeep into html Embed the html output in a markdown file Place the markdown file in docs_src/src_mdbook/src/main We describe step 1 in detail for the sake of record: Start a local-only server to serve the markdeep file (e.g. Filament.md.html) Start a selenium driver (essentially run chromium in headless mode) Visit the local page through the driver (i.e. open url http://localhost:xx/Filament.md.html?export) Parse out the exported output in the retrieved html (note that the output of the markdeep export is an html with the output captured in a tag). Replace css styling in the exported output as needed (so they don't interfere with the book's css. Replace resource urls to refer to locations relative to the mdbook structure. Any markdeep doc can be placed in docs_src/src_markdeep/ and they will be parsed to html and included in the book as above.","breadcrumbs":"Technical Notes » Documentation » Core concept docs","id":"131","title":"Core concept docs"},"132":{"body":"Filament depends on a number of libraries, which reside in the directory libs. These individual libaries often have README.md in their root to describe itself. We collect these descriptions into our book. In addition, client usage of Filament also requires using a set of binary tools, which are located in tools. Some of tools also have README.md as description. We also collect them into the book. The process for copying and processing these READMEs is outlined in Introductory docs .","breadcrumbs":"Technical Notes » Documentation » READMEs","id":"132","title":"READMEs"},"133":{"body":"These are technical documents that do not fit into a library, tool, or directory of the Filament source tree. We collect them into the docs_src/src_mdbook/src/notes directory. No additional processing is needed for these documents.","breadcrumbs":"Technical Notes » Documentation » Other technical notes","id":"133","title":"Other technical notes"},"134":{"body":"These are files that are not part of the mdbook generation, but should be included output in /docs to point to standalone pages or components (for example, the remote page for Android's gltf_viewer). These files are stored in docs_src/src_raw.","breadcrumbs":"Technical Notes » Documentation » Raw source files","id":"134","title":"Raw source files"},"135":{"body":"To add any documentation, first consider the type of the document you like to add. If it belongs to any of the above sources, then simply place the document in the appropriate place, add a link in SUMMARY.md, and perform the steps outlined in how-to create section . For example, if you are adding a general technical note, then you would Place the document (file with extension .md) in docs_src/src_mdbook/src/notes Add a link in docs_src/src_mdbook/src/SUMMARY.md Run the commands in the Generate section","breadcrumbs":"Technical Notes » Documentation » Adding more documents","id":"135","title":"Adding more documents"},"136":{"body":"Helpful documents for specific debugging needs.","breadcrumbs":"Technical Notes » Debugging » Debugging","id":"136","title":"Debugging"},"137":{"body":"","breadcrumbs":"Technical Notes » Debugging » Metal » Debugging Metal","id":"137","title":"Debugging Metal"},"138":{"body":"To enable the Metal validation layers when running a sample through the command-line, set the following environment variable: export METAL_DEVICE_WRAPPER_TYPE=1 You should then see the following output when running a sample with the Metal backend: 2020-10-13 18:01:44.101 gltf_viewer[73303:4946828] Metal API Validation Enabled","breadcrumbs":"Technical Notes » Debugging » Metal » Enable Metal Validation","id":"138","title":"Enable Metal Validation"},"139":{"body":"To capture Metal frames from within gltf_viewer:","breadcrumbs":"Technical Notes » Debugging » Metal » Metal Frame Capture from gltf_viewer","id":"139","title":"Metal Frame Capture from gltf_viewer"},"14":{"body":"See android/samples for examples of how to use Filament on Android. You must always first initialize Filament by calling Filament.init(). Rendering with Filament on Android is similar to rendering from native code (the APIs are largely the same across languages). You can render into a Surface by passing a Surface to the createSwapChain method. This allows you to render to a SurfaceTexture, a TextureView or a SurfaceView. To make things easier we provide an Android specific API called UiHelper in the package com.google.android.filament.android. All you need to do is set a render callback on the helper and attach your SurfaceView or TextureView to it. You are still responsible for creating the swap chain in the onNativeWindowChanged() callback.","breadcrumbs":"Introduction » Android","id":"14","title":"Android"},"140":{"body":"Create an Info.plist file in the same directory as gltf_viewer (cmake/samples). Set its contents to: \n\n\n MetalCaptureEnabled \n\n","breadcrumbs":"Technical Notes » Debugging » Metal » 1. Create an Info.plist file","id":"140","title":"1. Create an Info.plist file"},"141":{"body":"Run gltf_viewer as normal, and hit the \"Capture frame\" button under the Debug menu. The captured frame will be saved to filament.gputrace in the current working directory. This file can then be opened with Xcode for inspection.","breadcrumbs":"Technical Notes » Debugging » Metal » 2. Capture a frame","id":"141","title":"2. Capture a frame"},"142":{"body":"","breadcrumbs":"Technical Notes » Debugging » Vulkan » Debugging Vulkan","id":"142","title":"Debugging Vulkan"},"143":{"body":"Simply install the LunarG SDK (it's fast and easy), then make sure you've got the following environment variables set up in your bashrc file. For example: export VULKAN_SDK='/path_to_home/VulkanSDK/1.3.216.0/x86_64'\nexport VK_LAYER_PATH=\"$VULKAN_SDK/etc/explicit_layer.d\"\nexport PATH=\"$VULKAN_SDK/bin:$PATH\" As long as you're running a debug build of Filament, you should now see extra debugging spew in your console if there are any errors or performance issues being caught by validation.","breadcrumbs":"Technical Notes » Debugging » Vulkan » Enable Validation Logs","id":"143","title":"Enable Validation Logs"},"144":{"body":"There are 4 repositories at play here: KhronosGroup/glslang KhronosGroup/spirv-tools KhronosGroup/spirv-cross KhronosGroup/SPIRV-Headers Typically, the bug is present either in spirv-tools or spirv-cross.","breadcrumbs":"Technical Notes » Debugging » SPIR-V » Investigating SPIRV-Cross / SPIRV-Tools issues","id":"144","title":"Investigating SPIRV-Cross / SPIRV-Tools issues"},"145":{"body":"The goal is to replicate the bug outside of Filament, so we're going to use command-line versions of the SPIRV tools.","breadcrumbs":"Technical Notes » Debugging » SPIR-V » Build and install command-line tools on PATH","id":"145","title":"Build and install command-line tools on PATH"},"146":{"body":"Note: Filament checks-out versions of these repositories inside third_party/; however, I've found it easiser to check out fresh copies separately so I can simply git pull to get the latest versions. Furthermore, Filament has modified some of these repositories locally for its own use case. Checking them out separately \"proves\" that the issue isn't Filament-specific. git clone git@github.com:KhronosGroup/SPIRV-Tools.git\ngit clone git@github.com:KhronosGroup/SPIRV-Cross.git\ngit clone git@github.com:KhronosGroup/glslang.git\ngit clone git@github.com:KhronosGroup/SPIRV-Headers.git SPIRV-Tools/external/SPIRV-Headers cd SPIRV-Tools/\nmkdir build && cmake . -G Ninja -B build\nninja -C build\ncd .. cd SPIRV-Cross/\nmkdir build && cmake . -G Ninja -B build\nninja -C build\ncd .. cd glslang/\nmkdir build && cmake . -G Ninja -B build\nninja -C build\ncd ..","breadcrumbs":"Technical Notes » Debugging » SPIR-V » Clone and build each repo","id":"146","title":"Clone and build each repo"},"147":{"body":"export PATH=`pwd`/SPIRV-Tools/build/tools:$PATH\nexport PATH=`pwd`/glslang/build/StandAlone:$PATH\nexport PATH=`pwd`/spirv-cross/build:$PATH Ensure the following tools now exist on your PATH: glslangValidator spiv-opt spirv-val spirv-cross","breadcrumbs":"Technical Notes » Debugging » SPIR-V » Add directories to PATH","id":"147","title":"Add directories to PATH"},"148":{"body":"First determine the Filament material and variant that causes the problem. What we want is the \"raw\" GLSL version of the shader, before any optimizations / cross-compilation happens. We can use the --save-raw-variants debug flag in matc to export each GLSL shader to a file. For example: matc --save-raw-variants --optimize-size --variant-filter fog,ssr,vsm,stereo \\ -a all -p all -o mymaterial.filamat mymaterial.mat Files will be named like mymaterial_0x05.frag or mymaterial_0x05.vert. Note that gltfio material \"templates\" first go through a build step. After building gltfio, the gltfio Filament materials are output to: out/cmake-release/libs/gltfio/*.mat One of these materials can be compiled with the following command: matc \\ -TCUSTOM_PARAMS=\"// no custom params\" \\ -TCUSTOM_VERTEX=\"// no custom vertex\" \\ -TCUSTOM_FRAGMENT=\"// no custom fragment\" \\ -TDOUBLESIDED=false \\ -TTRANSPARENCY=default \\ -TSHADINGMODEL=unlit \\ -TBLENDING=opaque \\ --platform mobile --api metal -o temp.filamat \\ unlit_opaque.mat","breadcrumbs":"Technical Notes » Debugging » SPIR-V » Isolate the problematic GLSL shader","id":"148","title":"Isolate the problematic GLSL shader"},"149":{"body":"The goal is to generate a .spv file that doesn't pass validation (through the spirv-val tool). Reproducing the error usually involves a few steps: Compile the raw GLSL shader into SPIR-V. glslangValidator -V -o unoptimized.spv in.frag Optimize for performance. spirv-opt -Oconfig=optimizations.cfg unoptimized.spv -o optimized.spv See optimizations.cfg for a template. This file should contain the same list of optimizations that Filament employs. This should match the same optimizations specified in GLSLPostProcessor, for example, GLSLPostProcessor::registerPerformancePasses or GLSLPostProcessor::registerSizePasses. For shaders targeting Metal, convert relaxed ops to half. spirv-opt \\ --convert-relaxed-to-half \\ --simplify-instructions \\ --redundancy-elimination \\ --eliminate-dead-code-aggressive \\ optimized.spv \\ -o half.spv Finally, validate the final SPIR-V. spirv-val half.spv Sometimes validation will still pass, but still generate invalid shaders after cross-compiling. In these cases, you'll need to cross compile to the target language and manually pick out errors in the generated shader. # for OpenGL\nspirv-cross optimized.spv > optimized.frag # for OpenGL ES\nspirv-cross --es optimized.spv > optimized.frag # for MSL\nspirv-cross --msl optimized.spv > optimized.metal To invoke Apple's compiler to compile MSL, you can run: xcrun -sdk macosx metal -c optimized.metal -o /dev/null","breadcrumbs":"Technical Notes » Debugging » SPIR-V » Reproduce the compilation error","id":"149","title":"Reproduce the compilation error"},"15":{"body":"Filament is supported on iOS 11.0 and above. See ios/samples for examples of using Filament on iOS. Filament on iOS is largely the same as native rendering with C++. A CAEAGLLayer or CAMetalLayer is passed to the createSwapChain method. Filament for iOS supports both Metal (preferred) and OpenGL ES.","breadcrumbs":"Introduction » iOS","id":"15","title":"iOS"},"150":{"body":"These commands will run the preprocessor only on in.frag, and remove any empty lines. glslangValidator -E in.frag > preprocessed.frag\nsed '/^$/d' preprocessed.frag > preprocessed_small.frag You can also run clang-format on the preprocessed shader to make it easier to read: clang-format -i preprocessed_small.frag I always try to \"whittle down\" the shader to a smaller version that still reproduces the error. This might make it a bit easier on the Khronos team to diagnose the issue. I typically follow these steps in a loop until I'm satisfied: Delete an unnecessary part of the shader Run the steps to reproduce the error If the error still reproduces, repeat Otherwise, undo the change and make a smaller change There's also a Reducer tool that's part of SPIRV-Tools which can be used to automate these steps. I haven't experimented much with this, but it seems promising.","breadcrumbs":"Technical Notes » Debugging » SPIR-V » Clean up the shader for a bug report","id":"150","title":"Clean up the shader for a bug report"},"151":{"body":"See some example issues that have been filed in the past: https://github.com/KhronosGroup/SPIRV-Cross/issues/1935 https://github.com/KhronosGroup/SPIRV-Cross/issues/1088 https://github.com/KhronosGroup/SPIRV-Cross/issues/1026 https://github.com/KhronosGroup/SPIRV-Tools/issues/4452 https://github.com/KhronosGroup/SPIRV-Tools/issues/3406 https://github.com/KhronosGroup/SPIRV-Tools/issues/3099 https://github.com/KhronosGroup/SPIRV-Tools/issues/5044","breadcrumbs":"Technical Notes » Debugging » SPIR-V » Submit an Issue with the relevant Khronos repository","id":"151","title":"Submit an Issue with the relevant Khronos repository"},"152":{"body":"","breadcrumbs":"Technical Notes » Debugging » Running with ASAN and UBSAN » Running with ASAN/UBSAN","id":"152","title":"Running with ASAN/UBSAN"},"153":{"body":"When building though build.sh, pass the -b flag. This sets the cmake variable FILAMENT_ENABLE_ASAN_UBSAN=ON which eventually passes \"-fsanitize=address -fsanitize=undefined\" to all compile and link operations. It might be desirable to pair the -b with -y release. The -y flag indicates that targets in /tools will be built separately from the filament target, and the filament build depends on the /tools targets as prebuilt binaries. This separation reduces ASAN/UBSAN build time considerably. This option assumes that the user is trying to catch sanitization issues for filament and not the tools that are used to build filament. If building through CMake directly, or an IDE like CLion that doesn't use build.sh, instead pass -DFILAMENT_ENABLE_ASAN_UBSAN=ON to cmake in order to get the same result.","breadcrumbs":"Technical Notes » Debugging » Running with ASAN and UBSAN » Enabling","id":"153","title":"Enabling"},"154":{"body":"Memory leak detection isn't enabled by default on MacOS. There are two issues to address, first is using a version of clang that supports memory leak detection and second is enabling it at runtime. The version of clang distributed by Apple (with a version like \"Apple clang version 16.0.0\") doesn't currently support leak detection at all. Instead you will need to get or build a different LLVM, such as the one distributed through homebrew and get CMake to use that instead. Then during runtime you'll need to have the environment variable ASAN_OPTIONS include the option detect_leaks=1. Multiple ASAN_OPTIONS values are concatenated with :.","breadcrumbs":"Technical Notes » Debugging » Running with ASAN and UBSAN » Getting memory leak detection on Mac","id":"154","title":"Getting memory leak detection on Mac"},"155":{"body":"","breadcrumbs":"Technical Notes » Debugging » Running with ASAN and UBSAN » Getting memory leak output in CLion","id":"155","title":"Getting memory leak output in CLion"},"156":{"body":"Under Settings | Build, Execution, Deployment | Dynamic Analysis Tools | Sanitizers there is an ASAN Settings field that overrides whatever other ASAN_OPTIONS you might set elsewhere, so you must use that instead of setting it through your Run/Debug Configuration. To pass -DFILAMENT_ENABLE_ASAN_UBSAN=ON to CMake you'll want to create a new CMake Profile and pass it as a CMake argument.","breadcrumbs":"Technical Notes » Debugging » Running with ASAN and UBSAN » Setting variables","id":"156","title":"Setting variables"},"157":{"body":"CMake will consume ASAN output and display it through a separate \"Sanitizers\" tab. Unfortunately certain leak detection errors that interrupt the executable seem to not show up in this tab, but are still removed from the user-visible console output. If this is happening and you need to see the unfiltered console output you'll need to go to Settings | Build, Execution, Deployment | Dynamic Analysis Tools | Sanitizers and uncheck \"Use visual representation for Sanitizer's output\".","breadcrumbs":"Technical Notes » Debugging » Running with ASAN and UBSAN » Avoiding losing output","id":"157","title":"Avoiding losing output"},"158":{"body":"When running a binary under Instruments on macOS, you may run into the following issue when launching or attaching to an executable: Failed to gain authorization\nRecovery Suggestion: Target binary needs to be debuggable and signed with 'get-task-allow' This is a security precaution; the solution is to code sign the binary with the com.apple.security.get-task-allow entitlement. Create an entitlements.plist file with the following contents: \n\n\n com.apple.security.get-task-allow \n\n Run the following command: codesign -s - --entitlements entitlements.plist Replace with the name of the binary, for example: out/cmake-debug/samples/gltf_viewer. Afterwards, you should be able to successfully launch and attach to the executable using Instruments.","breadcrumbs":"Technical Notes » Debugging » Using Instruments on macOS » Using Instruments on macOS","id":"158","title":"Using Instruments on macOS"},"159":{"body":"Code coverage analysis helps visualize which parts of the backend are exercised by backend tests. This guide outlines the process for generating an HTML coverage report for Filament's backend on macOS.","breadcrumbs":"Technical Notes » Debugging » Code coverage analysis » Generating Backend Code Coverage","id":"159","title":"Generating Backend Code Coverage"},"16":{"body":"To get started you can use the textures and environment maps found respectively in third_party/textures and third_party/environments. These assets are under CC0 license. Please refer to their respective URL.txt files to know more about the original authors. Environments must be pre-processed using cmgen or using the libiblprefilter library.","breadcrumbs":"Introduction » Assets","id":"16","title":"Assets"},"160":{"body":"You'll need a recent version of Clang and its corresponding LLVM tools for code coverage. You can install these using Homebrew or MacPorts.","breadcrumbs":"Technical Notes » Debugging » Code coverage analysis » 1. Prerequisites: Install Clang and LLVM tools","id":"160","title":"1. Prerequisites: Install Clang and LLVM tools"},"161":{"body":"Install the llvm package: brew install llvm This typically installs the tools in a location like /usr/local/opt/llvm/bin. You may need to add this to your PATH environment variable.","breadcrumbs":"Technical Notes » Debugging » Code coverage analysis » Using Homebrew","id":"161","title":"Using Homebrew"},"162":{"body":"Install a specific version of Clang (e.g., version 18): sudo port install clang-18 MacPorts often adds version suffixes to the tool names (e.g., llvm-cov-mp-18).","breadcrumbs":"Technical Notes » Debugging » Code coverage analysis » Using MacPorts","id":"162","title":"Using MacPorts"},"163":{"body":"Ensure you can locate the following tools from your installation: clang and clang++ (The C/C++ compilers) llvm-profdata (For merging coverage data) llvm-cov (For generating reports) The rest of this guide assumes your tools are in your PATH. If not, you'll need to use the full path to each executable.","breadcrumbs":"Technical Notes » Debugging » Code coverage analysis » Required Tools","id":"163","title":"Required Tools"},"164":{"body":"Compile the backend_test_mac target with coverage instrumentation. This is done by setting the CC and CXX environment variables to point to your Clang compiler and using the -V flag in the build script. CC=clang CXX=clang++ ./build.sh -V -p desktop debug backend_test_mac If your Clang executables aren't in your PATH or have version suffixes, provide the full name or path (e.g., CC=/opt/local/bin/clang CXX=/opt/local/bin/clang++).","breadcrumbs":"Technical Notes » Debugging » Code coverage analysis » 2. Build Filament with Coverage Enabled","id":"164","title":"2. Build Filament with Coverage Enabled"},"165":{"body":"Running the test suite will generate the raw coverage data needed for the report. Navigate to the build output directory: cd out/cmake-debug/filament/backend Run the tests for a specific backend (e.g., Metal): ./backend_test_mac --api metal This command creates a default.profraw file in the current directory, which contains the raw execution profile data.","breadcrumbs":"Technical Notes » Debugging » Code coverage analysis » 3. Run the Backend Tests","id":"165","title":"3. Run the Backend Tests"},"166":{"body":"Finally, process the raw data and generate an HTML report. Merge the raw profile data into a single file using llvm-profdata. llvm-profdata merge -sparse default.profraw -o filament.profdata Remember to use the version-specific tool name if required (e.g., llvm-profdata-mp-18). Generate the HTML report using llvm-cov. This command creates a report for the entire backend_test_mac executable. llvm-cov show ./backend_test_mac \\ -instr-profile=filament.profdata \\ -format=html \\ -show-line-counts-or-regions > coverage.html To view coverage for a specific source file , add its path at the end of the command: llvm-cov show ./backend_test_mac \\ -instr-profile=filament.profdata \\ -format=html \\ -show-line-counts-or-regions \\ -- ../../../../filament/backend/src/metal/MetalDriver.mm > coverage.html Open the report in your browser: open coverage.html In the report, code paths that were not executed during the test run will be highlighted in red.","breadcrumbs":"Technical Notes » Debugging » Code coverage analysis » 4. Generate the Coverage Report","id":"166","title":"4. Generate the Coverage Report"},"167":{"body":"","breadcrumbs":"Technical Notes » Debugging » Performance analysis » Performance Analysis","id":"167","title":"Performance Analysis"},"168":{"body":"","breadcrumbs":"Technical Notes » Debugging » Performance analysis » Android","id":"168","title":"Android"},"169":{"body":"Download and install Android GPU Inspector (AGI). See https://developer.android.com/agi. Profiling Before profiling the application or analyzing the performance in a consistent way, ideally the GPU frequency on the target hardware should get locked . In order to do this, you need to do the following: 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\". 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. Connect the phone to the computer via a USB cable and run from the command line: adb reboot bootloader\n# once the phone is in bootloader mode, run the following to begin the unlocking\n# process:\nfastboot flashing unlock 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. 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 Android Flash Tool . Connect the tool to your device and find a build to flash ending in -userdebug or -eng. Once you have that selected run Install build. Shell into your device as root and configure the gpu frequency to be locked, e.g.: adb shell\nsu\n# navigate to the system GPU directory. this varies on different phones. One phone might have\n# it at /sys/class/kgsl/kgsl-3d0 and another might be in something similar, maybe with \"mali\" instead\n# of \"kgsl\". At the time of writing this for the device at hand it was /sys/devices/platform/1f000000.mali\ncd /sys/devices/platform/1f000000.mali\n# get the current available GPU governors and frequencies.\n# note that some systems may have these at gpu_available_governors and gpu_available_frequencies, but\n# the system at the time of writing this had available_governors and available_frequences\ncat available_governors\ncat available_frequencies\n# depending on the governors, you may want to set it prioritize performance over other things like\n# battery. Some systems allow you to do this with something like (although, for the device used at the\n# time of writing this did not have an equivalent option):\necho performance > gpu_governor\n# finally, lock your frequency in, usually to something high like 897 MHz. Some systems may have you\n# pipe the value to gpu_min_freq and gpu_max_freq, but the system used at the time of writing this had:\necho 940000 > hint_min_freq\necho 940000 > hint_max_freq\n# you can typically verify the GPU is running at that frequency consistently by running something like\n# the following a few times over time, which should show the frequency you want to lock the device to:\ncat cur_freq You may need to re-apply the hint_min_freq 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. 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. Build a release build of Filament with the applicable backend(s) enabled (+ any special flags for enabling sys strace. Nothing special is needed for Vulkan or WebGPU aside from building a release build with no flags) (debug builds for this are useless) # the following command assumes you are in the root filament directory\n# and ANDROID_HOME is exported (and possibly also CC and CXX on linux as needed)\n#\n# NOTE: to build with WebGPU support you need to explicitly include the -W flag\n# (it doesn't get compiled in by default), e.g.:\n# ./build.sh -W -p android,desktop -i release\n#\n# 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\n# will need to update the android/gradle.properties file to specify the ABI(s) you are targeting\n# with the com.google.android.filament.abis property.\n# Thus, a build command that would target BOTH Vulkan AND WebGPU AND only target the ARM64 ABI would look something\n# like:\n# ./build.sh -W -q arm64-v8a -p android,desktop -i release\n./build.sh -p android,desktop -i release 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. (to determine how these numbers map to the backends, see the enum class Backend definition in filament/filament/backend/include/backend/DriverEnums.h ) : # to set the backend to Vulkan: adb shell setprop debug.filament.backend 2\n# to set the backend to WebGPU:\nadb shell setprop debug.filament.backend 4\n# to view the current property:\nadb shell getprop debug.filament.backend Build and run a sample, e.g. sample-gltf-viewer, on your Android device ( Android Studio recommended) . Run AGI 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. We typically only run \"Capture System Profiler trace\" (not necessarily \"Capture Frame Profiler trace\") When configuring the trace: For both the WebGPU and Vulkan backends configure the profiler for the Vulkan API (since WebGPU should be using Vulkan under the hood as well) Running for ~1 seconds should suffice Hit the \"Configure\" button in Trace objects, select \"Switch to advanced mode\" and add: data_sources { config { name: \"track_event\" track_event_config { disabled_categories: \"*\" enabled_categories: \"filament/filament\" enabled_categories: \"filament/jobsystem\" enabled_categories: \"filament/gltfio\" } }\n} One you open the trace, zoom into a series of frames to get a sense of generally how long they typically take (use W, S, A and D keys and mouse wheel for navigation) and find a representative one. We are most interested in the performance of the FEngine::loop 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.","breadcrumbs":"Technical Notes » Debugging » Performance analysis » Prerequisites","id":"169","title":"Prerequisites"},"17":{"body":"Please read and follow the steps in CONTRIBUTING.md . Make sure you are familiar with the code style .","breadcrumbs":"Introduction » How to make contributions","id":"17","title":"How to make contributions"},"170":{"body":"FrameGraph is a framework within Filament for computing resources needed to render a frame. The framework enables declaring dependencies between resources. For example, when rendering shadows, we would need to first compute and store the shadow map into a texture resource, and then the later color pass would then sample that texture to attenuate the final output color. That creates a dependency on the shadow map from the color pass. Filament uses FrameGraph to declare that dependency.","breadcrumbs":"Technical Notes » Framegraph » FrameGraph","id":"170","title":"FrameGraph"},"171":{"body":"","breadcrumbs":"Technical Notes » Framegraph » Details","id":"171","title":"Details"},"172":{"body":"The core of this framework is a class that defines a dependency graph — that is, the class defines nodes and connections between nodes. This class makes assumptions about the types of its nodes. Like many other classes within Filament, this class is without virtual function declaration to avoid paying the cost of virtual calls. This class has additional functions to detect whether there is a cycle in the graph, and it is able to cull unreachable nodes.","breadcrumbs":"Technical Notes » Framegraph » Dependency Graph","id":"172","title":"Dependency Graph"},"173":{"body":"A frame graph consists of two types of nodes Resource This represents a generic resource such as a texture 90% of the time, this is a texture. Pass This represents a \"computation/rendering process\" It takes a set of resources It outputs a set of resources Edges can be created in the following three directions: Resource → Pass = A read Pass → Resource = A write Resource → Resource = A resource/subresource relationship.","breadcrumbs":"Technical Notes » Framegraph » FrameGraph","id":"173","title":"FrameGraph"},"174":{"body":"To better understand FrameGraph, we consider the following graphical representation of a real graph. In this graph, blue nodes denote \"Resources\" and orange nodes denote \"Passes.\" Sample frame graph In this graph, we see that the \"Color Pass\" takes as input the \"Shadowmap\", which has edges going into it, meaning that it's a texture array. The output of the \"Color Pass\" are \"viewRenderTarget\" and \"Depth Buffer.\" Note that there is an outgoing edge from \"viewRenderTarget\", where the color buffer will be used as input in the post-processing passes. But since \"Depth Buffer\" is not relevant to the rest of the rendering, it does not have an outgoing edge. Since the graph is guaranteed to be acyclic, we can produce a dependency-respecting ordering of the nodes by traversal of the graph (e.g. topological sort).","breadcrumbs":"Technical Notes » Framegraph » An example","id":"174","title":"An example"},"175":{"body":"We take a snippet of in production code to look through the details of building a graph. struct StructurePassData { FrameGraphId depth; FrameGraphId picking;\n}; ... // generate depth pass at the requested resolution\nauto& structurePass = fg.addPass(\"Structure Pass\", [&](FrameGraph::Builder& builder, auto& data) { bool const isES2 = mEngine.getDriverApi().getFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0; data.depth = builder.createTexture(\"Structure Buffer\", { .width = width, .height = height, .levels = uint8_t(levelCount), .format = isES2 ? TextureFormat::DEPTH24 : TextureFormat::DEPTH32F }); // workaround: since we have levels, this implies SAMPLEABLE (because of the gl // backend, which implements non-sampleables with renderbuffers, which don't have levels). // (should the gl driver revert to textures, in that case?) data.depth = builder.write(data.depth, FrameGraphTexture::Usage::DEPTH_ATTACHMENT | FrameGraphTexture::Usage::SAMPLEABLE); if (config.picking) { data.picking = builder.createTexture(\"Picking Buffer\", { .width = width, .height = height, .format = isES2 ? TextureFormat::RGBA8 : TextureFormat::RG32F }); data.picking = builder.write(data.picking, FrameGraphTexture::Usage::COLOR_ATTACHMENT); } builder.declareRenderPass(\"Structure Target\", { .attachments = { .color = { data.picking }, .depth = data.depth }, .clearFlags = TargetBufferFlags::COLOR0 | TargetBufferFlags::DEPTH }); }, [=, renderPass = pass](FrameGraphResources const& resources, auto const&, DriverApi&) mutable { Variant structureVariant(Variant::DEPTH_VARIANT); structureVariant.setPicking(config.picking); auto out = resources.getRenderPassInfo(); renderPass.setRenderFlags(structureRenderFlags); renderPass.setVariant(structureVariant); renderPass.appendCommands(mEngine, RenderPass::CommandTypeFlags::SSAO); renderPass.sortCommands(mEngine); renderPass.execute(mEngine, resources.getPassName(), out.target, out.params); }\n); The addPass method creates a node and it take in two lambda functions as its parameter. The first lambda sets up the resources that will be used in the execution of the Pass. This lambda is executed immediately and synchronously when addPass is called. The second lambda is the actual execution of the pass; it is executed when the graph has been completed and is traversed.","breadcrumbs":"Technical Notes » Framegraph » Example code","id":"175","title":"Example code"},"176":{"body":"In the above, we see through a graph and code what a frame graph looks like and how to build it. We provide here a more detailed description of what it does: Manages the lifetime of the resources Know how the resources are allocated, when it is used, and when it can be freed Calculates the usage bit of the texture resource The usage bit is used to indicate what the resources are used for: for example, will it be blitted to or sampled from? Calculates the load/store bits of the rendertargets within a renderpass. For example, if we are rendering into a texture, we would want to mark it with the bit \"keep\" as oppose to \"discard\".","breadcrumbs":"Technical Notes » Framegraph » What does it do?","id":"176","title":"What does it do?"},"177":{"body":"In a previous version of FrameGraph, there were only edges between Resource and Pass. For example, a Pass and Pass edge would not make logical sense. The following iteration, allowed for edges between two Resource nodes to indicate that one is a subresource of another (i.e. a layer in a mip-mapped texture). There are two extra features of FrameGraph that are important but has a lot subtlety, and, incidentally, their inclusion added great complexity to the implementation Importing/exporting resources outside of the graph In most cases, the graph and its resources are \"alive\" for only for a frame. For techniques like TAA (Temporal Anti-aliasing), we need to be able to import past output into the current FrameGraph Future Work For CPU only passes, explore multi-threading and re-ordering of the Pass nodes A graphical debugger for online debugging session in the spirit of matdbg. \"RenderGraph\" might be a more fitting name for this framework.","breadcrumbs":"Technical Notes » Framegraph » Additional details","id":"177","title":"Additional details"},"178":{"body":"Filament has a collection of tests that can be run locally. Many of them are used for in our Continuation Integration flow on github .","breadcrumbs":"Technical Notes » Tests » Tests","id":"178","title":"Tests"},"179":{"body":"This tool is a collections of scripts to run gltf_viewer and produce headless renderings. This is mainly useful for continuous integration where GPUs are generally not available on cloud machines. To perform software rasterization, these scripts are centered around Mesa 's software rasterizers, but nothing bars us from using another rasterizer like SwiftShader . Additionally, we should be able to use GPUs where available (though this is more of a future work). The script render.py contains the core logic for taking input parameters (such as the test description file) and then running gltf_viewer to produce the renderings. In the test directory is a list of test descriptions that are specified in json. Please see sample.json to glean the structure.","breadcrumbs":"Technical Notes » Tests » renderdiff » Rendering Difference Test","id":"179","title":"Rendering Difference Test"},"18":{"body":"This repository not only contains the core Filament engine, but also its supporting libraries and tools. android: Android libraries and projects filamat-android: Filament material generation library (AAR) for Android filament-android: Filament library (AAR) for Android filament-utils-android: Extra utilities (KTX loader, math types, etc.) gltfio-android: Filament glTF loading library (AAR) for Android samples: Android-specific Filament samples art: Source for various artworks (logos, PDF manuals, etc.) assets: 3D assets to use with sample applications build: CMake build scripts docs: Documentation math: Mathematica notebooks used to explore BRDFs, equations, etc. filament: Filament rendering engine (minimal dependencies) backend: Rendering backends/drivers (Vulkan, Metal, OpenGL/ES) ide: Configuration files for IDEs (CLion, etc.) ios: Sample projects for iOS libs: Libraries bluegl: OpenGL bindings for macOS, Linux and Windows bluevk: Vulkan bindings for macOS, Linux, Windows and Android camutils: Camera manipulation utilities filabridge: Library shared by the Filament engine and host tools filaflat: Serialization/deserialization library used for materials filagui: Helper library for Dear ImGui filamat: Material generation library filamentapp: SDL2 skeleton to build sample apps filameshio: Tiny filamesh parsing library (see also tools/filamesh) geometry: Mesh-related utilities gltfio: Loader for glTF 2.0 ibl: IBL generation tools image: Image filtering and simple transforms imageio: Image file reading / writing, only intended for internal use matdbg: DebugServer for inspecting shaders at run-time (debug builds only) math: Math library mathio: Math types support for output streams utils: Utility library (threads, memory, data structures, etc.) viewer: glTF viewer library (requires gltfio) samples: Sample desktop applications shaders: Shaders used by filamat and matc third_party: External libraries and assets environments: Environment maps under CC0 license that can be used with cmgen models: Models under permissive licenses textures: Textures under CC0 license tools: Host tools cmgen: Image-based lighting asset generator filamesh: Mesh converter glslminifier: Minifies GLSL source code matc: Material compiler filament-matp: Material parser matinfo Displays information about materials compiled with matc mipgen Generates a series of miplevels from a source image normal-blending: Tool to blend normal maps resgen Aggregates binary blobs into embeddable resources roughness-prefilter: Pre-filters a roughness map from a normal map to reduce aliasing specular-color: Computes the specular color of conductors based on spectral data web: JavaScript bindings, documentation, and samples","breadcrumbs":"Introduction » Directory structure","id":"18","title":"Directory structure"},"180":{"body":"The renderdiff project uses python extensively. To install the dependencies for producing renderings, do the following step Set up a virtual environment (from the root directory) python3 -m venv venv\n. ./venv/bin/activate Install the rendering dependencies pip install -r test/renderdiff/src/rendering_requirements.txt Install the viewer depdencies pip install -r test/renderdiff/src/viewer_requirements.txt For the commands in the following section, do not exit the virtual environment. Once you've completed all your work, you can exit with deactivate","breadcrumbs":"Technical Notes » Tests » renderdiff » Setting up python","id":"180","title":"Setting up python"},"181":{"body":"To run the same presbumit as test-renderdiff , you can do bash test/renderdiff/local_test.sh This script will generate the renderings based on the current state of your repo. Additionally, it will also compare the generated images with corresponding images in the golden repo. To just render without running the test, you could use the following script bash test/renderdiff/generate.sh","breadcrumbs":"Technical Notes » Tests » renderdiff » Running the test locally","id":"181","title":"Running the test locally"},"182":{"body":"You can control the behavior of the test scripts with the following flags passed to local_test.sh: --test_filter=: Run a subset of tests. The filter supports wildcards (*) to match test names. --no_rebuild: Skip rebuilding the gltf_viewer executable. --num_threads=: Set the number of threads for rendering. If not set, the system's default is used. For example, to run all MSAA tests without rebuilding and using 8 threads: bash test/renderdiff/local_test.sh --test_filter='MSAA.*.*' --no_rebuild --num_threads=8","breadcrumbs":"Technical Notes » Tests » renderdiff » Command-line Options","id":"182","title":"Command-line Options"},"183":{"body":"The golden images are stored in a github repository: https://github.com/google/filament-assets. Filament team members should have access to write to the repository. A typical flow for updating the goldens is to upload your changed images into branch of filament-assets. This branch is paired with a PR or commit on the filament repo. As an example, imagine I am working on a PR, and I've uploaded my change, which is in a branch called my-pr-branch, to filament. This PR requires updating the golden. We would do it in the following fashion","breadcrumbs":"Technical Notes » Tests » renderdiff » Update the golden images","id":"183","title":"Update the golden images"},"184":{"body":"Run interactive mode in the update_golden.py script. python3 test/renderdiff/src/update_golden.py This will guide you through a series of steps to push the changes to a remote branch on filament-assets.","breadcrumbs":"Technical Notes » Tests » renderdiff » Using a script to update the golden repo","id":"184","title":"Using a script to update the golden repo"},"185":{"body":"Check out the golden repo git clone git@github.com:google/filament-assets.git Create a branch on the golden repo cd filament-assets\ngit switch -c my-pr-branch-golden Copy the new images to their appropriate place in filament-assets Push the filament-assets working branch to remote git push origin my-pr-branch-golden In the commit message of your working branch on filament, add the following line RDIFF_BBRANCH=my-pr-branch-golden Doing the above has multiple effects: The presubmit test test-renderdiff will test against the provided branch of the golden repo (i.e. my-pr-branch-golden). If the PR is merged, then there is another workflow that will merge my-pr-branch-golden to the main branch of the golden repo.","breadcrumbs":"Technical Notes » Tests » renderdiff » Manually updating the golden repo","id":"185","title":"Manually updating the golden repo"},"186":{"body":"We provide a viewer for looking at the result of a test run. The viewer is a webapp that can be used by pointing your browser to a localhost port. If you input the viewer with a PR or a directory, it will parse the test result and show the results and the rendered and/or golden images. Viewer To run the viewer of a test output directory that has been generated locally, you would run the following python3 test/renderdiff/src/viewer.py --diff=[test output] where [test output] is a directory containing the compare_results.json of the test run. For example, it could be out/renderdiff/diffs/presubmit for the standard path to the presubmit test output. To see the results of a Pull Request initiated test run, you would do the following python3 test/renderdiff/src/viewer.py --pr_number=[PR #] --github_token=[github token] where [PR #] is the numeric ID of your pull request, and the [github token] is an acess token that you (as a github user) needs to generate ( reference ). To see the results of a specific run, you would do the following python3 test/renderdiff/src/viewer.py --run_number=[RUN #] --github_token=[github token] where [RUN #] is the numeric ID of the run. You can find the run number in the URL of the GitHub Actions page. For example, in the URL https://github.com/google/filament/actions/runs/18023632663/job/51286323708?pr=9264, the run number is 18023632663.","breadcrumbs":"Technical Notes » Tests » renderdiff » Viewing test results","id":"186","title":"Viewing test results"},"187":{"body":"Collection of README.md from the /libs folder.","breadcrumbs":"Technical Notes » Libraries » Libraries","id":"187","title":"Libraries"},"188":{"body":"So you want to call glClear()?","breadcrumbs":"Technical Notes » Libraries » bluegl » BlueGL Mechanics","id":"188","title":"BlueGL Mechanics"},"189":{"body":"This step is only required if updating or modifying BlueGL. These artifacts should already be checked into the Filament repository. From the libs/bluegl folder, run: ./bluegl-gen.py The bluegl-gen.py script generates a set of files: assembly (proxy) files: BlueGLCore*.S header files: include/BlueGLDefines.h and include/bluegl/BlueGL.h a private header:include/private_BlueGL.h","breadcrumbs":"Technical Notes » Libraries » bluegl » Step 0: Run bluegl-gen.py","id":"189","title":"Step 0: Run bluegl-gen.py"},"19":{"body":"Please see LICENSE .","breadcrumbs":"Introduction » License","id":"19","title":"License"},"190":{"body":"#include This headers adds a bunch of defines: ...\n#define glClear bluegl_glClear\n...","breadcrumbs":"Technical Notes » Libraries » bluegl » Step 1: Include the BlueGL defines header:","id":"190","title":"Step 1: Include the BlueGL defines header:"},"191":{"body":"#include \n#include This also includes the GL headers, like for you.","breadcrumbs":"Technical Notes » Libraries » bluegl » Step 2: Include the BlueGL header after the defines header:","id":"191","title":"Step 2: Include the BlueGL header after the defines header:"},"192":{"body":"Internally, the BlueGL library maintains a list of function pointers: void* __blue_glCore_glClear; During bluegl::bind(), each function gets assigned to the appropriate symbol loaded from the OS-specific GL shared library via dlopen, dlsym, and equivalents.","breadcrumbs":"Technical Notes » Libraries » bluegl » Step 3: Call bluegl::bind()","id":"192","title":"Step 3: Call bluegl::bind()"},"193":{"body":"Because of the prior #define, you'll actually be calling bluegl_glClear(). This is a trampoline function, defined in the BlueGLCore*.S assembly file (the exact implementation varies slightly on each platform): .private_extern _bluegl_glClear\n_bluegl_glClear: mov ___blue_glCore_glClear@GOTPCREL(%rip), %r11 jmp *(%r11) The invokes the __blue_glCore_glClear function, which was previously assigned to the actual GL function.","breadcrumbs":"Technical Notes » Libraries » bluegl » Step 4: Call glClear()","id":"193","title":"Step 4: Call glClear()"},"194":{"body":"To update the Vulkan headers, perform the following steps. First, find the latest version of the Vulkan headers here: https://github.com/KhronosGroup/Vulkan-Headers/tags Replace v1.3.232 with the latest version of the headers in the following commands. cd libs/bluevk\ncurl -OL https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/v1.3.232.zip\nunzip v1.3.232.zip\nrsync -r Vulkan-Headers-1.3.232/include/vulkan/ include/vulkan --delete\nrsync -r Vulkan-Headers-1.3.232/include/vk_video/ include/vk_video --delete\nrm include/vulkan/*.hpp\nrm -r Vulkan-Headers-1.3.232 v1.3.232.zip","breadcrumbs":"Technical Notes » Libraries » bluevk » Updating Vulkan headers","id":"194","title":"Updating Vulkan headers"},"195":{"body":"Capabilities Setup for Desktop Setup for Android Debugger Usage Architecture Overview C++ Server JavaScript Client HTTP Requests Wish List","breadcrumbs":"Technical Notes » Libraries » fgviewer » fgviewer","id":"195","title":"fgviewer"},"196":{"body":"fgviewer is a library and web application for real-time visualization of the frame graph in Filament. It displays active passes and resource usage, providing insights into the rendering pipeline.","breadcrumbs":"Technical Notes » Libraries » fgviewer » Capabilities","id":"196","title":"Capabilities"},"197":{"body":"When using the easy build script, include the -t argument. For example: ./build.sh -ft debug gltf_viewer The t enables a CMake option called FILAMENT_ENABLE_FGVIEWER and the f ensures that CMake gets re-run so that the option is honored. Next, set an environment variable as follows. In Windows, use set instead of export. export FILAMENT_FGVIEWER_PORT=8050 Next, launch any app that links against a debug build of a Filament and point your web browser to http://localhost:8050. Skip ahead to Debugger Usage .","breadcrumbs":"Technical Notes » Libraries » fgviewer » Setup for Desktop","id":"197","title":"Setup for Desktop"},"198":{"body":"Rebuild Filament for Android after enabling a CMake option called FILAMENT_ENABLE_FGVIEWER. Note that CMake is invoked from several places for Android (both gradle and our easy build script), so one pragmatic and reliable way of doing this is to simply hack CMakeLists.txt and filament-android/CMakeLists.txt by unconditionally setting FILAMENT_ENABLE_FGVIEWER to ON. After rebuilding Filament with the option enabled, ensure that internet permissions are enabled in your app by adding the following into your manifest as a child of the element. Now launch your app as usual. The Filament Engine sets up a server that is hardcoded to listen to port 8085. Next, you will need to forward your device's TCP port 8085 to your host port of choice. For example, to forward the fgviewer server on your device to port 8085 on your host machine, do the following: adb forward tcp:8085 tcp:8085 This lets you go to http://localhost:8085 in Chrome on your host machine.","breadcrumbs":"Technical Notes » Libraries » fgviewer » Setup for Android","id":"198","title":"Setup for Android"},"199":{"body":"After opening the fgviewer page in your browser, you can see the active views are on the left panel. Then you can select any of them to see the active passes and resources for that view.","breadcrumbs":"Technical Notes » Libraries » fgviewer » Debugger Usage","id":"199","title":"Debugger Usage"},"2":{"body":"Android projects can simply declare Filament libraries as Maven dependencies: repositories { // ... mavenCentral()\n} dependencies { implementation 'com.google.android.filament:filament-android:1.67.1'\n} Here are all the libraries available in the group com.google.android.filament: Artifact Description filament-android The Filament rendering engine itself. filament-android-debug Debug version of filament-android. gltfio-android A glTF 2.0 loader for Filament, depends on filament-android. filament-utils-android KTX loading, Kotlin math, and camera utilities, depends on gltfio-android. filamat-android A runtime material builder/compiler. This library is large but contains a full shader compiler/validator/optimizer and supports both OpenGL and Vulkan. filamat-android-lite A much smaller alternative to filamat-android that can only generate OpenGL shaders. It does not provide validation or optimizations.","breadcrumbs":"Introduction » Android","id":"2","title":"Android"},"20":{"body":"This is not an officially supported Google product.","breadcrumbs":"Introduction » Disclaimer","id":"20","title":"Disclaimer"},"200":{"body":"The fgviewer library has two parts: a C++ server and a JavaScript client. The C++ server is responsible for instancing a civetweb context that handles HTTP requests. The JavaScript client is a small web app that contains a view into an in-browser database of framegraphs. When a new connection is established, the client asks the server for a list of framegraphs in order to populate its in-browser database. If the connection is lost (e.g. if the app crashes), then the database stays intact and the web app is still functional.","breadcrumbs":"Technical Notes » Libraries » fgviewer » Architecture Overview","id":"200","title":"Architecture Overview"},"201":{"body":"The civetweb server is wrapped by our DebugServer class, which provides a public interface consisting of a few methods invoked by the Filament engine. Since each view corresponds to a frame graph, the engine should notify DebugServer of any changes to the views on the engine side. createView Notifies the debugger that a new view has been created. updateView Notifies the debugger of updates to an existing view. destroyView Notifies the debugger that a view is being removed.","breadcrumbs":"Technical Notes » Libraries » fgviewer » C++ Server","id":"201","title":"C++ Server"},"202":{"body":"The web app is built using LitElement, a lightweight library for creating Web Components. Our goal is to keep the code simple and modern, avoiding frameworks like React or Angular. The app presents a view over a pseudo-database, which is essentially a global variable holding a dictionary that maps frame graph ids to objects following the JSON structure described below.","breadcrumbs":"Technical Notes » Libraries » fgviewer » JavaScript Client","id":"202","title":"JavaScript Client"},"203":{"body":"The server responds to the following GET requests by returning a JSON blob. The {id} in these requests is a concept specific to fgviewer (not Filament) which is an 8-digit hex string for identifying frame graphs. /api/framegraphs Returns an array containing all framegraphs in an app. Example: [{ \"fgid\": \"00000000\", \"viewName\": \"Main View\", \"passes\": [{ \"name\": \"shadow pass\", \"reads\": [], \"writes\": [\"0\"] }], \"resources\": [{ \"id\": \"0\", \"name\": \"shadowmap\", \"properties\": [{\"resolution\": \"256x256\"}, {\"is_subresource\": \"false\"}] }]\n},\n{ \"fgid\": \"00000001\", \"viewName\": \"UI view\", ...\n}] /api/framegraph?fg={id} Returns a specific framegraph info. Example: { \"fgid\": \"00000000\", \"viewName\": \"Main View\", \"passes\": [{ \"name\": \"shadow pass\", \"reads\": [], \"writes\": [\"0\"] }], \"resources\": [{ \"id\": \"0\", \"name\": \"shadowmap\", \"properties\": [{\"resolution\": \"256x256\"}, {\"is_subresource\": \"false\"}] }]\n} /api/status Returns one of the below: 0: first time connected 1: no-op {fgid}: the corresponding frame graph has an update Then the web view can request for the actual info using the previous api If the request gets timeout, the web page show disconnected to the user.","breadcrumbs":"Technical Notes » Libraries » fgviewer » HTTP requests","id":"203","title":"HTTP requests"},"204":{"body":"Display the texture contents on the webview","breadcrumbs":"Technical Notes » Libraries » fgviewer » Wish List","id":"204","title":"Wish List"},"205":{"body":"Filamat allows for generating materials programatically on the device as opposed to with the matc tool on the host machine. The cost is a binary size increase of your app due to the relatively larger size of the filamat library. For a smaller-sized library, see filamat_lite . It has no dependencies on glslang, but can only compile materials for OpenGL and does no shader code optimization. The filamat package is included in the releases available on GitHub .","breadcrumbs":"Technical Notes » Libraries » filamat » Filamat","id":"205","title":"Filamat"},"206":{"body":"Filamat is distributed as a set of static libraries you must link against: filamat, Filamat main library filabridge, Support library for Filament / Filamat shaders, Shader text for material generation utils, Support library for Filament / Filamat smol-v, SPIR-V compression library To use Filamat from Java you must use the following two libraries instead: filamat-java.jar, Contains Filamat's Java classes filamat-jni, Filamat's JNI bindings","breadcrumbs":"Technical Notes » Libraries » filamat » Libraries","id":"206","title":"Libraries"},"207":{"body":"This walkthrough will get you successfully compiling and linking native code against Filamat with minimum dependencies. To start, download Filament's latest binary release and extract into a directory of your choosing. Binary releases are suffixed with the platform name, for example, filament-20181009-linux.tgz. Create a file, main.cpp, in the same directory with the following contents: #include #include using namespace filamat; int main(int argc, char** argv)\n{ // Must be called before any materials can be built. MaterialBuilder::init(); MaterialBuilder builder; builder .name(\"My material\") .material(\"void material (inout MaterialInputs material) {\" \" prepareMaterial(material);\" \" material.baseColor.rgb = float3(1.0, 0.0, 0.0);\" \"}\") .shading(MaterialBuilder::Shading::LIT) .targetApi(MaterialBuilder::TargetApi::ALL) .platform(MaterialBuilder::Platform::ALL); Package package = builder.build(); if (package.isValid()) { std::cout << \"Success!\" << std::endl; } // Call when finished building all materials to release internal MaterialBuilder resources. MaterialBuilder::shutdown(); return 0;\n} The directory should look like: |-- README.md\n|-- bin\n|-- docs\n|-- include\n|-- lib\n|-- main.cpp We'll use a platform-specific Makefile to compile and link main.cpp with Filamat's libraries. Copy your platform's Makefile below into a Makefile inside the same directory.","breadcrumbs":"Technical Notes » Libraries » filamat » Linking against Filamat","id":"207","title":"Linking against Filamat"},"208":{"body":"FILAMENT_LIBS=-lfilamat -lfilabridge -lshaders -lutils -lsmol-v\nCC=clang++ main: main.o $(CC) -Llib/x86_64/ -stdlib=libc++ main.o $(FILAMENT_LIBS) -lpthread -ldl -o main main.o: main.cpp $(CC) -Iinclude/ -std=c++20 -stdlib=libc++ -pthread -c main.cpp clean: rm -f main main.o .PHONY: clean","breadcrumbs":"Technical Notes » Libraries » filamat » Linux","id":"208","title":"Linux"},"209":{"body":"FILAMENT_LIBS=-lfilamat -lfilabridge -lshaders -lutils -lsmol-v\nCC=clang++ main: main.o $(CC) -Llib/x86_64/ main.o $(FILAMENT_LIBS) -o main main.o: main.cpp $(CC) -Iinclude/ -std=c++20 -c main.cpp clean: rm -f main main.o .PHONY: clean","breadcrumbs":"Technical Notes » Libraries » filamat » macOS","id":"209","title":"macOS"},"21":{"body":"","breadcrumbs":"Introduction » Build » Building Filament","id":"21","title":"Building Filament"},"210":{"body":"Note that the static libraries distributed for Windows include several variants: mt, md, mtd, mdd. These correspond to the run-time library flags /MT, /MD, /MTd, and /MDd, respectively. Here we use the mt variant. When building Filamat from source, the USE_STATIC_CRT CMake option can be used to change the run-time library version. FILAMENT_LIBS=lib/x86_64/mt/filamat.lib lib/x86_64/mt/filabridge.lib lib/x86_64/mt/shaders.lib \\ lib/x86_64/mt/utils.lib lib/x86_64/mt/smol-v.lib\nCC=clang-cl.exe main.exe: main.obj $(CC) main.obj $(FILAMENT_LIBS) gdi32.lib user32.lib opengl32.lib main.obj: main.cpp $(CC) /MT /Iinclude/ /std:c++20 /c main.cpp clean: del main.exe main.obj .PHONY: clean","breadcrumbs":"Technical Notes » Libraries » filamat » Windows","id":"210","title":"Windows"},"211":{"body":"You should be able to invoke make and run the executable successfully: $ make\n$ ./main\nSuccess! On Windows, you'll need to open up a Visual Studio Native Tools Command Prompt and invoke nmake instead of make.","breadcrumbs":"Technical Notes » Libraries » filamat » Compiling","id":"211","title":"Compiling"},"212":{"body":"For simplicity, this demo doesn't do anything useful with the built material package. To use the material with Filament, pass the material package's data into a Filament Material builder: Package package = builder.build(); filament::Material* myMaterial = Material::Builder() .package(package.getData(), package.getSize()) .build(*engine); Note that this will require linking against Filament's libraries in addition to Filamat's.","breadcrumbs":"Technical Notes » Libraries » filamat » Using the Material with Filament","id":"212","title":"Using the Material with Filament"},"213":{"body":"The filamat_lite library is interchangeable with filamat, with a few caveats: Material compilation is only supported for the OpenGL backend. No shader-level optimization is performed. GLSL correctness is not checked. In addition, filamat_lite only performs a simple text match to determine which properties on the MaterialInputs structure are set. The material input variable must also always be refered to by the name material. void anotherFunction(inout MaterialInputs m) { // Incorrect! The MaterialInputs is being referred to by the name \"m\". m.metallic = 0.0;\n} void aFunction(inout MaterialInputs material) { // Works, but only because the variable name \"material\" is used. material.reflectance = 0.5;\n} // The MaterialInputs variable must be named material.\nvoid material(inout MaterialInputs material) { prepareMaterial(material); // Good. material.roughness = materialParams.roughness; material.baseColor.rgb = vec3(1.0, 0.0, 1.0); aFunction(material); anotherFunction(material);\n}","breadcrumbs":"Technical Notes » Libraries » filamat » Filamat Lite","id":"213","title":"Filamat Lite"},"214":{"body":"gltfio is a loader library that consumes gltf or glb content and produces Filament objects. For usage details, see the docstring for AssetLoader. gltfio has two plug-in interfaces, TextureProvider and MaterialProvider. Filament ships with several ready-to-go implementations described below. MaterialProvider creates Filament materials in response to certain glTF requirements. UbershaderProvider loads pre-built materials. JitShaderProvider builds materials at run time using the filamat library. TextureProvider creates and populates Filament Texture objects. StbProvider uses the STB library to read PNG and JPEG files. Ktx2Provider uses the BasisU library to read KTX2 files.","breadcrumbs":"Technical Notes » Libraries » gltfio » Description","id":"214","title":"Description"},"215":{"body":"UbershaderProvider is a ready-to-go implementation of the MaterialProvider interface that should be used in applications that need fast startup times. There is no material compilation that occurs at run time, but the shaders might be relatively large and complex. At load time, the ubershader loader consumes an ubershader archive which is a precompiled set of materials bundled with formal descriptions of the glTF features that they support. The uberz command line tool consumes a list of .spec and .filamat files and produces a single .uberz file. For details on these two file formats, see the README in libs/uberz.","breadcrumbs":"Technical Notes » Libraries » gltfio » UbershaderProvider","id":"215","title":"UbershaderProvider"},"216":{"body":"This library can be used to generate the reflections texture used by filament's IndirectLight class. It is similar to the cmgen tool except that all computations are performed on the GPU and are therefore significantly faster. cmgen however offers more functionalities. IBL Prefilter is designed entirely as a client of filament, that is, it only uses filament public APIs.","breadcrumbs":"Technical Notes » Libraries » iblprefilter » IBL Prefilter","id":"216","title":"IBL Prefilter"},"217":{"body":"The library is called libfilament-iblprefilter.a and its public headers can be found in .","breadcrumbs":"Technical Notes » Libraries » iblprefilter » Library and headers","id":"217","title":"Library and headers"},"218":{"body":"Expect a total processing time of about 100ms to 300ms for a 5-levels 256 x 256 cubemap with 1024 samples.","breadcrumbs":"Technical Notes » Libraries » iblprefilter » Performance","id":"218","title":"Performance"},"219":{"body":"#include \n#include using namespace filament; Engine* engine = Engine::create(); // create an IBLPrefilterContext, keep it around if several cubemap will be processed.\nIBLPrefilterContext context(engine); // create the specular (reflections) filter. This operation generates the kernel, so it's important\n// to keep it around if it will be reused for several cubemaps.\nIBLPrefilterContext::SpecularFilter filter(context); // launch the heaver computation. Expect 100-100ms on the GPU.\nTexture* texture = filter(environment_cubemap); IndirectLight* indirectLight = IndirectLight::Builder() .reflections(texture) .build(engine);","breadcrumbs":"Technical Notes » Libraries » iblprefilter » Example","id":"219","title":"Example"},"22":{"body":"To build Filament, you must first install the following tools: CMake 3.22.1 (or more recent) clang 16.0 (or more recent) ninja 1.10 (or more recent) Additional dependencies may be required for your operating system. Please refer to the appropriate section below. To build Filament for Android you must also install the following: Android Studio Flamingo or more recent Android SDK Android NDK 25.1 or higher Java 17","breadcrumbs":"Introduction » Build » Prerequisites","id":"22","title":"Prerequisites"},"220":{"body":"Capabilities Setup for Desktop Setup for Android Debugger Usage Architecture Overview C++ Server JavaScript Client HTTP Requests WebSocket Messages Wish List Screenshot Material Chunks","breadcrumbs":"Technical Notes » Libraries » matdbg » matdbg","id":"220","title":"matdbg"},"221":{"body":"matdbg is a library and web application that enables debugging and live-editing of Filament shaders. At the time of this writing, the following capabilities are supported. OpenGL: Editing GLSL Metal: Editing MSL Vulkan: Editing transpiled GLSL, displaying disassembled SPIR-V WebGPU: Editing WGSL Note that a given material can be built with multiple backends, even though only one backend is active in a particular session. For example, if the current app is using Vulkan, it is still possible to inspect the Metal shaders, as long as the material has been built with Metal support included.","breadcrumbs":"Technical Notes » Libraries » matdbg » Capabilities","id":"221","title":"Capabilities"},"222":{"body":"When using the easy build script, include the -d argument. For example: ./build.sh -fd debug gltf_viewer The d enables a CMake option called FILAMENT_ENABLE_MATDBG and the f ensures that CMake gets re-run so that the option is honored. Next, set an environment variable as follows. In Windows, use set instead of export. export FILAMENT_MATDBG_PORT=8080 Next, launch any app that links against a debug build of a Filament and point your web browser to http://localhost:8080. Skip ahead to Debugger Usage .","breadcrumbs":"Technical Notes » Libraries » matdbg » Setup for Desktop","id":"222","title":"Setup for Desktop"},"223":{"body":"Rebuild Filament for Android after enabling a CMake option called FILAMENT_ENABLE_MATDBG. Note that CMake is invoked from several places for Android (both gradle and our easy build script), so one pragmatic and reliable way of doing this is to simply hack CMakeLists.txt and filament-android/CMakeLists.txt by unconditionally setting FILAMENT_ENABLE_MATDBG to ON. After rebuilding Filament with the option enabled, ensure that internet permissions are enabled in your app by adding the following into your manifest as a child of the element. Now launch your app as usual. The Filament Engine sets up a server that is hardcoded to listen to port 8081. Next, you will need to forward your device's TCP port 8081 to your host port of choice. For example, to forward the matdbg server on your device to port 8081 on your host machine, do the following: adb forward tcp:8081 tcp:8081 This lets you go to http://localhost:8081 in Chrome on your host machine. Note that we generally use a release build of Filament when running on Android, so the shaders are optimized and very unreadable. This can be avoided by modifying the build such that -g is passed to matc even in release builds.","breadcrumbs":"Technical Notes » Libraries » matdbg » Setup for Android","id":"223","title":"Setup for Android"},"224":{"body":"After opening the matdbg page in your browser, the usual first step is to select a material in the upper-left pane. Sometimes you might need force your app to redraw (e.g. by resizing the window) in order make the materials selectable. The next step is to select an active (boldface) shader variant in the lower-left pane. This allows you to view the GLSL, MSL, and SPIR-V code that was generated by matc or filamat. In the sidebar, inactive shader variants have a disabled appearance, but they can still be examined in the shader editor. The active status of each shader program is refreshed every second. You can also make modifications to GLSL or MSL, so long as the shader inputs and uniforms remain intact. After making an edit, click the [rebuild] button in the header. Note that your edits will be lost after closing the web page.","breadcrumbs":"Technical Notes » Libraries » matdbg » Debugger Usage","id":"224","title":"Debugger Usage"},"225":{"body":"To save an edit, press Cmd+S ( Ctrl+S on Linux/Windows) as an alternative to clicking [rebuild]. If the editor has focus, you can navigate between materials by holding Shift+Ctrl while pressing the up or down arrow. Navigation between variants is similar, just use left / right instead of up / down.","breadcrumbs":"Technical Notes » Libraries » matdbg » Keyboard Shortcuts","id":"225","title":"Keyboard Shortcuts"},"226":{"body":"The matdbg library has two parts: a C++ server and a JavaScript client. The C++ server is responsible for instancing a civetweb context that handles HTTP and WebSocket requests. The JavaScript client is a small web app that contains a view into an in-browser database of materials. The WebSocket server receives push-style notifications from the client (such as edits) while the HTTP server responds to material queries using simple JSON messages. When a new WebSocket connection is established, the client asks the server for a list of materials in order to populate its in-browser database. If the connection is lost (e.g. if the app crashes), then the database stays intact and the web app is still functional. If a new Filament app is launched, the client inserts entries into its database rather than replacing the existing set. The material database is cleared only when the web page is manually refreshed by the user.","breadcrumbs":"Technical Notes » Libraries » matdbg » Architecture Overview","id":"226","title":"Architecture Overview"},"227":{"body":"The civetweb server is wrapped by our DebugServer class, whose public interface is comprised of a couple methods that are called from the Filament engine: addMaterial Notifies the debugger that the given material package is being loaded into the engine. setEditCallback Sets up a callback that allows the Filament engine to listen for shader edits. setQueryCallback Sets up a callback that allows the debugger to ask for current information.","breadcrumbs":"Technical Notes » Libraries » matdbg » C++ Server","id":"227","title":"C++ Server"},"228":{"body":"The web app is written in simple, modern JavaScript. It uses third-party libraries which are fetched from a CDN using