Compare commits

...
Author SHA1 Message Date
Powei Feng c5462621eb vk: adding logs just for debugging [DO NOT COMMIT] 2026-03-18 10:15:56 -07:00
Mathias Agopian e2b195706a fix overdraw visualization in gltf_viewer (#9805) 2026-03-18 09:01:18 -07:00
Powei Feng 3ebb2086ed github: use arm linux instead of x86 whenever possible (#9794)
- Simplify getting cmake, ninja for linux
 - Move linux, web, webgpu builds to use arm (more cores for less)
 - Android cannot be moved due to Android SDK not available on
   arm linux yet.
 - Add Arm Linux release artifacts

Fixes #8674
2026-03-18 07:19:38 +00:00
Mathias Agopian 052092f553 remove the remaining instances of std::string (#9802)
libfilament (including libutils and libmath) are 100% std::string
free.

std::string is pulled in the .so (on android) through libc++ for 
exception handling, even if we're not using them. There is not much
we can do here, but at least, it's not because of us!

utils::ostream still references it but only as an inline function,
so if the inline is not called, std::string won't be pulled in.

It's also referenced from Path.cpp, but that's not included in
libfilament.
2026-03-17 15:27:12 -07:00
Mathias Agopian 7163aaa627 don't output the full shader when matc fails (#9803)
This made it nearly impossible to find the actual error. Now, we
output only the error from the compiler + the material name, variant
and shader stage all in one line.
2026-03-17 13:37:14 -07:00
Mathias Agopian 0c7ff3fcf4 store shadow atlas resolution in frameUniforms (#9804) 2026-03-17 13:36:58 -07:00
Powei Feng 962756e283 gl: add getter for GL_VERSION (#9798)
On Android, GL_VERSION contains information about the driver
version number.  This can be useful when debugging or running
tests.
2026-03-17 17:56:51 +00:00
Sungun Park 48ee727c8d fix: Resolve a TSan warning for OpenGLTimerQuery (#9790)
The main thread invokes `getTimerQueryValue` synchronously, reading
`tq->state`. Meanwhile, the driver thread handles `createTimerQuery`
asynchronously and initializes `tq->state = std::make_shared<State>()`.

Eliminate this race by initializing the state in createTimerQueryS.

BUGS=[491522442]
2026-03-16 20:48:31 +00:00
Powei Feng 2d1e4b8ce2 github: fix broken header check (#9800)
- Move header check from postsubmit to presubmit
 - Install third_party/getop if needed
 - Modify check-headers test to use system getopt when it's available.
2026-03-16 10:26:59 -07:00
Powei Feng 749b03ed2a utils: refactor getopt into utils namespace (#9796)
On certain linux, macOS environment, there is already a system
getopt. This often creates conflict when compiling filament.
Here we alias utils::getopt to either the system getopt (if
present) or third_party/getopt.

Fixes #7551
2026-03-13 17:22:44 -07:00
Mathias Agopian 497a1cc42d fix android CMake so LTO can be turned on (#9797)
our custom build system didn't set CMAKE_ANDROID_NDK_VERSION which
is needed for CMake's check_ipo_supported.
2026-03-13 16:32:59 -07:00
Run Yu 256a494cd0 webgpu: implement the scissor backend function (#9783)
also enable ScissorViewportRegion backend test.
It was previously skipped, now it is passing.

BUGS=474393992
2026-03-13 21:37:54 +00:00
Powei Feng b2531fff15 android: [sample-render-val] add difference/output viewer (#9781)
- Add viewer for closer examination
 - Add slider to enhance difference
 - Fixed ImageDiff jni bug to account for stride and
   premultiplication by alpha
2026-03-13 18:39:22 +00:00
Powei Feng f18afe1d3e Try to fix verify-notes breakage (#9795)
- Update python3 version to 3.12.13
 - Use action/checkout instead of Bhacaz/checkout-files because action/checkout can
   use the action/files of the current PR, where as checkout-files is checking out
   a file on the main branch
 - action/checkout seems to run in less than a minute, so acceptable performance
   difference.

--------------------------------------------------------------------

Breakage is:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/jwt/algorithms.py", line 36, in <module>
    from cryptography.exceptions import InvalidSignature, UnsupportedAlgorithm
ModuleNotFoundError: No module named 'cryptography'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/verify_release_notes.py", line 17, in <module>
    from github import Github
  File "/usr/local/lib/python3.10/site-packages/github/__init__.py", line 56, in <module>
    from github.MainClass import Github, GithubIntegration
  File "/usr/local/lib/python3.10/site-packages/github/MainClass.py", line 54, in <module>
    import jwt
  File "/usr/local/lib/python3.10/site-packages/jwt/__init__.py", line 1, in <module>
    from .api_jwk import PyJWK, PyJWKSet
  File "/usr/local/lib/python3.10/site-packages/jwt/api_jwk.py", line 8, in <module>
    from .algorithms import get_default_algorithms, has_crypto, requires_cryptography
  File "/usr/local/lib/python3.10/site-packages/jwt/algorithms.py", line 113, in <module>
    from typing_extensions import Never
ModuleNotFoundError: No module named 'typing_extensions'
2026-03-13 11:06:55 -07:00
Sungun Park 771eb4c1a4 fix: Resolve a TSan warning for ShaderCompilerService (#9792)
When the backend thread checks the availability of the token, it
directly accesses `gl.program`, which caused a TSan warning.

BUGS=[491819760]
2026-03-12 17:19:11 +00:00
Powei Feng 70e7cb2a27 github: fix bad conditional in presubmit (#9793)
The previous conditional used
github.event.head_commit.verification.verified, which is not a
real field. Hence, the attempt to reduce presubmit runs did not
actually succeed.  Here we replace it with a more correct
verification step.
2026-03-11 16:09:29 -07:00
Powei Feng f95f127495 github: reduce presubmit runs (#9791)
We make two adjustments to make the presubmit workflows run less.
 - Only run on commit merge when the commit is not "verified".
   While not a 1-1 definition, "verified" commit typically implies
   that the commit came from a PR merge (which requires that
   presubmit passes). A commit could also be made by owners on
   main directly, in which case, the commit would not be verified.
 - Cancel any in progress presubmit runs are "overwritten" by an
   update to the PR.
2026-03-11 18:43:39 +00:00
Evan Mezeske c0d63e826d Metal: fix crash from exceeding max texture dimensions for Bloom buffer (#9784)
I recently added a new fuzz test for my Filament-based app, which creates a window and then rapidly issues changes such as toggling View features, changing the window size, and other operations that the users of my app can do.

It quickly found a crash when Bloom is enabled and the window dimensions get resized to weird aspect ratios on a large monitor. Eventually I narrowed it down to the Bloom buffer's width exceeding the Metal max texture dimension (on my machine, 16K). Applying this patch fixes the crash.
2026-03-11 10:39:35 -07:00
haroonq 36583618f1 Allow child classes to configure the EGLDisplay. (#9779) 2026-03-10 23:42:17 +00:00
Powei Feng 9d322e7208 github: reduce action runner costs (#9789)
This is a speculative reduction of github runner costs by using
less costly machines. The usage time will be longer, but
hopefully the total cost will still be lower.

Note we disabled most of the large runners for postsubmit builds,
since we should have caught all breakages in presubmit.
2026-03-10 21:30:47 +00:00
Filament Bot b897d22d20 [automated] Updating /docs due to commit e5fe3d4
Full commit hash is e5fe3d495e

DOCS_ALLOW_DIRECT_EDITS
2026-03-10 20:49:10 +00:00
128 changed files with 2012 additions and 1184 deletions
+1 -12
View File
@@ -11,24 +11,13 @@ runs:
echo "set man-db/auto-update false" | sudo debconf-communicate
sudo dpkg-reconfigure man-db
# Install ninja
source ./build/common/get-ninja.sh
# Install CMake
mkdir -p cmake
cd cmake
sudo wget https://github.com/Kitware/CMake/releases/download/v$GITHUB_CMAKE_VERSION/cmake-$GITHUB_CMAKE_VERSION-Linux-x86_64.sh
sudo chmod +x ./cmake-$GITHUB_CMAKE_VERSION-Linux-x86_64.sh
sudo ./cmake-$GITHUB_CMAKE_VERSION-Linux-x86_64.sh --skip-license > /dev/null
sudo update-alternatives --install /usr/bin/cmake cmake $(pwd)/bin/cmake 1000 --force
cd ..
sudo wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install clang-$GITHUB_CLANG_VERSION libc++-$GITHUB_CLANG_VERSION-dev libc++abi-$GITHUB_CLANG_VERSION-dev
sudo apt-get install mesa-common-dev libxi-dev libxxf86vm-dev
sudo apt-get install cmake ninja-build
# For dawn
sudo apt-get install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libx11-xcb-dev
@@ -1,4 +1,4 @@
FROM python:3.10.4
FROM python:3.12.13
RUN pip3 install pygithub==1.55
+1 -1
View File
@@ -8,7 +8,7 @@ runs:
uses: actions/cache@v4 # Use a specific version
with:
path: emsdk
key: ${{ runner.os }}-emsdk-${{ env.GITHUB_EMSDK_VERSION }}
key: ${{ runner.os }}-${{ runner.arch }}-emsdk-${{ env.GITHUB_EMSDK_VERSION }}
- name: Install Web Prerequisites
shell: bash
run: |
+2 -2
View File
@@ -10,7 +10,7 @@ jobs:
# a branch on filament-assets.
update-renderdiff-goldens:
name: update-renderdiff-goldens
runs-on: 'macos-14-xlarge'
runs-on: 'macos-14'
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -90,7 +90,7 @@ jobs:
# filament-assets
update-sizeguard:
name: update-sizeguard
runs-on: 'ubuntu-24.04-16core'
runs-on: 'ubuntu-24.04-4core'
steps:
- uses: actions/checkout@v4.1.6
with:
+8 -16
View File
@@ -12,8 +12,7 @@ jobs:
name: build-android
# We intentially use a larger runner here to enable larger disk space
# (standard linux runner will fail on disk space and faster build time).
runs-on: 'ubuntu-24.04-16core'
runs-on: 'ubuntu-24.04-4core'
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -26,8 +25,7 @@ jobs:
build-ios:
name: build-ios
runs-on: macos-14-xlarge
runs-on: 'macos-14'
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -46,8 +44,7 @@ jobs:
build-linux:
name: build-linux
runs-on: 'ubuntu-24.04-16core'
runs-on: 'arm-ubuntu-24.04-16core'
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -58,13 +55,12 @@ jobs:
cd build/linux && printf "y" | ./build.sh continuous
- uses: actions/upload-artifact@v4
with:
name: filament-linux
path: out/filament-release-linux.tgz
name: filament-arm-linux
path: out/filament-release-arm-linux.tgz
build-mac:
name: build-mac
runs-on: macos-14-xlarge
runs-on: 'macos-14'
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -77,14 +73,10 @@ jobs:
with:
name: filament-mac
path: out/filament-release-darwin.tgz
- name: Check public headers
run: |
test/check-headers/test.sh out/release/filament/include
build-web:
name: build-web
runs-on: 'ubuntu-24.04-16core'
runs-on: 'arm-ubuntu-24.04-16core'
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -101,7 +93,7 @@ jobs:
build-windows:
name: build-windows
runs-on: windows-2022-32core
runs-on: 'windows-2022'
steps:
- uses: actions/checkout@v4.1.6
+171 -11
View File
@@ -8,10 +8,54 @@ on:
branches:
- main
# This will cancel in-flight runs when there is an update to a PR
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# The conditional 'if' on each job is meant to skip presubmit jobs when a commit is pushed to main
# and that commit is cryptographically "verified". Typically, a verified commit (like a GitHub UI
# squash-and-merge) has already passed through presubmit during the Pull Request phase.
# The conditional explicitly checks:
# 1. always() && !cancelled(): Ensures the job runs even if 'check-verification' is skipped, but
# aborts if the workflow was manually cancelled.
# 2. github.event_name == 'pull_request': Presubmits should always run normally on PRs.
# 3. github.event_name == 'push' && ...: If it's a push to main, it only runs if the
# 'check-verification' job confirmed the commit is NOT verified.
jobs:
check-verification:
if: github.event_name == 'push'
runs-on: ubuntu-latest
outputs:
verified: ${{ steps.check.outputs.verified }}
steps:
- name: Check commit verification
id: check
uses: actions/github-script@v7
with:
script: |
const { data } = await github.rest.repos.getCommit({
owner: context.repo.owner,
repo: context.repo.repo,
ref: context.sha
});
core.setOutput('verified', data.commit.verification.verified);
build-desktop-mac:
name: build-mac
runs-on: macos-14-xlarge
runs-on: 'macos-14-xlarge'
needs: [check-verification]
if: >
always() && !cancelled() &&
(
github.event_name == 'pull_request' ||
(
github.event_name == 'push' &&
needs.check-verification.result == 'success' &&
needs.check-verification.outputs.verified == 'false'
)
)
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -20,13 +64,30 @@ jobs:
- name: Run build script
run: |
cd build/mac && printf "y" | ./build.sh presubmit-with-test
- name: Test material parser
- name: Test - material parser
run: |
out/cmake-release/filament/test/test_material_parser
- name: Test - public headers
run: |
# out/cmake-release should have the artifacts ready for installation. Here we install it
# to test the public headers
ninja -C out/cmake-release install
test/check-headers/test.sh out/release/filament/include
build-desktop-linux:
name: build-linux
runs-on: 'ubuntu-24.04-16core'
runs-on: 'arm-ubuntu-24.04-16core'
needs: [check-verification]
if: >
always() && !cancelled() &&
(
github.event_name == 'pull_request' ||
(
github.event_name == 'push' &&
needs.check-verification.result == 'success' &&
needs.check-verification.outputs.verified == 'false'
)
)
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -41,7 +102,18 @@ jobs:
build-windows:
name: build-windows
runs-on: windows-2022-32core
runs-on: 'windows-2022'
needs: [check-verification]
if: >
always() && !cancelled() &&
(
github.event_name == 'pull_request' ||
(
github.event_name == 'push' &&
needs.check-verification.result == 'success' &&
needs.check-verification.outputs.verified == 'false'
)
)
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -53,7 +125,18 @@ jobs:
build-android:
name: build-android
runs-on: 'ubuntu-24.04-16core'
runs-on: 'ubuntu-24.04-4core'
needs: [check-verification]
if: >
always() && !cancelled() &&
(
github.event_name == 'pull_request' ||
(
github.event_name == 'push' &&
needs.check-verification.result == 'success' &&
needs.check-verification.outputs.verified == 'false'
)
)
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -80,7 +163,18 @@ jobs:
build-ios:
name: build-iOS
runs-on: macos-14-xlarge
runs-on: 'macos-14-xlarge'
needs: [check-verification]
if: >
always() && !cancelled() &&
(
github.event_name == 'pull_request' ||
(
github.event_name == 'push' &&
needs.check-verification.result == 'success' &&
needs.check-verification.outputs.verified == 'false'
)
)
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -95,7 +189,18 @@ jobs:
build-web:
name: build-web
runs-on: 'ubuntu-24.04-16core'
runs-on: 'arm-ubuntu-24.04-16core'
needs: [check-verification]
if: >
always() && !cancelled() &&
(
github.event_name == 'pull_request' ||
(
github.event_name == 'push' &&
needs.check-verification.result == 'success' &&
needs.check-verification.outputs.verified == 'false'
)
)
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -108,7 +213,18 @@ jobs:
validate-docs:
name: validate-docs
runs-on: 'ubuntu-24.04-4core'
runs-on: 'ubuntu-24.04'
needs: [check-verification]
if: >
always() && !cancelled() &&
(
github.event_name == 'pull_request' ||
(
github.event_name == 'push' &&
needs.check-verification.result == 'success' &&
needs.check-verification.outputs.verified == 'false'
)
)
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -121,7 +237,18 @@ jobs:
test-renderdiff:
name: test-renderdiff
runs-on: macos-14-xlarge
runs-on: 'macos-14-xlarge'
needs: [check-verification]
if: >
always() && !cancelled() &&
(
github.event_name == 'pull_request' ||
(
github.event_name == 'push' &&
needs.check-verification.result == 'success' &&
needs.check-verification.outputs.verified == 'false'
)
)
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -190,7 +317,18 @@ jobs:
validate-wgsl-webgpu:
name: validate-wgsl-webgpu
runs-on: 'ubuntu-24.04-16core'
runs-on: 'arm-ubuntu-24.04-16core'
needs: [check-verification]
if: >
always() && !cancelled() &&
(
github.event_name == 'pull_request' ||
(
github.event_name == 'push' &&
needs.check-verification.result == 'success' &&
needs.check-verification.outputs.verified == 'false'
)
)
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -204,6 +342,17 @@ jobs:
test-code-correctness:
name: test-code-correctness
runs-on: 'macos-14-xlarge'
needs: [check-verification]
if: >
always() && !cancelled() &&
(
github.event_name == 'pull_request' ||
(
github.event_name == 'push' &&
needs.check-verification.result == 'success' &&
needs.check-verification.outputs.verified == 'false'
)
)
steps:
- uses: actions/checkout@v4.1.6
with:
@@ -224,7 +373,18 @@ jobs:
test-backend:
name: test-backend
runs-on: macos-14-xlarge
runs-on: 'macos-14-xlarge'
needs: [check-verification]
if: >
always() && !cancelled() &&
(
github.event_name == 'pull_request' ||
(
github.event_name == 'push' &&
needs.check-verification.result == 'success' &&
needs.check-verification.outputs.verified == 'false'
)
)
steps:
- uses: actions/checkout@v4.1.6
with:
+34 -1
View File
@@ -63,6 +63,39 @@ jobs:
const globber = await glob.create('out/*.tgz');
await upload({ github, context }, await globber.glob(), TAG);
build-arm-linux:
name: build-arm-linux
runs-on: 'arm-ubuntu-24.04-16core'
if: github.event_name == 'release' || github.event.inputs.platform == 'desktop'
steps:
- name: Decide Git ref
id: git_ref
run: |
REF=${RELEASE_TAG:-${GITHUB_REF}}
TAG=${REF##*/}
echo "ref=${REF}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- uses: actions/checkout@v4.1.6
with:
ref: ${{ steps.git_ref.outputs.ref }}
- uses: ./.github/actions/linux-prereq
- name: Run build script
env:
TAG: ${{ steps.git_ref.outputs.tag }}
run: |
cd build/linux && printf "y" | ./build.sh release
cd ../..
mv out/filament-release-linux.tgz out/filament-${TAG}-arm-linux.tgz
- uses: actions/github-script@v6
env:
TAG: ${{ steps.git_ref.outputs.tag }}
with:
script: |
const upload = require('./build/common/upload-release-assets');
const { TAG } = process.env;
const globber = await glob.create('out/*.tgz');
await upload({ github, context }, await globber.glob(), TAG);
build-mac:
name: build-mac
runs-on: macos-14-xlarge
@@ -99,7 +132,7 @@ jobs:
build-web:
name: build-web
runs-on: 'ubuntu-24.04-16core'
runs-on: 'arm-ubuntu-24.04-16core'
if: github.event_name == 'release' || github.event.inputs.platform == 'web'
steps:
+4 -7
View File
@@ -11,14 +11,11 @@ jobs:
name: Verify Release Notes
runs-on: ubuntu-latest
steps:
# We *only* need to check out the .github/ directory.
# The verify RELEASE_NOTES script uses the GitHub API to verify that RELEASE_NOTES was
# modified.
- name: Check out action
uses: Bhacaz/checkout-files@73e17cfbe8d7e0c6b2672b20cb05a718e20d18d4
- uses: actions/checkout@v6
with:
files: .github
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
sparse-checkout: |
.github
- name: Verify release notes
uses: ./.github/actions/verify-release-notes
with:
+10 -3
View File
@@ -326,11 +326,13 @@ endif()
if (FILAMENT_ENABLE_LTO)
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORT)
check_ipo_supported(RESULT IPO_SUPPORT OUTPUT IPO_ERROR)
if (IPO_SUPPORT)
message(STATUS "LTO support is enabled")
message(STATUS "IPO / LTO is enabled")
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
else()
message(WARNING "IPO / LTO is not supported by this architecture: ${IPO_ERROR}")
endif()
endif()
@@ -867,6 +869,12 @@ endfunction()
# Sub-projects
# ==================================================================================================
include(CheckSymbolExists)
check_symbol_exists(getopt_long "getopt.h" HAS_SYSTEM_GETOPT)
if (NOT HAS_SYSTEM_GETOPT)
add_subdirectory(${EXTERNAL}/getopt)
endif()
# Common to all platforms
add_subdirectory(${EXTERNAL}/libgtest/tnt)
add_subdirectory(${LIBRARIES}/camutils)
@@ -902,7 +910,6 @@ add_subdirectory(${EXTERNAL}/cgltf/tnt)
add_subdirectory(${EXTERNAL}/draco/tnt)
add_subdirectory(${EXTERNAL}/jsmn/tnt)
add_subdirectory(${EXTERNAL}/stb/tnt)
add_subdirectory(${EXTERNAL}/getopt)
add_subdirectory(${EXTERNAL}/perfetto/tnt)
add_subdirectory(${EXTERNAL}/basisu/tnt)
@@ -20,8 +20,6 @@
#include <imagediff/ImageDiff.h>
#include <utils/Log.h>
#include <vector>
using namespace imagediff;
using namespace utils;
@@ -102,30 +100,48 @@ jobject createResult(JNIEnv* env, ImageDiffResult const& result, bool generateDi
if (generateDiff && result.diffImage.getWidth() > 0) {
jclass bitmapClass = env->FindClass("android/graphics/Bitmap");
jmethodID createBitmap = env->GetStaticMethodID(bitmapClass, "createBitmap",
jmethodID createBitmap = env->GetStaticMethodID(bitmapClass, "createBitmap",
"(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
jclass configClass = env->FindClass("android/graphics/Bitmap$Config");
jfieldID argb8888 = env->GetStaticFieldID(configClass, "ARGB_8888", "Landroid/graphics/Bitmap$Config;");
jobject configObj = env->GetStaticObjectField(configClass, argb8888);
uint32_t width = result.diffImage.getWidth();
uint32_t height = result.diffImage.getHeight();
jobject diffBitmap = env->CallStaticObjectMethod(bitmapClass, createBitmap, (jint)width, (jint)height, configObj);
jobject diffBitmap = env->CallStaticObjectMethod(bitmapClass, createBitmap, (jint) width,
(jint) height, configObj);
if (diffBitmap) {
// We need to transport the bit differences accurately to the java side, so set
// premultiplied to false. From the java-side, if the bitmap is used to draw to a
// canvas, then client needs to set premultiplied to true again.
jmethodID setPremultiplied = env->GetMethodID(bitmapClass, "setPremultiplied", "(Z)V");
if (setPremultiplied) {
env->CallVoidMethod(diffBitmap, setPremultiplied, JNI_FALSE);
}
void* diffPixels;
if (AndroidBitmap_lockPixels(env, diffBitmap, &diffPixels) == 0) {
AndroidBitmapInfo info;
AndroidBitmap_getInfo(env, diffBitmap, &info);
float const* src = result.diffImage.getPixelRef();
uint8_t* dst = (uint8_t*) diffPixels;
uint32_t channels = result.diffImage.getChannels(); // usually 4
for (size_t i = 0; i < width * height; ++i) {
for (int c = 0; c < 4; ++c) {
float v = 0.0f;
if (c < channels) v = src[i * channels + c];
if (c == 3 && channels < 4) v = 1.0f; // Alpha 1.0 if missing
dst[i * 4 + c] = (uint8_t) std::min(255.0f, std::max(0.0f, v * 255.0f));
uint32_t const channels = result.diffImage.getChannels(); // usually 4
for (size_t y = 0; y < height; ++y) {
uint8_t* row = dst + y * info.stride;
for (size_t x = 0; x < width; ++x) {
size_t srcIdx = (y * width + x) * channels;
for (int c = 0; c < 4; ++c) {
float v = 0.0f;
if (c < channels) v = src[srcIdx + c];
if (c == 3 && channels < 4) v = 1.0f; // Alpha 1.0 if missing
row[x * 4 + c] = uint8_t(
std::min(255.0f, std::max(0.0f, std::round(v * 255.0f))));
}
}
}
AndroidBitmap_unlockPixels(env, diffBitmap);
@@ -133,7 +149,7 @@ jobject createResult(JNIEnv* env, ImageDiffResult const& result, bool generateDi
}
}
}
return resultObj;
}
@@ -147,7 +163,7 @@ Java_com_google_android_filament_utils_ImageDiff_nCompareBasic(JNIEnv* env, jcla
BitmapLock maskArg(env, maskBitmap);
if (!refArg.isValid() || !candArg.isValid()) {
ImageDiffResult emptyResult;
ImageDiffResult emptyResult;
emptyResult.status = ImageDiffResult::Status::SIZE_MISMATCH; // or ERROR
return createResult(env, emptyResult, false);
}
@@ -175,13 +191,13 @@ Java_com_google_android_filament_utils_ImageDiff_nCompareBasic(JNIEnv* env, jcla
extern "C" JNIEXPORT jobject JNICALL
Java_com_google_android_filament_utils_ImageDiff_nCompareJson(JNIEnv* env, jclass,
jobject refBitmap, jobject candBitmap, jstring jsonConfig, jobject maskBitmap) {
BitmapLock refArg(env, refBitmap);
BitmapLock candArg(env, candBitmap);
BitmapLock maskArg(env, maskBitmap);
if (!refArg.isValid() || !candArg.isValid()) {
ImageDiffResult emptyResult;
ImageDiffResult emptyResult;
emptyResult.status = ImageDiffResult::Status::SIZE_MISMATCH; // or ERROR
return createResult(env, emptyResult, false);
}
@@ -189,7 +205,7 @@ Java_com_google_android_filament_utils_ImageDiff_nCompareJson(JNIEnv* env, jclas
ImageDiffConfig config;
const char* nativeJson = env->GetStringUTFChars(jsonConfig, 0);
size_t length = env->GetStringUTFLength(jsonConfig);
bool parsed = parseConfig(nativeJson, length, &config);
env->ReleaseStringUTFChars(jsonConfig, nativeJson);
@@ -214,4 +230,3 @@ Java_com_google_android_filament_utils_ImageDiff_nCompareJson(JNIEnv* env, jclas
return createResult(env, result, generateDiff);
}
@@ -66,10 +66,26 @@ class MainActivity : Activity(), ValidationRunner.Callback {
private lateinit var inputManager: ValidationInputManager
private var currentInput: ValidationInputManager.ValidationInput? = null
private var currentAlphaDiffBitmap: Bitmap? = null
private var globalEnhancementFactor: Float = 1.0f
private data class TestImages(
val testName: String,
val golden: Bitmap?,
val rendered: Bitmap?,
val diff: Bitmap?,
val alphaDiff: Bitmap?
)
private val diffImageViews = mutableListOf<ImageView>()
// UI Elements
private lateinit var runButton: Button
private lateinit var loadButton: Button
private lateinit var optionsButton: Button
private lateinit var enhancementContainer: LinearLayout
private lateinit var enhancementLabel: TextView
private lateinit var enhancementSlider: android.widget.SeekBar
private var resultManager: ValidationResultManager? = null
private var validationRunner: ValidationRunner? = null
@@ -98,6 +114,19 @@ class MainActivity : Activity(), ValidationRunner.Callback {
runButton = findViewById(R.id.run_button)
loadButton = findViewById(R.id.load_button)
optionsButton = findViewById(R.id.options_button)
enhancementContainer = findViewById(R.id.enhancement_container)
enhancementLabel = findViewById(R.id.enhancement_label)
enhancementSlider = findViewById(R.id.enhancement_slider)
enhancementSlider.setOnSeekBarChangeListener(object : android.widget.SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: android.widget.SeekBar?, progress: Int, fromUser: Boolean) {
globalEnhancementFactor = 1.0f + (progress / 100f) * 49.0f
enhancementLabel.text = String.format(Locale.US, "Enhancement: %.1fx", globalEnhancementFactor)
applyGlobalEnhancement()
}
override fun onStartTrackingTouch(seekBar: android.widget.SeekBar?) {}
override fun onStopTrackingTouch(seekBar: android.widget.SeekBar?) {}
})
// Setup Run Button
runButton.setOnClickListener {
@@ -120,6 +149,7 @@ class MainActivity : Activity(), ValidationRunner.Callback {
popup.menu.add(0, 3, 0, "Export Result")
popup.menu.add(0, 4, 0, "Test ADB Info")
popup.menu.add(0, 5, 0, "Result ADB Info")
popup.menu.add(0, 6, 0, "Toggle Enhancement Slider")
popup.setOnMenuItemClickListener { item ->
when (item.itemId) {
@@ -133,6 +163,9 @@ class MainActivity : Activity(), ValidationRunner.Callback {
3 -> exportTestResultsAction()
4 -> showTestAdbInfo()
5 -> showResultAdbInfo()
6 -> {
enhancementContainer.visibility = if (enhancementContainer.visibility == View.VISIBLE) View.GONE else View.VISIBLE
}
}
true
}
@@ -256,6 +289,7 @@ class MainActivity : Activity(), ValidationRunner.Callback {
// Clear existing results UI and state
resultsContainer.removeAllViews()
diffImageViews.clear()
resultManager = null
val newInput = ValidationInputManager.ValidationInput(
@@ -337,6 +371,8 @@ class MainActivity : Activity(), ValidationRunner.Callback {
private fun startValidation(input: ValidationInputManager.ValidationInput) {
try {
resultsContainer.removeAllViews()
diffImageViews.clear()
enhancementSlider.isEnabled = false
Log.i(TAG, "Starting validation with config: ${input.config.name}")
Log.i(TAG, "Output dir: ${input.outputDir.absolutePath}")
@@ -420,7 +456,15 @@ class MainActivity : Activity(), ValidationRunner.Callback {
val imagesRow = LinearLayout(this)
imagesRow.orientation = LinearLayout.HORIZONTAL
fun addImage(label: String, bitmap: Bitmap?) {
val testImages = TestImages(
testName = result.testName,
golden = currentGoldenBitmap,
rendered = currentRenderedBitmap,
diff = currentDiffBitmap,
alphaDiff = currentAlphaDiffBitmap
)
fun addImage(label: String, bitmap: Bitmap?, isDiff: Boolean) {
if (bitmap != null) {
val container = LinearLayout(this)
container.orientation = LinearLayout.VERTICAL
@@ -436,16 +480,29 @@ class MainActivity : Activity(), ValidationRunner.Callback {
iv.layoutParams = LinearLayout.LayoutParams(250, 250) // Smaller thumbnails
iv.scaleType = ImageView.ScaleType.FIT_CENTER
iv.setBackgroundColor(0xFF404040.toInt())
if (isDiff) {
diffImageViews.add(iv)
applyEnhancementToView(iv, globalEnhancementFactor)
}
iv.setOnClickListener {
showImageDialog(testImages, label)
}
container.addView(iv)
imagesRow.addView(container)
}
}
addImage("Rendered", currentRenderedBitmap)
addImage("Golden", currentGoldenBitmap)
addImage("Rendered", currentRenderedBitmap, false)
addImage("Golden", currentGoldenBitmap, false)
if (!result.passed) {
addImage("Diff", currentDiffBitmap)
addImage("Diff", currentDiffBitmap, true)
}
if (currentAlphaDiffBitmap != null) {
addImage("Alpha Diff", currentAlphaDiffBitmap, true)
}
resultContainer.addView(imagesRow)
@@ -455,12 +512,14 @@ class MainActivity : Activity(), ValidationRunner.Callback {
currentRenderedBitmap = null
currentGoldenBitmap = null
currentDiffBitmap = null
currentAlphaDiffBitmap = null
}
}
override fun onAllTestsFinished() {
runOnUiThread {
statusTextView.text = "All tests finished!"
enhancementSlider.isEnabled = true
Log.i(TAG, "All tests finished " + if (currentInput?.autoExport == true) "Exporting bundle" else "x")
if (currentInput?.autoExport == true) {
@@ -523,7 +582,165 @@ class MainActivity : Activity(), ValidationRunner.Callback {
"Diff" -> {
currentDiffBitmap = bitmap
}
"Alpha Diff" -> {
currentAlphaDiffBitmap = bitmap
}
}
}
}
private fun applyEnhancementToView(iv: ImageView, factor: Float) {
val cm = android.graphics.ColorMatrix()
cm.setScale(factor, factor, factor, 1.0f)
iv.colorFilter = android.graphics.ColorMatrixColorFilter(cm)
}
private fun applyGlobalEnhancement() {
for (iv in diffImageViews) {
applyEnhancementToView(iv, globalEnhancementFactor)
}
}
private fun showImageDialog(images: TestImages, initialLabel: String) {
val dialogView = layoutInflater.inflate(R.layout.dialog_image_viewer, null)
val dialog = AlertDialog.Builder(this)
.setView(dialogView)
.create()
val titleView = dialogView.findViewById<TextView>(R.id.dialog_title)
val typeView = dialogView.findViewById<TextView>(R.id.dialog_image_type)
val imageView = dialogView.findViewById<ImageView>(R.id.dialog_image)
val btnClose = dialogView.findViewById<View>(R.id.btn_close)
val btnReset = dialogView.findViewById<View>(R.id.btn_reset)
val btnPrev = dialogView.findViewById<View>(R.id.btn_prev)
val btnNext = dialogView.findViewById<View>(R.id.btn_next)
val enhancementContainer = dialogView.findViewById<View>(R.id.dialog_enhancement_container)
val enhancementLabel = dialogView.findViewById<TextView>(R.id.dialog_enhancement_label)
val enhancementSlider = dialogView.findViewById<android.widget.SeekBar>(R.id.dialog_enhancement_slider)
titleView.text = images.testName
val availableImages = mutableListOf<Pair<String, Bitmap>>()
images.rendered?.let { availableImages.add(Pair("Rendered", it)) }
images.golden?.let { availableImages.add(Pair("Golden", it)) }
images.diff?.let { availableImages.add(Pair("Diff", it)) }
images.alphaDiff?.let { availableImages.add(Pair("Alpha Diff", it)) }
if (availableImages.isEmpty()) return
var currentIndex = availableImages.indexOfFirst { it.first == initialLabel }
if (currentIndex == -1) currentIndex = 0
var currentDialogEnhancement = globalEnhancementFactor
val matrix = android.graphics.Matrix()
// Save initial values for translation tracking
var lastTouchX = 0f
var lastTouchY = 0f
var isDragging = false
val scaleDetector = android.view.ScaleGestureDetector(this, object : android.view.ScaleGestureDetector.SimpleOnScaleGestureListener() {
override fun onScale(detector: android.view.ScaleGestureDetector): Boolean {
matrix.postScale(detector.scaleFactor, detector.scaleFactor, detector.focusX, detector.focusY)
imageView.imageMatrix = matrix
return true
}
})
imageView.setOnTouchListener { _, event ->
scaleDetector.onTouchEvent(event)
when (event.actionMasked) {
android.view.MotionEvent.ACTION_DOWN -> {
lastTouchX = event.x
lastTouchY = event.y
isDragging = true
}
android.view.MotionEvent.ACTION_MOVE -> {
if (isDragging && !scaleDetector.isInProgress) {
val dx = event.x - lastTouchX
val dy = event.y - lastTouchY
matrix.postTranslate(dx, dy)
imageView.imageMatrix = matrix
}
lastTouchX = event.x
lastTouchY = event.y
}
android.view.MotionEvent.ACTION_UP, android.view.MotionEvent.ACTION_CANCEL -> {
isDragging = false
}
}
true
}
fun updateView() {
val (label, bitmap) = availableImages[currentIndex]
typeView.text = label
imageView.setImageBitmap(bitmap)
(imageView.drawable as? android.graphics.drawable.BitmapDrawable)?.setAntiAlias(false)
(imageView.drawable as? android.graphics.drawable.BitmapDrawable)?.setFilterBitmap(false)
imageView.imageMatrix = matrix
if (label == "Diff" || label == "Alpha Diff") {
enhancementContainer.visibility = View.VISIBLE
applyEnhancementToView(imageView, currentDialogEnhancement)
} else {
enhancementContainer.visibility = View.GONE
imageView.colorFilter = null
}
}
fun resetMatrix() {
val drawable = imageView.drawable ?: return
val width = imageView.width.toFloat()
val height = imageView.height.toFloat()
val dw = drawable.intrinsicWidth.toFloat()
val dh = drawable.intrinsicHeight.toFloat()
val scaleX = width / dw
val scaleY = height / dh
val scale = Math.min(scaleX, scaleY)
val dx = (width - dw * scale) / 2f
val dy = (height - dh * scale) / 2f
matrix.reset()
matrix.postScale(scale, scale)
matrix.postTranslate(dx, dy)
imageView.imageMatrix = matrix
}
btnClose.setOnClickListener { dialog.dismiss() }
btnReset.setOnClickListener { resetMatrix() }
btnPrev.setOnClickListener {
currentIndex = (currentIndex - 1 + availableImages.size) % availableImages.size
updateView()
}
btnNext.setOnClickListener {
currentIndex = (currentIndex + 1) % availableImages.size
updateView()
}
val defaultProgress = ((currentDialogEnhancement - 1.0f) / 49.0f * 100).toInt()
val safeProgress = Math.max(0, Math.min(100, defaultProgress))
enhancementSlider.progress = safeProgress
enhancementLabel.text = String.format(Locale.US, "Enhance: %.1fx", currentDialogEnhancement)
enhancementSlider.setOnSeekBarChangeListener(object : android.widget.SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: android.widget.SeekBar?, progress: Int, fromUser: Boolean) {
currentDialogEnhancement = 1.0f + (progress / 100f) * 49.0f
enhancementLabel.text = String.format(Locale.US, "Enhance: %.1fx", currentDialogEnhancement)
updateView()
}
override fun onStartTrackingTouch(seekBar: android.widget.SeekBar?) {}
override fun onStopTrackingTouch(seekBar: android.widget.SeekBar?) {}
})
imageView.post {
resetMatrix()
}
updateView()
dialog.show()
}
}
@@ -115,10 +115,6 @@ class ValidationRunner(
}
fun onFrame(frameTimeNanos: Long) {
if (frameCounter % 60 == 0) {
Log.i("ValidationRunner", "onFrame: $currentState (frame: $frameCounter)")
}
when (currentState) {
State.IDLE -> {}
State.WAITING_FOR_RESOURCES -> {
@@ -136,7 +132,6 @@ class ValidationRunner(
}
}
State.RUNNING_TEST -> {
// Log.i("ValidationRunner", "Running test...")
currentEngine?.let { engine ->
val content = AutomationEngine.ViewerContent()
content.view = modelViewer.view
@@ -257,10 +252,54 @@ class ValidationRunner(
passed = (result.status == ImageDiff.Result.Status.PASSED)
diffMetric = result.failingPixelCount.toFloat()
if (!passed) {
if (!passed) {
if (result.diffImage != null) {
callback?.onImageResult("Diff", result.diffImage!!)
resultManager.saveImage("${testFullName}_diff", result.diffImage!!)
val diffImg = result.diffImage!!
val width = diffImg.width
val height = diffImg.height
val pixels = IntArray(width * height)
diffImg.getPixels(pixels, 0, width, 0, 0, width, height)
var hasAlphaDiff = false
val alphaPixels = IntArray(width * height)
for (i in pixels.indices) {
val color = pixels[i]
val a = android.graphics.Color.alpha(color)
val r = android.graphics.Color.red(color)
val g = android.graphics.Color.green(color)
val b = android.graphics.Color.blue(color)
if (a > 0) {
hasAlphaDiff = true
}
// Map alpha diff to grayscale RGB
alphaPixels[i] = android.graphics.Color.argb(255, a, a, a)
// Force main diff image alpha to 255
pixels[i] = android.graphics.Color.argb(255, r, g, b)
}
// Apply updated pixels to diff image
diffImg.setPixels(pixels, 0, width, 0, 0, width, height)
// The C++ ImageDiff code sets isPremultiplied to false so Android
// doesn't erase RGB diff values when Alpha diff is 0. However, Android's
// Canvas will crash if we try to draw a non-premultiplied bitmap.
// Since we just forced all alpha values to 255 (fully opaque) in the
// loop above, we can safely mark it as premultiplied again here.
diffImg.isPremultiplied = true
callback?.onImageResult("Diff", diffImg)
resultManager.saveImage("${testFullName}_diff", diffImg)
if (hasAlphaDiff) {
val alphaDiffImg = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
alphaDiffImg.setPixels(alphaPixels, 0, width, 0, 0, width, height)
callback?.onImageResult("Alpha Diff", alphaDiffImg)
resultManager.saveImage("${testFullName}_alpha_diff", alphaDiffImg)
}
}
}
} else {
@@ -81,6 +81,33 @@
android:contentDescription="More Options"
android:layout_marginStart="8dp"/>
</LinearLayout>
<!-- Global Enhancement Controls (Hidden by default) -->
<LinearLayout
android:id="@+id/enhancement_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:visibility="gone"
android:paddingBottom="8dp">
<TextView
android:id="@+id/enhancement_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Enhancement: 1.0x"
android:textSize="12sp"
android:minWidth="120dp" />
<SeekBar
android:id="@+id/enhancement_slider"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:max="100"
android:progress="0" />
</LinearLayout>
</LinearLayout>
<TextView
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#FF202020"
android:padding="8dp">
<!-- Header with title and close button -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:id="@+id/dialog_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Test Result"
android:textColor="#FFFFFF"
android:textSize="16sp"
android:textStyle="bold" />
<ImageButton
android:id="@+id/btn_close"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@android:drawable/ic_menu_close_clear_cancel" />
</LinearLayout>
<!-- Subtitle for Image Type -->
<TextView
android:id="@+id/dialog_image_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:text="Rendered"
android:textColor="#BBBBBB"
android:textSize="14sp"
android:paddingBottom="8dp" />
<!-- Image Area with Arrows -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintDimensionRatio="1:1">
<ImageView
android:id="@+id/dialog_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="matrix" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- Navigation Arrows -->
<LinearLayout
android:id="@+id/dialog_arrow_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<ImageButton
android:id="@+id/btn_prev"
android:layout_width="64dp"
android:layout_height="64dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@android:drawable/ic_media_previous"
app:tint="#FFFFFF" />
<ImageButton
android:id="@+id/btn_reset"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginHorizontal="16dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@android:drawable/ic_menu_revert"
app:tint="#FFFFFF" />
<ImageButton
android:id="@+id/btn_next"
android:layout_width="64dp"
android:layout_height="64dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@android:drawable/ic_media_next"
app:tint="#FFFFFF" />
</LinearLayout>
<!-- Enhancement Controls (only for diff images) -->
<LinearLayout
android:id="@+id/dialog_enhancement_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:paddingTop="12dp"
android:paddingBottom="8dp"
android:visibility="gone">
<TextView
android:id="@+id/dialog_enhancement_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Enhance: 1.0x"
android:textColor="#FFFFFF"
android:textSize="12sp"
android:minWidth="100dp" />
<SeekBar
android:id="@+id/dialog_enhancement_slider"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:max="100"
android:progress="0" />
</LinearLayout>
</LinearLayout>
@@ -46,6 +46,7 @@ list(SORT NDK_VERSIONS)
list(GET NDK_VERSIONS -1 NDK_VERSION)
get_filename_component(NDK_VERSION ${NDK_VERSION} NAME)
set(TOOLCHAIN ${ANDROID_HOME_UNIX}/ndk/${NDK_VERSION}/toolchains/llvm/prebuilt/${HOST_NAME_L}-x86_64)
set(CMAKE_ANDROID_NDK_VERSION ${NDK_VERSION})
# specify the cross compiler
set(COMPILER_SUFFIX)
+1
View File
@@ -47,6 +47,7 @@ list(SORT NDK_VERSIONS)
list(GET NDK_VERSIONS -1 NDK_VERSION)
get_filename_component(NDK_VERSION ${NDK_VERSION} NAME)
set(TOOLCHAIN ${ANDROID_HOME_UNIX}/ndk/${NDK_VERSION}/toolchains/llvm/prebuilt/${HOST_NAME_L}-x86_64)
set(CMAKE_ANDROID_NDK_VERSION ${NDK_VERSION})
# specify the cross compiler
set(COMPILER_SUFFIX)
+1
View File
@@ -46,6 +46,7 @@ list(SORT NDK_VERSIONS)
list(GET NDK_VERSIONS -1 NDK_VERSION)
get_filename_component(NDK_VERSION ${NDK_VERSION} NAME)
set(TOOLCHAIN ${ANDROID_HOME_UNIX}/ndk/${NDK_VERSION}/toolchains/llvm/prebuilt/${HOST_NAME_L}-x86_64)
set(CMAKE_ANDROID_NDK_VERSION ${NDK_VERSION})
# specify the cross compiler
set(COMPILER_SUFFIX)
@@ -46,6 +46,7 @@ list(SORT NDK_VERSIONS)
list(GET NDK_VERSIONS -1 NDK_VERSION)
get_filename_component(NDK_VERSION ${NDK_VERSION} NAME)
set(TOOLCHAIN ${ANDROID_HOME_UNIX}/ndk/${NDK_VERSION}/toolchains/llvm/prebuilt/${HOST_NAME_L}-x86_64)
set(CMAKE_ANDROID_NDK_VERSION ${NDK_VERSION})
# specify the cross compiler
set(COMPILER_SUFFIX)
+2 -2
View File
@@ -181,7 +181,7 @@ important for <code>matc</code> (material compiler).</p>
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.69.5'
implementation 'com.google.android.filament:filament-android:1.70.0'
}
</code></pre>
<p>Here are all the libraries available in the group <code>com.google.android.filament</code>:</p>
@@ -195,7 +195,7 @@ dependencies {
</div>
<h3 id="ios"><a class="header" href="#ios">iOS</a></h3>
<p>iOS projects can use CocoaPods to install the latest release:</p>
<pre><code class="language-shell">pod 'Filament', '~&gt; 1.69.5'
<pre><code class="language-shell">pod 'Filament', '~&gt; 1.70.0'
</code></pre>
<h2 id="documentation"><a class="header" href="#documentation">Documentation</a></h2>
<ul>
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-2
View File
@@ -616,7 +616,6 @@ if (FILAMENT_BUILD_TESTING)
set(BACKEND_TEST_LIBS
absl::str_format
backend
getopt
gtest
imageio
filamat
@@ -725,7 +724,6 @@ if (FILAMENT_BUILD_TESTING)
target_link_libraries(metal_utils_test PRIVATE
backend
getopt
gtest
)
@@ -222,6 +222,7 @@ public:
enum class DeviceInfoType {
OPENGL_RENDERER, //!< glGetString(GL_RENDERER)
OPENGL_VENDOR, //!< glGetString(GL_VENDOR)
OPENGL_VERSION, //!< glGetString(GL_VERSION)
VULKAN_DEVICE_NAME, //!< VkPhysicalDeviceProperties::deviceName
VULKAN_DRIVER_NAME, //!< VkPhysicalDeviceDriverProperties::driverName
VULKAN_DRIVER_INFO, //!< VkPhysicalDeviceDriverProperties::driverInfo
@@ -73,6 +73,12 @@ public:
*/
static utils::CString getRendererString(Driver const* UTILS_NONNULL driver);
/**
* Return the OpenGL version string of the specified Driver instance.
* @return The GL_VERSION string
*/
static utils::CString getVersionString(Driver const* UTILS_NONNULL driver);
/**
* Called by the driver to destroy the OpenGL context. This should clean up any windows
* or buffers from initialization. This is for instance where `eglDestroyContext` would be
@@ -159,6 +159,12 @@ protected:
EGLConfig getEglConfig() const noexcept { return mEGLConfig; }
EGLConfig getSuitableConfigForSwapChain(uint64_t flags, bool window, bool pbuffer) const;
// Sets the EGLDisplay to be used by this platform. This should only be called by derived
// classes before invoking createDriver. Calling it after that point will result in
// undefined behaviour. This class will take ownership of the display and call eglTerminate
// on it during shutdown.
void setEglDisplay(EGLDisplay display) noexcept;
// supported extensions detected at runtime
struct {
struct {
@@ -31,7 +31,6 @@
#include <cstring>
#include <cstddef>
#include <functional>
#include <string>
#include <tuple>
#include <unordered_set>
@@ -69,7 +68,7 @@ public:
struct ExtensionHashFn {
std::size_t operator()(utils::CString const& s) const noexcept {
return std::hash<std::string>{}(s.data());
return std::hash<utils::CString>{}(s.data());
}
};
// Note: utils::CString::operator== has an edge case that breaks for the extension set.
+1 -1
View File
@@ -32,7 +32,7 @@
#include <cstddef>
#include <functional>
#include <string>
#include <string_view>
#include <utility>
#ifdef __ANDROID__
+5 -1
View File
@@ -716,7 +716,11 @@ Handle<HwSwapChain> OpenGLDriver::createSwapChainHeadlessS() noexcept {
}
Handle<HwTimerQuery> OpenGLDriver::createTimerQueryS() noexcept {
return initHandle<GLTimerQuery>();
Handle<HwTimerQuery> tqh = initHandle<GLTimerQuery>();
// The state must be constructed here, as a synchronous call to getTimerQueryValue might happen
// before createTimerQueryR is executed on the backend thread.
handle_cast<GLTimerQuery*>(tqh)->state = std::make_shared<GLTimerQuery::State>();
return tqh;
}
Handle<HwDescriptorSetLayout> OpenGLDriver::createDescriptorSetLayoutS() noexcept {
@@ -250,6 +250,10 @@ private:
return utils::CString{ mContext.state.renderer };
}
utils::CString getVersionString() const noexcept override {
return utils::CString{ mContext.state.version };
}
JobQueue* getJobQueue() const noexcept { return mJobQueue.get(); }
JobWorker* getJobWorker() const noexcept { return mJobWorker.get(); }
@@ -34,6 +34,7 @@ protected:
public:
virtual utils::CString getVendorString() const noexcept = 0;
virtual utils::CString getRendererString() const noexcept = 0;
virtual utils::CString getVersionString() const noexcept = 0;
};
} // filament::backend
@@ -52,6 +52,8 @@ utils::CString OpenGLPlatform::getDeviceInfo(DeviceInfoType infoType,
return getRendererString(driver);
case DeviceInfoType::OPENGL_VENDOR:
return getVendorString(driver);
case DeviceInfoType::OPENGL_VERSION:
return getVersionString(driver);
default:
FILAMENT_CHECK_POSTCONDITION(false) << "Unsupported DeviceInfoType for OpenGLPlatform";
return {};
@@ -76,6 +78,15 @@ utils::CString OpenGLPlatform::getRendererString(Driver const* driver) {
return p->getRendererString();
}
utils::CString OpenGLPlatform::getVersionString(Driver const* driver) {
auto const p = static_cast<OpenGLDriverBase const*>(driver);
#if UTILS_HAS_RTTI
FILAMENT_CHECK_POSTCONDITION(dynamic_cast<OpenGLDriverBase const*>(driver))
<< "Driver* has not been allocated with OpenGLPlatform";
#endif
return p->getVersionString();
}
void OpenGLPlatform::makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain,
utils::Invocable<void()>, utils::Invocable<void(size_t)>) {
makeCurrent(getCurrentContextType(), drawSwapChain, readSwapChain);
@@ -88,15 +88,14 @@ TimerQueryFactoryInterface::~TimerQueryFactoryInterface() = default;
// This is a backend synchronous call
TimerQueryResult TimerQueryFactoryInterface::getTimerQueryValue(
GLTimerQuery* tq, uint64_t* elapsedTime) noexcept {
if (UTILS_LIKELY(tq->state)) {
int64_t const elapsed = tq->state->elapsed.load(std::memory_order_relaxed);
if (elapsed > 0) {
*elapsedTime = elapsed;
return TimerQueryResult::AVAILABLE;
}
return TimerQueryResult(elapsed);
assert_invariant(tq->state);
int64_t const elapsed = tq->state->elapsed.load(std::memory_order_relaxed);
if (elapsed > 0) {
*elapsedTime = elapsed;
return TimerQueryResult::AVAILABLE;
}
return TimerQueryResult::ERROR;
return TimerQueryResult(elapsed);
}
// ------------------------------------------------------------------------------------------------
@@ -110,9 +109,8 @@ TimerQueryNativeFactory::TimerQueryNativeFactory(OpenGLContext& context)
TimerQueryNativeFactory::~TimerQueryNativeFactory() = default;
void TimerQueryNativeFactory::createTimerQuery(GLTimerQuery* tq) {
assert_invariant(!tq->state);
assert_invariant(tq->state);
tq->state = std::make_shared<GLTimerQuery::State>();
mContext.procs.genQueries(1u, &tq->state->gl.query);
CHECK_GL_ERROR()
}
@@ -181,8 +179,7 @@ TimerQueryFenceFactory::~TimerQueryFenceFactory() {
}
void TimerQueryFenceFactory::createTimerQuery(GLTimerQuery* tq) {
assert_invariant(!tq->state);
tq->state = std::make_shared<GLTimerQuery::State>();
assert_invariant(tq->state);
}
void TimerQueryFenceFactory::destroyTimerQuery(GLTimerQuery* tq) {
@@ -238,8 +235,7 @@ TimerQueryFallbackFactory::TimerQueryFallbackFactory() = default;
TimerQueryFallbackFactory::~TimerQueryFallbackFactory() = default;
void TimerQueryFallbackFactory::createTimerQuery(GLTimerQuery* tq) {
assert_invariant(!tq->state);
tq->state = std::make_shared<GLTimerQuery::State>();
assert_invariant(tq->state);
}
void TimerQueryFallbackFactory::destroyTimerQuery(GLTimerQuery* tq) {
@@ -117,6 +117,13 @@ struct ShaderCompilerService::OpenGLProgramToken : ProgramToken {
cond.wait(l, [this] { return signaled; });
}
// Used in THREAD_POOL mode. Returns true if the token is signaled, meaning it's ready to be
// used.
bool isReady() const noexcept {
std::unique_lock const l(lock);
return signaled;
}
// This is invoked upon token completion, which occurs after a successful `gl.program`
// population or upon cancellation. In either scenario, the callback handle must be submitted
// to notify the caller that resource loading has concluded.
@@ -524,8 +531,15 @@ GLuint ShaderCompilerService::initialize(program_token_t& token) {
}
void ShaderCompilerService::ensureTokenIsReady(program_token_t const& token) {
if (token->gl.program) {
return;// It's ready.
if (mMode == Mode::THREAD_POOL) {
// Check if `token->gl.program` is populated
if (token->isReady()) {
return;
}
} else {
if (token->gl.program) {
return;
}
}
switch (mMode) {
@@ -935,6 +949,7 @@ void ShaderCompilerService::cancelPendingSynchronousProgram(program_token_t cons
return false;
}
token->retrievedFromBlobCache = true;
token->signal(); // notify that `token->gl.program` is ready to use
return true;
}
@@ -34,6 +34,7 @@
#include <utils/Invocable.h>
#include <utils/Logger.h>
#include <utils/Panic.h>
#include <utils/debug.h>
#include <utils/ostream.h>
@@ -119,31 +120,41 @@ bool PlatformEGL::isOpenGL() const noexcept {
PlatformEGL::ExternalImageEGL::~ExternalImageEGL() = default;
void PlatformEGL::setEglDisplay(EGLDisplay display) noexcept {
FILAMENT_CHECK_PRECONDITION(mEGLDisplay == EGL_NO_DISPLAY)
<< "EGL Display has already been set.";
FILAMENT_CHECK_PRECONDITION(display != EGL_NO_DISPLAY)
<< "Must specify a valid EGL Display.";
mEGLDisplay = display;
}
Driver* PlatformEGL::createDriver(void* sharedContext, const DriverConfig& driverConfig) {
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert_invariant(mEGLDisplay != EGL_NO_DISPLAY);
if (mEGLDisplay == EGL_NO_DISPLAY) {
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert_invariant(mEGLDisplay != EGL_NO_DISPLAY);
EGLint major, minor;
EGLBoolean initialized = eglInitialize(mEGLDisplay, &major, &minor);
EGLint major, minor;
EGLBoolean initialized = eglInitialize(mEGLDisplay, &major, &minor);
if (!initialized) {
EGLDeviceEXT eglDevice;
EGLint numDevices;
PFNEGLQUERYDEVICESEXTPROC const eglQueryDevicesEXT =
PFNEGLQUERYDEVICESEXTPROC(eglGetProcAddress("eglQueryDevicesEXT"));
if (eglQueryDevicesEXT != nullptr) {
eglQueryDevicesEXT(1, &eglDevice, &numDevices);
if(auto* getPlatformDisplay = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
eglGetProcAddress("eglGetPlatformDisplay"))) {
mEGLDisplay = getPlatformDisplay(EGL_PLATFORM_DEVICE_EXT, eglDevice, nullptr);
initialized = eglInitialize(mEGLDisplay, &major, &minor);
if (!initialized) {
EGLDeviceEXT eglDevice;
EGLint numDevices;
PFNEGLQUERYDEVICESEXTPROC const eglQueryDevicesEXT =
PFNEGLQUERYDEVICESEXTPROC(eglGetProcAddress("eglQueryDevicesEXT"));
if (eglQueryDevicesEXT != nullptr) {
eglQueryDevicesEXT(1, &eglDevice, &numDevices);
if(auto* getPlatformDisplay = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
eglGetProcAddress("eglGetPlatformDisplay"))) {
mEGLDisplay = getPlatformDisplay(EGL_PLATFORM_DEVICE_EXT, eglDevice, nullptr);
initialized = eglInitialize(mEGLDisplay, &major, &minor);
}
}
}
}
if (UTILS_UNLIKELY(!initialized)) {
LOG(ERROR) << "eglInitialize failed";
return nullptr;
if (UTILS_UNLIKELY(!initialized)) {
LOG(ERROR) << "eglInitialize failed";
return nullptr;
}
}
#if defined(FILAMENT_IMPORT_ENTRY_POINTS)
@@ -106,6 +106,12 @@ void VulkanBufferCache::gc() noexcept {
}
}
size_t totalBuffers = 0;
for (auto& bufferPool : mGpuBufferPools) {
totalBuffers += bufferPool.size();
}
FVK_LOGD << "VulkanBufferCache sizes: buffers=" << totalBuffers;
FVK_SYSTRACE_END();
}
@@ -157,6 +163,10 @@ VulkanGpuBuffer const* VulkanBufferCache::allocate(VulkanBufferBinding binding,
UTILS_UNUSED_IN_RELEASE VkResult result = vmaCreateBuffer(mAllocator, &bufferInfo, &allocInfo,
&gpuBuffer->vkbuffer, &gpuBuffer->vmaAllocation, &gpuBuffer->allocationInfo);
FVK_LOGD << "VulkanBufferCache - allocated a vkBuffer " << gpuBuffer->vkbuffer
<< " of size " << numBytes << " and binding = " << static_cast<int>(binding)
<< " result=" << (int)result;
#if FVK_ENABLED(FVK_DEBUG_VULKAN_BUFFER_CACHE)
if (result != VK_SUCCESS) {
FVK_LOGE << "VulkanBufferCache - failed to allocate a new vkBuffer of size " << numBytes
@@ -173,6 +183,7 @@ VulkanGpuBuffer const* VulkanBufferCache::allocate(VulkanBufferBinding binding,
}
void VulkanBufferCache::destroy(VulkanGpuBuffer const* gpuBuffer) noexcept {
FVK_LOGD << "VulkanBufferCache - Destroying vkBuffer " << gpuBuffer->vkbuffer;
vmaDestroyBuffer(mAllocator, gpuBuffer->vkbuffer, gpuBuffer->vmaAllocation);
delete gpuBuffer;
gpuBuffer = nullptr;
@@ -194,6 +194,7 @@ void VulkanCommandBuffer::begin() noexcept {
}
fvkmemory::resource_ptr<VulkanSemaphore> VulkanCommandBuffer::submit() {
FVK_LOGD << "Submitting VulkanCommandBuffer: " << mBuffer << " (age=" << age() << ")";
while (mMarkerCount > 0) {
popMarker();
}
@@ -24,7 +24,7 @@
// If any VkRenderPass or VkFramebuffer is unused for more than TIME_BEFORE_EVICTION frames, it
// is evicted from the cache.
static constexpr uint32_t TIME_BEFORE_EVICTION = FVK_MAX_COMMAND_BUFFERS;
static constexpr uint32_t TIME_BEFORE_EVICTION = 3;
using namespace bluevk;
@@ -120,6 +120,8 @@ fvkmemory::resource_ptr<VulkanFramebuffer> VulkanFboCache::getFramebuffer(FboKey
VkResult error = vkCreateFramebuffer(mDevice, &info, VKALLOC, &framebuffer);
FILAMENT_CHECK_POSTCONDITION(error == VK_SUCCESS) << "Unable to create framebuffer."
<< " error=" << static_cast<int32_t>(error);
FVK_LOGD << "VulkanFboCache - Created VkFramebuffer " << framebuffer << " for renderTarget " << renderTarget.get()
<< " size=" << config.width << "x" << config.height;
fvkmemory::resource_ptr<VulkanFramebuffer> fbh =
fvkmemory::resource_ptr<VulkanFramebuffer>::construct(resManager, mDevice, framebuffer,
renderTarget);
@@ -404,6 +406,8 @@ void VulkanFboCache::gc() noexcept {
}
}
FVK_LOGD << "VulkanFboCache sizes: framebuffers=" << mFramebufferCache.size() << " renderpasses=" << mRenderPassCache.size();
FVK_SYSTRACE_END();
}
+13 -2
View File
@@ -403,10 +403,13 @@ VulkanRenderTarget::VulkanRenderTarget()
mOffscreen(false),
mProtected(false),
mInfo(std::make_unique<Auxiliary>()) {
FVK_LOGD << "Creating default VulkanRenderTarget: " << this;
mInfo->rpkey.samples = mInfo->fbkey.samples = 1;
}
VulkanRenderTarget::~VulkanRenderTarget() = default;
VulkanRenderTarget::~VulkanRenderTarget() {
FVK_LOGD << "Destroying VulkanRenderTarget: " << this << " (offscreen=" << mOffscreen << ")";
}
void VulkanRenderTarget::bindSwapChain(fvkmemory::resource_ptr<VulkanSwapChain> swapchain) {
assert_invariant(!mOffscreen);
@@ -443,9 +446,12 @@ void VulkanRenderTarget::bindSwapChain(fvkmemory::resource_ptr<VulkanSwapChain>
fbkey.depth = VK_NULL_HANDLE;
}
mInfo->colors.set(0);
FVK_LOGD << "bindSwapChain: target=" << this << ", swapchain=" << swapchain.get()
<< ", size=" << width << "x" << height;
}
void VulkanRenderTarget::releaseSwapchain() {
FVK_LOGD << "releaseSwapchain: target=" << this;
mInfo->colors = {};
mInfo->attachments.clear();
}
@@ -459,6 +465,7 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
mOffscreen(true),
mProtected(false),
mInfo(std::make_unique<Auxiliary>()) {
FVK_LOGD << "Creating offscreen VulkanRenderTarget: " << this << ", size=" << width << "x" << height << ", samples=" << (int)samples;
auto& depth = depthStencil[0];
// Constrain the sample count according to both kinds of sample count masks obtained from
@@ -719,9 +726,13 @@ VulkanFramebuffer::VulkanFramebuffer(VkDevice device, VkFramebuffer framebuffer,
fvkmemory::resource_ptr<VulkanRenderTarget> renderTarget)
: mDevice(device),
mFramebuffer(framebuffer),
mRenderTarget(renderTarget) {}
mRenderTarget(renderTarget) {
FVK_LOGD << "Creating VulkanFramebuffer: " << framebuffer
<< ", target=" << renderTarget.get();
}
VulkanFramebuffer::~VulkanFramebuffer() {
FVK_LOGD << "Destroying VulkanFramebuffer: " << mFramebuffer;
vkDestroyFramebuffer(mDevice, mFramebuffer, VKALLOC);
}
@@ -534,6 +534,8 @@ void VulkanPipelineCache::gc() noexcept {
++iter;
}
}
FVK_LOGD << "VulkanPipelineCache sizes: pipelines=" << mPipelines.size();
}
bool VulkanPipelineCache::PipelineEqual::operator()(const PipelineKey& k1,
@@ -271,6 +271,8 @@ void VulkanStagePool::gc() noexcept {
}
}
FVK_LOGD << "VulkanStagePool sizes: stages=" << mStages.size() << " freeImages=" << mFreeImages.size();
FVK_SYSTRACE_END();
}
@@ -46,6 +46,7 @@ VulkanSwapChain::VulkanSwapChain(VulkanPlatform* platform, VulkanContext const&
mCurrentSwapIndex(0),
mAcquired(false),
mIsFirstRenderPass(true) {
FVK_LOGD << "Creating VulkanSwapChain: " << this << ", window=" << nativeWindow << ", size=" << extent.width << "x" << extent.height;
swapChain = mPlatform->createSwapChain(nativeWindow, flags, extent);
FILAMENT_CHECK_POSTCONDITION(swapChain) << "Unable to create swapchain";
@@ -53,6 +54,7 @@ VulkanSwapChain::VulkanSwapChain(VulkanPlatform* platform, VulkanContext const&
}
VulkanSwapChain::~VulkanSwapChain() {
FVK_LOGD << "Destroying VulkanSwapChain: " << this;
// Must wait for the inflight command buffers to finish since they might contain the images
// we're about to destroy.
mCommands->flush();
@@ -68,6 +70,7 @@ VulkanSwapChain::~VulkanSwapChain() {
}
void VulkanSwapChain::update() {
FVK_LOGD << "VulkanSwapChain::update: " << this;
mColors.clear();
auto const bundle = mPlatform->getSwapChainBundle(swapChain);
@@ -89,6 +92,7 @@ void VulkanSwapChain::update() {
colorUsage |= TextureUsage::PROTECTED;
}
for (auto const color: bundle.colors) {
FVK_LOGD << "VulkanSwapChain::update: Adding color image=" << color << " to swapchain " << this;
auto colorTexture = fvkmemory::resource_ptr<VulkanTexture>::construct(mResourceManager,
mContext, device, mAllocator, mResourceManager, mCommands, color, VK_NULL_HANDLE,
bundle.colorFormat, VK_NULL_HANDLE /*ycrcb */, 1, bundle.extent.width,
@@ -157,6 +161,7 @@ void VulkanSwapChain::acquire(bool& resized) {
// Check if the swapchain should be resized.
if ((resized = mPlatform->hasResized(swapChain))) {
FVK_LOGD << "VulkanSwapChain::acquire: Resizing " << this;
if (mFlushAndWaitOnResize) {
mCommands->flush();
mCommands->wait();
@@ -176,6 +181,7 @@ void VulkanSwapChain::acquire(bool& resized) {
mCurrentSwapIndex = imageSyncData.imageIndex;
assert_invariant(mCurrentSwapIndex < mFinishedDrawing.size());
FVK_LOGD << "VulkanSwapChain::acquire: " << this << ", index=" << mCurrentSwapIndex << ", image=" << mColors[mCurrentSwapIndex]->getVkImage();
mFinishedDrawing[mCurrentSwapIndex] = {};
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR)
<< "Cannot acquire in swapchain. error=" << static_cast<int32_t>(result);
+29 -4
View File
@@ -294,9 +294,19 @@ VulkanTextureState::VulkanTextureState(VulkanStagePool& stagePool, VulkanCommand
mYcbcr{ ycbcrConversion },
mDefaultLayout(getDefaultLayoutImpl(usage)),
mUsage(usage),
mIsProtected(isProtected) {}
mIsProtected(isProtected) {
FVK_LOGD << "Creating VulkanTextureState: image=" << image
<< ", memory=" << deviceMemory
<< ", format=" << format
<< ", viewType=" << viewType
<< ", levels=" << (int)levels
<< ", layers=" << (int)layerCount
<< ", usage=" << usage;
}
VulkanTextureState::~VulkanTextureState() {
FVK_LOGD << "Destroying VulkanTextureState: image=" << mTextureImage
<< ", memory=" << mTextureImageMemory;
clearCachedImageViews();
if (mTextureImageMemory != VK_NULL_HANDLE) {
vkDestroyImage(mDevice, mTextureImage, VKALLOC);
@@ -512,6 +522,12 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t width, uint32_t height,
uint32_t depth, uint32_t xoffset, uint32_t yoffset, uint32_t zoffset, uint32_t miplevel) {
FVK_LOGD << "updateImage: texture=" << mState->mTextureImage
<< ", format=" << (int)data.format
<< ", type=" << (int)data.type
<< ", size=" << width << "x" << height << "x" << depth
<< ", offset=" << xoffset << "," << yoffset << "," << zoffset
<< ", mip=" << miplevel;
assert_invariant(width <= this->width && height <= this->height);
assert_invariant(depth <= this->depth * ((target == SamplerType::SAMPLER_CUBEMAP ||
target == SamplerType::SAMPLER_CUBEMAP_ARRAY) ? 6 : 1));
@@ -616,6 +632,11 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt
void VulkanTexture::updateImageWithBlit(const PixelBufferDescriptor& data, uint32_t width,
uint32_t height, uint32_t depth, uint32_t miplevel) {
FVK_LOGD << "updateImageWithBlit: texture=" << mState->mTextureImage
<< ", format=" << (int)data.format
<< ", type=" << (int)data.type
<< ", size=" << width << "x" << height << "x" << depth
<< ", mip=" << miplevel;
// Otherwise, use vkCmdCopyBufferToImage.
size_t const bpp = PixelBufferDescriptor::computeDataSize(data.format, data.type, 1, 1, 1);
// Note: if bpp = 0, we're dealing with a compressed format; we should fall
@@ -755,10 +776,14 @@ bool VulkanTexture::transitionLayout(VkCommandBuffer cmdbuf, VkImageSubresourceR
setLayout(range, newLayout);
if (hasTransitions) {
FVK_LOGD << "transition texture=" << mState->mTextureImage << " (" << range.baseArrayLayer
<< "," << range.baseMipLevel << ")" << " count=(" << range.layerCount << ","
<< range.levelCount << ")" << " from=" << (int)oldLayout << " to=" << (int)newLayout
<< " format=" << mState->mVkFormat;
#if FVK_ENABLED(FVK_DEBUG_LAYOUT_TRANSITION)
FVK_LOGD << "transition texture=" << mState->mTextureImage << " (" << range.baseArrayLayer
<< "," << range.baseMipLevel << ")" << " count=(" << range.layerCount << ","
<< range.levelCount << ")" << " from=" << oldLayout << " to=" << newLayout
<< range.levelCount << ")" << " from=" << (int)oldLayout << " to=" << (int)newLayout
<< " format=" << mState->mVkFormat << " depth="
<< fvkutils::isVkDepthFormat(mState->mVkFormat)
<< " slice-by-slice=" << transitionSliceBySlice;
@@ -767,7 +792,7 @@ bool VulkanTexture::transitionLayout(VkCommandBuffer cmdbuf, VkImageSubresourceR
#if FVK_ENABLED(FVK_DEBUG_LAYOUT_TRANSITION)
FVK_LOGD << "transition texture=" << mState->mTextureImage << " (" << range.baseArrayLayer
<< "," << range.baseMipLevel << ")" << " count=(" << range.layerCount << ","
<< range.levelCount << ")" << " to=" << newLayout
<< range.levelCount << ")" << " to=" << (int)newLayout
<< " is skipped because of no change in layout";
#endif
}
@@ -878,7 +903,7 @@ void VulkanTexture::print() const {
level >= mPrimaryViewRange.baseMipLevel &&
level < (mPrimaryViewRange.baseMipLevel + mPrimaryViewRange.levelCount);
FVK_LOGD << "[" << mState->mTextureImage << "]: (" << layer << "," << level
<< ")=" << getLayout(layer, level)
<< ")=" << (int)getLayout(layer, level)
<< " primary=" << primary;
}
}
+13 -3
View File
@@ -1970,9 +1970,19 @@ void WebGPUDriver::dispatchCompute(Handle<HwProgram> program, math::uint3 workGr
//todo
}
void WebGPUDriver::scissor(
Viewport scissor) {
//todo
void WebGPUDriver::scissor(Viewport scissor) {
assert_invariant(mRenderPassEncoder);
assert_invariant(mCurrentRenderTarget);
// The WebGPU scissor starts from the top-left corner
assert_invariant(scissor.left >= 0 &&
mCurrentRenderTarget->height >= scissor.bottom + scissor.height /*top >= 0*/ &&
scissor.width <= mCurrentRenderTarget->width &&
scissor.height <= mCurrentRenderTarget->height);
mRenderPassEncoder.SetScissorRect(scissor.left,
mCurrentRenderTarget->height - scissor.bottom - scissor.height /*top*/, scissor.width,
scissor.height);
}
void WebGPUDriver::beginTimerQuery(Handle<HwTimerQuery> tqh) {
+8 -8
View File
@@ -16,7 +16,7 @@
#include "PlatformRunner.h"
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <iostream>
#include <string>
@@ -30,18 +30,18 @@ TestArguments parseArguments(int argc, char* argv[]) {
// The first colon in OPTSTR turns on silent error reporting. This is important, as the
// arguments may also contain gtest parameters we don't know about.
static constexpr const char* OPTSTR = ":a:kc";
static const struct option OPTIONS[] = {
{ "api", required_argument, nullptr, 'a' },
{ "headless_only", no_argument, nullptr, 'k' },
{ "ci", no_argument, nullptr, 'c' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ "headless_only", utils::getopt::no_argument, nullptr, 'k' },
{ "ci", utils::getopt::no_argument, nullptr, 'c' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int optionIndex = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &optionIndex)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &optionIndex)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
case 'a':
if (arg == "opengl") {
-1
View File
@@ -32,7 +32,6 @@ using namespace filament;
using namespace filament::backend;
TEST_F(BackendTest, ScissorViewportRegion) {
SKIP_IF(Backend::WEBGPU, "test cases fail in WebGPU, see b/424157731");
auto& api = getDriverApi();
constexpr int kSrcTexWidth = 1024;
+1 -1
View File
@@ -182,7 +182,7 @@ Program::SpecializationConstant LocalProgramCache::getConstantImpl(
return getConstantImpl(it->second + CONFIG_MAX_RESERVED_SPEC_CONSTANTS);
}
std::string name_cstring(name);
CString name_cstring(name);
PANIC_PRECONDITION("No such constant exists: %s", name_cstring.c_str());
return {};
}
+12
View File
@@ -2248,6 +2248,18 @@ PostProcessManager::BloomPassOutput PostProcessManager::bloom(FrameGraph& fg,
float bloomHeight = float(inoutBloomOptions.resolution);
float bloomWidth = bloomHeight * aspect;
// With extreme aspect ratios the major axis can exceed the GPU's maximum
// texture dimension. Scale both axes down proportionally so that the larger
// one stays within the hardware limit.
const float maxDimension = float(
FTexture::getMaxTextureSize(mEngine, SamplerType::SAMPLER_2D));
const float bloomMajor = std::max(bloomWidth, bloomHeight);
if (bloomMajor > maxDimension) {
const float clampScale = maxDimension / bloomMajor;
bloomWidth *= clampScale;
bloomHeight *= clampScale;
}
// we might need to adjust the max # of levels
const uint32_t major = uint32_t(std::max(bloomWidth, bloomHeight));
const uint8_t maxLevels = FTexture::maxLevelCount(major);
+1
View File
@@ -1138,6 +1138,7 @@ void FView::prepareShadowMapping() const noexcept {
constexpr uint32_t SHADOW_SAMPLING_RUNTIME_PCSS = 3u;
auto& s = mUniforms.edit();
s.cascadeSplits = uniforms.cascadeSplits;
s.shadowAtlasResolution = uniforms.atlasResolution;
s.ssContactShadowDistance = uniforms.ssContactShadowDistance;
s.directionalShadows = int32_t(uniforms.directionalShadows);
s.cascades = int32_t(uniforms.cascades);
-2
View File
@@ -27,8 +27,6 @@
#include <utils/debug.h>
#include <utils/CString.h>
#include <string>
using namespace filament::backend;
namespace filament {
@@ -153,13 +153,17 @@ struct PerViewUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
int32_t directionalShadows;
float ssContactShadowDistance;
math::float2 shadowAtlasResolution; // dim, 1/dim
float shadowReserved0;
float shadowReserved1;
// position of cascade splits, in world space (not including the near plane)
// -Inf stored in unused components
math::float4 cascadeSplits;
// bit 0-3: cascade count
// bit 8-11: cascade has visible shadows
int32_t cascades;
float shadowPenumbraRatioScale; // For DPCF or PCSS, scale penumbra ratio for artistic use
float shadowPenumbraRatioScale; // For DPCF or PCSS, scale penumbra ratio for artistic use
math::float2 lightFarAttenuationParams; // a, a/far (a=1/pct-of-far)
// --------------------------------------------------------------------------------------------
@@ -213,7 +217,7 @@ struct PerViewUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
float es2Reserved2;
// bring PerViewUib to 2 KiB
math::float4 reserved[22];
math::float4 reserved[21];
};
// 2 KiB == 128 float4s
+23 -23
View File
@@ -18,7 +18,7 @@
#define TNT_ENUMMANAGER_H
#include <algorithm>
#include <string>
#include <string_view>
#include <unordered_map>
#include <filamat/MaterialBuilder.h>
@@ -37,55 +37,55 @@ using OutputType = MaterialBuilder::OutputType;
using ConstantType = MaterialBuilder::ConstantType;
using ShaderStageType = MaterialBuilder::ShaderStageFlags;
// Convenience methods to convert std::string to Enum and also iterate over Enum values.
// Convenience methods to convert std::string_view to Enum and also iterate over Enum values.
class Enums {
public:
// Returns true if string "s" is a valid string representation of an element of enum T.
template<typename T>
static bool isValid(const std::string& s) noexcept {
std::unordered_map<std::string, T>& map = getMap<T>();
static bool isValid(const std::string_view& s) noexcept {
std::unordered_map<std::string_view, T>& map = getMap<T>();
return map.find(s) != map.end();
}
// Return enum matching its string representation. Returns undefined if s is not a valid enum T
// value. You should always call isValid() first to validate a string before calling toEnum().
template<typename T>
static T toEnum(const std::string& s) noexcept {
std::unordered_map<std::string, T>& map = getMap<T>();
static T toEnum(const std::string_view& s) noexcept {
std::unordered_map<std::string_view, T>& map = getMap<T>();
return map.at(s);
}
template<typename T>
static std::string toString(T t) noexcept;
static std::string_view toString(T t) noexcept;
// Return a map of all values in an enum with their string representation.
template<typename T>
static std::unordered_map<std::string, T>& map() noexcept {
std::unordered_map<std::string, T>& map = getMap<T>();
static std::unordered_map<std::string_view, T>& map() noexcept {
auto& map = getMap<T>();
return map;
};
private:
template<typename T>
static std::unordered_map<std::string, T>& getMap() noexcept;
static std::unordered_map<std::string_view, T>& getMap() noexcept;
static std::unordered_map<std::string, Property> mStringToProperty;
static std::unordered_map<std::string, UniformType> mStringToUniformType;
static std::unordered_map<std::string, SamplerType> mStringToSamplerType;
static std::unordered_map<std::string, SubpassType> mStringToSubpassType;
static std::unordered_map<std::string, SamplerFormat> mStringToSamplerFormat;
static std::unordered_map<std::string, ParameterPrecision> mStringToSamplerPrecision;
static std::unordered_map<std::string, OutputTarget> mStringToOutputTarget;
static std::unordered_map<std::string, OutputQualifier> mStringToOutputQualifier;
static std::unordered_map<std::string, OutputType> mStringToOutputType;
static std::unordered_map<std::string, ConstantType> mStringToConstantType;
static std::unordered_map<std::string, ShaderStageType> mStringToShaderStageType;
static std::unordered_map<std::string_view, Property> mStringToProperty;
static std::unordered_map<std::string_view, UniformType> mStringToUniformType;
static std::unordered_map<std::string_view, SamplerType> mStringToSamplerType;
static std::unordered_map<std::string_view, SubpassType> mStringToSubpassType;
static std::unordered_map<std::string_view, SamplerFormat> mStringToSamplerFormat;
static std::unordered_map<std::string_view, ParameterPrecision> mStringToSamplerPrecision;
static std::unordered_map<std::string_view, OutputTarget> mStringToOutputTarget;
static std::unordered_map<std::string_view, OutputQualifier> mStringToOutputQualifier;
static std::unordered_map<std::string_view, OutputType> mStringToOutputType;
static std::unordered_map<std::string_view, ConstantType> mStringToConstantType;
static std::unordered_map<std::string_view, ShaderStageType> mStringToShaderStageType;
};
template<typename T>
std::string Enums::toString(T t) noexcept {
std::unordered_map<std::string, T>& map = getMap<T>();
std::string_view Enums::toString(T t) noexcept {
auto& map = getMap<T>();
auto result = std::find_if(map.begin(), map.end(), [t](auto& pair) {
return pair.second == t;
});
+24 -22
View File
@@ -18,9 +18,11 @@
#include "filamat/MaterialBuilder.h"
#include <string_view>
namespace filamat {
std::unordered_map<std::string, Property> Enums::mStringToProperty = {
std::unordered_map<std::string_view, Property> Enums::mStringToProperty = {
{ "baseColor", Property::BASE_COLOR },
{ "roughness", Property::ROUGHNESS },
{ "metallic", Property::METALLIC },
@@ -55,11 +57,11 @@ std::unordered_map<std::string, Property> Enums::mStringToProperty = {
};
template <>
std::unordered_map<std::string, Property>& Enums::getMap<Property>() noexcept {
std::unordered_map<std::string_view, Property>& Enums::getMap<Property>() noexcept {
return mStringToProperty;
};
std::unordered_map<std::string, UniformType> Enums::mStringToUniformType = {
std::unordered_map<std::string_view, UniformType> Enums::mStringToUniformType = {
{ "bool", UniformType::BOOL },
{ "bool2", UniformType::BOOL2 },
{ "bool3", UniformType::BOOL3 },
@@ -83,11 +85,11 @@ std::unordered_map<std::string, UniformType> Enums::mStringToUniformType = {
};
template <>
std::unordered_map<std::string, UniformType>& Enums::getMap<UniformType>() noexcept {
std::unordered_map<std::string_view, UniformType>& Enums::getMap<UniformType>() noexcept {
return mStringToUniformType;
};
std::unordered_map<std::string, SamplerType> Enums::mStringToSamplerType = {
std::unordered_map<std::string_view, SamplerType> Enums::mStringToSamplerType = {
{ "sampler2d", SamplerType::SAMPLER_2D },
{ "sampler2dArray", SamplerType::SAMPLER_2D_ARRAY },
{ "sampler3d", SamplerType::SAMPLER_3D },
@@ -97,20 +99,20 @@ std::unordered_map<std::string, SamplerType> Enums::mStringToSamplerType = {
};
template <>
std::unordered_map<std::string, SamplerType>& Enums::getMap<SamplerType>() noexcept {
std::unordered_map<std::string_view, SamplerType>& Enums::getMap<SamplerType>() noexcept {
return mStringToSamplerType;
};
std::unordered_map<std::string, SubpassType> Enums::mStringToSubpassType = {
std::unordered_map<std::string_view, SubpassType> Enums::mStringToSubpassType = {
{ "subpassInput", SubpassType::SUBPASS_INPUT },
};
template <>
std::unordered_map<std::string, SubpassType>& Enums::getMap<SubpassType>() noexcept {
std::unordered_map<std::string_view, SubpassType>& Enums::getMap<SubpassType>() noexcept {
return mStringToSubpassType;
};
std::unordered_map<std::string, ParameterPrecision> Enums::mStringToSamplerPrecision = {
std::unordered_map<std::string_view, ParameterPrecision> Enums::mStringToSamplerPrecision = {
{ "default", ParameterPrecision::DEFAULT },
{ "low", ParameterPrecision::LOW },
{ "medium", ParameterPrecision::MEDIUM },
@@ -118,30 +120,30 @@ std::unordered_map<std::string, ParameterPrecision> Enums::mStringToSamplerPreci
};
template <>
std::unordered_map<std::string, ParameterPrecision>& Enums::getMap<ParameterPrecision>() noexcept {
std::unordered_map<std::string_view, ParameterPrecision>& Enums::getMap<ParameterPrecision>() noexcept {
return mStringToSamplerPrecision;
};
std::unordered_map<std::string, OutputTarget> Enums::mStringToOutputTarget = {
std::unordered_map<std::string_view, OutputTarget> Enums::mStringToOutputTarget = {
{ "color", OutputTarget::COLOR },
{ "depth", OutputTarget::DEPTH }
};
template <>
std::unordered_map<std::string, OutputTarget>& Enums::getMap<OutputTarget>() noexcept {
std::unordered_map<std::string_view, OutputTarget>& Enums::getMap<OutputTarget>() noexcept {
return mStringToOutputTarget;
};
std::unordered_map<std::string, OutputQualifier> Enums::mStringToOutputQualifier = {
std::unordered_map<std::string_view, OutputQualifier> Enums::mStringToOutputQualifier = {
{ "out", OutputQualifier::OUT }
};
template <>
std::unordered_map<std::string, OutputQualifier>& Enums::getMap<OutputQualifier>() noexcept {
std::unordered_map<std::string_view, OutputQualifier>& Enums::getMap<OutputQualifier>() noexcept {
return mStringToOutputQualifier;
};
std::unordered_map<std::string, OutputType> Enums::mStringToOutputType = {
std::unordered_map<std::string_view, OutputType> Enums::mStringToOutputType = {
{ "float", OutputType::FLOAT },
{ "float2", OutputType::FLOAT2 },
{ "float3", OutputType::FLOAT3 },
@@ -149,11 +151,11 @@ std::unordered_map<std::string, OutputType> Enums::mStringToOutputType = {
};
template <>
std::unordered_map<std::string, OutputType>& Enums::getMap<OutputType>() noexcept {
std::unordered_map<std::string_view, OutputType>& Enums::getMap<OutputType>() noexcept {
return mStringToOutputType;
};
std::unordered_map<std::string, SamplerFormat> Enums::mStringToSamplerFormat = {
std::unordered_map<std::string_view, SamplerFormat> Enums::mStringToSamplerFormat = {
{ "int", SamplerFormat::INT },
{ "uint", SamplerFormat::UINT },
{ "float", SamplerFormat::FLOAT },
@@ -161,29 +163,29 @@ std::unordered_map<std::string, SamplerFormat> Enums::mStringToSamplerFormat = {
};
template <>
std::unordered_map<std::string, SamplerFormat>& Enums::getMap<SamplerFormat>() noexcept {
std::unordered_map<std::string_view, SamplerFormat>& Enums::getMap<SamplerFormat>() noexcept {
return mStringToSamplerFormat;
};
std::unordered_map<std::string, ConstantType > Enums::mStringToConstantType = {
std::unordered_map<std::string_view, ConstantType > Enums::mStringToConstantType = {
{ "int", ConstantType::INT },
{ "float", ConstantType::FLOAT },
{ "bool", ConstantType::BOOL },
};
template <>
std::unordered_map<std::string, ConstantType>& Enums::getMap<ConstantType>() noexcept {
std::unordered_map<std::string_view, ConstantType>& Enums::getMap<ConstantType>() noexcept {
return mStringToConstantType;
};
std::unordered_map<std::string, ShaderStageType> Enums::mStringToShaderStageType = {
std::unordered_map<std::string_view, ShaderStageType> Enums::mStringToShaderStageType = {
{ "fragment", ShaderStageType::FRAGMENT },
{ "vertex", ShaderStageType::VERTEX },
{ "compute", ShaderStageType::COMPUTE },
};
template <>
std::unordered_map<std::string, ShaderStageType>& Enums::getMap<ShaderStageType>() noexcept {
std::unordered_map<std::string_view, ShaderStageType>& Enums::getMap<ShaderStageType>() noexcept {
return mStringToShaderStageType;
};
+10 -15
View File
@@ -849,17 +849,16 @@ static void showErrorMessage(const char* materialName, filament::Variant const v
const char* targetApiString = "unknown";
switch (targetApi) {
case TargetApi::OPENGL:
targetApiString = (featureLevel == MaterialBuilder::FeatureLevel::FEATURE_LEVEL_0)
? "GLES 2.0.\n" : "OpenGL.\n";
targetApiString = (featureLevel == MaterialBuilder::FeatureLevel::FEATURE_LEVEL_0) ? "GLES 2.0" : "OpenGL";
break;
case TargetApi::VULKAN:
targetApiString = "Vulkan.\n";
targetApiString = "Vulkan";
break;
case TargetApi::METAL:
targetApiString = "Metal.\n";
targetApiString = "Metal";
break;
case TargetApi::WEBGPU:
targetApiString = "WebGPU.\n";
targetApiString = "WebGPU";
break;
case TargetApi::ALL:
assert_invariant(false); // Unreachable.
@@ -869,24 +868,20 @@ static void showErrorMessage(const char* materialName, filament::Variant const v
const char* shaderStageString = "unknown";
switch (shaderType) {
case ShaderStage::VERTEX:
shaderStageString = "Vertex Shader\n";
shaderStageString = "Vertex Shader";
break;
case ShaderStage::FRAGMENT:
shaderStageString = "Fragment Shader\n";
shaderStageString = "Fragment Shader";
break;
case ShaderStage::COMPUTE:
shaderStageString = "Compute Shader\n";
shaderStageString = "Compute Shader";
break;
}
LOG(ERROR)
<< "Error in \"" << materialName << "\""
<< ", Variant 0x" << io::hex << +variant.key
<< ", " << targetApiString
<< "=========================\n"
<< "Generated " << shaderStageString
<< "=========================\n"
<< shaderCode;
<< ", " << shaderStageString
<< ", Variant " << io::hex << +variant.key;
}
bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector<Variant>& variants,
@@ -1417,7 +1412,7 @@ bool MaterialBuilder::checkMaterialLevelFeatures(MaterialInfo const& info) const
auto const* stage = to_string(sib.getStageFlags());
for (auto const& sampler: samplers) {
LOG(ERROR) << "\"" << sampler.name.c_str() << "\" "
<< Enums::toString(sampler.type).c_str() << " " << stage << '\n';
<< Enums::toString(sampler.type) << " " << stage << '\n';
}
};
@@ -165,6 +165,9 @@ BufferInterfaceBlock const& UibGenerator::getPerViewUib() noexcept {
// ------------------------------------------------------------------------------------
{ "directionalShadows", 0, Type::INT },
{ "ssContactShadowDistance", 0, Type::FLOAT },
{ "shadowAtlasResolution", 0, Type::FLOAT2, Precision::HIGH },
{ "shadowReserved0", 0, Type::FLOAT },
{ "shadowReserved1", 0, Type::FLOAT },
{ "cascadeSplits", 0, Type::FLOAT4, Precision::HIGH },
{ "cascades", 0, Type::INT },
+1 -1
View File
@@ -44,7 +44,7 @@ target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
target_include_directories(${TARGET} PRIVATE ${filamat_SOURCE_DIR}/src)
set_target_properties(${TARGET} PROPERTIES FOLDER Libs)
target_link_libraries(${TARGET} getopt filamat filabridge utils)
target_link_libraries(${TARGET} filamat filabridge utils)
# ==================================================================================================
# Installation
+2 -2
View File
@@ -41,13 +41,13 @@ bool DirIncluder::operator()(const utils::CString& includedBy, IncludeResult& re
const utils::Path headerPath = getHeaderPath();
if (!headerPath.isFile()) {
utils::slog.e << "File " << headerPath << " does not exist." << utils::io::endl;
utils::slog.e << "File " << headerPath.c_str() << " does not exist." << utils::io::endl;
return false;
}
std::ifstream stream(headerPath.getPath(), std::ios::binary);
if (!stream) {
utils::slog.e << "Unable to open " << headerPath << "." << utils::io::endl;
utils::slog.e << "Unable to open " << headerPath.c_str() << "." << utils::io::endl;
return false;
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -52,7 +52,7 @@ set(LIBS
filament
filament-iblprefilter
geometry
getopt
image
imageio
imgui
+6
View File
@@ -12,6 +12,7 @@ set(PUBLIC_HDR_DIR include)
file(GLOB_RECURSE PUBLIC_HDRS ${PUBLIC_HDR_DIR}/${TARGET}/*.h)
set(DIST_HDRS
${PUBLIC_HDR_DIR}/${TARGET}/getopt.h
${PUBLIC_HDR_DIR}/${TARGET}/algorithm.h
${PUBLIC_HDR_DIR}/${TARGET}/bitset.h
${PUBLIC_HDR_DIR}/${TARGET}/CallStack.h
@@ -122,6 +123,11 @@ endif()
include_directories(${PUBLIC_HDR_DIR})
add_library(${TARGET} STATIC ${PUBLIC_HDRS} ${SRCS})
if (HAS_SYSTEM_GETOPT)
target_compile_definitions(${TARGET} PUBLIC HAS_SYSTEM_GETOPT)
else()
target_link_libraries(${TARGET} PUBLIC getopt)
endif()
target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
set_target_properties(${TARGET} PROPERTIES FOLDER Libs)
target_link_libraries(${TARGET} PUBLIC tsl)
+8 -8
View File
@@ -28,9 +28,9 @@
#include <utils/CallStack.h>
#include <utils/compiler.h>
#include <utils/CString.h>
#include <utils/sstream.h>
#include <string>
#include <string_view>
#ifdef __EXCEPTIONS
@@ -394,14 +394,14 @@ public:
* @param file the file where the above function in implemented
* @param line the line in the above file where the error was detected
* @param literal a literal version of the error message
* @param reason std::string describing the error
* @param reason CString describing the error
* @see ASSERT_PRECONDITION, ASSERT_POSTCONDITION, ASSERT_ARITHMETIC
* @see PANIC_PRECONDITION, PANIC_POSTCONDITION, PANIC_ARITHMETIC
* @see setMode()
*/
static void panic(
char const* function, char const* file, int line, char const* literal,
std::string reason) UTILS_NORETURN;
CString reason) UTILS_NORETURN;
private:
/**
@@ -413,7 +413,7 @@ private:
* @param reason a description of the cause of the error
*/
TPanic(char const* function, char const* file, int line, char const* literal,
std::string reason);
CString reason);
friend class PreconditionPanic;
friend class PostconditionPanic;
@@ -426,9 +426,9 @@ private:
char const* const mFile = nullptr; // file where the panic happened
char const* const mFunction = nullptr; // function where the panic happened
int const mLine = -1; // line where the panic happened
std::string mLiteral; // reason for the panic, built only from literals
std::string mReason; // reason for the panic
mutable std::string mWhat; // fully formatted reason
CString mLiteral; // reason for the panic, built only from literals
CString mReason; // reason for the panic
mutable CString mWhat; // fully formatted reason
CallStack mCallstack;
};
@@ -525,7 +525,7 @@ public:
PanicStream& operator<<(const char* value) noexcept;
PanicStream& operator<<(const unsigned char* value) noexcept;
PanicStream& operator<<(std::string const& value) noexcept;
PanicStream& operator<<(CString const& value) noexcept;
PanicStream& operator<<(std::string_view const& value) noexcept;
protected:
+54
View File
@@ -0,0 +1,54 @@
/*
* Copyright (C) 2026 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef UTILS_GETOPT_H
#define UTILS_GETOPT_H
// If system has getopt, we just include it
#if defined(HAS_SYSTEM_GETOPT)
#include <getopt.h>
#else
#include <getopt/getopt.h>
#endif
#ifdef __cplusplus
#undef no_argument
#undef required_argument
#undef optional_argument
// This is an aliasing of getopt to prevent compilation conflicts with the system getop (if
// it exists). Please refer to third_party/getopt for API details.
namespace utils {
namespace getopt {
using ::getopt;
using ::optarg;
using ::optind;
using ::opterr;
using ::optopt;
using ::option;
using ::getopt_long;
using ::getopt_long_only;
constexpr int no_argument = 0;
constexpr int required_argument = 1;
constexpr int optional_argument = 2;
}
}
#endif // __cplusplus
#endif // UTILS_GETOPT_H
+12 -3
View File
@@ -24,8 +24,12 @@
#include <ostream>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <stddef.h>
#include <stdint.h>
namespace utils::io {
struct ostream_;
@@ -62,7 +66,6 @@ public:
ostream& operator<<(const char* string) noexcept;
ostream& operator<<(const unsigned char* string) noexcept;
ostream& operator<<(std::string const& s) noexcept;
ostream& operator<<(std::string_view const& s) noexcept;
ostream& operator<<(ostream& (* f)(ostream&)) noexcept { return f(*this); }
@@ -149,11 +152,17 @@ class ostream;
}
inline std::ostream& operator<<(std::ostream& o, bitset32 const& s) noexcept {
return o << (void*) uintptr_t(s.getValue());
return o << reinterpret_cast<void*>(uintptr_t(s.getValue()));
}
inline io::ostream& operator<<(io::ostream& o, bitset32 const& s) noexcept {
return o << (void*) uintptr_t(s.getValue());
return o << reinterpret_cast<void*>(uintptr_t(s.getValue()));
}
inline io::ostream& operator<<(io::ostream& o, std::string const& s) noexcept {
return o << static_cast<std::string_view>(s);
}
}// namespace utils
+10 -3
View File
@@ -56,7 +56,6 @@
#if defined(WIN32)
# define NOMINMAX
# include <windows.h>
# include <string>
# else
# include <pthread.h>
#endif
@@ -210,14 +209,22 @@ JobSystem::JobSystem(const size_t userThreadCount, const size_t adoptableThreads
static_assert(std::atomic<bool>::is_always_lock_free);
static_assert(std::atomic<uint16_t>::is_always_lock_free);
std::random_device rd;
const size_t hardwareThreadCount = mThreadCount;
auto& states = mThreadStates;
#pragma nounroll
for (size_t i = 0, n = states.size(); i < n; i++) {
// don't use std::random_device because it forces the use of std::string
constexpr uint32_t base_seed = 1337;
uint32_t seed = base_seed + static_cast<uint32_t>(i);
seed = (seed ^ 61) ^ (seed >> 16);
seed = seed + (seed << 3);
seed = seed ^ (seed >> 4);
seed = seed * 0x27d4eb2d;
seed = seed ^ (seed >> 15);
auto& state = states[i];
state.rndGen = default_random_engine(rd());
state.rndGen = default_random_engine(seed);
state.js = this;
if (i < hardwareThreadCount) {
// don't start a thread of adoptable thread slots
+14 -14
View File
@@ -20,6 +20,7 @@
#include <utils/CallStack.h>
#include <utils/compiler.h>
#include <utils/CString.h>
#include <utils/Log.h>
#include <utils/Logger.h>
#include <utils/ostream.h>
@@ -33,7 +34,6 @@
#include <cstring>
#include <mutex>
#include <new>
#include <string>
#include <string_view>
#include <utility>
@@ -79,8 +79,8 @@ public:
// ------------------------------------------------------------------------------------------------
UTILS_NOINLINE
static std::string sprintfToString(const char* format, va_list args) noexcept {
std::string s;
static CString sprintfToString(const char* format, va_list args) noexcept {
CString s;
va_list tmp;
va_copy(tmp, args);
int n = vsnprintf(nullptr, 0, format, tmp);
@@ -91,22 +91,22 @@ static std::string sprintfToString(const char* format, va_list args) noexcept {
char* const buf = new(std::nothrow) char[n];
if (buf) {
vsnprintf(buf, size_t(n), format, args);
s.assign(buf);
s = CString(buf);
delete [] buf;
}
}
return s;
}
static std::string sprintfToString(const char* format, ...) noexcept {
static CString sprintfToString(const char* format, ...) noexcept {
va_list args;
va_start(args, format);
std::string const s{ sprintfToString(format, args) };
CString const s{ sprintfToString(format, args) };
va_end(args);
return s;
}
static std::string buildPanicString(
static CString buildPanicString(
std::string_view const& msg, const char* function, int line,
const char* file, const char* reason) {
#ifndef NDEBUG
@@ -130,7 +130,7 @@ void Panic::setPanicHandler(PanicHandlerCallback const handler, void* user) noex
template<typename T>
TPanic<T>::TPanic(const char* function, const char* file, int const line, char const* literal,
std::string reason)
CString reason)
: mFile(file),
mFunction(function),
mLine(line),
@@ -200,7 +200,7 @@ void TPanic<T>::panic(char const* function, char const* file, int const line, ch
const char* format, ...) {
va_list args;
va_start(args, format);
std::string reason{ sprintfToString(format, args) };
CString reason{ sprintfToString(format, args) };
va_end(args);
panic(function, file, line, literal, std::move(reason));
@@ -208,10 +208,10 @@ void TPanic<T>::panic(char const* function, char const* file, int const line, ch
template<typename T>
void TPanic<T>::panic(char const* function, char const* file, int line, char const* literal,
std::string reason) {
CString reason) {
if (reason.empty()) {
reason = literal;
reason = CString(literal);
}
T e(function, formatFile(file), line, literal, std::move(reason));
@@ -238,10 +238,10 @@ namespace details {
void panicLog(char const* function, char const* file, int const line, const char* format, ...) noexcept {
va_list args;
va_start(args, format);
std::string const reason{ sprintfToString(format, args) };
CString const reason{ sprintfToString(format, args) };
va_end(args);
std::string const msg = buildPanicString("PanicLog",
CString const msg = buildPanicString("PanicLog",
function, line, file, reason.c_str());
slog.e << msg << io::endl;
@@ -343,7 +343,7 @@ PanicStream& PanicStream::operator<<(unsigned char const* value) noexcept {
return *this;
}
PanicStream& PanicStream::operator<<(std::string const& value) noexcept {
PanicStream& PanicStream::operator<<(CString const& value) noexcept {
mStream << value;
return *this;
}
-5
View File
@@ -25,7 +25,6 @@
#include <algorithm>
#include <mutex>
#include <string>
#include <string_view>
#include <utility>
@@ -206,10 +205,6 @@ ostream& ostream::operator<<(const void* value) noexcept {
return print("%p", value);
}
ostream& ostream::operator<<(std::string const& s) noexcept {
return print("%s", s.c_str());
}
ostream& ostream::operator<<(std::string_view const& s) noexcept {
return print("%.*s", s.length(), s.data());
}
-1
View File
@@ -228,7 +228,6 @@ add_library(samples-common STATIC
)
target_include_directories(samples-common PRIVATE
${ROOT_DIR}/third_party/getopt/include
)
target_link_libraries(samples-common filament)
+6 -6
View File
@@ -20,7 +20,7 @@
#include <utils/Path.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <iostream>
#include <string>
@@ -73,16 +73,16 @@ filament::Engine::Backend parseArgumentsForBackend(int argc, char* argv[]) {
// The first colon in OPTSTR turns on silent error reporting. This is important, as the
// arguments may also contain gtest parameters we don't know about.
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 }
};
int opt;
int optionIndex = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &optionIndex)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &optionIndex)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
+19 -19
View File
@@ -68,7 +68,7 @@
#include <math/vec3.h>
#include <math/vec4.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <algorithm>
#include <atomic>
@@ -151,7 +151,7 @@ static void printUsage(char* name) {
" Prints this message\n\n"
"API_USAGE"
" --ibl=<path to cmgen IBL>, -i <path>\n"
" Applies an IBL generated by cmgen's deploy option\n\n"
" Applies an IBL generated by cmgen's deploy utils::getopt::option\n\n"
" --scale=[number], -s [number]\n"
" Applies uniform scale\n\n"
" --material=<path>, -m <path>\n"
@@ -186,25 +186,25 @@ static void printUsage(char* name) {
// Parses command line arguments and populates the Config object.
static int handleCommandLineArguments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "ha:s:li:m:c:p:x:yb:S:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ "ibl", required_argument, nullptr, 'i' },
{ "scale", required_argument, nullptr, 's' },
{ "material", required_argument, nullptr, 'm' },
{ "params", required_argument, nullptr, 'p' },
{ "count", required_argument, nullptr, 'c' },
{ "light-on", no_argument, nullptr, 'l' },
{ "skybox-off", no_argument, nullptr, 'y' },
{ "prefix", required_argument, nullptr, 'x' },
{ "clear-color", required_argument, nullptr, 'b' },
{ "size", required_argument, nullptr, 'S' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ "ibl", utils::getopt::required_argument, nullptr, 'i' },
{ "scale", utils::getopt::required_argument, nullptr, 's' },
{ "material", utils::getopt::required_argument, nullptr, 'm' },
{ "params", utils::getopt::required_argument, nullptr, 'p' },
{ "count", utils::getopt::required_argument, nullptr, 'c' },
{ "light-on", utils::getopt::no_argument, nullptr, 'l' },
{ "skybox-off", utils::getopt::no_argument, nullptr, 'y' },
{ "prefix", utils::getopt::required_argument, nullptr, 'x' },
{ "clear-color", utils::getopt::required_argument, nullptr, 'b' },
{ "size", utils::getopt::required_argument, nullptr, 'S' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string const arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string const arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -272,7 +272,7 @@ static int handleCommandLineArguments(int argc, char* argv[], Config* config) {
}
}
return optind;
return utils::getopt::optind;
}
// Cleans up Filament resources (entities, materials, etc.) before exit.
+11 -11
View File
@@ -36,7 +36,7 @@
#include <camutils/Manipulator.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <utils/NameComponentManager.h>
@@ -112,19 +112,19 @@ static void printUsage(char* name) {
static int handleCommandLineArguments(int argc, char* argv[], App* app) {
static constexpr const char* OPTSTR = "ha:i:un:m:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ "ibl", required_argument, nullptr, 'i' },
{ "num", required_argument, nullptr, 'n' },
{ "animate", required_argument, nullptr, 'm' },
{ "ubershader", no_argument, nullptr, 'u' },
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ "ibl", utils::getopt::required_argument, nullptr, 'i' },
{ "num", utils::getopt::required_argument, nullptr, 'n' },
{ "animate", utils::getopt::required_argument, nullptr, 'm' },
{ "ubershader", utils::getopt::no_argument, nullptr, 'u' },
{ nullptr, 0, nullptr, 0 }
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -147,7 +147,7 @@ static int handleCommandLineArguments(int argc, char* argv[], App* app) {
break;
}
}
return optind;
return utils::getopt::optind;
}
static std::ifstream::pos_type getFileSize(const char* filename) {
+23 -29
View File
@@ -46,7 +46,7 @@
#include <private/filament/EngineEnums.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <utils/NameComponentManager.h>
#include <utils/Log.h>
@@ -219,29 +219,29 @@ static std::ifstream::pos_type getFileSize(const char* filename) {
static int handleCommandLineArguments(int argc, char* argv[], App* app) {
static constexpr const char* OPTSTR = "ha:f:i:usc:rt:y:b:evg:dw:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ "feature-level", required_argument, nullptr, 'f' },
{ "batch", required_argument, nullptr, 'b' },
{ "headless", no_argument, nullptr, 'e' },
{ "ibl", required_argument, nullptr, 'i' },
{ "ubershader", no_argument, nullptr, 'u' },
{ "actual-size", no_argument, nullptr, 's' },
{ "camera", required_argument, nullptr, 'c' },
{ "eyes", required_argument, nullptr, 'y' },
{ "recompute-aabb", no_argument, nullptr, 'r' },
{ "settings", required_argument, nullptr, 't' },
{ "split-view", no_argument, nullptr, 'v' },
{ "vulkan-gpu-hint", required_argument, nullptr, 'g' },
{ "screenshot-as-ppm", no_argument, nullptr, 'd' },
{ "webgpu-backend", required_argument, nullptr, 'w' },
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ "feature-level", utils::getopt::required_argument, nullptr, 'f' },
{ "batch", utils::getopt::required_argument, nullptr, 'b' },
{ "headless", utils::getopt::no_argument, nullptr, 'e' },
{ "ibl", utils::getopt::required_argument, nullptr, 'i' },
{ "ubershader", utils::getopt::no_argument, nullptr, 'u' },
{ "actual-size", utils::getopt::no_argument, nullptr, 's' },
{ "camera", utils::getopt::required_argument, nullptr, 'c' },
{ "eyes", utils::getopt::required_argument, nullptr, 'y' },
{ "recompute-aabb", utils::getopt::no_argument, nullptr, 'r' },
{ "settings", utils::getopt::required_argument, nullptr, 't' },
{ "split-view", utils::getopt::no_argument, nullptr, 'v' },
{ "vulkan-gpu-hint", utils::getopt::required_argument, nullptr, 'g' },
{ "screenshot-as-ppm", utils::getopt::no_argument, nullptr, 'd' },
{ "webgpu-backend", utils::getopt::required_argument, nullptr, 'w' },
{ nullptr, 0, nullptr, 0 }
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string const arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string const arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -327,7 +327,7 @@ static int handleCommandLineArguments(int argc, char* argv[], App* app) {
std::cerr << "--headless is allowed only when --batch is present." << std::endl;
app->config.headless = false;
}
return optind;
return utils::getopt::optind;
}
static bool loadSettings(const char* filename, Settings* out) {
@@ -1017,16 +1017,10 @@ int main(int argc, char** argv) {
#endif
const auto overdrawVisibilityBit = (1u << App::Scene::OVERDRAW_VISIBILITY_LAYER);
bool visualizeOverdraw = view->getVisibleLayers() & overdrawVisibilityBit;
// TODO: enable after stencil buffer supported is added for Vulkan.
const bool overdrawDisabled = engine->getBackend() == backend::Backend::VULKAN;
ImGui::BeginDisabled(overdrawDisabled);
ImGui::Checkbox(!overdrawDisabled ? "Visualize overdraw"
: "Visualize overdraw (disabled for Vulkan)",
&visualizeOverdraw);
ImGui::EndDisabled();
ImGui::Checkbox("Visualize overdraw", &visualizeOverdraw);
view->setVisibleLayers(overdrawVisibilityBit,
(uint8_t)visualizeOverdraw << App::Scene::OVERDRAW_VISIBILITY_LAYER);
view->setStencilBufferEnabled(visualizeOverdraw);
app.viewer->getSettings().view.stencilBufferEnabled = visualizeOverdraw;
}
if (ImGui::BeginPopupModal("MessageBox", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
+8 -8
View File
@@ -34,7 +34,7 @@
#include <utils/JobSystem.h>
#include <utils/Path.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <filamentapp/FilamentApp.h>
@@ -123,15 +123,15 @@ static void printUsage(char* name) {
static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg != nullptr ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg != nullptr ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -143,7 +143,7 @@ static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
}
}
return optind;
return utils::getopt::optind;
}
template<typename T>
+7 -7
View File
@@ -37,7 +37,7 @@
#include <filamentapp/Config.h>
#include <filamentapp/FilamentApp.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <stb_image.h>
@@ -94,15 +94,15 @@ static void printUsage(char* name) {
static int handleCommandLineArguments(int argc, char* argv[], Config& config) {
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 }
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -113,7 +113,7 @@ static int handleCommandLineArguments(int argc, char* argv[], Config& config) {
break;
}
}
return optind;
return utils::getopt::optind;
}
struct App {
+8 -8
View File
@@ -31,7 +31,7 @@
#include <utils/EntityManager.h>
#include <utils/Path.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <filamentapp/Config.h>
#include <filamentapp/FilamentApp.h>
@@ -113,15 +113,15 @@ static void printUsage(char* name) {
static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg != nullptr ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg != nullptr ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -133,7 +133,7 @@ static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
}
}
return optind;
return utils::getopt::optind;
}
int main(int argc, char** argv) {
+7 -7
View File
@@ -31,7 +31,7 @@
#include <filamentapp/Config.h>
#include <filamentapp/FilamentApp.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <iostream>
#include <string>// for printing usage/help
@@ -80,15 +80,15 @@ static void printUsage(char* name) {
static int handleCommandLineArguments(int argc, char* argv[], App* app) {
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 }
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -99,7 +99,7 @@ static int handleCommandLineArguments(int argc, char* argv[], App* app) {
break;
}
}
return optind;
return utils::getopt::optind;
}
int main(int argc, char** argv) {
+8 -8
View File
@@ -37,7 +37,7 @@
#include <cmath>
#include <iostream>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include "generated/resources/resources.h"
@@ -89,15 +89,15 @@ static void printUsage(char* name) {
static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg != nullptr ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg != nullptr ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -109,7 +109,7 @@ static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
}
}
return optind;
return utils::getopt::optind;
}
+8 -8
View File
@@ -31,7 +31,7 @@
#include <utils/EntityManager.h>
#include <utils/Path.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <filamentapp/Config.h>
#include <filamentapp/FilamentApp.h>
@@ -116,15 +116,15 @@ static void printUsage(char* name) {
static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg != nullptr ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg != nullptr ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -136,7 +136,7 @@ static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
}
}
return optind;
return utils::getopt::optind;
}
int main(int argc, char** argv) {
+8 -8
View File
@@ -31,7 +31,7 @@
#include <utils/EntityManager.h>
#include <utils/Path.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <filamentapp/Config.h>
#include <filamentapp/FilamentApp.h>
@@ -108,15 +108,15 @@ static void printUsage(char* name) {
static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg != nullptr ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg != nullptr ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -128,7 +128,7 @@ static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
}
}
return optind;
return utils::getopt::optind;
}
int main(int argc, char** argv) {
+9 -9
View File
@@ -39,7 +39,7 @@
#include <filamentapp/Config.h>
#include <filamentapp/FilamentApp.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <iostream>
#include <vector>
@@ -108,17 +108,17 @@ static void printUsage(char* name) {
static int handleCommandLineArguments(int argc, char* argv[], App* app) {
static constexpr const char* OPTSTR = "ha:y:m:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ "eyes", required_argument, nullptr, 'y' },
{ "samples", required_argument, nullptr, 'm'},
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ "eyes", utils::getopt::required_argument, nullptr, 'y' },
{ "samples", utils::getopt::required_argument, nullptr, 'm'},
{ nullptr, 0, nullptr, 0 }
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -156,7 +156,7 @@ static int handleCommandLineArguments(int argc, char* argv[], App* app) {
}
}
}
return optind;
return utils::getopt::optind;
}
int main(int argc, char** argv) {
+7 -7
View File
@@ -33,7 +33,7 @@
#include <filamentapp/Config.h>
#include <filamentapp/FilamentApp.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <cmath>
#include <iostream>
@@ -94,15 +94,15 @@ static void printUsage(char* name) {
static int handleCommandLineArguments(int argc, char* argv[], App* app) {
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 }
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -113,7 +113,7 @@ static int handleCommandLineArguments(int argc, char* argv[], App* app) {
break;
}
}
return optind;
return utils::getopt::optind;
}
int main(int argc, char** argv) {
+6 -6
View File
@@ -36,7 +36,7 @@
#include <utils/EntityManager.h>
#include <utils/Path.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <filamentapp/Config.h>
#include <filamentapp/FilamentApp.h>
@@ -105,13 +105,13 @@ static void printUsage(char* name) {
static int handleCommandLineArguments(int argc, char* argv[], App* app) {
static constexpr const char* OPTSTR = "ha:p";
static const struct option OPTIONS[] = { { "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' }, { "positions", no_argument, nullptr, 'p' },
static const utils::getopt::option OPTIONS[] = { { "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' }, { "positions", utils::getopt::no_argument, nullptr, 'p' },
{ nullptr, 0, nullptr, 0 } };
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -125,7 +125,7 @@ static int handleCommandLineArguments(int argc, char* argv[], App* app) {
break;
}
}
return optind;
return utils::getopt::optind;
}
int main(int argc, char** argv) {
+9 -9
View File
@@ -66,7 +66,7 @@
#include <utils/EntityManager.h>
#include <utils/Path.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <algorithm>
#include <iostream>
@@ -392,16 +392,16 @@ static void printUsage(char* name) {
// Parses command-line arguments.
static int handleCommandLineArguments(int const argc, char* argv[], App* app) {
static constexpr const char* OPTSTR = "he:a:c:";
static constexpr option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ "emitters", required_argument, nullptr, 'e' },
{ "camera", required_argument, nullptr, 'c' },
static constexpr utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ "emitters", utils::getopt::required_argument, nullptr, 'e' },
{ "camera", utils::getopt::required_argument, nullptr, 'c' },
{ nullptr, 0, nullptr, 0 } };
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
const std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
const std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -427,7 +427,7 @@ static int handleCommandLineArguments(int const argc, char* argv[], App* app) {
break;
}
}
return optind;
return utils::getopt::optind;
}
// Resets a particle to a new random state.
+8 -8
View File
@@ -38,7 +38,7 @@
#include <camutils/Manipulator.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <math/half.h>
#include <math/vec3.h>
@@ -119,16 +119,16 @@ static void printUsage(char* name) {
static int handleCommandLineArguments(int argc, char* argv[], App* app) {
static constexpr const char* OPTSTR = "ha:c:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ "camera", required_argument, nullptr, 'c' },
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ "camera", utils::getopt::required_argument, nullptr, 'c' },
{ nullptr, 0, nullptr, 0 }
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -148,7 +148,7 @@ static int handleCommandLineArguments(int argc, char* argv[], App* app) {
break;
}
}
return optind;
return utils::getopt::optind;
}
static constexpr float4 sFullScreenTriangleVertices[3] = {
+15 -15
View File
@@ -21,7 +21,7 @@
#include <map>
#include <vector>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <utils/EntityManager.h>
#include <utils/Path.h>
@@ -111,22 +111,22 @@ static void printUsage(char* name) {
static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "hi:vs:mdcpa:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ "ibl", required_argument, nullptr, 'i' },
{ "split-view", no_argument, nullptr, 'v' },
{ "scale", required_argument, nullptr, 's' },
{ "more-lights", no_argument, nullptr, 'm' },
{ "disco", no_argument, nullptr, 'd' },
{ "clear-coat", no_argument, nullptr, 'c' },
{ "shadow-plane", no_argument, nullptr, 'p' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ "ibl", utils::getopt::required_argument, nullptr, 'i' },
{ "split-view", utils::getopt::no_argument, nullptr, 'v' },
{ "scale", utils::getopt::required_argument, nullptr, 's' },
{ "more-lights", utils::getopt::no_argument, nullptr, 'm' },
{ "disco", utils::getopt::no_argument, nullptr, 'd' },
{ "clear-coat", utils::getopt::no_argument, nullptr, 'c' },
{ "shadow-plane", utils::getopt::no_argument, nullptr, 'p' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg != nullptr ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg != nullptr ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -162,7 +162,7 @@ static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
}
}
return optind;
return utils::getopt::optind;
}
#pragma clang diagnostic push
+15 -15
View File
@@ -21,7 +21,7 @@
#include <map>
#include <vector>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <imgui.h>
@@ -127,22 +127,22 @@ static void printUsage(char* name) {
static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "ha:vps:i:d:c:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ "ibl", required_argument, nullptr, 'i' },
{ "split-view", no_argument, nullptr, 'v' },
{ "scale", required_argument, nullptr, 's' },
{ "shadow-plane", no_argument, nullptr, 'p' },
{ "single", no_argument, nullptr, 'n' },
{ "dirt", required_argument, nullptr, 'd' },
{ "camera", required_argument, nullptr, 'c' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ "ibl", utils::getopt::required_argument, nullptr, 'i' },
{ "split-view", utils::getopt::no_argument, nullptr, 'v' },
{ "scale", utils::getopt::required_argument, nullptr, 's' },
{ "shadow-plane", utils::getopt::no_argument, nullptr, 'p' },
{ "single", utils::getopt::no_argument, nullptr, 'n' },
{ "dirt", utils::getopt::required_argument, nullptr, 'd' },
{ "camera", utils::getopt::required_argument, nullptr, 'c' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -187,7 +187,7 @@ static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
}
}
return optind;
return utils::getopt::optind;
}
static void cleanup(Engine* engine, View*, Scene*) {
+7 -7
View File
@@ -33,7 +33,7 @@
#include <filameshio/MeshReader.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <imgui.h>
@@ -97,15 +97,15 @@ static void printUsage(char* name) {
static int handleCommandLineArguments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 }
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -116,7 +116,7 @@ static int handleCommandLineArguments(int argc, char* argv[], Config* config) {
break;
}
}
return optind;
return utils::getopt::optind;
}
static void removeObjects(Engine* engine, Scene* scene, App& app, int count) {
+8 -8
View File
@@ -37,7 +37,7 @@
#include <filamentapp/Config.h>
#include <filamentapp/FilamentApp.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <iostream>
@@ -149,16 +149,16 @@ static void printUsage(char* name) {
static int handleCommandLineArguments(int argc, char* argv[], App* app) {
static constexpr const char* OPTSTR = "ha:m:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ "mode", required_argument, nullptr, 'm' },
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ "mode", utils::getopt::required_argument, nullptr, 'm' },
{ nullptr, 0, nullptr, 0 }
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -179,7 +179,7 @@ static int handleCommandLineArguments(int argc, char* argv[], App* app) {
break;
}
}
return optind;
return utils::getopt::optind;
}
int main(int argc, char** argv) {
+12 -12
View File
@@ -21,7 +21,7 @@
#include <map>
#include <vector>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <utils/Path.h>
@@ -76,7 +76,7 @@ static void printUsage(char* name) {
" Prints this message\n\n"
"API_USAGE"
" --ibl=<path to cmgen IBL>, -i <path>\n"
" Applies an IBL generated by cmgen's deploy option\n\n"
" Applies an IBL generated by cmgen's deploy utils::getopt::option\n\n"
" --split-view, -v\n"
" Splits the window into 4 views\n\n"
" --scale=[number], -s [number]\n"
@@ -95,18 +95,18 @@ static void printUsage(char* name) {
static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "ha:i:vs:";
static const struct option OPTIONS[] = {
{ "help", no_argument, 0, 'h' },
{ "api", required_argument, 0, 'a' },
{ "ibl", required_argument, 0, 'i' },
{ "split-view", no_argument, 0, 'v' },
{ "scale", required_argument, 0, 's' },
{ 0, 0, 0, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, 0, 'h' },
{ "api", utils::getopt::required_argument, 0, 'a' },
{ "ibl", utils::getopt::required_argument, 0, 'i' },
{ "split-view", utils::getopt::no_argument, 0, 'v' },
{ "scale", utils::getopt::required_argument, 0, 's' },
{ 0, 0, 0, 0 } // termination of the utils::getopt::option list
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -133,7 +133,7 @@ static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
}
}
return optind;
return utils::getopt::optind;
}
static void cleanup(Engine* engine, View* view, Scene* scene) {
+15 -15
View File
@@ -39,7 +39,7 @@
#include <math/mat4.h>
#include <math/vec3.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <stb_image.h>
@@ -106,7 +106,7 @@ static void printUsage(char* name) {
" Prints this message\n\n"
"API_USAGE"
" --ibl=<path to cmgen IBL>, -i <path>\n"
" Applies an IBL generated by cmgen's deploy option\n\n"
" Applies an IBL generated by cmgen's deploy utils::getopt::option\n\n"
" --split-view, -v\n"
" Splits the window into 4 views\n\n"
" --scale=[number], -s [number]\n"
@@ -140,21 +140,21 @@ static void printUsage(char* name) {
static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "ha:i:vs:m:cA";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ "ibl", required_argument, nullptr, 'i' },
{ "split-view", no_argument, nullptr, 'v' },
{ "scale", required_argument, nullptr, 's' },
{ "material", required_argument, nullptr, 'm' },
{ "clear-coat", no_argument, nullptr, 'c' },
{ "anisotropy", no_argument, nullptr, 'A' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ "ibl", utils::getopt::required_argument, nullptr, 'i' },
{ "split-view", utils::getopt::no_argument, nullptr, 'v' },
{ "scale", utils::getopt::required_argument, nullptr, 's' },
{ "material", utils::getopt::required_argument, nullptr, 'm' },
{ "clear-coat", utils::getopt::no_argument, nullptr, 'c' },
{ "anisotropy", utils::getopt::no_argument, nullptr, 'A' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string const arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string const arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -190,7 +190,7 @@ static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
}
}
return optind;
return utils::getopt::optind;
}
static void cleanup(Engine* engine, View*, Scene*) {
+15 -15
View File
@@ -21,7 +21,7 @@
#include <map>
#include <vector>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <utils/Path.h>
@@ -82,7 +82,7 @@ static void printUsage(char* name) {
" Prints this message\n\n"
"API_USAGE"
" --ibl=<path to cmgen IBL>, -i <path>\n"
" Applies an IBL generated by cmgen's deploy option\n\n"
" Applies an IBL generated by cmgen's deploy utils::getopt::option\n\n"
" --split-view, -v\n"
" Splits the window into 4 views\n\n"
" --scale=[number], -s [number]\n"
@@ -107,21 +107,21 @@ static void printUsage(char* name) {
static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "ha:i:vs:n:a:c:b:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ "ibl", required_argument, nullptr, 'i' },
{ "split-view", no_argument, nullptr, 'v' },
{ "scale", required_argument, nullptr, 's' },
{ "normal-map", required_argument, nullptr, 'n' },
{ "clear-coat-normal-map", required_argument, nullptr, 'c' },
{ "basecolor-map", required_argument, nullptr, 'b' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ "ibl", utils::getopt::required_argument, nullptr, 'i' },
{ "split-view", utils::getopt::no_argument, nullptr, 'v' },
{ "scale", utils::getopt::required_argument, nullptr, 's' },
{ "normal-map", utils::getopt::required_argument, nullptr, 'n' },
{ "clear-coat-normal-map", utils::getopt::required_argument, nullptr, 'c' },
{ "basecolor-map", utils::getopt::required_argument, nullptr, 'b' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -157,7 +157,7 @@ static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
}
}
return optind;
return utils::getopt::optind;
}
static void cleanup(Engine* engine, View*, Scene*) {
+8 -8
View File
@@ -32,7 +32,7 @@
#include <utils/EntityManager.h>
#include <utils/Path.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <filamentapp/Config.h>
#include <filamentapp/FilamentApp.h>
@@ -160,15 +160,15 @@ static void printUsage(char* name) {
static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg != nullptr ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg != nullptr ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -180,7 +180,7 @@ static int handleCommandLineArgments(int argc, char* argv[], Config* config) {
}
}
return optind;
return utils::getopt::optind;
}
int main(int argc, char** argv) {
+7 -7
View File
@@ -37,7 +37,7 @@
#include <filamentapp/FilamentApp.h>
#include <filamentapp/IBL.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <utils/Path.h>
@@ -90,15 +90,15 @@ static void printUsage(char* name) {
static int handleCommandLineArguments(int argc, char* argv[], Config* config) {
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 }
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -109,7 +109,7 @@ static int handleCommandLineArguments(int argc, char* argv[], Config* config) {
break;
}
}
return optind;
return utils::getopt::optind;
}
static Texture* loadNormalMap(Engine* engine, const uint8_t* normals, size_t nbytes) {
+7 -7
View File
@@ -36,7 +36,7 @@
#include <filamentapp/Config.h>
#include <filamentapp/FilamentApp.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <stb_image.h>
@@ -103,15 +103,15 @@ static void printUsage(char* name) {
static int handleCommandLineArguments(int argc, char* argv[], Config& config) {
static constexpr const char* OPTSTR = "ha:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 }
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -122,7 +122,7 @@ static int handleCommandLineArguments(int argc, char* argv[], Config& config) {
break;
}
}
return optind;
return utils::getopt::optind;
}
int main(int argc, char** argv) {
+7 -7
View File
@@ -28,7 +28,7 @@
#include <utils/EntityManager.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
#include <iostream>
#include <string>
@@ -72,15 +72,15 @@ static void printUsage(char* name) {
static int handleCommandLineArguments(int argc, char* argv[], App* app) {
static constexpr const char* OPTSTR = "ha:f:i:usc:rt:b:ev";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "api", required_argument, nullptr, 'a' },
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "api", utils::getopt::required_argument, nullptr, 'a' },
{ nullptr, 0, nullptr, 0 }
};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -91,7 +91,7 @@ static int handleCommandLineArguments(int argc, char* argv[], App* app) {
break;
}
}
return optind;
return utils::getopt::optind;
}
int main(int argc, char** argv) {
+17 -4
View File
@@ -53,6 +53,12 @@ for f in $(find . -name '*.h'); do
done
popd >/dev/null
# Check if the system has getopt
HAS_SYSTEM_GETOPT=0
if echo "#include <getopt.h>" | clang -x c++ -std=c++17 -E - > /dev/null 2>&1; then
HAS_SYSTEM_GETOPT=1
fi
rm -rf out/check-headers
mkdir -p out/check-headers
@@ -61,10 +67,17 @@ echo "Checking that public headers compile independently..."
for include in "${includes[@]}"; do
rm -f ${TMP_FILE}
echo "Checking ${include}"
if [[ "${include}" == "utils/Systrace.h" ]]; then
# A necessary define before we can include utils/Systrace.h
echo "#define SYSTRACE_TAG SYSTRACE_TAG_DISABLED" >> ${TMP_FILE}
fi
case "${include}" in
"utils/Systrace.h")
# A necessary define before we can include utils/Systrace.h
echo "#define SYSTRACE_TAG SYSTRACE_TAG_DISABLED" >> ${TMP_FILE}
;;
"utils/getopt.h")
if [[ $HAS_SYSTEM_GETOPT -eq 1 ]]; then
echo "#define HAS_SYSTEM_GETOPT 1" >> ${TMP_FILE}
fi
;;
esac
echo "#include <${include}>" >> ${TMP_FILE}
# Filament is built internally with C++20, but we maintain C++17 compatibility (for the time
# being) in our public headers to support projects on older toolchains.
+30 -24
View File
@@ -1,24 +1,30 @@
cmake_minimum_required(VERSION 3.10)
project(getopt)
set(TARGET getopt)
set(PUBLIC_HDR_DIR include)
# ==================================================================================================
# Sources and headers
# ==================================================================================================
set(PUBLIC_HDRS include/getopt/getopt.h)
set(PRIVATE_HDRS include/getopt/getopt.h)
set(SRCS
src/getopt.c
src/getopt_long.c)
# ==================================================================================================
# Include and target definitions
# ==================================================================================================
include_directories(${PUBLIC_HDR_DIR})
add_library(${TARGET} STATIC ${PRIVATE_HDRS} ${PUBLIC_HDRS} ${SRCS})
target_include_directories (${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
set_target_properties(${TARGET} PROPERTIES FOLDER ThirdParty)
cmake_minimum_required(VERSION 3.10)
project(getopt)
set(TARGET getopt)
set(PUBLIC_HDR_DIR include)
# ==================================================================================================
# Sources and headers
# ==================================================================================================
set(PUBLIC_HDRS include/getopt/getopt.h)
set(PRIVATE_HDRS include/getopt/getopt.h)
set(SRCS
src/getopt.c
src/getopt_long.c)
# ==================================================================================================
# Include and target definitions
# ==================================================================================================
include_directories(${PUBLIC_HDR_DIR})
add_library(${TARGET} STATIC ${PRIVATE_HDRS} ${PUBLIC_HDRS} ${SRCS})
target_include_directories (${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
set_target_properties(${TARGET} PROPERTIES FOLDER ThirdParty)
# ==================================================================================================
# Installation
# ==================================================================================================
install(TARGETS ${TARGET} ARCHIVE DESTINATION lib/${DIST_DIR})
install(DIRECTORY ${PUBLIC_HDR_DIR}/getopt DESTINATION include)
+12 -12
View File
@@ -7,12 +7,12 @@ set(TARGET cmgen)
# Sources and headers
# ==================================================================================================
set(HDRS
src/ProgressUpdater.h
src/ProgressUpdater.h
)
set(SRCS
src/cmgen.cpp
src/ProgressUpdater.cpp
src/cmgen.cpp
src/ProgressUpdater.cpp
)
# ==================================================================================================
@@ -20,28 +20,28 @@ set(SRCS
# ==================================================================================================
add_executable(${TARGET} ${HDRS} ${SRCS})
target_link_libraries(${TARGET} PRIVATE ibl imageio getopt)
target_link_libraries(${TARGET} PRIVATE ibl imageio )
set_target_properties(${TARGET} PROPERTIES FOLDER Tools)
# ==================================================================================================
# Compile options and optimizations
# ==================================================================================================
if (MSVC)
target_compile_options(${TARGET} PRIVATE /fp:fast)
target_compile_options(${TARGET} PRIVATE /fp:fast)
else()
target_compile_options(${TARGET} PRIVATE -ffast-math -fno-finite-math-only)
target_compile_options(${TARGET} PRIVATE -ffast-math -fno-finite-math-only)
endif()
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W0 /Zc:__cplusplus")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W0 /Zc:__cplusplus")
endif()
# =================================================================================================
# Licenses
# ==================================================================================================
set(MODULE_LICENSES getopt libpng tinyexr libz)
set(MODULE_LICENSES libpng tinyexr libz)
set(GENERATION_ROOT ${CMAKE_CURRENT_BINARY_DIR}/generated)
list_licenses(${GENERATION_ROOT}/licenses/licenses.inc ${MODULE_LICENSES})
list_licenses(${GENERATION_ROOT}/licenses/licenses.inc "${MODULE_LICENSES}")
target_include_directories(${TARGET} PRIVATE ${GENERATION_ROOT})
# ==================================================================================================
@@ -53,7 +53,7 @@ install(TARGETS ${TARGET} RUNTIME DESTINATION bin)
# Tests
# ==================================================================================================
if (FILAMENT_BUILD_TESTING AND NOT ANDROID)
add_executable(test_${TARGET} tests/test_cmgen.cpp)
target_link_libraries(test_${TARGET} PRIVATE imageio gtest)
set_target_properties(test_${TARGET} PROPERTIES FOLDER Tests)
add_executable(test_${TARGET} tests/test_cmgen.cpp)
target_link_libraries(test_${TARGET} PRIVATE imageio gtest)
set_target_properties(test_${TARGET} PROPERTIES FOLDER Tests)
endif()
+34 -34
View File
@@ -44,7 +44,7 @@
#include <string.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
using namespace filament::math;
@@ -245,35 +245,35 @@ static void license() {
static int handleCommandLineArgments(int argc, char* argv[]) {
static constexpr const char* OPTSTR = "hqidt:f:c:s:x:w:S:";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "license", no_argument, nullptr, 'l' },
{ "quiet", no_argument, nullptr, 'q' },
{ "type", required_argument, nullptr, 't' },
{ "format", required_argument, nullptr, 'f' },
{ "compression", required_argument, nullptr, 'c' },
{ "size", required_argument, nullptr, 's' },
{ "extract", required_argument, nullptr, 'e' },
{ "extract-blur", required_argument, nullptr, 'r' },
{ "sh", optional_argument, nullptr, 'z' },
{ "sh-output", required_argument, nullptr, 'o' },
{ "sh-irradiance", no_argument, nullptr, 'i' },
{ "sh-shader", no_argument, nullptr, 'b' },
{ "sh-window", required_argument, nullptr, 'w' },
{ "clamp", no_argument, nullptr, 'K' },
{ "ibl-is-mipmap", required_argument, nullptr, 'y' },
{ "ibl-ld", required_argument, nullptr, 'p' },
{ "ibl-irradiance", required_argument, nullptr, 'P' },
{ "ibl-dfg", required_argument, nullptr, 'a' },
{ "ibl-dfg-multiscatter", no_argument, nullptr, 'u' },
{ "ibl-dfg-cloth", no_argument, nullptr, 'C' },
{ "ibl-no-prefilter", no_argument, nullptr, 'n' },
{ "ibl-min-lod-size", required_argument, nullptr, 'S' },
{ "ibl-samples", required_argument, nullptr, 'k' },
{ "deploy", required_argument, nullptr, 'x' },
{ "no-mirror", no_argument, nullptr, 'm' },
{ "debug", no_argument, nullptr, 'd' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "license", utils::getopt::no_argument, nullptr, 'l' },
{ "quiet", utils::getopt::no_argument, nullptr, 'q' },
{ "type", utils::getopt::required_argument, nullptr, 't' },
{ "format", utils::getopt::required_argument, nullptr, 'f' },
{ "compression", utils::getopt::required_argument, nullptr, 'c' },
{ "size", utils::getopt::required_argument, nullptr, 's' },
{ "extract", utils::getopt::required_argument, nullptr, 'e' },
{ "extract-blur", utils::getopt::required_argument, nullptr, 'r' },
{ "sh", utils::getopt::optional_argument, nullptr, 'z' },
{ "sh-output", utils::getopt::required_argument, nullptr, 'o' },
{ "sh-irradiance", utils::getopt::no_argument, nullptr, 'i' },
{ "sh-shader", utils::getopt::no_argument, nullptr, 'b' },
{ "sh-window", utils::getopt::required_argument, nullptr, 'w' },
{ "clamp", utils::getopt::no_argument, nullptr, 'K' },
{ "ibl-is-mipmap", utils::getopt::required_argument, nullptr, 'y' },
{ "ibl-ld", utils::getopt::required_argument, nullptr, 'p' },
{ "ibl-irradiance", utils::getopt::required_argument, nullptr, 'P' },
{ "ibl-dfg", utils::getopt::required_argument, nullptr, 'a' },
{ "ibl-dfg-multiscatter", utils::getopt::no_argument, nullptr, 'u' },
{ "ibl-dfg-cloth", utils::getopt::no_argument, nullptr, 'C' },
{ "ibl-no-prefilter", utils::getopt::no_argument, nullptr, 'n' },
{ "ibl-min-lod-size", utils::getopt::required_argument, nullptr, 'S' },
{ "ibl-samples", utils::getopt::required_argument, nullptr, 'k' },
{ "deploy", utils::getopt::required_argument, nullptr, 'x' },
{ "no-mirror", utils::getopt::no_argument, nullptr, 'm' },
{ "debug", utils::getopt::no_argument, nullptr, 'd' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int option_index = 0;
@@ -281,8 +281,8 @@ static int handleCommandLineArgments(int argc, char* argv[]) {
bool format_specified = false;
bool type_specified = false;
bool ktx_format_requested = false;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -471,7 +471,7 @@ static int handleCommandLineArgments(int argc, char* argv[]) {
if (num_sh_bands && g_sh_compute) {
g_sh_compute = (size_t) num_sh_bands;
}
return optind;
return utils::getopt::optind;
}
int main(int argc, char* argv[]) {
@@ -617,7 +617,7 @@ int main(int argc, char* argv[]) {
levels.push_back(std::move(cml));
}
// we mirror by default -- the mirror option in fact un-mirrors.
// we mirror by default -- the mirror utils::getopt::option in fact un-mirrors.
g_mirror = !g_mirror;
if (g_mirror) {
if (!g_quiet) {
+4 -4
View File
@@ -15,20 +15,20 @@ set(SRCS src/main.cpp)
# ==================================================================================================
add_executable(${TARGET} ${HDRS} ${SRCS})
target_link_libraries(${TARGET} PRIVATE imageio getopt)
target_link_libraries(${TARGET} PRIVATE imageio )
set_target_properties(${TARGET} PROPERTIES FOLDER Tools)
# ==================================================================================================
# Compile options and optimizations
# ==================================================================================================
if (NOT LINUX)
target_compile_options(${TARGET} PRIVATE )
target_compile_options(${TARGET} PRIVATE )
endif()
# =================================================================================================
# Licenses
# ==================================================================================================
set(MODULE_LICENSES getopt libpng tinyexr libz)
set(MODULE_LICENSES libpng tinyexr libz)
set(GENERATION_ROOT ${CMAKE_CURRENT_BINARY_DIR}/generated)
list_licenses(${GENERATION_ROOT}/licenses/licenses.inc ${MODULE_LICENSES})
list_licenses(${GENERATION_ROOT}/licenses/licenses.inc "${MODULE_LICENSES}")
target_include_directories(${TARGET} PRIVATE ${GENERATION_ROOT})
+11 -11
View File
@@ -31,7 +31,7 @@
#include <utils/compiler.h>
#include <utils/Path.h>
#include <getopt/getopt.h>
#include <utils/getopt.h>
using namespace filament::math;
using namespace image;
@@ -90,20 +90,20 @@ static void license() {
static int handleArguments(int argc, char* argv[]) {
static constexpr const char* OPTSTR = "hc:f:g";
static const struct option OPTIONS[] = {
{ "help", no_argument, nullptr, 'h' },
{ "license", no_argument, nullptr, 's' },
{ "ground-truth", no_argument, nullptr, 'g' },
{ "format", required_argument, nullptr, 'f' },
{ "compression", required_argument, nullptr, 'c' },
{ nullptr, 0, nullptr, 0 } // termination of the option list
static const utils::getopt::option OPTIONS[] = {
{ "help", utils::getopt::no_argument, nullptr, 'h' },
{ "license", utils::getopt::no_argument, nullptr, 's' },
{ "ground-truth", utils::getopt::no_argument, nullptr, 'g' },
{ "format", utils::getopt::required_argument, nullptr, 'f' },
{ "compression", utils::getopt::required_argument, nullptr, 'c' },
{ nullptr, 0, nullptr, 0 } // termination of the utils::getopt::option list
};
int opt;
int optionIndex = 0;
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &optionIndex)) >= 0) {
std::string arg(optarg ? optarg : "");
while ((opt = utils::getopt::getopt_long(argc, argv, OPTSTR, OPTIONS, &optionIndex)) >= 0) {
std::string arg(utils::getopt::optarg ? utils::getopt::optarg : "");
switch (opt) {
default:
case 'h':
@@ -145,7 +145,7 @@ static int handleArguments(int argc, char* argv[]) {
}
}
return optind;
return utils::getopt::optind;
}
static bool isIncludeFile(const Path& filename) {
+8 -8
View File
@@ -6,12 +6,12 @@ set(TARGET diffimg)
add_executable(${TARGET} main.cpp)
target_link_libraries(${TARGET} PRIVATE
getopt
imagediff
imageio
imageio-lite
image
utils
imagediff
imageio
imageio-lite
image
utils
)
set_target_properties(${TARGET} PROPERTIES FOLDER Tools)
@@ -19,9 +19,9 @@ set_target_properties(${TARGET} PROPERTIES FOLDER Tools)
# =================================================================================================
# Licenses
# ==================================================================================================
set(MODULE_LICENSES getopt)
set(MODULE_LICENSES )
set(GENERATION_ROOT ${CMAKE_CURRENT_BINARY_DIR}/generated)
list_licenses(${GENERATION_ROOT}/licenses/licenses.inc ${MODULE_LICENSES})
list_licenses(${GENERATION_ROOT}/licenses/licenses.inc "${MODULE_LICENSES}")
target_include_directories(${TARGET} PRIVATE ${GENERATION_ROOT})
# ==================================================================================================

Some files were not shown because too many files have changed in this diff Show More